1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/* 2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project 3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * 4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */ 7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 8bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkScanPriv.h" 9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkBlitter.h" 10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkEdge.h" 11dc9be913d13b7e44e9fe02426f79cec624f1dc6bmike@reedtribe.org#include "SkEdgeBuilder.h" 12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkGeometry.h" 13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPath.h" 14b35fe4e1b04229a849227ea6c2561fe84929ab8breed@android.com#include "SkQuadClipper.h" 1526f5a398c38318eb7eab44f72e024ef784d247fareed@google.com#include "SkRasterClip.h" 16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkRegion.h" 17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkTemplates.h" 18bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#include "SkTSort.h" 19bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com 20c2c953d9a0f2ff8c46d89d92bb6017ceaaf8de83reed@google.com#ifdef SK_USE_LEGACY_AA_COVERAGE 21c2c953d9a0f2ff8c46d89d92bb6017ceaaf8de83reed@google.com #define SK_USE_STD_SORT_FOR_EDGES 22c2c953d9a0f2ff8c46d89d92bb6017ceaaf8de83reed@google.com#endif 23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define kEDGE_HEAD_Y SK_MinS32 25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define kEDGE_TAIL_Y SK_MaxS32 26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 28b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org static void validate_sort(const SkEdge* edge) { 29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int y = kEDGE_HEAD_Y; 30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 31b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org while (edge->fFirstY != SK_MaxS32) { 32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com edge->validate(); 33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(y <= edge->fFirstY); 34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com y = edge->fFirstY; 36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com edge = edge->fNext; 37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else 40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com #define validate_sort(edge) 41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 42bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 43b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.orgstatic inline void remove_edge(SkEdge* edge) { 44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com edge->fPrev->fNext = edge->fNext; 45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com edge->fNext->fPrev = edge->fPrev; 46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 48b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.orgstatic inline void swap_edges(SkEdge* prev, SkEdge* next) { 49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(prev->fNext == next && next->fPrev == prev); 50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // remove prev from the list 52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prev->fPrev->fNext = next; 53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com next->fPrev = prev->fPrev; 54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // insert prev after next 56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prev->fNext = next->fNext; 57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com next->fNext->fPrev = prev; 58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com next->fNext = prev; 59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prev->fPrev = next; 60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 62b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.orgstatic void backward_insert_edge_based_on_x(SkEdge* edge SkDECLAREPARAM(int, curr_y)) { 63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed x = edge->fX; 64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 65b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org for (;;) { 66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkEdge* prev = edge->fPrev; 67434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // add 1 to curr_y since we may have added new edges (built from curves) 69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // that start on the next scanline 70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(prev && prev->fFirstY <= curr_y + 1); 71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 72b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org if (prev->fX <= x) { 73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 74b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org } 75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com swap_edges(prev, edge); 76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 79b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.orgstatic void insert_new_edges(SkEdge* newEdge, int curr_y) { 80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(newEdge->fFirstY >= curr_y); 81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 82b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org while (newEdge->fFirstY == curr_y) { 83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkEdge* next = newEdge->fNext; 84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com backward_insert_edge_based_on_x(newEdge SkPARAM(curr_y)); 85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com newEdge = next; 86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 90b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.orgstatic void validate_edges_for_y(const SkEdge* edge, int curr_y) { 91b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org while (edge->fFirstY <= curr_y) { 92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(edge->fPrev && edge->fNext); 93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(edge->fPrev->fNext == edge); 94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(edge->fNext->fPrev == edge); 95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(edge->fFirstY <= edge->fLastY); 96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(edge->fPrev->fX <= edge->fX); 98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com edge = edge->fNext; 99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else 102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com #define validate_edges_for_y(edge, curr_y) 103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized 106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( push ) 107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( disable : 4701 ) 108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comtypedef void (*PrePostProc)(SkBlitter* blitter, int y, bool isStartOfScanline); 111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define PREPOST_START true 112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define PREPOST_END false 113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic void walk_edges(SkEdge* prevHead, SkPath::FillType fillType, 115c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com SkBlitter* blitter, int start_y, int stop_y, 116b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org PrePostProc proc) { 117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com validate_sort(prevHead->fNext); 118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 119c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com int curr_y = start_y; 120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // returns 1 for evenodd, -1 for winding, regardless of inverse-ness 121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int windingMask = (fillType & 1) ? 1 : -1; 122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 123b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org for (;;) { 124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int w = 0; 125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int left SK_INIT_TO_AVOID_WARNING; 126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bool in_interval = false; 127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkEdge* currE = prevHead->fNext; 128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed prevX = prevHead->fX; 129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com validate_edges_for_y(currE, curr_y); 131434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (proc) { 133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com proc(blitter, curr_y, PREPOST_START); // pre-proc 134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 135434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 136b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org while (currE->fFirstY <= curr_y) { 137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(currE->fLastY >= curr_y); 138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 13966c8ab166dba7798dfd649bdbccad863ae22f405reed@google.com int x = SkFixedRoundToInt(currE->fX); 140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com w += currE->fWinding; 141b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org if ((w & windingMask) == 0) { // we finished an interval 142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(in_interval); 143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int width = x - left; 144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(width >= 0); 145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (width) 146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter->blitH(left, curr_y, width); 147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com in_interval = false; 148b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org } else if (!in_interval) { 149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com left = x; 150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com in_interval = true; 151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkEdge* next = currE->fNext; 154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkFixed newX; 155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 156b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org if (currE->fLastY == curr_y) { // are we done with this edge? 157b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org if (currE->fCurveCount < 0) { 158b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org if (((SkCubicEdge*)currE)->updateCubic()) { 159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(currE->fFirstY == curr_y + 1); 160434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com newX = currE->fX; 162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com goto NEXT_X; 163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 164b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org } else if (currE->fCurveCount > 0) { 165b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org if (((SkQuadraticEdge*)currE)->updateQuadratic()) { 166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com newX = currE->fX; 167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com goto NEXT_X; 168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com remove_edge(currE); 171b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org } else { 172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(currE->fLastY > curr_y); 173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com newX = currE->fX + currE->fDX; 174bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com currE->fX = newX; 175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com NEXT_X: 176b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org if (newX < prevX) { // ripple currE backwards until it is x-sorted 177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com backward_insert_edge_based_on_x(currE SkPARAM(curr_y)); 178b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org } else { 179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prevX = newX; 180b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org } 181bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com currE = next; 183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(currE); 184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 185434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (proc) { 187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com proc(blitter, curr_y, PREPOST_END); // post-proc 188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com curr_y += 1; 191b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org if (curr_y >= stop_y) { 192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 193b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org } 194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // now currE points to the first edge with a Yint larger than curr_y 195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com insert_new_edges(currE, curr_y); 196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 199e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com// return true if we're done with this edge 200e85a548b33e0471d64a68b246e640770a89ef51dreed@google.comstatic bool update_edge(SkEdge* edge, int last_y) { 201e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkASSERT(edge->fLastY >= last_y); 202e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com if (last_y == edge->fLastY) { 203e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com if (edge->fCurveCount < 0) { 204e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com if (((SkCubicEdge*)edge)->updateCubic()) { 205e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkASSERT(edge->fFirstY == last_y + 1); 206e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com return false; 207e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 208e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } else if (edge->fCurveCount > 0) { 209e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com if (((SkQuadraticEdge*)edge)->updateQuadratic()) { 210e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkASSERT(edge->fFirstY == last_y + 1); 211e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com return false; 212e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 213e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 214e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com return true; 215e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 216e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com return false; 217e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com} 218e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com 219e85a548b33e0471d64a68b246e640770a89ef51dreed@google.comstatic void walk_convex_edges(SkEdge* prevHead, SkPath::FillType, 220e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkBlitter* blitter, int start_y, int stop_y, 221e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com PrePostProc proc) { 222e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com validate_sort(prevHead->fNext); 223935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 224e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkEdge* leftE = prevHead->fNext; 225e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkEdge* riteE = leftE->fNext; 226e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkEdge* currE = riteE->fNext; 227e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org 228e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org#if 0 229e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com int local_top = leftE->fFirstY; 230e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkASSERT(local_top == riteE->fFirstY); 231e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org#else 232e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org // our edge choppers for curves can result in the initial edges 233e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org // not lining up, so we take the max. 234e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org int local_top = SkMax32(leftE->fFirstY, riteE->fFirstY); 235e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org#endif 236e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkASSERT(local_top >= start_y); 237935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 238e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com for (;;) { 239e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkASSERT(leftE->fFirstY <= stop_y); 240e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkASSERT(riteE->fFirstY <= stop_y); 241e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com 242e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com if (leftE->fX > riteE->fX || (leftE->fX == riteE->fX && 243e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com leftE->fDX > riteE->fDX)) { 244e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkTSwap(leftE, riteE); 245e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 246935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 247e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com int local_bot = SkMin32(leftE->fLastY, riteE->fLastY); 248018395ca1906954a256b072777f4d67387a9c853reed@google.com local_bot = SkMin32(local_bot, stop_y - 1); 249e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkASSERT(local_top <= local_bot); 250935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 251e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkFixed left = leftE->fX; 252e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkFixed dLeft = leftE->fDX; 253e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkFixed rite = riteE->fX; 254e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkFixed dRite = riteE->fDX; 255e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com int count = local_bot - local_top; 256e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkASSERT(count >= 0); 257a87977ce51bdb353d85629facb293e634ae39983reed@google.com if (0 == (dLeft | dRite)) { 25866c8ab166dba7798dfd649bdbccad863ae22f405reed@google.com int L = SkFixedRoundToInt(left); 25966c8ab166dba7798dfd649bdbccad863ae22f405reed@google.com int R = SkFixedRoundToInt(rite); 260e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com if (L < R) { 261e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com count += 1; 262e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com blitter->blitRect(L, local_top, R - L, count); 263e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com left += count * dLeft; 264e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com rite += count * dRite; 265e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 266e5b84603f7b131c9c20543c7bf17d31af2462940mike@reedtribe.org local_top = local_bot + 1; 267e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } else { 268e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com do { 26966c8ab166dba7798dfd649bdbccad863ae22f405reed@google.com int L = SkFixedRoundToInt(left); 27066c8ab166dba7798dfd649bdbccad863ae22f405reed@google.com int R = SkFixedRoundToInt(rite); 271e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com if (L < R) { 272e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com blitter->blitH(L, local_top, R - L); 273e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 274e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com left += dLeft; 275e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com rite += dRite; 276e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com local_top += 1; 277e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } while (--count >= 0); 278e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 279e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com 280e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com leftE->fX = left; 281e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com riteE->fX = rite; 282e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com 283e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com if (update_edge(leftE, local_bot)) { 284e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com if (currE->fFirstY >= stop_y) { 285e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com break; 286e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 287e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com leftE = currE; 288e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com currE = currE->fNext; 289e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 290e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com if (update_edge(riteE, local_bot)) { 291e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com if (currE->fFirstY >= stop_y) { 292e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com break; 293e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 294e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com riteE = currE; 295e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com currE = currE->fNext; 296e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 297935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 298e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkASSERT(leftE); 299e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com SkASSERT(riteE); 300018395ca1906954a256b072777f4d67387a9c853reed@google.com 301018395ca1906954a256b072777f4d67387a9c853reed@google.com // check our bottom clip 302018395ca1906954a256b072777f4d67387a9c853reed@google.com SkASSERT(local_top == local_bot + 1); 303018395ca1906954a256b072777f4d67387a9c853reed@google.com if (local_top >= stop_y) { 304018395ca1906954a256b072777f4d67387a9c853reed@google.com break; 305018395ca1906954a256b072777f4d67387a9c853reed@google.com } 306e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 307e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com} 308e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com 309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// this guy overrides blitH, and will call its proxy blitter with the inverse 312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// of the spans it is given (clipped to the left/right of the cliprect) 313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// 314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// used to implement inverse filltypes on paths 315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// 316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass InverseBlitter : public SkBlitter { 317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic: 318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void setBlitter(SkBlitter* blitter, const SkIRect& clip, int shift) { 319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter = blitter; 320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fFirstX = clip.fLeft << shift; 321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fLastX = clip.fRight << shift; 322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void prepost(int y, bool isStart) { 324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (isStart) { 325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPrevX = fFirstX; 326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int invWidth = fLastX - fPrevX; 328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (invWidth > 0) { 329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter->blitH(fPrevX, y, invWidth); 330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // overrides 335bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com virtual void blitH(int x, int y, int width) { 336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int invWidth = x - fPrevX; 337bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (invWidth > 0) { 338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter->blitH(fPrevX, y, invWidth); 339bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 340bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPrevX = x + width; 341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 342434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // we do not expect to get called with these entrypoints 344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com virtual void blitAntiH(int, int, const SkAlpha[], const int16_t runs[]) { 3452d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("blitAntiH unexpected"); 346bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com virtual void blitV(int x, int y, int height, SkAlpha alpha) { 3482d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("blitV unexpected"); 349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com virtual void blitRect(int x, int y, int width, int height) { 3512d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("blitRect unexpected"); 352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 353bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com virtual void blitMask(const SkMask&, const SkIRect& clip) { 3542d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("blitMask unexpected"); 355bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com virtual const SkBitmap* justAnOpaqueColor(uint32_t* value) { 3572d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("justAnOpaqueColor unexpected"); 358bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return NULL; 359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 360434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 361bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate: 362bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBlitter* fBlitter; 363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int fFirstX, fLastX, fPrevX; 364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 365bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 366bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic void PrePostInverseBlitterProc(SkBlitter* blitter, int y, bool isStart) { 367bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ((InverseBlitter*)blitter)->prepost(y, isStart); 368bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 369bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 370bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 371bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if defined _WIN32 && _MSC_VER >= 1300 373bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( pop ) 374bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 376bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#ifdef SK_USE_STD_SORT_FOR_EDGES 377f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.comextern "C" { 378f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com static int edge_compare(const void* a, const void* b) { 379f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com const SkEdge* edgea = *(const SkEdge**)a; 380f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com const SkEdge* edgeb = *(const SkEdge**)b; 381434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 382f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com int valuea = edgea->fFirstY; 383f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com int valueb = edgeb->fFirstY; 384434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 385f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com if (valuea == valueb) { 386f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com valuea = edgea->fX; 387f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com valueb = edgeb->fX; 388f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com } 389434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 390f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com // this overflows if valuea >>> valueb or vice-versa 391f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com // return valuea - valueb; 392f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com // do perform the slower but safe compares 393f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com return (valuea < valueb) ? -1 : (valuea > valueb); 394f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com } 395f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com} 396bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#else 397bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.comstatic bool operator<(const SkEdge& a, const SkEdge& b) { 398bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com int valuea = a.fFirstY; 399bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com int valueb = b.fFirstY; 400935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 401bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com if (valuea == valueb) { 402bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com valuea = a.fX; 403bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com valueb = b.fX; 404bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com } 405935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 406bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com return valuea < valueb; 407bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com} 408bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#endif 409f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com 410f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.comstatic SkEdge* sort_edges(SkEdge* list[], int count, SkEdge** last) { 411bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#ifdef SK_USE_STD_SORT_FOR_EDGES 412f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com qsort(list, count, sizeof(SkEdge*), edge_compare); 413bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#else 414bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com SkTQSort(list, list + count - 1); 415bcc091934e2f37b13c112179af1eb4e27bafb2bareed@google.com#endif 416434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 417f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com // now make the edges linked in sorted order 418f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com for (int i = 1; i < count; i++) { 419f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com list[i - 1]->fNext = list[i]; 420f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com list[i]->fPrev = list[i - 1]; 421f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com } 422434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 423f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com *last = list[count - 1]; 424f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com return list[0]; 425f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com} 426f89965bebd372b993ee9949b60af9e6144c75bb7reed@android.com 427bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// clipRect may be null, even though we always have a clip. This indicates that 428bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// the path is contained in the clip, and so we can ignore it during the blit 429bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// 430bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// clipRect (if no null) has already been shifted up 431bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// 432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid sk_fill_path(const SkPath& path, const SkIRect* clipRect, SkBlitter* blitter, 433b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org int start_y, int stop_y, int shiftEdgesUp, 434b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org const SkRegion& clipRgn) { 435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(&path && blitter); 436bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 437cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com SkEdgeBuilder builder; 438434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 439cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com int count = builder.build(path, clipRect, shiftEdgesUp); 440cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com SkEdge** list = builder.edgeList(); 441cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com 442b44d151b082d859c467808a843dc01a7118ce5cfreed@android.com if (count < 2) { 4437d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org if (path.isInverseFillType()) { 44401ec0596b2116253ec0d623e2b83efda131fffabreed@google.com /* 44501ec0596b2116253ec0d623e2b83efda131fffabreed@google.com * Since we are in inverse-fill, our caller has already drawn above 44601ec0596b2116253ec0d623e2b83efda131fffabreed@google.com * our top (start_y) and will draw below our bottom (stop_y). Thus 44701ec0596b2116253ec0d623e2b83efda131fffabreed@google.com * we need to restrict our drawing to the intersection of the clip 44801ec0596b2116253ec0d623e2b83efda131fffabreed@google.com * and those two limits. 44901ec0596b2116253ec0d623e2b83efda131fffabreed@google.com */ 45001ec0596b2116253ec0d623e2b83efda131fffabreed@google.com SkIRect rect = clipRgn.getBounds(); 45101ec0596b2116253ec0d623e2b83efda131fffabreed@google.com if (rect.fTop < start_y) { 45201ec0596b2116253ec0d623e2b83efda131fffabreed@google.com rect.fTop = start_y; 45301ec0596b2116253ec0d623e2b83efda131fffabreed@google.com } 45401ec0596b2116253ec0d623e2b83efda131fffabreed@google.com if (rect.fBottom > stop_y) { 45501ec0596b2116253ec0d623e2b83efda131fffabreed@google.com rect.fBottom = stop_y; 45601ec0596b2116253ec0d623e2b83efda131fffabreed@google.com } 45701ec0596b2116253ec0d623e2b83efda131fffabreed@google.com if (!rect.isEmpty()) { 45801ec0596b2116253ec0d623e2b83efda131fffabreed@google.com blitter->blitRect(rect.fLeft << shiftEdgesUp, 45901ec0596b2116253ec0d623e2b83efda131fffabreed@google.com rect.fTop << shiftEdgesUp, 46001ec0596b2116253ec0d623e2b83efda131fffabreed@google.com rect.width() << shiftEdgesUp, 46101ec0596b2116253ec0d623e2b83efda131fffabreed@google.com rect.height() << shiftEdgesUp); 46201ec0596b2116253ec0d623e2b83efda131fffabreed@google.com } 4637d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org } 4647d27207b0d54e59a7b5722247322fbf4344d44a1agl@chromium.org 465bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 467bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 468cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com SkEdge headEdge, tailEdge, *last; 469bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // this returns the first and last edge after they're sorted into a dlink list 470cfaf6fa015476b3283441e11a74c488aa8d700e6reed@android.com SkEdge* edge = sort_edges(list, count, &last); 471bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 472bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com headEdge.fPrev = NULL; 473bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com headEdge.fNext = edge; 474bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com headEdge.fFirstY = kEDGE_HEAD_Y; 475bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com headEdge.fX = SK_MinS32; 476bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com edge->fPrev = &headEdge; 477bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 478bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tailEdge.fPrev = last; 479bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tailEdge.fNext = NULL; 480bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tailEdge.fFirstY = kEDGE_TAIL_Y; 481bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com last->fNext = &tailEdge; 482bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 483bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // now edge is the head of the sorted linklist 484bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 485c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com start_y <<= shiftEdgesUp; 486bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com stop_y <<= shiftEdgesUp; 487c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com if (clipRect && start_y < clipRect->fTop) { 488c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com start_y = clipRect->fTop; 489c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com } 490bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (clipRect && stop_y > clipRect->fBottom) { 491bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com stop_y = clipRect->fBottom; 492bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 493bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 494bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com InverseBlitter ib; 495bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com PrePostProc proc = NULL; 496bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 497bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (path.isInverseFillType()) { 498bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ib.setBlitter(blitter, clipRgn.getBounds(), shiftEdgesUp); 499bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter = &ib; 500bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com proc = PrePostInverseBlitterProc; 501bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 502bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 503018395ca1906954a256b072777f4d67387a9c853reed@google.com if (path.isConvex() && (NULL == proc)) { 504e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com walk_convex_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, NULL); 505e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } else { 506e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com walk_edges(&headEdge, path.getFillType(), blitter, start_y, stop_y, proc); 507e85a548b33e0471d64a68b246e640770a89ef51dreed@google.com } 508bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 509bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 510434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.comvoid sk_blit_above(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) { 511bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkIRect& cr = clip.getBounds(); 512bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkIRect tmp; 513434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 514bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.fLeft = cr.fLeft; 515bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.fRight = cr.fRight; 516bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.fTop = cr.fTop; 517bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.fBottom = ir.fTop; 518bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (!tmp.isEmpty()) { 519bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter->blitRectRegion(tmp, clip); 520bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 521434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com} 522434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 523434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.comvoid sk_blit_below(SkBlitter* blitter, const SkIRect& ir, const SkRegion& clip) { 524434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com const SkIRect& cr = clip.getBounds(); 525434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com SkIRect tmp; 526bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 527434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com tmp.fLeft = cr.fLeft; 528434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com tmp.fRight = cr.fRight; 529bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.fTop = ir.fBottom; 530bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tmp.fBottom = cr.fBottom; 531bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (!tmp.isEmpty()) { 532bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter->blitRectRegion(tmp, clip); 533bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 534bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 535bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 536b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org/////////////////////////////////////////////////////////////////////////////// 537bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5382dad15adc1754325a3cf4dacd02162c39b3259d0reed@google.com/** 5398194d23bf9bba13b8e6ef223ceae4bd41b46f7dereed@google.com * If the caller is drawing an inverse-fill path, then it pass true for 5408194d23bf9bba13b8e6ef223ceae4bd41b46f7dereed@google.com * skipRejectTest, so we don't abort drawing just because the src bounds (ir) 5418194d23bf9bba13b8e6ef223ceae4bd41b46f7dereed@google.com * is outside of the clip. 5422dad15adc1754325a3cf4dacd02162c39b3259d0reed@google.com */ 543b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.orgSkScanClipper::SkScanClipper(SkBlitter* blitter, const SkRegion* clip, 5448194d23bf9bba13b8e6ef223ceae4bd41b46f7dereed@google.com const SkIRect& ir, bool skipRejectTest) { 545bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter = NULL; // null means blit nothing 546bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fClipRect = NULL; 547bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 548b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org if (clip) { 549bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fClipRect = &clip->getBounds(); 5508194d23bf9bba13b8e6ef223ceae4bd41b46f7dereed@google.com if (!skipRejectTest && !SkIRect::Intersects(*fClipRect, ir)) { // completely clipped out 551bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 552b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org } 553bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 554b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org if (clip->isRect()) { 555b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org if (fClipRect->contains(ir)) { 556bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fClipRect = NULL; 557b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org } else { 558bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // only need a wrapper blitter if we're horizontally clipped 559b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org if (fClipRect->fLeft > ir.fLeft || fClipRect->fRight < ir.fRight) { 560bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRectBlitter.init(blitter, *fClipRect); 561bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter = &fRectBlitter; 562bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 563bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 564b038ac4517fa760b01ec06002ccda9913ffcbdddmike@reedtribe.org } else { 565bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRgnBlitter.init(blitter, clip); 566bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter = &fRgnBlitter; 567bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 568bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 569bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter = blitter; 570bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 571bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 572bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 573bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 57454843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.comstatic bool clip_to_limit(const SkRegion& orig, SkRegion* reduced) { 57554843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com const int32_t limit = 32767; 57654843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com 57754843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com SkIRect limitR; 57854843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com limitR.set(-limit, -limit, limit, limit); 57954843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com if (limitR.contains(orig.getBounds())) { 58054843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com return false; 58154843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com } 58254843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com reduced->op(orig, limitR, SkRegion::kIntersect_Op); 58354843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com return true; 58454843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com} 58554843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com 58654843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.comvoid SkScan::FillPath(const SkPath& path, const SkRegion& origClip, 587bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBlitter* blitter) { 58854843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com if (origClip.isEmpty()) { 589bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 590bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 591bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 59254843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com // Our edges are fixed-point, and don't like the bounds of the clip to 59354843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com // exceed that. Here we trim the clip just so we don't overflow later on 59454843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com const SkRegion* clipPtr = &origClip; 59554843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com SkRegion finiteClip; 59654843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com if (clip_to_limit(origClip, &finiteClip)) { 59754843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com if (finiteClip.isEmpty()) { 59854843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com return; 59954843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com } 60054843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com clipPtr = &finiteClip; 60154843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com } 60254843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com // don't reference "origClip" any more, just use clipPtr 60354843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com 604bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkIRect ir; 605155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com path.getBounds().round(&ir); 606bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (ir.isEmpty()) { 607bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (path.isInverseFillType()) { 60854843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com blitter->blitRegion(*clipPtr); 609bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 610bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 611bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 612bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 6138194d23bf9bba13b8e6ef223ceae4bd41b46f7dereed@google.com SkScanClipper clipper(blitter, clipPtr, ir, path.isInverseFillType()); 614bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 615bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter = clipper.getBlitter(); 616bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (blitter) { 617434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com // we have to keep our calls to blitter in sorted order, so we 618434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com // must blit the above section first, then the middle, then the bottom. 619bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (path.isInverseFillType()) { 62054843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com sk_blit_above(blitter, ir, *clipPtr); 621bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 62254843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com sk_fill_path(path, clipper.getClipRect(), blitter, ir.fTop, ir.fBottom, 62354843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com 0, *clipPtr); 624434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com if (path.isInverseFillType()) { 62554843bab21ba85e70ec9c3a0e8011eb56030c208reed@google.com sk_blit_below(blitter, ir, *clipPtr); 626434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com } 627bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 628bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // what does it mean to not have a blitter if path.isInverseFillType??? 629bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 630bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 631bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 63226f5a398c38318eb7eab44f72e024ef784d247fareed@google.comvoid SkScan::FillPath(const SkPath& path, const SkIRect& ir, 63326f5a398c38318eb7eab44f72e024ef784d247fareed@google.com SkBlitter* blitter) { 63426f5a398c38318eb7eab44f72e024ef784d247fareed@google.com SkRegion rgn(ir); 63526f5a398c38318eb7eab44f72e024ef784d247fareed@google.com FillPath(path, rgn, blitter); 63626f5a398c38318eb7eab44f72e024ef784d247fareed@google.com} 63726f5a398c38318eb7eab44f72e024ef784d247fareed@google.com 638bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 639bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 640bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic int build_tri_edges(SkEdge edge[], const SkPoint pts[], 641bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkIRect* clipRect, SkEdge* list[]) { 642bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkEdge** start = list; 643434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 644bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (edge->setLine(pts[0], pts[1], clipRect, 0)) { 645bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *list++ = edge; 646bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com edge = (SkEdge*)((char*)edge + sizeof(SkEdge)); 647bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 648bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (edge->setLine(pts[1], pts[2], clipRect, 0)) { 649bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *list++ = edge; 650bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com edge = (SkEdge*)((char*)edge + sizeof(SkEdge)); 651bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 652bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (edge->setLine(pts[2], pts[0], clipRect, 0)) { 653bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *list++ = edge; 654bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 655bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (int)(list - start); 656bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 657bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 658bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 6592258a80c91fa183971ea3ed987c528e835fe9481reed@android.comstatic void sk_fill_triangle(const SkPoint pts[], const SkIRect* clipRect, 6602258a80c91fa183971ea3ed987c528e835fe9481reed@android.com SkBlitter* blitter, const SkIRect& ir) { 661bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(pts && blitter); 662434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 663bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkEdge edgeStorage[3]; 664bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkEdge* list[3]; 665bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 666bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int count = build_tri_edges(edgeStorage, pts, clipRect, list); 667bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (count < 2) { 668bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 669bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 670bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 671bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkEdge headEdge, tailEdge, *last; 672bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 673bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // this returns the first and last edge after they're sorted into a dlink list 674bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkEdge* edge = sort_edges(list, count, &last); 675434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 676bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com headEdge.fPrev = NULL; 677bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com headEdge.fNext = edge; 678bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com headEdge.fFirstY = kEDGE_HEAD_Y; 679bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com headEdge.fX = SK_MinS32; 680bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com edge->fPrev = &headEdge; 681434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 682bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tailEdge.fPrev = last; 683bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tailEdge.fNext = NULL; 684bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tailEdge.fFirstY = kEDGE_TAIL_Y; 685bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com last->fNext = &tailEdge; 686434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 687bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // now edge is the head of the sorted linklist 688bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int stop_y = ir.fBottom; 689bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (clipRect && stop_y > clipRect->fBottom) { 690bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com stop_y = clipRect->fBottom; 691bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 692c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com int start_y = ir.fTop; 693c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com if (clipRect && start_y < clipRect->fTop) { 694c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com start_y = clipRect->fTop; 695c5f637cf3cecf921d7899c60181447a41ef5f10creed@android.com } 696018395ca1906954a256b072777f4d67387a9c853reed@google.com walk_convex_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y, NULL); 697018395ca1906954a256b072777f4d67387a9c853reed@google.com// walk_edges(&headEdge, SkPath::kEvenOdd_FillType, blitter, start_y, stop_y, NULL); 698bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 699bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 70026f5a398c38318eb7eab44f72e024ef784d247fareed@google.comvoid SkScan::FillTriangle(const SkPoint pts[], const SkRasterClip& clip, 701bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBlitter* blitter) { 70226f5a398c38318eb7eab44f72e024ef784d247fareed@google.com if (clip.isEmpty()) { 703bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 704bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 705434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 706bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkRect r; 707bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkIRect ir; 708bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com r.set(pts, 3); 709bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com r.round(&ir); 71026f5a398c38318eb7eab44f72e024ef784d247fareed@google.com if (ir.isEmpty() || !SkIRect::Intersects(ir, clip.getBounds())) { 711bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 712bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 713434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 71426f5a398c38318eb7eab44f72e024ef784d247fareed@google.com SkAAClipBlitterWrapper wrap; 71526f5a398c38318eb7eab44f72e024ef784d247fareed@google.com const SkRegion* clipRgn; 71626f5a398c38318eb7eab44f72e024ef784d247fareed@google.com if (clip.isBW()) { 71726f5a398c38318eb7eab44f72e024ef784d247fareed@google.com clipRgn = &clip.bwRgn(); 71826f5a398c38318eb7eab44f72e024ef784d247fareed@google.com } else { 71926f5a398c38318eb7eab44f72e024ef784d247fareed@google.com wrap.init(clip, blitter); 72026f5a398c38318eb7eab44f72e024ef784d247fareed@google.com clipRgn = &wrap.getRgn(); 72126f5a398c38318eb7eab44f72e024ef784d247fareed@google.com blitter = wrap.getBlitter(); 72226f5a398c38318eb7eab44f72e024ef784d247fareed@google.com } 723434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 72426f5a398c38318eb7eab44f72e024ef784d247fareed@google.com SkScanClipper clipper(blitter, clipRgn, ir); 725bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter = clipper.getBlitter(); 726bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (NULL != blitter) { 727bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sk_fill_triangle(pts, clipper.getClipRect(), blitter, ir); 728bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 729bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 730