SkRegion_path.cpp revision fbfcd5602128ec010c82cb733c9cdc0a3254f9f3
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRegionPriv.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScan.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTDArray.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkRgnBuilder : public SkBlitter { 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual ~SkRgnBuilder(); 19fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // returns true if it could allocate the working storage needed 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool init(int maxHeight, int maxTransitions); 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void done() { 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fCurrScanline != NULL) { 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline->fXCount = (SkRegion::RunType)((int)(fCurrXPtr - fCurrScanline->firstX())); 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!this->collapsWithPrev()) { // flush the last line 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline = fCurrScanline->nextScanline(); 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int computeRunCount() const; 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void copyToRect(SkIRect*) const; 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void copyToRgn(SkRegion::RunType runs[]) const; 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual void blitH(int x, int y, int width); 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void dump() const { 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("SkRgnBuilder: Top = %d\n", fTop); 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Scanline* line = (Scanline*)fStorage; 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (line < fCurrScanline) { 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("SkRgnBuilder::Scanline: LastY=%d, fXCount=%d", line->fLastY, line->fXCount); 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < line->fXCount; i++) { 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf(" %d", line->firstX()[i]); 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("\n"); 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com line = line->nextScanline(); 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 549c36a76102453db964cb6e51078a3d74d4126b2creed@google.com /* 559c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * Scanline mimics a row in the region, nearly. A row in a region is: 569c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * [Bottom IntervalCount [L R]... Sentinel] 579c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * while a Scanline is 589c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * [LastY XCount [L R]... uninitialized] 599c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * The two are the same length (which is good), but we have to transmute 609c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * the scanline a little when we convert it to a region-row. 619c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * 629c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * Potentially we could recode this to exactly match the row format, in 639c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * which case copyToRgn() could be a single memcpy. Not sure that is worth 649c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * the effort. 659c36a76102453db964cb6e51078a3d74d4126b2creed@google.com */ 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com struct Scanline { 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType fLastY; 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType fXCount; 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType* firstX() const { return (SkRegion::RunType*)(this + 1); } 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Scanline* nextScanline() const { 729c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // add final +1 for the x-sentinel 739c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return (Scanline*)((SkRegion::RunType*)(this + 1) + fXCount + 1); 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType* fStorage; 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Scanline* fCurrScanline; 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Scanline* fPrevScanline; 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // points at next avialable x[] in fCurrScanline 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType* fCurrXPtr; 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType fTop; // first Y value 82fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fStorageCount; 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool collapsWithPrev() { 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fPrevScanline != NULL && 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevScanline->fLastY + 1 == fCurrScanline->fLastY && 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevScanline->fXCount == fCurrScanline->fXCount && 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com !memcmp(fPrevScanline->firstX(), 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline->firstX(), 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline->fXCount * sizeof(SkRegion::RunType))) 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // update the height of fPrevScanline 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevScanline->fLastY = fCurrScanline->fLastY; 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRgnBuilder::~SkRgnBuilder() { 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_free(fStorage); 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkRgnBuilder::init(int maxHeight, int maxTransitions) { 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((maxHeight | maxTransitions) < 0) { 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Sk64 count, size; 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // compute the count with +1 and +3 slop for the working buffer 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count.setMul(maxHeight + 1, 3 + maxTransitions); 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!count.is32() || count.isNeg()) { 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fStorageCount = count.get32(); 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size.setMul(fStorageCount, sizeof(SkRegion::RunType)); 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!size.is32() || size.isNeg()) { 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fStorage = (SkRegion::RunType*)sk_malloc_flags(size.get32(), 0); 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == fStorage) { 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline = NULL; // signal empty collection 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevScanline = NULL; // signal first scanline 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRgnBuilder::blitH(int x, int y, int width) { 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fCurrScanline == NULL) { // first time 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTop = (SkRegion::RunType)(y); 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline = (Scanline*)fStorage; 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline->fLastY = (SkRegion::RunType)(y); 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrXPtr = fCurrScanline->firstX(); 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(y >= fCurrScanline->fLastY); 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (y > fCurrScanline->fLastY) { 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we get here, we're done with fCurrScanline 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline->fXCount = (SkRegion::RunType)((int)(fCurrXPtr - fCurrScanline->firstX())); 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int prevLastY = fCurrScanline->fLastY; 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!this->collapsWithPrev()) { 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevScanline = fCurrScanline; 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline = fCurrScanline->nextScanline(); 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (y - 1 > prevLastY) { // insert empty run 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline->fLastY = (SkRegion::RunType)(y - 1); 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline->fXCount = 0; 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline = fCurrScanline->nextScanline(); 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // setup for the new curr line 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrScanline->fLastY = (SkRegion::RunType)(y); 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrXPtr = fCurrScanline->firstX(); 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check if we should extend the current run, or add a new one 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fCurrXPtr > fCurrScanline->firstX() && fCurrXPtr[-1] == x) { 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrXPtr[-1] = (SkRegion::RunType)(x + width); 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrXPtr[0] = (SkRegion::RunType)(x); 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrXPtr[1] = (SkRegion::RunType)(x + width); 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrXPtr += 2; 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fCurrXPtr - fStorage < fStorageCount); 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkRgnBuilder::computeRunCount() const { 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fCurrScanline == NULL) { 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion::RunType* line = fStorage; 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion::RunType* stop = (const SkRegion::RunType*)fCurrScanline; 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 2 + (int)(stop - line); 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRgnBuilder::copyToRect(SkIRect* r) const { 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fCurrScanline != NULL); 1879c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // A rect's scanline is [bottom intervals left right sentinel] == 5 1889c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT((const SkRegion::RunType*)fCurrScanline - fStorage == 5); 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Scanline* line = (const Scanline*)fStorage; 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(line->fXCount == 2); 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r->set(line->firstX()[0], fTop, line->firstX()[1], line->fLastY + 1); 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRgnBuilder::copyToRgn(SkRegion::RunType runs[]) const { 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fCurrScanline != NULL); 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((const SkRegion::RunType*)fCurrScanline - fStorage > 4); 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Scanline* line = (const Scanline*)fStorage; 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Scanline* stop = fCurrScanline; 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *runs++ = fTop; 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *runs++ = (SkRegion::RunType)(line->fLastY + 1); 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = line->fXCount; 2079c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *runs++ = count >> 1; // intervalCount 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count) { 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(runs, line->firstX(), count * sizeof(SkRegion::RunType)); 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *runs++ = SkRegion::kRunTypeSentinel; 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com line = line->nextScanline(); 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (line < stop); 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(line == stop); 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *runs = SkRegion::kRunTypeSentinel; 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int count_path_runtype_values(const SkPath& path, int* itop, int* ibot) { 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const uint8_t gPathVerbToInitialLastIndex[] = { 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 0, // kMove_Verb 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1, // kLine_Verb 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2, // kQuad_Verb 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3, // kCubic_Verb 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 0, // kClose_Verb 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 0 // kDone_Verb 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const uint8_t gPathVerbToMaxEdges[] = { 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 0, // kMove_Verb 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1, // kLine_Verb 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2, // kQuad_VerbB 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3, // kCubic_Verb 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 0, // kClose_Verb 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 0 // kDone_Verb 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath::Iter iter(path, true); 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pts[4]; 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath::Verb verb; 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int maxEdges = 0; 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar top = SkIntToScalar(SK_MaxS16); 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar bot = SkIntToScalar(SK_MinS16); 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2464a3b714d73e585a3985d614600c6b79d5c8b1f1ereed@google.com while ((verb = iter.next(pts, false)) != SkPath::kDone_Verb) { 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com maxEdges += gPathVerbToMaxEdges[verb]; 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int lastIndex = gPathVerbToInitialLastIndex[verb]; 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (lastIndex > 0) { 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 1; i <= lastIndex; i++) { 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (top > pts[i].fY) { 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top = pts[i].fY; 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (bot < pts[i].fY) { 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bot = pts[i].fY; 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (SkPath::kMove_Verb == verb) { 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (top > pts[0].fY) { 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top = pts[0].fY; 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (bot < pts[0].fY) { 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bot = pts[0].fY; 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(top <= bot); 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *itop = SkScalarRound(top); 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *ibot = SkScalarRound(bot); 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return maxEdges; 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkRegion::setPath(const SkPath& path, const SkRegion& clip) { 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (clip.isEmpty()) { 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setEmpty(); 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (path.isEmpty()) { 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (path.isInverseFillType()) { 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->set(clip); 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setEmpty(); 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // compute worst-case rgn-size for the path 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int pathTop, pathBot; 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int pathTransitions = count_path_runtype_values(path, &pathTop, &pathBot); 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int clipTop, clipBot; 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int clipTransitions; 293fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com clipTransitions = clip.count_runtype_values(&clipTop, &clipBot); 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int top = SkMax32(pathTop, clipTop); 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int bot = SkMin32(pathBot, clipBot); 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (top >= bot) 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setEmpty(); 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRgnBuilder builder; 303fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!builder.init(bot - top, SkMax32(pathTransitions, clipTransitions))) { 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // can't allocate working space, so return false 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setEmpty(); 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::FillPath(path, clip, &builder); 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com builder.done(); 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = builder.computeRunCount(); 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count == 0) { 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setEmpty(); 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (count == kRectRegionRuns) { 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com builder.copyToRect(&fBounds); 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setRect(fBounds); 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 3199c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkRegion tmp; 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.fRunHead = RunHead::Alloc(count); 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com builder.copyToRgn(tmp.fRunHead->writable_runs()); 3239c36a76102453db964cb6e51078a3d74d4126b2creed@google.com tmp.fRunHead->computeRunBounds(&tmp.fBounds); 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->swap(tmp); 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////////////////////// 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////////////////////// 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct Edge { 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com enum { 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kY0Link = 0x01, 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kY1Link = 0x02, 337fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kCompleteLink = (kY0Link | kY1Link) 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType fX; 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType fY0, fY1; 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t fFlags; 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Edge* fNext; 345fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void set(int x, int y0, int y1) { 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(y0 != y1); 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fX = (SkRegion::RunType)(x); 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fY0 = (SkRegion::RunType)(y0); 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fY1 = (SkRegion::RunType)(y1); 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fFlags = 0; 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(fNext = NULL;) 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 355fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int top() const { 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkFastMin32(fY0, fY1); 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void find_link(Edge* base, Edge* stop) { 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(base < stop); 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (base->fFlags == Edge::kCompleteLink) { 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(base->fNext); 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(base + 1 < stop); 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y0 = base->fY0; 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y1 = base->fY1; 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Edge* e = base; 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((base->fFlags & Edge::kY0Link) == 0) { 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com e += 1; 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((e->fFlags & Edge::kY1Link) == 0 && y0 == e->fY1) { 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(NULL == e->fNext); 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com e->fNext = base; 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com e->fFlags = SkToU8(e->fFlags | Edge::kY1Link); 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 386fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com e = base; 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((base->fFlags & Edge::kY1Link) == 0) { 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com e += 1; 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((e->fFlags & Edge::kY0Link) == 0 && y1 == e->fY0) { 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(NULL == base->fNext); 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base->fNext = e; 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com e->fFlags = SkToU8(e->fFlags | Edge::kY0Link); 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 399fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base->fFlags = Edge::kCompleteLink; 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int extract_path(Edge* edge, Edge* stop, SkPath* path) { 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (0 == edge->fFlags) { 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge++; // skip over "used" edges 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(edge < stop); 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Edge* base = edge; 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Edge* prev = edge; 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge = edge->fNext; 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(edge != base); 4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = 1; 4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path->moveTo(SkIntToScalar(prev->fX), SkIntToScalar(prev->fY0)); 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev->fFlags = 0; 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (prev->fX != edge->fX || prev->fY1 != edge->fY0) { // skip collinear 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path->lineTo(SkIntToScalar(prev->fX), SkIntToScalar(prev->fY1)); // V 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path->lineTo(SkIntToScalar(edge->fX), SkIntToScalar(edge->fY0)); // H 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev = edge; 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge = edge->fNext; 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count += 1; 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev->fFlags = 0; 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (edge != base); 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path->lineTo(SkIntToScalar(prev->fX), SkIntToScalar(prev->fY1)); // V 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path->close(); 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTSearch.h" 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int EdgeProc(const Edge* a, const Edge* b) { 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (a->fX == b->fX) ? a->top() - b->top() : a->fX - b->fX; 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkRegion::getBoundaryPath(SkPath* path) const { 440d5d9dadcdd5fdbc8a17f3f398e3199b9d12c8d70tomhudson@google.com // path could safely be NULL if we're empty, but the caller shouldn't 441d5d9dadcdd5fdbc8a17f3f398e3199b9d12c8d70tomhudson@google.com // *know* that 442d5d9dadcdd5fdbc8a17f3f398e3199b9d12c8d70tomhudson@google.com SkASSERT(path); 443d5d9dadcdd5fdbc8a17f3f398e3199b9d12c8d70tomhudson@google.com 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->isEmpty()) { 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& bounds = this->getBounds(); 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->isRect()) { 451fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkRect r; 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(bounds); // this converts the ints to scalars 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path->addRect(r); 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Iterator iter(*this); 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTDArray<Edge> edges; 459fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (const SkIRect& r = iter.rect(); !iter.done(); iter.next()) { 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Edge* edge = edges.append(2); 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge[0].set(r.fLeft, r.fBottom, r.fTop); 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com edge[1].set(r.fRight, r.fTop, r.fBottom); 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 465c7a67cb57e43f8e140c7bd21318b5ad3e2db6b2freed@google.com qsort(edges.begin(), edges.count(), sizeof(Edge), SkCastForQSort(EdgeProc)); 466fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = edges.count(); 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Edge* start = edges.begin(); 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Edge* stop = start + count; 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Edge* e; 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (e = start; e != stop; e++) { 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com find_link(e, stop); 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (e = start; e != stop; e++) { 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(e->fNext != NULL); 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(e->fFlags == Edge::kCompleteLink); 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path->incReserve(count << 1); 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count > 1); 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= extract_path(start, stop, path); 4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (count > 0); 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 492