1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScanPriv.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkEdge.h" 11948639b823dc76dbaa8cc68f32c1f7defcb8fb07mike@reedtribe.org#include "SkEdgeBuilder.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGeometry.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h" 14c07d23a6e220c0aff36e3e4e06c1b685a440108ereed@android.com#include "SkQuadClipper.h" 15045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#include "SkRasterClip.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRegion.h" 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h" 180a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com#include "SkTSort.h" 190a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com 200951ded8d887174a3ca575e3295daae547c3c6f7reed@google.com#ifdef SK_USE_LEGACY_AA_COVERAGE 210951ded8d887174a3ca575e3295daae547c3c6f7reed@google.com #define SK_USE_STD_SORT_FOR_EDGES 220951ded8d887174a3ca575e3295daae547c3c6f7reed@google.com#endif 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define kEDGE_HEAD_Y SK_MinS32 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define kEDGE_TAIL_Y SK_MaxS32 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 2899219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org static void validate_sort(const SkEdge* edge) { 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y = kEDGE_HEAD_Y; 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3199219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org while (edge->fFirstY != SK_MaxS32) { 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge->validate(); 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(y <= edge->fFirstY); 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y = edge->fFirstY; 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge = edge->fNext; 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define validate_sort(edge) 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4399219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.orgstatic inline void remove_edge(SkEdge* edge) { 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge->fPrev->fNext = edge->fNext; 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge->fNext->fPrev = edge->fPrev; 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4899219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.orgstatic inline void swap_edges(SkEdge* prev, SkEdge* next) { 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(prev->fNext == next && next->fPrev == prev); 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // remove prev from the list 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev->fPrev->fNext = next; 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com next->fPrev = prev->fPrev; 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // insert prev after next 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev->fNext = next->fNext; 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com next->fNext->fPrev = prev; 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com next->fNext = prev; 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev->fPrev = next; 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6299219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.orgstatic void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, curr_y)) { 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = edge->fX; 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6599219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org for (;;) { 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkEdge* prev = edge->fPrev; 6755b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // add 1 to curr_y since we may have added new edges (built from curves) 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // that start on the next scanline 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(prev && prev->fFirstY <= curr_y + 1); 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7299219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org if (prev->fX <= x) { 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 7499219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org } 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com swap_edges(prev, edge); 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7999219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.orgstatic void insert_new_edges(SkEdge* newEdge, int curr_y) { 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(newEdge->fFirstY >= curr_y); 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8299219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org while (newEdge->fFirstY == curr_y) { 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkEdge* next = newEdge->fNext; 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com backward_insert_edge_based_on_x(newEdge SkPARAM(curr_y)); 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com newEdge = next; 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 9099219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.orgstatic void validate_edges_for_y(const SkEdge* edge, int curr_y) { 9199219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org while (edge->fFirstY <= curr_y) { 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(edge->fPrev && edge->fNext); 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(edge->fPrev->fNext == edge); 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(edge->fNext->fPrev == edge); 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(edge->fFirstY <= edge->fLastY); 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(edge->fPrev->fX <= edge->fX); 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge = edge->fNext; 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define validate_edges_for_y(edge, curr_y) 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( push ) 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( disable : 4701 ) 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline); 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define PREPOST_START true 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define PREPOST_END false 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, 115dca6a56b71b922aab32098d6a55bbb041f3a2b48reed@android.com SkBlitter* blitter, int start_y, int stop_y, 11699219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org PrePostProc proc) { 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com validate_sort(prevHead->fNext); 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 119dca6a56b71b922aab32098d6a55bbb041f3a2b48reed@android.com int curr_y = start_y; 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // returns 1 for evenodd, -1 for winding, regardless of inverse-ness 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int windingMask = (fillType & 1) ? 1 : -1; 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12399219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org for (;;) { 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int w = 0; 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int left SK_INIT_TO_AVOID_WARNING; 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool in_interval = false; 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkEdge* currE = prevHead->fNext; 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed prevX = prevHead->fX; 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com validate_edges_for_y(currE, curr_y); 13155b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (proc) { 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(blitter, curr_y, PREPOST_START); // pre-proc 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13555b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 13699219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org while (currE->fFirstY <= curr_y) { 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(currE->fLastY >= curr_y); 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1390a9cc44a40a2bc101da1af89926152098ffcc44breed@google.com int x = SkFixedRoundToInt(currE->fX); 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com w += currE->fWinding; 14199219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org if ((w & windingMask) == 0) { // we finished an interval 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(in_interval); 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = x - left; 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(width >= 0); 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (width) 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(left, curr_y, width); 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com in_interval = false; 14899219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org } else if (!in_interval) { 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left = x; 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com in_interval = true; 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkEdge* next = currE->fNext; 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed newX; 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15699219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org if (currE->fLastY == curr_y) { // are we done with this edge? 15799219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org if (currE->fCurveCount < 0) { 15899219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org if (((SkCubicEdge*)currE)->updateCubic()) { 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(currE->fFirstY == curr_y + 1); 16055b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com newX = currE->fX; 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto NEXT_X; 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16499219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org } else if (currE->fCurveCount > 0) { 16599219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org if (((SkQuadraticEdge*)currE)->updateQuadratic()) { 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com newX = currE->fX; 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto NEXT_X; 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com remove_edge(currE); 17199219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org } else { 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(currE->fLastY > curr_y); 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com newX = currE->fX + currE->fDX; 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com currE->fX = newX; 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com NEXT_X: 17699219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org if (newX < prevX) { // ripple currE backwards until it is x-sorted 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com backward_insert_edge_based_on_x(currE SkPARAM(curr_y)); 17899219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org } else { 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevX = newX; 18099219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org } 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com currE = next; 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(currE); 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18555b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (proc) { 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(blitter, curr_y, PREPOST_END); // post-proc 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com curr_y += 1; 19199219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org if (curr_y >= stop_y) { 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 19399219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org } 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now currE points to the first edge with a Yint larger than curr_y 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com insert_new_edges(currE, curr_y); 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 199e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com// return true if we're done with this edge 200e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.comstatic bool update_edge(SkEdge* edge, int last_y) { 201e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkASSERT(edge->fLastY >= last_y); 202e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com if (last_y == edge->fLastY) { 203e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com if (edge->fCurveCount < 0) { 204e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com if (((SkCubicEdge*)edge)->updateCubic()) { 205e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkASSERT(edge->fFirstY == last_y + 1); 206e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com return false; 207e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 208e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } else if (edge->fCurveCount > 0) { 209e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com if (((SkQuadraticEdge*)edge)->updateQuadratic()) { 210e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkASSERT(edge->fFirstY == last_y + 1); 211e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com return false; 212e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 213e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 214e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com return true; 215e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 216e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com return false; 217e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com} 218e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com 219e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.comstatic void walk_convex_edges(SkEdge* prevHead, SkPath::FillType, 220e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkBlitter* blitter, int start_y, int stop_y, 221e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com PrePostProc proc) { 222e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com validate_sort(prevHead->fNext); 223fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 224e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkEdge* leftE = prevHead->fNext; 225e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkEdge* riteE = leftE->fNext; 226e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkEdge* currE = riteE->fNext; 227fc5da9266eae18f1ee3635a061af27788ad4b62emike@reedtribe.org 228fc5da9266eae18f1ee3635a061af27788ad4b62emike@reedtribe.org#if 0 229e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com int local_top = leftE->fFirstY; 230e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkASSERT(local_top == riteE->fFirstY); 231fc5da9266eae18f1ee3635a061af27788ad4b62emike@reedtribe.org#else 232fc5da9266eae18f1ee3635a061af27788ad4b62emike@reedtribe.org // our edge choppers for curves can result in the initial edges 233fc5da9266eae18f1ee3635a061af27788ad4b62emike@reedtribe.org // not lining up, so we take the max. 234fc5da9266eae18f1ee3635a061af27788ad4b62emike@reedtribe.org int local_top = SkMax32(leftE->fFirstY, riteE->fFirstY); 235fc5da9266eae18f1ee3635a061af27788ad4b62emike@reedtribe.org#endif 236e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkASSERT(local_top >= start_y); 237fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 238e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com for (;;) { 239e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkASSERT(leftE->fFirstY <= stop_y); 240e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkASSERT(riteE->fFirstY <= stop_y); 241e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com 242e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com if (leftE->fX > riteE->fX || (leftE->fX == riteE->fX && 243e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com leftE->fDX > riteE->fDX)) { 244e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkTSwap(leftE, riteE); 245e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 246fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 247e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com int local_bot = SkMin32(leftE->fLastY, riteE->fLastY); 248a6c7c4803e144f5c1d0a86a437ac1e2e8ff5e211reed@google.com local_bot = SkMin32(local_bot, stop_y - 1); 249e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkASSERT(local_top <= local_bot); 250fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 251e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkFixed left = leftE->fX; 252e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkFixed dLeft = leftE->fDX; 253e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkFixed rite = riteE->fX; 254e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkFixed dRite = riteE->fDX; 255e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com int count = local_bot - local_top; 256e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkASSERT(count >= 0); 257562a2ac95b8cd8b359574f8c4d6300b0475938dbreed@google.com if (0 == (dLeft | dRite)) { 2580a9cc44a40a2bc101da1af89926152098ffcc44breed@google.com int L = SkFixedRoundToInt(left); 2590a9cc44a40a2bc101da1af89926152098ffcc44breed@google.com int R = SkFixedRoundToInt(rite); 260e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com if (L < R) { 261e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com count += 1; 262e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com blitter->blitRect(L, local_top, R - L, count); 263e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com left += count * dLeft; 264e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com rite += count * dRite; 265e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 266fc5da9266eae18f1ee3635a061af27788ad4b62emike@reedtribe.org local_top = local_bot + 1; 267e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } else { 268e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com do { 2690a9cc44a40a2bc101da1af89926152098ffcc44breed@google.com int L = SkFixedRoundToInt(left); 2700a9cc44a40a2bc101da1af89926152098ffcc44breed@google.com int R = SkFixedRoundToInt(rite); 271e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com if (L < R) { 272e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com blitter->blitH(L, local_top, R - L); 273e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 274e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com left += dLeft; 275e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com rite += dRite; 276e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com local_top += 1; 277e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } while (--count >= 0); 278e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 279e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com 280e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com leftE->fX = left; 281e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com riteE->fX = rite; 282e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com 283e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com if (update_edge(leftE, local_bot)) { 284e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com if (currE->fFirstY >= stop_y) { 285e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com break; 286e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 287e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com leftE = currE; 288e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com currE = currE->fNext; 289e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 290e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com if (update_edge(riteE, local_bot)) { 291e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com if (currE->fFirstY >= stop_y) { 292e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com break; 293e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 294e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com riteE = currE; 295e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com currE = currE->fNext; 296e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 297fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 298e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkASSERT(leftE); 299e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com SkASSERT(riteE); 300a6c7c4803e144f5c1d0a86a437ac1e2e8ff5e211reed@google.com 301a6c7c4803e144f5c1d0a86a437ac1e2e8ff5e211reed@google.com // check our bottom clip 302a6c7c4803e144f5c1d0a86a437ac1e2e8ff5e211reed@google.com SkASSERT(local_top == local_bot + 1); 303a6c7c4803e144f5c1d0a86a437ac1e2e8ff5e211reed@google.com if (local_top >= stop_y) { 304a6c7c4803e144f5c1d0a86a437ac1e2e8ff5e211reed@google.com break; 305a6c7c4803e144f5c1d0a86a437ac1e2e8ff5e211reed@google.com } 306e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 307e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com} 308e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this guy overrides blitH, and will call its proxy blitter with the inverse 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// of the spans it is given (clipped to the left/right of the cliprect) 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// used to implement inverse filltypes on paths 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass InverseBlitter : public SkBlitter { 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void setBlitter(SkBlitter* blitter, const SkIRect& clip, int shift) { 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter = blitter; 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFirstX = clip.fLeft << shift; 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLastX = clip.fRight << shift; 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void prepost(int y, bool isStart) { 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (isStart) { 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevX = fFirstX; 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int invWidth = fLastX - fPrevX; 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (invWidth > 0) { 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter->blitH(fPrevX, y, invWidth); 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // overrides 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual void blitH(int x, int y, int width) { 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int invWidth = x - fPrevX; 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (invWidth > 0) { 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter->blitH(fPrevX, y, invWidth); 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevX = x + width; 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 34255b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we do not expect to get called with these entrypoints 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual void blitAntiH(int, int, const SkAlpha[], const int16_t runs[]) { 3450c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("blitAntiH unexpected"); 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual void blitV(int x, int y, int height, SkAlpha alpha) { 3480c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("blitV unexpected"); 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual void blitRect(int x, int y, int width, int height) { 3510c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("blitRect unexpected"); 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual void blitMask(const SkMask&, const SkIRect& clip) { 3540c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("blitMask unexpected"); 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual const SkBitmap* justAnOpaqueColor(uint32_t* value) { 3570c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("justAnOpaqueColor unexpected"); 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 36055b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* fBlitter; 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fFirstX, fLastX, fPrevX; 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void PrePostInverseBlitterProc(SkBlitter* blitter, int y, bool isStart) { 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((InverseBlitter*)blitter)->prepost(y, isStart); 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( pop ) 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3760a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com#ifdef SK_USE_STD_SORT_FOR_EDGES 377e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.comextern "C" { 378e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com static int edge_compare(const void* a, const void* b) { 379e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com const SkEdge* edgea = *(const SkEdge**)a; 380e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com const SkEdge* edgeb = *(const SkEdge**)b; 38155b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 382e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com int valuea = edgea->fFirstY; 383e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com int valueb = edgeb->fFirstY; 38455b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 385e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com if (valuea == valueb) { 386e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com valuea = edgea->fX; 387e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com valueb = edgeb->fX; 388e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com } 38955b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 390e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com // this overflows if valuea >>> valueb or vice-versa 391e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com // return valuea - valueb; 392e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com // do perform the slower but safe compares 393e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com return (valuea < valueb) ? -1 : (valuea > valueb); 394e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com } 395e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com} 3960a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com#else 3970a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.comstatic bool operator<(const SkEdge& a, const SkEdge& b) { 3980a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com int valuea = a.fFirstY; 3990a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com int valueb = b.fFirstY; 400fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4010a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com if (valuea == valueb) { 4020a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com valuea = a.fX; 4030a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com valueb = b.fX; 4040a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com } 405fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4060a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com return valuea < valueb; 4070a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com} 4080a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com#endif 409e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com 410e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.comstatic SkEdge* sort_edges(SkEdge* list[], int count, SkEdge** last) { 4110a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com#ifdef SK_USE_STD_SORT_FOR_EDGES 412e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com qsort(list, count, sizeof(SkEdge*), edge_compare); 4130a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com#else 4140a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com SkTQSort(list, list + count - 1); 4150a71a9cc372c2fd42e3b1623321878aaa27aa103reed@google.com#endif 41655b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 417e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com // now make the edges linked in sorted order 418e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com for (int i = 1; i < count; i++) { 419e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com list[i - 1]->fNext = list[i]; 420e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com list[i]->fPrev = list[i - 1]; 421e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com } 42255b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 423e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com *last = list[count - 1]; 424e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com return list[0]; 425e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com} 426e72fee513a5f903d6aa17066d2f3b79ac31f05dereed@android.com 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// clipRect may be null, even though we always have a clip. This indicates that 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// the path is contained in the clip, and so we can ignore it during the blit 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// clipRect (if no null) has already been shifted up 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitter, 43399219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org int start_y, int stop_y, int shiftEdgesUp, 43499219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org const SkRegion& clipRgn) { 435a10742c69ce47d346e3cf23e7be909c9f29b401ecaryclark SkASSERT(blitter); 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 437909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkEdgeBuilder builder; 43855b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 439909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com int count = builder.build(path, clipRect, shiftEdgesUp); 440909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkEdge** list = builder.edgeList(); 441909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com 4429da1ae3f35a6f25adf4f58ae2589129ceec6d11breed@android.com if (count < 2) { 4438cfdf01ff953b47fdd5c29ebd54fea8a7a9be83eagl@chromium.org if (path.isInverseFillType()) { 4449d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com /* 4459d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com * Since we are in inverse-fill, our caller has already drawn above 4469d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com * our top (start_y) and will draw below our bottom (stop_y). Thus 4479d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com * we need to restrict our drawing to the intersection of the clip 4489d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com * and those two limits. 4499d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com */ 4509d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com SkIRect rect = clipRgn.getBounds(); 4519d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com if (rect.fTop < start_y) { 4529d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com rect.fTop = start_y; 4539d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com } 4549d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com if (rect.fBottom > stop_y) { 4559d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com rect.fBottom = stop_y; 4569d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com } 4579d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com if (!rect.isEmpty()) { 4589d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com blitter->blitRect(rect.fLeft << shiftEdgesUp, 4599d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com rect.fTop << shiftEdgesUp, 4609d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com rect.width() << shiftEdgesUp, 4619d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com rect.height() << shiftEdgesUp); 4629d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com } 4638cfdf01ff953b47fdd5c29ebd54fea8a7a9be83eagl@chromium.org } 4648cfdf01ff953b47fdd5c29ebd54fea8a7a9be83eagl@chromium.org 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 468909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkEdge headEdge, tailEdge, *last; 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // this returns the first and last edge after they're sorted into a dlink list 470909994fbae0ffb532f42feac8859f8d86bbf64dereed@android.com SkEdge* edge = sort_edges(list, count, &last); 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com headEdge.fPrev = NULL; 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com headEdge.fNext = edge; 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com headEdge.fFirstY = kEDGE_HEAD_Y; 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com headEdge.fX = SK_MinS32; 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge->fPrev = &headEdge; 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tailEdge.fPrev = last; 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tailEdge.fNext = NULL; 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tailEdge.fFirstY = kEDGE_TAIL_Y; 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com last->fNext = &tailEdge; 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now edge is the head of the sorted linklist 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 485dca6a56b71b922aab32098d6a55bbb041f3a2b48reed@android.com start_y <<= shiftEdgesUp; 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stop_y <<= shiftEdgesUp; 487dca6a56b71b922aab32098d6a55bbb041f3a2b48reed@android.com if (clipRect && start_y < clipRect->fTop) { 488dca6a56b71b922aab32098d6a55bbb041f3a2b48reed@android.com start_y = clipRect->fTop; 489dca6a56b71b922aab32098d6a55bbb041f3a2b48reed@android.com } 4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (clipRect && stop_y > clipRect->fBottom) { 4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stop_y = clipRect->fBottom; 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com InverseBlitter ib; 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PrePostProc proc = NULL; 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (path.isInverseFillType()) { 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ib.setBlitter(blitter, clipRgn.getBounds(), shiftEdgesUp); 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter = &ib; 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = PrePostInverseBlitterProc; 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 503a6c7c4803e144f5c1d0a86a437ac1e2e8ff5e211reed@google.com if (path.isConvex() && (NULL == proc)) { 504e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com walk_convex_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, NULL); 505e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } else { 506e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc); 507e3a83ec4e5c0abd2f5b756d7a6e7d58515969f18reed@google.com } 5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 51055b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.comvoid sk_blit_above(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) { 5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& cr = clip.getBounds(); 5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect tmp; 51355b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.fLeft = cr.fLeft; 5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.fRight = cr.fRight; 5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.fTop = cr.fTop; 5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.fBottom = ir.fTop; 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!tmp.isEmpty()) { 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitRectRegion(tmp, clip); 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 52155b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com} 52255b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 52355b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.comvoid sk_blit_below(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) { 52455b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com const SkIRect& cr = clip.getBounds(); 52555b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com SkIRect tmp; 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 52755b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com tmp.fLeft = cr.fLeft; 52855b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com tmp.fRight = cr.fRight; 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.fTop = ir.fBottom; 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.fBottom = cr.fBottom; 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!tmp.isEmpty()) { 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitRectRegion(tmp, clip); 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 53699219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 53897caebc7462c202ab0ec5cce4eb26a616930813ereed@google.com/** 5395ee6491b7a1e7c177abc0186c2749ebe1f71fcf7reed@google.com * If the caller is drawing an inverse-fill path, then it pass true for 5405ee6491b7a1e7c177abc0186c2749ebe1f71fcf7reed@google.com * skipRejectTest, so we don't abort drawing just because the src bounds (ir) 5415ee6491b7a1e7c177abc0186c2749ebe1f71fcf7reed@google.com * is outside of the clip. 54297caebc7462c202ab0ec5cce4eb26a616930813ereed@google.com */ 54399219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.orgSkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip, 5445ee6491b7a1e7c177abc0186c2749ebe1f71fcf7reed@google.com const SkIRect& ir, bool skipRejectTest) { 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter = NULL; // null means blit nothing 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClipRect = NULL; 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 54899219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org if (clip) { 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClipRect = &clip->getBounds(); 5505ee6491b7a1e7c177abc0186c2749ebe1f71fcf7reed@google.com if (!skipRejectTest && !SkIRect::Intersects(*fClipRect, ir)) { // completely clipped out 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 55299219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org } 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 55499219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org if (clip->isRect()) { 55599219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org if (fClipRect->contains(ir)) { 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClipRect = NULL; 55799219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org } else { 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // only need a wrapper blitter if we're horizontally clipped 55999219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org if (fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight) { 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRectBlitter.init(blitter, *fClipRect); 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter = &fRectBlitter; 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 56499219d337f66cb6a8e566e1c6407bfb4b1b6cb8bmike@reedtribe.org } else { 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRgnBlitter.init(blitter, clip); 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter = &fRgnBlitter; 5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter = blitter; 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5741501803e93a9c76b4632086d05c2813cb475db27reed@google.comstatic bool clip_to_limit(const SkRegion& orig, SkRegion* reduced) { 5751501803e93a9c76b4632086d05c2813cb475db27reed@google.com const int32_t limit = 32767; 5761501803e93a9c76b4632086d05c2813cb475db27reed@google.com 5771501803e93a9c76b4632086d05c2813cb475db27reed@google.com SkIRect limitR; 5781501803e93a9c76b4632086d05c2813cb475db27reed@google.com limitR.set(-limit, -limit, limit, limit); 5791501803e93a9c76b4632086d05c2813cb475db27reed@google.com if (limitR.contains(orig.getBounds())) { 5801501803e93a9c76b4632086d05c2813cb475db27reed@google.com return false; 5811501803e93a9c76b4632086d05c2813cb475db27reed@google.com } 5821501803e93a9c76b4632086d05c2813cb475db27reed@google.com reduced->op(orig, limitR, SkRegion::kIntersect_Op); 5831501803e93a9c76b4632086d05c2813cb475db27reed@google.com return true; 5841501803e93a9c76b4632086d05c2813cb475db27reed@google.com} 5851501803e93a9c76b4632086d05c2813cb475db27reed@google.com 5861501803e93a9c76b4632086d05c2813cb475db27reed@google.comvoid SkScan::FillPath(const SkPath& path, const SkRegion& origClip, 5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* blitter) { 5881501803e93a9c76b4632086d05c2813cb475db27reed@google.com if (origClip.isEmpty()) { 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5921501803e93a9c76b4632086d05c2813cb475db27reed@google.com // Our edges are fixed-point, and don't like the bounds of the clip to 5931501803e93a9c76b4632086d05c2813cb475db27reed@google.com // exceed that. Here we trim the clip just so we don't overflow later on 5941501803e93a9c76b4632086d05c2813cb475db27reed@google.com const SkRegion* clipPtr = &origClip; 5951501803e93a9c76b4632086d05c2813cb475db27reed@google.com SkRegion finiteClip; 5961501803e93a9c76b4632086d05c2813cb475db27reed@google.com if (clip_to_limit(origClip, &finiteClip)) { 5971501803e93a9c76b4632086d05c2813cb475db27reed@google.com if (finiteClip.isEmpty()) { 5981501803e93a9c76b4632086d05c2813cb475db27reed@google.com return; 5991501803e93a9c76b4632086d05c2813cb475db27reed@google.com } 6001501803e93a9c76b4632086d05c2813cb475db27reed@google.com clipPtr = &finiteClip; 6011501803e93a9c76b4632086d05c2813cb475db27reed@google.com } 6021501803e93a9c76b4632086d05c2813cb475db27reed@google.com // don't reference "origClip" any more, just use clipPtr 6031501803e93a9c76b4632086d05c2813cb475db27reed@google.com 6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect ir; 6054e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org // We deliberately call dround() instead of round(), since we can't afford to generate a 6064e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org // bounds that is tighter than the corresponding SkEdges. The edge code basically converts 6074e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org // the floats to fixed, and then "rounds". If we called round() instead of dround() here, 6084e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org // we could generate the wrong ir for values like 0.4999997. 6094e332f82fce0126045e9cb2ef0a2097a6c4c40a3commit-bot@chromium.org path.getBounds().dround(&ir); 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ir.isEmpty()) { 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (path.isInverseFillType()) { 6121501803e93a9c76b4632086d05c2813cb475db27reed@google.com blitter->blitRegion(*clipPtr); 6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6175ee6491b7a1e7c177abc0186c2749ebe1f71fcf7reed@google.com SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType()); 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter = clipper.getBlitter(); 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (blitter) { 62155b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com // we have to keep our calls to blitter in sorted order, so we 62255b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com // must blit the above section first, then the middle, then the bottom. 6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (path.isInverseFillType()) { 6241501803e93a9c76b4632086d05c2813cb475db27reed@google.com sk_blit_above(blitter, ir, *clipPtr); 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6261501803e93a9c76b4632086d05c2813cb475db27reed@google.com sk_fill_path(path, clipper.getClipRect(), blitter, ir.fTop, ir.fBottom, 6271501803e93a9c76b4632086d05c2813cb475db27reed@google.com 0, *clipPtr); 62855b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com if (path.isInverseFillType()) { 6291501803e93a9c76b4632086d05c2813cb475db27reed@google.com sk_blit_below(blitter, ir, *clipPtr); 63055b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com } 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // what does it mean to not have a blitter if path.isInverseFillType??? 6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 636045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkScan::FillPath(const SkPath& path, const SkIRect& ir, 637045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter) { 638045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRegion rgn(ir); 639045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com FillPath(path, rgn, blitter); 640045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 641045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int build_tri_edges(SkEdge edge[], const SkPoint pts[], 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect* clipRect, SkEdge* list[]) { 6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkEdge** start = list; 64755b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (edge->setLine(pts[0], pts[1], clipRect, 0)) { 6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *list++ = edge; 6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge = (SkEdge*)((char*)edge + sizeof(SkEdge)); 6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (edge->setLine(pts[1], pts[2], clipRect, 0)) { 6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *list++ = edge; 6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge = (SkEdge*)((char*)edge + sizeof(SkEdge)); 6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (edge->setLine(pts[2], pts[0], clipRect, 0)) { 6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *list++ = edge; 6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (int)(list - start); 6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 663800046eba45c9e982ecfe8964b2107f7713ed639reed@android.comstatic void sk_fill_triangle(const SkPoint pts[], const SkIRect* clipRect, 664800046eba45c9e982ecfe8964b2107f7713ed639reed@android.com SkBlitter* blitter, const SkIRect& ir) { 6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pts && blitter); 66655b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkEdge edgeStorage[3]; 6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkEdge* list[3]; 6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = build_tri_edges(edgeStorage, pts, clipRect, list); 6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count < 2) { 6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkEdge headEdge, tailEdge, *last; 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // this returns the first and last edge after they're sorted into a dlink list 6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkEdge* edge = sort_edges(list, count, &last); 67955b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com headEdge.fPrev = NULL; 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com headEdge.fNext = edge; 6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com headEdge.fFirstY = kEDGE_HEAD_Y; 6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com headEdge.fX = SK_MinS32; 6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge->fPrev = &headEdge; 68555b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tailEdge.fPrev = last; 6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tailEdge.fNext = NULL; 6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tailEdge.fFirstY = kEDGE_TAIL_Y; 6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com last->fNext = &tailEdge; 69055b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now edge is the head of the sorted linklist 6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int stop_y = ir.fBottom; 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (clipRect && stop_y > clipRect->fBottom) { 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stop_y = clipRect->fBottom; 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 696dca6a56b71b922aab32098d6a55bbb041f3a2b48reed@android.com int start_y = ir.fTop; 697dca6a56b71b922aab32098d6a55bbb041f3a2b48reed@android.com if (clipRect && start_y < clipRect->fTop) { 698dca6a56b71b922aab32098d6a55bbb041f3a2b48reed@android.com start_y = clipRect->fTop; 699dca6a56b71b922aab32098d6a55bbb041f3a2b48reed@android.com } 700a6c7c4803e144f5c1d0a86a437ac1e2e8ff5e211reed@google.com walk_convex_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y, NULL); 701a6c7c4803e144f5c1d0a86a437ac1e2e8ff5e211reed@google.com// walk_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y, NULL); 7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 704045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkScan::FillTriangle(const SkPoint pts[], const SkRasterClip& clip, 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* blitter) { 706045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (clip.isEmpty()) { 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 70955b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect ir; 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(pts, 3); 7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.round(&ir); 714045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (ir.isEmpty() || !SkIRect::Intersects(ir, clip.getBounds())) { 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 71755b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 718045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitterWrapper wrap; 719045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRegion* clipRgn; 720045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (clip.isBW()) { 721045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clipRgn = &clip.bwRgn(); 722045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 723045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com wrap.init(clip, blitter); 724045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clipRgn = &wrap.getRgn(); 725045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = wrap.getBlitter(); 726045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 72755b6b58d8f6e7529c9b9cea606a6e3637c8e2e39reed@google.com 728045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScanClipper clipper(blitter, clipRgn, ir); 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter = clipper.getBlitter(); 73049f085dddff10473b6ebf832a974288300224e60bsalomon if (blitter) { 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir); 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 734