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 "SkTemplates.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkThread.h" 139c36a76102453db964cb6e51078a3d74d4126b2creed@google.com#include "SkUtils.h" 149c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 159c36a76102453db964cb6e51078a3d74d4126b2creed@google.com/* Region Layout 169c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * 179c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * TOP 189c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * 199c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * [ Bottom, X-Intervals, [Left, Right]..., X-Sentinel ] 209c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * ... 219c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * 229c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * Y-Sentinel 239c36a76102453db964cb6e51078a3d74d4126b2creed@google.com */ 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDEBUGCODE(int32_t gRgnAllocCounter;) 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////////////////////// 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 299c36a76102453db964cb6e51078a3d74d4126b2creed@google.com/* Pass in the beginning with the intervals. 309c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * We back up 1 to read the interval-count. 319c36a76102453db964cb6e51078a3d74d4126b2creed@google.com * Return the beginning of the next scanline (i.e. the next Y-value) 329c36a76102453db964cb6e51078a3d74d4126b2creed@google.com */ 339c36a76102453db964cb6e51078a3d74d4126b2creed@google.comstatic SkRegion::RunType* skip_intervals(const SkRegion::RunType runs[]) { 349c36a76102453db964cb6e51078a3d74d4126b2creed@google.com int intervals = runs[-1]; 359c36a76102453db964cb6e51078a3d74d4126b2creed@google.com#ifdef SK_DEBUG 369c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (intervals > 0) { 379c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(runs[0] < runs[1]); 389c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(runs[1] < SkRegion::kRunTypeSentinel); 399c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } else { 409c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(0 == intervals); 419c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(SkRegion::kRunTypeSentinel == runs[0]); 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 439c36a76102453db964cb6e51078a3d74d4126b2creed@google.com#endif 449c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += intervals * 2 + 1; 459c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return const_cast<SkRegion::RunType*>(runs); 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 489c36a76102453db964cb6e51078a3d74d4126b2creed@google.combool SkRegion::RunsAreARect(const SkRegion::RunType runs[], int count, 499c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkIRect* bounds) { 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(runs[0], false); // top 519c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(count >= kRectRegionRuns); 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 53c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (count == kRectRegionRuns) { 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(runs[1], false); // bottom 559c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(1 == runs[2]); 569c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(runs[3], false); // left 579c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(runs[4], false); // right 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(runs[5], true); 599c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(runs[6], true); 60fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(runs[0] < runs[1]); // valid height 629c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(runs[3] < runs[4]); // valid width 63fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 649c36a76102453db964cb6e51078a3d74d4126b2creed@google.com bounds->set(runs[3], runs[0], runs[4], runs[1]); 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////// 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 720a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comSkRegion::SkRegion() { 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounds.set(0, 0, 0, 0); 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRunHead = SkRegion_gEmptyRunHeadPtr; 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 770a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comSkRegion::SkRegion(const SkRegion& src) { 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead) 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setRegion(src); 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 820a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comSkRegion::SkRegion(const SkIRect& rect) { 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead) 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->setRect(rect); 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 870a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comSkRegion::~SkRegion() { 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->freeRuns(); 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 910a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comvoid SkRegion::freeRuns() { 92b77b69f89f2551a4a14a30b1a44dd93ea5927bb1bungeman@google.com if (this->isComplex()) { 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fRunHead->fRefCnt >= 1); 940a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com if (sk_atomic_dec(&fRunHead->fRefCnt) == 1) { 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com //SkASSERT(gRgnAllocCounter > 0); 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com //SkDEBUGCODE(sk_atomic_dec(&gRgnAllocCounter)); 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com //SkDEBUGF(("************** gRgnAllocCounter::free %d\n", gRgnAllocCounter)); 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_free(fRunHead); 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 103af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.comvoid SkRegion::allocateRuns(int count, int ySpanCount, int intervalCount) { 104af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com fRunHead = RunHead::Alloc(count, ySpanCount, intervalCount); 105af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com} 106af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com 1079c36a76102453db964cb6e51078a3d74d4126b2creed@google.comvoid SkRegion::allocateRuns(int count) { 1089c36a76102453db964cb6e51078a3d74d4126b2creed@google.com fRunHead = RunHead::Alloc(count); 1099c36a76102453db964cb6e51078a3d74d4126b2creed@google.com} 1109c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 111af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.comvoid SkRegion::allocateRuns(const RunHead& head) { 112af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com fRunHead = RunHead::Alloc(head.fRunCount, 113af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com head.getYSpanCount(), 114af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com head.getIntervalCount()); 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1170a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comSkRegion& SkRegion::operator=(const SkRegion& src) { 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (void)this->setRegion(src); 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return *this; 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1220a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comvoid SkRegion::swap(SkRegion& other) { 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap<SkIRect>(fBounds, other.fBounds); 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap<RunHead*>(fRunHead, other.fRunHead); 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1275dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.orgint SkRegion::computeRegionComplexity() const { 1285dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org if (this->isEmpty()) { 1295dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org return 0; 1305dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org } else if (this->isRect()) { 1315dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org return 1; 1325dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org } 1335dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org return fRunHead->getIntervalCount(); 1345dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org} 135f7d01ce1849aa029743e9e0b810a8f955ad99f28skia.committer@gmail.com 1360a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.combool SkRegion::setEmpty() { 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->freeRuns(); 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounds.set(0, 0, 0, 0); 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRunHead = SkRegion_gEmptyRunHeadPtr; 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1430a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.combool SkRegion::setRect(int32_t left, int32_t top, 1440a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com int32_t right, int32_t bottom) { 1450a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com if (left >= right || top >= bottom) { 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setEmpty(); 1470a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com } 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->freeRuns(); 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounds.set(left, top, right, bottom); 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRunHead = SkRegion_gRectRunHeadPtr; 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1540a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.combool SkRegion::setRect(const SkIRect& r) { 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setRect(r.fLeft, r.fTop, r.fRight, r.fBottom); 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1580a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.combool SkRegion::setRegion(const SkRegion& src) { 1590a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com if (this != &src) { 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->freeRuns(); 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounds = src.fBounds; 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRunHead = src.fRunHead; 164b77b69f89f2551a4a14a30b1a44dd93ea5927bb1bungeman@google.com if (this->isComplex()) { 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_atomic_inc(&fRunHead->fRefCnt); 1660a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com } 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fRunHead != SkRegion_gEmptyRunHeadPtr; 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1710a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.combool SkRegion::op(const SkIRect& rect, const SkRegion& rgn, Op op) { 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion tmp(rect); 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->op(tmp, rgn, op); 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1770a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.combool SkRegion::op(const SkRegion& rgn, const SkIRect& rect, Op op) { 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion tmp(rect); 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->op(rgn, tmp, op); 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1830a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com/////////////////////////////////////////////////////////////////////////////// 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18556c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID 1862c8e9d40a42ef24e811c3a2614b361cad1036110bungeman@google.com#include <stdio.h> 187c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.comchar* SkRegion::toString() { 188cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com Iterator iter(*this); 189cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com int count = 0; 190cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com while (!iter.done()) { 191cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com count++; 192cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com iter.next(); 193cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com } 194cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com // 4 ints, up to 10 digits each plus sign, 3 commas, '(', ')', SkRegion() and '\0' 195cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com const int max = (count*((11*4)+5))+11+1; 196cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com char* result = (char*)malloc(max); 197cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com if (result == NULL) { 198cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com return NULL; 199cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com } 200cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com count = sprintf(result, "SkRegion("); 201cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com iter.reset(*this); 202cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com while (!iter.done()) { 203cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com const SkIRect& r = iter.rect(); 204cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com count += sprintf(result+count, "(%d,%d,%d,%d)", r.fLeft, r.fTop, r.fRight, r.fBottom); 205cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com iter.next(); 206cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com } 207cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com count += sprintf(result+count, ")"); 208cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com return result; 209cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com} 210cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com#endif 211cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com 212c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com/////////////////////////////////////////////////////////////////////////////// 213cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com 214c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.comint SkRegion::count_runtype_values(int* itop, int* ibot) const { 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int maxT; 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 217c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (this->isRect()) { 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com maxT = 2; 219c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } else { 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(this->isComplex()); 221af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com maxT = fRunHead->getIntervalCount() * 2; 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *itop = fBounds.fTop; 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *ibot = fBounds.fBottom; 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return maxT; 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2287d4aee34e23e536e1115f132d20a20fb629bb66areed@google.comstatic bool isRunCountEmpty(int count) { 2297d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return count <= 2; 2307d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com} 2317d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com 232c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.combool SkRegion::setRuns(RunType runs[], int count) { 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count > 0); 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 236c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (isRunCountEmpty(count)) { 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // SkDEBUGF(("setRuns: empty\n")); 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(runs[count-1], true); 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setEmpty(); 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // trim off any empty spans from the top and bottom 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // weird I should need this, perhaps op() could be smarter... 244c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (count > kRectRegionRuns) { 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com RunType* stop = runs + count; 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(runs[0], false); // top 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(runs[1], false); // bottom 2489c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // runs[2] is uncomputed intervalCount 249fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2509c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (runs[3] == SkRegion::kRunTypeSentinel) { // should be first left... 2519c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 3; // skip empty initial span 2529c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs[0] = runs[-2]; // set new top to prev bottom 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(runs[1], false); // bot: a sentinal would mean two in a row 2549c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(runs[2], false); // intervalcount 2559c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(runs[3], false); // left 2569c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(runs[4], false); // right 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(stop[-1], true); 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(stop[-2], true); 2619c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 2629c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // now check for a trailing empty span 2639c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (stop[-5] == SkRegion::kRunTypeSentinel) { // eek, stop[-4] was a bottom with no x-runs 2649c36a76102453db964cb6e51078a3d74d4126b2creed@google.com stop[-4] = SkRegion::kRunTypeSentinel; // kill empty last span 2659c36a76102453db964cb6e51078a3d74d4126b2creed@google.com stop -= 3; 2669c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(stop[-1], true); // last y-sentinel 2679c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(stop[-2], true); // last x-sentinel 2689c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(stop[-3], false); // last right 2699c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(stop[-4], false); // last left 2709c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(stop[-5], false); // last interval-count 2719c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(stop[-6], false); // last bottom 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count = (int)(stop - runs); 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count >= kRectRegionRuns); 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2789c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (SkRegion::RunsAreARect(runs, count, &fBounds)) { 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setRect(fBounds); 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 281fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we get here, we need to become a complex region 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 284b77b69f89f2551a4a14a30b1a44dd93ea5927bb1bungeman@google.com if (!this->isComplex() || fRunHead->fRunCount != count) { 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->freeRuns(); 2869c36a76102453db964cb6e51078a3d74d4126b2creed@google.com this->allocateRuns(count); 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 288fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // must call this before we can write directly into runs() 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // in case we are sharing the buffer with another region (copy on write) 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRunHead = fRunHead->ensureWritable(); 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(fRunHead->writable_runs(), runs, count * sizeof(RunType)); 2939c36a76102453db964cb6e51078a3d74d4126b2creed@google.com fRunHead->computeRunBounds(&fBounds); 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRegion::BuildRectRuns(const SkIRect& bounds, 301c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com RunType runs[kRectRegionRuns]) { 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs[0] = bounds.fTop; 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs[1] = bounds.fBottom; 3049c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs[2] = 1; // 1 interval for this scanline 3059c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs[3] = bounds.fLeft; 3069c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs[4] = bounds.fRight; 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs[5] = kRunTypeSentinel; 3089c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs[6] = kRunTypeSentinel; 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 311c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.combool SkRegion::contains(int32_t x, int32_t y) const { 3129c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkDEBUGCODE(this->validate();) 3139c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 314c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (!fBounds.contains(x, y)) { 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 316c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } 317c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (this->isRect()) { 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 319c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(this->isComplex()); 321bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com 3229c36a76102453db964cb6e51078a3d74d4126b2creed@google.com const RunType* runs = fRunHead->findScanline(y); 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3249c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // Skip the Bottom and IntervalCount 3259c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 2; 326fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3279c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // Just walk this scanline, checking each interval. The X-sentinel will 3289c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // appear as a left-inteval (runs[0]) and should abort the search. 3299c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // 3309c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // We could do a bsearch, using interval-count (runs[1]), but need to time 3319c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // when that would be worthwhile. 3329c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // 3339c36a76102453db964cb6e51078a3d74d4126b2creed@google.com for (;;) { 3349c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (x < runs[0]) { 3359c36a76102453db964cb6e51078a3d74d4126b2creed@google.com break; 3369c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 3379c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (x < runs[1]) { 3389c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return true; 3399c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 3409c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 2; 3419c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 3429c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return false; 3439c36a76102453db964cb6e51078a3d74d4126b2creed@google.com} 3449c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 345796a1753d96eb0c76e742c8288617d758ddf33dfmike@reedtribe.orgstatic SkRegion::RunType scanline_bottom(const SkRegion::RunType runs[]) { 346796a1753d96eb0c76e742c8288617d758ddf33dfmike@reedtribe.org return runs[0]; 347796a1753d96eb0c76e742c8288617d758ddf33dfmike@reedtribe.org} 348796a1753d96eb0c76e742c8288617d758ddf33dfmike@reedtribe.org 3499c36a76102453db964cb6e51078a3d74d4126b2creed@google.comstatic const SkRegion::RunType* scanline_next(const SkRegion::RunType runs[]) { 3509c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // skip [B N [L R]... S] 3519c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return runs + 2 + runs[1] * 2 + 1; 3529c36a76102453db964cb6e51078a3d74d4126b2creed@google.com} 3539c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 3549c36a76102453db964cb6e51078a3d74d4126b2creed@google.comstatic bool scanline_contains(const SkRegion::RunType runs[], 3559c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkRegion::RunType L, SkRegion::RunType R) { 3569c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 2; // skip Bottom and IntervalCount 3579c36a76102453db964cb6e51078a3d74d4126b2creed@google.com for (;;) { 3589c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (L < runs[0]) { 3599c36a76102453db964cb6e51078a3d74d4126b2creed@google.com break; 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3619c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (R <= runs[1]) { 3629c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return true; 3639c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 3649c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 2; 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 369c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.combool SkRegion::contains(const SkIRect& r) const { 3709c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkDEBUGCODE(this->validate();) 3719c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 3729c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (!fBounds.contains(r)) { 3739c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return false; 3749c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 3759c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (this->isRect()) { 3769c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return true; 3779c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 3789c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(this->isComplex()); 379bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com 3809c36a76102453db964cb6e51078a3d74d4126b2creed@google.com const RunType* scanline = fRunHead->findScanline(r.fTop); 381bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com for (;;) { 3829c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (!scanline_contains(scanline, r.fLeft, r.fRight)) { 3839c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return false; 3849c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 385bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com if (r.fBottom <= scanline_bottom(scanline)) { 386bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com break; 387bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com } 3889c36a76102453db964cb6e51078a3d74d4126b2creed@google.com scanline = scanline_next(scanline); 389bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com } 3909c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return true; 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 393c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.combool SkRegion::contains(const SkRegion& rgn) const { 3949c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkDEBUGCODE(this->validate();) 3959c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkDEBUGCODE(rgn.validate();) 3969c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 397c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (this->isEmpty() || rgn.isEmpty() || !fBounds.contains(rgn.fBounds)) { 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 399c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } 400c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (this->isRect()) { 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 402c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } 4039c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (rgn.isRect()) { 4049c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return this->contains(rgn.getBounds()); 4059c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4077d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com /* 4087d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com * A contains B is equivalent to 4097d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com * B - A == 0 4107d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com */ 4117d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return !Oper(rgn, *this, kDifference_Op, NULL); 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 414c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.comconst SkRegion::RunType* SkRegion::getRuns(RunType tmpStorage[], 415af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com int* intervals) const { 416af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com SkASSERT(tmpStorage && intervals); 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const RunType* runs = tmpStorage; 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 419c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (this->isEmpty()) { 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmpStorage[0] = kRunTypeSentinel; 421af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com *intervals = 0; 422c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } else if (this->isRect()) { 4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BuildRectRuns(fBounds, tmpStorage); 424af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com *intervals = 1; 425c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } else { 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs = fRunHead->readonly_runs(); 427af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com *intervals = fRunHead->getIntervalCount(); 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return runs; 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 432c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com/////////////////////////////////////////////////////////////////////////////// 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4349c36a76102453db964cb6e51078a3d74d4126b2creed@google.comstatic bool scanline_intersects(const SkRegion::RunType runs[], 4359c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkRegion::RunType L, SkRegion::RunType R) { 4369c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 2; // skip Bottom and IntervalCount 4379c36a76102453db964cb6e51078a3d74d4126b2creed@google.com for (;;) { 4389c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (R <= runs[0]) { 4399c36a76102453db964cb6e51078a3d74d4126b2creed@google.com break; 4409c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 4419c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (L < runs[1]) { 4429c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return true; 4439c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 4449c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 2; 4459c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 4469c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return false; 4479c36a76102453db964cb6e51078a3d74d4126b2creed@google.com} 4489c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkRegion::intersects(const SkIRect& r) const { 4509c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkDEBUGCODE(this->validate();) 451fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->isEmpty() || r.isEmpty()) { 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 455fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4569c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkIRect sect; 4579c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (!sect.intersect(fBounds, r)) { 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->isRect()) { 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 463bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com SkASSERT(this->isComplex()); 464fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4659c36a76102453db964cb6e51078a3d74d4126b2creed@google.com const RunType* scanline = fRunHead->findScanline(sect.fTop); 466bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com for (;;) { 4679c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (scanline_intersects(scanline, sect.fLeft, sect.fRight)) { 4689c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return true; 4699c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 470bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com if (sect.fBottom <= scanline_bottom(scanline)) { 471bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com break; 472bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com } 4739c36a76102453db964cb6e51078a3d74d4126b2creed@google.com scanline = scanline_next(scanline); 474bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com } 4759c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return false; 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkRegion::intersects(const SkRegion& rgn) const { 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->isEmpty() || rgn.isEmpty()) { 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 482fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!SkIRect::Intersects(fBounds, rgn.fBounds)) { 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 486fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 4879c36a76102453db964cb6e51078a3d74d4126b2creed@google.com bool weAreARect = this->isRect(); 4889c36a76102453db964cb6e51078a3d74d4126b2creed@google.com bool theyAreARect = rgn.isRect(); 4899c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 4909c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (weAreARect && theyAreARect) { 4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4939c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (weAreARect) { 4949c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return rgn.intersects(this->getBounds()); 4959c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 4969c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (theyAreARect) { 4979c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return this->intersects(rgn.getBounds()); 4989c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 499fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 5009c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // both of us are complex 5017d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return Oper(*this, rgn, kIntersect_Op, NULL); 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 504c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com/////////////////////////////////////////////////////////////////////////////// 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5066d428d3e6e4238786a38caca6002dae92637958dreed@google.combool SkRegion::operator==(const SkRegion& b) const { 5076d428d3e6e4238786a38caca6002dae92637958dreed@google.com SkDEBUGCODE(validate();) 5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(b.validate();) 5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5106d428d3e6e4238786a38caca6002dae92637958dreed@google.com if (this == &b) { 5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 51297fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com } 5136d428d3e6e4238786a38caca6002dae92637958dreed@google.com if (fBounds != b.fBounds) { 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 51597fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com } 516fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 5176d428d3e6e4238786a38caca6002dae92637958dreed@google.com const SkRegion::RunHead* ah = fRunHead; 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion::RunHead* bh = b.fRunHead; 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // this catches empties and rects being equal 52197fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com if (ah == bh) { 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 52397fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com } 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now we insist that both are complex (but different ptrs) 525b77b69f89f2551a4a14a30b1a44dd93ea5927bb1bungeman@google.com if (!this->isComplex() || !b.isComplex()) { 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 52797fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com } 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return ah->fRunCount == bh->fRunCount && 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com !memcmp(ah->readonly_runs(), bh->readonly_runs(), 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ah->fRunCount * sizeof(SkRegion::RunType)); 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 53397fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.comvoid SkRegion::translate(int dx, int dy, SkRegion* dst) const { 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 53697fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com if (NULL == dst) { 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 53897fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com } 53997fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com if (this->isEmpty()) { 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->setEmpty(); 54197fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com } else if (this->isRect()) { 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->setRect(fBounds.fLeft + dx, fBounds.fTop + dy, 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounds.fRight + dx, fBounds.fBottom + dy); 54497fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com } else { 54597fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com if (this == dst) { 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fRunHead = dst->fRunHead->ensureWritable(); 54797fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com } else { 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion tmp; 549af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com tmp.allocateRuns(*fRunHead); 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.fBounds = fBounds; 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->swap(tmp); 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->fBounds.offset(dx, dy); 555fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const RunType* sruns = fRunHead->readonly_runs(); 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com RunType* druns = dst->fRunHead->writable_runs(); 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *druns++ = (SkRegion::RunType)(*sruns++ + dy); // top 56097fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com for (;;) { 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int bottom = *sruns++; 56297fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com if (bottom == kRunTypeSentinel) { 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 56497fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com } 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *druns++ = (SkRegion::RunType)(bottom + dy); // bottom; 5669c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *druns++ = *sruns++; // copy intervalCount; 56797fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com for (;;) { 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x = *sruns++; 56997fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com if (x == kRunTypeSentinel) { 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 57197fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com } 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *druns++ = (SkRegion::RunType)(x + dx); 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *druns++ = (SkRegion::RunType)(*sruns++ + dx); 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *druns++ = kRunTypeSentinel; // x sentinel 5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *druns++ = kRunTypeSentinel; // y sentinel 5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(sruns - fRunHead->readonly_runs() == fRunHead->fRunCount); 5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(druns - dst->fRunHead->readonly_runs() == dst->fRunHead->fRunCount); 5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 586097a3513535ad854c1b049c32c080ec875ab1411reed@android.com/////////////////////////////////////////////////////////////////////////////// 587097a3513535ad854c1b049c32c080ec875ab1411reed@android.com 588097a3513535ad854c1b049c32c080ec875ab1411reed@android.combool SkRegion::setRects(const SkIRect rects[], int count) { 589097a3513535ad854c1b049c32c080ec875ab1411reed@android.com if (0 == count) { 590cb34235f46b6259b612e72c416e850e26803250areed@android.com this->setEmpty(); 591cb34235f46b6259b612e72c416e850e26803250areed@android.com } else { 592cb34235f46b6259b612e72c416e850e26803250areed@android.com this->setRect(rects[0]); 593cb34235f46b6259b612e72c416e850e26803250areed@android.com for (int i = 1; i < count; i++) { 594cb34235f46b6259b612e72c416e850e26803250areed@android.com this->op(rects[i], kUnion_Op); 595097a3513535ad854c1b049c32c080ec875ab1411reed@android.com } 596097a3513535ad854c1b049c32c080ec875ab1411reed@android.com } 597cb34235f46b6259b612e72c416e850e26803250areed@android.com return !this->isEmpty(); 598097a3513535ad854c1b049c32c080ec875ab1411reed@android.com} 599097a3513535ad854c1b049c32c080ec875ab1411reed@android.com 600097a3513535ad854c1b049c32c080ec875ab1411reed@android.com/////////////////////////////////////////////////////////////////////////////// 6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used without having been initialized 6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( push ) 6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( disable : 4701 ) 6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void assert_valid_pair(int left, int rite) 6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(left == SkRegion::kRunTypeSentinel || left < rite); 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com #define assert_valid_pair(left, rite) 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct spanRec { 6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion::RunType* fA_runs; 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion::RunType* fB_runs; 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fA_left, fA_rite, fB_left, fB_rite; 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fLeft, fRite, fInside; 621fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 622c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com void init(const SkRegion::RunType a_runs[], 623c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com const SkRegion::RunType b_runs[]) { 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fA_left = *a_runs++; 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fA_rite = *a_runs++; 6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fB_left = *b_runs++; 6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fB_rite = *b_runs++; 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fA_runs = a_runs; 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fB_runs = b_runs; 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 632fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 633c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com bool done() const { 6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fA_left <= SkRegion::kRunTypeSentinel); 6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fB_left <= SkRegion::kRunTypeSentinel); 636c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com return fA_left == SkRegion::kRunTypeSentinel && 637c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com fB_left == SkRegion::kRunTypeSentinel; 6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 640c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com void next() { 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_valid_pair(fA_left, fA_rite); 6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_valid_pair(fB_left, fB_rite); 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int inside, left, rite SK_INIT_TO_AVOID_WARNING; 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool a_flush = false; 6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool b_flush = false; 647fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int a_left = fA_left; 6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int a_rite = fA_rite; 6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int b_left = fB_left; 6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int b_rite = fB_rite; 6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 653c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (a_left < b_left) { 6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inside = 1; 6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left = a_left; 656c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (a_rite <= b_left) { // [...] <...> 6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rite = a_rite; 6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a_flush = true; 659c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } else { // [...<..]...> or [...<...>...] 6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rite = a_left = b_left; 661c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } 662c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } else if (b_left < a_left) { 6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inside = 2; 6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left = b_left; 665c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (b_rite <= a_left) { // [...] <...> 6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rite = b_rite; 6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b_flush = true; 668c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } else { // [...<..]...> or [...<...>...] 6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rite = b_left = a_left; 670c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } 671c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } else { // a_left == b_left 6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inside = 3; 6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left = a_left; // or b_left 674c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (a_rite <= b_rite) { 6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rite = b_left = a_rite; 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a_flush = true; 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 678c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (b_rite <= a_rite) { 6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rite = a_left = b_rite; 6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b_flush = true; 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 684c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (a_flush) { 6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a_left = *fA_runs++; 6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a_rite = *fA_runs++; 6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 688c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (b_flush) { 6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b_left = *fB_runs++; 6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b_rite = *fB_runs++; 6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(left <= rite); 694fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now update our state 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fA_left = a_left; 6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fA_rite = a_rite; 6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fB_left = b_left; 6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fB_rite = b_rite; 700fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLeft = left; 7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRite = rite; 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fInside = inside; 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkRegion::RunType* operate_on_span(const SkRegion::RunType a_runs[], 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion::RunType b_runs[], 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType dst[], 710c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com int min, int max) { 7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com spanRec rec; 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool firstInterval = true; 713fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rec.init(a_runs, b_runs); 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 716c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com while (!rec.done()) { 7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rec.next(); 718fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int left = rec.fLeft; 7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rite = rec.fRite; 721fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // add left,rite to our dst buffer (checking for coincidence 7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((unsigned)(rec.fInside - min) <= (unsigned)(max - min) && 724c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com left < rite) { // skip if equal 725c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (firstInterval || dst[-1] < left) { 7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst++ = (SkRegion::RunType)(left); 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst++ = (SkRegion::RunType)(rite); 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com firstInterval = false; 729c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } else { 730c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com // update the right edge 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[-1] = (SkRegion::RunType)(rite); 732c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst++ = SkRegion::kRunTypeSentinel; 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return dst; 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( pop ) 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const struct { 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t fMin; 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t fMax; 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} gOpMinMax[] = { 7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1, 1 }, // Difference 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 3, 3 }, // Intersection 7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1, 3 }, // Union 7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1, 2 } // XOR 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass RgnOper { 7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 756c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com RgnOper(int top, SkRegion::RunType dst[], SkRegion::Op op) { 7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need to ensure that the op enum lines up with our minmax array 7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SkRegion::kDifference_Op == 0); 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SkRegion::kIntersect_Op == 1); 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SkRegion::kUnion_Op == 2); 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SkRegion::kXOR_Op == 3); 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)op <= 3); 7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fStartDst = dst; 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevDst = dst + 1; 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevLen = 0; // will never match a length from operate_on_span 7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTop = (SkRegion::RunType)(top); // just a first guess, we might update this 7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMin = gOpMinMax[op].fMin; 7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMax = gOpMinMax[op].fMax; 7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 773c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com void addSpan(int bottom, const SkRegion::RunType a_runs[], 774c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com const SkRegion::RunType b_runs[]) { 7759c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // skip X values and slots for the next Y+intervalCount 7769c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkRegion::RunType* start = fPrevDst + fPrevLen + 2; 7779c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // start points to beginning of dst interval 7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType* stop = operate_on_span(a_runs, b_runs, start, fMin, fMax); 7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t len = stop - start; 7809c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(len >= 1 && (len & 1) == 1); 7819c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(SkRegion::kRunTypeSentinel == stop[-1]); 7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 783c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (fPrevLen == len && 7849c36a76102453db964cb6e51078a3d74d4126b2creed@google.com (1 == len || !memcmp(fPrevDst, start, 7859c36a76102453db964cb6e51078a3d74d4126b2creed@google.com (len - 1) * sizeof(SkRegion::RunType)))) { 786c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com // update Y value 7879c36a76102453db964cb6e51078a3d74d4126b2creed@google.com fPrevDst[-2] = (SkRegion::RunType)(bottom); 788c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } else { // accept the new span 7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (len == 1 && fPrevLen == 0) { 7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTop = (SkRegion::RunType)(bottom); // just update our bottom 7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 7929c36a76102453db964cb6e51078a3d74d4126b2creed@google.com start[-2] = (SkRegion::RunType)(bottom); 793f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org start[-1] = SkToS32(len >> 1); 7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevDst = start; 7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevLen = len; 7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 799fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 800c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com int flush() { 8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fStartDst[0] = fTop; 8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevDst[fPrevLen] = SkRegion::kRunTypeSentinel; 8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (int)(fPrevDst - fStartDst + fPrevLen + 1); 8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8067d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com bool isEmpty() const { return 0 == fPrevLen; } 8077d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com 8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t fMin, fMax; 8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType* fStartDst; 8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType* fPrevDst; 8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t fPrevLen; 8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::RunType fTop; 8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8177d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com// want a unique value to signal that we exited due to quickExit 8187d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com#define QUICK_EXIT_TRUE_COUNT (-1) 8197d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com 8201deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.comstatic int operate(const SkRegion::RunType a_runs[], 8211deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com const SkRegion::RunType b_runs[], 8221deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com SkRegion::RunType dst[], 8237d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com SkRegion::Op op, 8247d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com bool quickExit) { 8259c36a76102453db964cb6e51078a3d74d4126b2creed@google.com const SkRegion::RunType gEmptyScanline[] = { 8269c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 0, // dummy bottom value 8279c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 0, // zero intervals 8285f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com SkRegion::kRunTypeSentinel, 8295f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com // just need a 2nd value, since spanRec.init() reads 2 values, even 8305f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com // though if the first value is the sentinel, it ignores the 2nd value. 8315f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com // w/o the 2nd value here, we might read uninitialized memory. 8325f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com // This happens when we are using gSentinel, which is pointing at 8335f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com // our sentinel value. 8345f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com 0 835fbb02e7e96745cec30c6c21ad58cc596b4e1c64dreed@android.com }; 8369c36a76102453db964cb6e51078a3d74d4126b2creed@google.com const SkRegion::RunType* const gSentinel = &gEmptyScanline[2]; 8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int a_top = *a_runs++; 8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int a_bot = *a_runs++; 8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int b_top = *b_runs++; 8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int b_bot = *b_runs++; 8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8439c36a76102453db964cb6e51078a3d74d4126b2creed@google.com a_runs += 1; // skip the intervalCount; 8449c36a76102453db964cb6e51078a3d74d4126b2creed@google.com b_runs += 1; // skip the intervalCount; 8459c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 8469c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // Now a_runs and b_runs to their intervals (or sentinel) 8479c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(a_top, false); 8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(a_bot, false); 8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(b_top, false); 8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com assert_sentinel(b_bot, false); 8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com RgnOper oper(SkMin32(a_top, b_top), dst, op); 854fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int prevBot = SkRegion::kRunTypeSentinel; // so we fail the first test 856fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 8571deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com while (a_bot < SkRegion::kRunTypeSentinel || 8581deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com b_bot < SkRegion::kRunTypeSentinel) { 8591deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com int top, bot SK_INIT_TO_AVOID_WARNING; 860fbb02e7e96745cec30c6c21ad58cc596b4e1c64dreed@android.com const SkRegion::RunType* run0 = gSentinel; 861fbb02e7e96745cec30c6c21ad58cc596b4e1c64dreed@android.com const SkRegion::RunType* run1 = gSentinel; 8621deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com bool a_flush = false; 8631deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com bool b_flush = false; 8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8651deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com if (a_top < b_top) { 8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top = a_top; 8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com run0 = a_runs; 8681deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com if (a_bot <= b_top) { // [...] <...> 8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bot = a_bot; 8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a_flush = true; 8711deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com } else { // [...<..]...> or [...<...>...] 8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bot = a_top = b_top; 8731deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com } 8741deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com } else if (b_top < a_top) { 8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top = b_top; 8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com run1 = b_runs; 8771deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com if (b_bot <= a_top) { // [...] <...> 8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bot = b_bot; 8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b_flush = true; 8801deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com } else { // [...<..]...> or [...<...>...] 8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bot = b_top = a_top; 8821deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com } 8831deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com } else { // a_top == b_top 8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top = a_top; // or b_top 8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com run0 = a_runs; 8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com run1 = b_runs; 8871deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com if (a_bot <= b_bot) { 8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bot = b_top = a_bot; 8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a_flush = true; 8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8911deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com if (b_bot <= a_bot) { 8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bot = a_top = b_bot; 8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b_flush = true; 8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 896fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 8971deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com if (top > prevBot) { 898fbb02e7e96745cec30c6c21ad58cc596b4e1c64dreed@android.com oper.addSpan(top, gSentinel, gSentinel); 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9001deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com oper.addSpan(bot, run0, run1); 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9027d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com if (quickExit && !oper.isEmpty()) { 9037d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return QUICK_EXIT_TRUE_COUNT; 9047d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 9057d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com 9061deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com if (a_flush) { 9079c36a76102453db964cb6e51078a3d74d4126b2creed@google.com a_runs = skip_intervals(a_runs); 9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a_top = a_bot; 9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a_bot = *a_runs++; 9109c36a76102453db964cb6e51078a3d74d4126b2creed@google.com a_runs += 1; // skip uninitialized intervalCount 9111deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com if (a_bot == SkRegion::kRunTypeSentinel) { 9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a_top = a_bot; 9131deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com } 9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9151deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com if (b_flush) { 9169c36a76102453db964cb6e51078a3d74d4126b2creed@google.com b_runs = skip_intervals(b_runs); 9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b_top = b_bot; 9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b_bot = *b_runs++; 9199c36a76102453db964cb6e51078a3d74d4126b2creed@google.com b_runs += 1; // skip uninitialized intervalCount 9201deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com if (b_bot == SkRegion::kRunTypeSentinel) { 9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b_top = b_bot; 9221deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com } 9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 924fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevBot = bot; 9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return oper.flush(); 9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* Given count RunTypes in a complex region, return the worst case number of 9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com logical intervals that represents (i.e. number of rects that would be 9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com returned from the iterator). 935fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com We could just return count/2, since there must be at least 2 values per 9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com interval, but we can first trim off the const overhead of the initial TOP 9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value, plus the final BOTTOM + 2 sentinels. 9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 940803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#if 0 // UNUSED 9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int count_to_intervals(int count) { 9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count >= 6); // a single rect is 6 values 9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (count - 4) >> 1; 9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 945803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#endif 9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* Given a number of intervals, what is the worst case representation of that 9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com many intervals? 949fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Worst case (from a storage perspective), is a vertical stack of single 9519c36a76102453db964cb6e51078a3d74d4126b2creed@google.com intervals: TOP + N * (BOTTOM INTERVALCOUNT LEFT RIGHT SENTINEL) + SENTINEL 9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int intervals_to_count(int intervals) { 9549c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return 1 + intervals * 5 + 1; 9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 957af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com/* Given the intervalCounts of RunTypes in two regions, return the worst-case number 9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com of RunTypes need to store the result after a region-op. 9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 960af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.comstatic int compute_worst_case_count(int a_intervals, int b_intervals) { 9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Our heuristic worst case is ai * (bi + 1) + bi * (ai + 1) 9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int intervals = 2 * a_intervals * b_intervals + a_intervals + b_intervals; 9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // convert back to number of RunType values 9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return intervals_to_count(intervals); 9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9677d4aee34e23e536e1115f132d20a20fb629bb66areed@google.comstatic bool setEmptyCheck(SkRegion* result) { 9687d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return result ? result->setEmpty() : false; 9697d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com} 9707d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com 9717d4aee34e23e536e1115f132d20a20fb629bb66areed@google.comstatic bool setRectCheck(SkRegion* result, const SkIRect& rect) { 9727d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return result ? result->setRect(rect) : !rect.isEmpty(); 9737d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com} 9747d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com 9757d4aee34e23e536e1115f132d20a20fb629bb66areed@google.comstatic bool setRegionCheck(SkRegion* result, const SkRegion& rgn) { 9767d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return result ? result->setRegion(rgn) : !rgn.isEmpty(); 9777d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com} 9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9797d4aee34e23e536e1115f132d20a20fb629bb66areed@google.combool SkRegion::Oper(const SkRegion& rgnaOrig, const SkRegion& rgnbOrig, Op op, 9807d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com SkRegion* result) { 9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)op < kOpCount); 982fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 9837d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com if (kReplace_Op == op) { 9847d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return setRegionCheck(result, rgnbOrig); 9857d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 986fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // swith to using pointers, so we can swap them as needed 9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion* rgna = &rgnaOrig; 9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion* rgnb = &rgnbOrig; 9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // after this point, do not refer to rgnaOrig or rgnbOrig!!! 9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // collaps difference and reverse-difference into just difference 9937d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com if (kReverseDifference_Op == op) { 9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap<const SkRegion*>(rgna, rgnb); 9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kDifference_Op; 9968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect bounds; 9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool a_empty = rgna->isEmpty(); 10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool b_empty = rgnb->isEmpty(); 10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool a_rect = rgna->isRect(); 10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool b_rect = rgnb->isRect(); 10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (op) { 10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case kDifference_Op: 10067d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com if (a_empty) { 10077d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return setEmptyCheck(result); 10087d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 10090d10280190c411b18feb569a2248552047d1aa93reed@google.com if (b_empty || !SkIRect::IntersectsNoEmptyCheck(rgna->fBounds, 10100d10280190c411b18feb569a2248552047d1aa93reed@google.com rgnb->fBounds)) { 10117d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return setRegionCheck(result, *rgna); 10127d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 10130d10280190c411b18feb569a2248552047d1aa93reed@google.com if (b_rect && rgnb->fBounds.containsNoEmptyCheck(rgna->fBounds)) { 10140d10280190c411b18feb569a2248552047d1aa93reed@google.com return setEmptyCheck(result); 10150d10280190c411b18feb569a2248552047d1aa93reed@google.com } 10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case kIntersect_Op: 10198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((a_empty | b_empty) 10207d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com || !bounds.intersect(rgna->fBounds, rgnb->fBounds)) { 10217d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return setEmptyCheck(result); 10227d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 10237d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com if (a_rect & b_rect) { 10247d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return setRectCheck(result, bounds); 10257d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 1026633c32b13b5d199d797be669d3dc7981d603a945reed@google.com if (a_rect && rgna->fBounds.contains(rgnb->fBounds)) { 1027633c32b13b5d199d797be669d3dc7981d603a945reed@google.com return setRegionCheck(result, *rgnb); 1028633c32b13b5d199d797be669d3dc7981d603a945reed@google.com } 1029633c32b13b5d199d797be669d3dc7981d603a945reed@google.com if (b_rect && rgnb->fBounds.contains(rgna->fBounds)) { 1030633c32b13b5d199d797be669d3dc7981d603a945reed@google.com return setRegionCheck(result, *rgna); 1031633c32b13b5d199d797be669d3dc7981d603a945reed@google.com } 10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 10338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case kUnion_Op: 10357d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com if (a_empty) { 10367d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return setRegionCheck(result, *rgnb); 10377d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 10387d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com if (b_empty) { 10397d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return setRegionCheck(result, *rgna); 10407d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 10417d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com if (a_rect && rgna->fBounds.contains(rgnb->fBounds)) { 10427d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return setRegionCheck(result, *rgna); 10437d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 10447d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com if (b_rect && rgnb->fBounds.contains(rgna->fBounds)) { 10457d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return setRegionCheck(result, *rgnb); 10467d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case kXOR_Op: 10507d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com if (a_empty) { 10517d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return setRegionCheck(result, *rgnb); 10527d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 10537d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com if (b_empty) { 10547d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return setRegionCheck(result, *rgna); 10557d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 10580c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unknown region op"); 10597d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return false; 10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com RunType tmpA[kRectRegionRuns]; 10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com RunType tmpB[kRectRegionRuns]; 10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1065af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com int a_intervals, b_intervals; 1066af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com const RunType* a_runs = rgna->getRuns(tmpA, &a_intervals); 1067af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com const RunType* b_runs = rgnb->getRuns(tmpB, &b_intervals); 10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1069af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com int dstCount = compute_worst_case_count(a_intervals, b_intervals); 1070af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com SkAutoSTMalloc<256, RunType> array(dstCount); 10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10729c36a76102453db964cb6e51078a3d74d4126b2creed@google.com#ifdef SK_DEBUG 10739c36a76102453db964cb6e51078a3d74d4126b2creed@google.com// Sometimes helpful to seed everything with a known value when debugging 10749c36a76102453db964cb6e51078a3d74d4126b2creed@google.com// sk_memset32((uint32_t*)array.get(), 0x7FFFFFFF, dstCount); 10759c36a76102453db964cb6e51078a3d74d4126b2creed@google.com#endif 10769c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 10777d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com int count = operate(a_runs, b_runs, array.get(), op, NULL == result); 10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count <= dstCount); 1079af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com 10807d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com if (result) { 10817d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com SkASSERT(count >= 0); 10827d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return result->setRuns(array.get(), count); 10837d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } else { 10847d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return (QUICK_EXIT_TRUE_COUNT == count) || !isRunCountEmpty(count); 10857d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com } 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10887d4aee34e23e536e1115f132d20a20fb629bb66areed@google.combool SkRegion::op(const SkRegion& rgna, const SkRegion& rgnb, Op op) { 10897d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com SkDEBUGCODE(this->validate();) 10907d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com return SkRegion::Oper(rgna, rgnb, op, this); 10917d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com} 10927d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com 10937d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com/////////////////////////////////////////////////////////////////////////////// 10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBuffer.h" 10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10974faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.orgsize_t SkRegion::writeToMemory(void* storage) const { 10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == storage) { 10994faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org size_t size = sizeof(int32_t); // -1 (empty), 0 (rect), runCount 11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!this->isEmpty()) { 11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size += sizeof(fBounds); 11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->isComplex()) { 1103af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com size += 2 * sizeof(int32_t); // ySpanCount + intervalCount 11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size += fRunHead->fRunCount * sizeof(RunType); 11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return size; 11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkWBuffer buffer(storage); 11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->isEmpty()) { 11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buffer.write32(-1); 11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool isRect = this->isRect(); 11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buffer.write32(isRect ? 0 : fRunHead->fRunCount); 11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buffer.write(&fBounds, sizeof(fBounds)); 11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!isRect) { 1121af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com buffer.write32(fRunHead->getYSpanCount()); 1122af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com buffer.write32(fRunHead->getIntervalCount()); 11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buffer.write(fRunHead->readonly_runs(), 11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRunHead->fRunCount * sizeof(RunType)); 11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return buffer.pos(); 11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11304faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.orgsize_t SkRegion::readFromMemory(const void* storage, size_t length) { 11314faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org SkRBufferWithSizeCheck buffer(storage, length); 11324faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org SkRegion tmp; 11334faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org int32_t count; 1134382fde3a3c5cb5e8e3dcdc4c549541453851d8d0skia.committer@gmail.com 11358f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org if (buffer.readS32(&count) && (count >= 0) && buffer.read(&tmp.fBounds, sizeof(tmp.fBounds))) { 11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count == 0) { 11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.fRunHead = SkRegion_gRectRunHeadPtr; 11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 11398f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org int32_t ySpanCount, intervalCount; 11408f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org if (buffer.readS32(&ySpanCount) && buffer.readS32(&intervalCount)) { 11414faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org tmp.allocateRuns(count, ySpanCount, intervalCount); 11424faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org buffer.read(tmp.fRunHead->writable_runs(), count * sizeof(RunType)); 11434faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org } 11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11464faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org size_t sizeRead = 0; 11474faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org if (buffer.isValid()) { 11484faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org this->swap(tmp); 11494faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org sizeRead = buffer.pos(); 11504faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org } 11514faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org return sizeRead; 11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11540a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com/////////////////////////////////////////////////////////////////////////////// 11550a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com 11560a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comconst SkRegion& SkRegion::GetEmptyRegion() { 11570a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com static SkRegion gEmpty; 11580a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com return gEmpty; 11590a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com} 11600a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com 11610a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com/////////////////////////////////////////////////////////////////////////////// 11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11659c36a76102453db964cb6e51078a3d74d4126b2creed@google.com// Starts with first X-interval, and returns a ptr to the X-sentinel 11669c36a76102453db964cb6e51078a3d74d4126b2creed@google.comstatic const SkRegion::RunType* skip_intervals_slow(const SkRegion::RunType runs[]) { 11679c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // want to track that our intevals are all disjoint, such that 11689c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // prev-right < next-left. We rely on this optimization in places such as 11699c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // contains(). 11709c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // 11719c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkRegion::RunType prevR = -SkRegion::kRunTypeSentinel; 1172fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 11739c36a76102453db964cb6e51078a3d74d4126b2creed@google.com while (runs[0] < SkRegion::kRunTypeSentinel) { 11749c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(prevR < runs[0]); 11759c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(runs[0] < runs[1]); 11769c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(runs[1] < SkRegion::kRunTypeSentinel); 11779c36a76102453db964cb6e51078a3d74d4126b2creed@google.com prevR = runs[1]; 11789c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 2; 11799c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 11809c36a76102453db964cb6e51078a3d74d4126b2creed@google.com return runs; 11819c36a76102453db964cb6e51078a3d74d4126b2creed@google.com} 11829c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 1183e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.comstatic void compute_bounds(const SkRegion::RunType runs[], 11849c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkIRect* bounds, int* ySpanCountPtr, 11859c36a76102453db964cb6e51078a3d74d4126b2creed@google.com int* intervalCountPtr) { 11869c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(runs[0], false); // top 1187fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 11889c36a76102453db964cb6e51078a3d74d4126b2creed@google.com int left = SK_MaxS32; 11899c36a76102453db964cb6e51078a3d74d4126b2creed@google.com int rite = SK_MinS32; 11909c36a76102453db964cb6e51078a3d74d4126b2creed@google.com int bot; 11919c36a76102453db964cb6e51078a3d74d4126b2creed@google.com int ySpanCount = 0; 11929c36a76102453db964cb6e51078a3d74d4126b2creed@google.com int intervalCount = 0; 1193fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 11949c36a76102453db964cb6e51078a3d74d4126b2creed@google.com bounds->fTop = *runs++; 11959c36a76102453db964cb6e51078a3d74d4126b2creed@google.com do { 11969c36a76102453db964cb6e51078a3d74d4126b2creed@google.com bot = *runs++; 11979c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(SkRegion::kRunTypeSentinel > bot); 11989c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 11999c36a76102453db964cb6e51078a3d74d4126b2creed@google.com ySpanCount += 1; 1200fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 12019c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 1; // skip intervalCount for now 12029c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (*runs < SkRegion::kRunTypeSentinel) { 12039c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (left > *runs) { 12049c36a76102453db964cb6e51078a3d74d4126b2creed@google.com left = *runs; 12059c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 1206fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 12079c36a76102453db964cb6e51078a3d74d4126b2creed@google.com const SkRegion::RunType* prev = runs; 12089c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs = skip_intervals_slow(runs); 1209f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org int intervals = SkToInt((runs - prev) >> 1); 12109c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(prev[-1] == intervals); 12119c36a76102453db964cb6e51078a3d74d4126b2creed@google.com intervalCount += intervals; 1212fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 12139c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (rite < runs[-1]) { 12149c36a76102453db964cb6e51078a3d74d4126b2creed@google.com rite = runs[-1]; 12159c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 12169c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } else { 12179c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(0 == runs[-1]); // no intervals 12189c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 12199c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(SkRegion::kRunTypeSentinel == *runs); 12209c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 1; 12219c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } while (SkRegion::kRunTypeSentinel != *runs); 1222fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 12239c36a76102453db964cb6e51078a3d74d4126b2creed@google.com bounds->fLeft = left; 12249c36a76102453db964cb6e51078a3d74d4126b2creed@google.com bounds->fRight = rite; 12259c36a76102453db964cb6e51078a3d74d4126b2creed@google.com bounds->fBottom = bot; 12269c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *ySpanCountPtr = ySpanCount; 12279c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *intervalCountPtr = intervalCount; 12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1230c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.comvoid SkRegion::validate() const { 1231c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (this->isEmpty()) { 12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check for explicit empty (the zero rect), so we can compare rects to know when 12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // two regions are equal (i.e. emptyRectA == emptyRectB) 12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // this is stricter than just asserting fBounds.isEmpty() 12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fBounds.fLeft == 0 && fBounds.fTop == 0 && fBounds.fRight == 0 && fBounds.fBottom == 0); 1236c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } else { 12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(!fBounds.isEmpty()); 1238c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (!this->isRect()) { 12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fRunHead->fRefCnt >= 1); 12409c36a76102453db964cb6e51078a3d74d4126b2creed@google.com SkASSERT(fRunHead->fRunCount > kRectRegionRuns); 12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const RunType* run = fRunHead->readonly_runs(); 12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // check that our bounds match our runs 12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect bounds; 1247af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com int ySpanCount, intervalCount; 1248e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.com compute_bounds(run, &bounds, &ySpanCount, &intervalCount); 12499c36a76102453db964cb6e51078a3d74d4126b2creed@google.com 12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(bounds == fBounds); 1251af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com SkASSERT(ySpanCount > 0); 1252af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com SkASSERT(fRunHead->getYSpanCount() == ySpanCount); 12539c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // SkASSERT(intervalCount > 1); 1254af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com SkASSERT(fRunHead->getIntervalCount() == intervalCount); 12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1260c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.comvoid SkRegion::dump() const { 1261c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com if (this->isEmpty()) { 12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf(" rgn: empty\n"); 1263c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com } else { 12648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf(" rgn: [%d %d %d %d]", fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom); 12659c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (this->isComplex()) { 12668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const RunType* runs = fRunHead->readonly_runs(); 12678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < fRunHead->fRunCount; i++) 12688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf(" %d", runs[i]); 12698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("\n"); 12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 12758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1276c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com/////////////////////////////////////////////////////////////////////////////// 12778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRegion::Iterator::Iterator(const SkRegion& rgn) { 12798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->reset(rgn); 12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkRegion::Iterator::rewind() { 12838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fRgn) { 12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->reset(*fRgn); 12858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 12868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRegion::Iterator::reset(const SkRegion& rgn) { 12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRgn = &rgn; 12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rgn.isEmpty()) { 12938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = true; 12948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 12958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = false; 12968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rgn.isRect()) { 12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRect = rgn.fBounds; 12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRuns = NULL; 12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRuns = rgn.fRunHead->readonly_runs(); 13019c36a76102453db964cb6e51078a3d74d4126b2creed@google.com fRect.set(fRuns[3], fRuns[0], fRuns[4], fRuns[1]); 13029c36a76102453db964cb6e51078a3d74d4126b2creed@google.com fRuns += 5; 13039c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // Now fRuns points to the 2nd interval (or x-sentinel) 13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRegion::Iterator::next() { 13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDone) { 13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fRuns == NULL) { // rect case 13148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = true; 13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const RunType* runs = fRuns; 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (runs[0] < kRunTypeSentinel) { // valid X value 13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRect.fLeft = runs[0]; 13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRect.fRight = runs[1]; 13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += 2; 13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // we're at the end of a line 13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += 1; 13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (runs[0] < kRunTypeSentinel) { // valid Y value 13279c36a76102453db964cb6e51078a3d74d4126b2creed@google.com int intervals = runs[1]; 13289c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (0 == intervals) { // empty line 13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRect.fTop = runs[0]; 13309c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 3; 13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRect.fTop = fRect.fBottom; 13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1334fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRect.fBottom = runs[0]; 13369c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(runs[2], false); 13379c36a76102453db964cb6e51078a3d74d4126b2creed@google.com assert_sentinel(runs[3], false); 13389c36a76102453db964cb6e51078a3d74d4126b2creed@google.com fRect.fLeft = runs[2]; 13399c36a76102453db964cb6e51078a3d74d4126b2creed@google.com fRect.fRight = runs[3]; 13409c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 4; 13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // end of rgn 13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = true; 13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRuns = runs; 13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRegion::Cliperator::Cliperator(const SkRegion& rgn, const SkIRect& clip) 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fIter(rgn), fClip(clip), fDone(true) { 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& r = fIter.rect(); 13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (!fIter.done()) { 13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (r.fTop >= clip.fBottom) { 13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fRect.intersect(clip, r)) { 13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = false; 13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fIter.next(); 13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRegion::Cliperator::next() { 13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDone) { 13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& r = fIter.rect(); 13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = true; 13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fIter.next(); 13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (!fIter.done()) { 13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (r.fTop >= fClip.fBottom) { 13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fRect.intersect(fClip, r)) { 13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = false; 13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fIter.next(); 13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1385e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com/////////////////////////////////////////////////////////////////////////////// 13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1387e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.comSkRegion::Spanerator::Spanerator(const SkRegion& rgn, int y, int left, 1388e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com int right) { 13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(rgn.validate();) 13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& r = rgn.getBounds(); 13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = true; 1394e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com if (!rgn.isEmpty() && y >= r.fTop && y < r.fBottom && 1395e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com right > r.fLeft && left < r.fRight) { 1396e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com if (rgn.isRect()) { 1397e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com if (left < r.fLeft) { 13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left = r.fLeft; 1399e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com } 1400e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com if (right > r.fRight) { 14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com right = r.fRight; 1402e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com } 14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLeft = left; 14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRight = right; 14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRuns = NULL; // means we're a rect, not a rgn 14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = false; 1407e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com } else { 14089c36a76102453db964cb6e51078a3d74d4126b2creed@google.com const SkRegion::RunType* runs = rgn.fRunHead->findScanline(y); 14099c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 2; // skip Bottom and IntervalCount 14109c36a76102453db964cb6e51078a3d74d4126b2creed@google.com for (;;) { 14119c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // runs[0..1] is to the right of the span, so we're done 14129c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (runs[0] >= right) { 14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14159c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // runs[0..1] is to the left of the span, so continue 14169c36a76102453db964cb6e51078a3d74d4126b2creed@google.com if (runs[1] <= left) { 14179c36a76102453db964cb6e51078a3d74d4126b2creed@google.com runs += 2; 14189c36a76102453db964cb6e51078a3d74d4126b2creed@google.com continue; 14199c36a76102453db964cb6e51078a3d74d4126b2creed@google.com } 14209c36a76102453db964cb6e51078a3d74d4126b2creed@google.com // runs[0..1] intersects the span 14219c36a76102453db964cb6e51078a3d74d4126b2creed@google.com fRuns = runs; 14229c36a76102453db964cb6e51078a3d74d4126b2creed@google.com fLeft = left; 14239c36a76102453db964cb6e51078a3d74d4126b2creed@google.com fRight = right; 14249c36a76102453db964cb6e51078a3d74d4126b2creed@google.com fDone = false; 14259c36a76102453db964cb6e51078a3d74d4126b2creed@google.com break; 14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1431e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.combool SkRegion::Spanerator::next(int* left, int* right) { 1432e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com if (fDone) { 1433e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com return false; 1434e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com } 14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1436e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com if (fRuns == NULL) { // we're a rect 14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = true; // ok, now we're done 1438e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com if (left) { 1439e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com *left = fLeft; 1440e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com } 1441e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com if (right) { 1442e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com *right = fRight; 1443e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com } 14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; // this interval is legal 14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion::RunType* runs = fRuns; 14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1449e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com if (runs[0] >= fRight) { 14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = true; 14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(runs[1] > fLeft); 14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1456e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com if (left) { 14578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *left = SkMax32(fLeft, runs[0]); 1458e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com } 1459e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com if (right) { 14608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *right = SkMin32(fRight, runs[1]); 1461e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com } 14628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRuns = runs + 2; 14638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 14648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkRegion::debugSetRuns(const RunType runs[], int count) { 14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we need to make a copy, since the real method may modify the array, and 14728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // so it cannot be const. 1473fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 14748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoTArray<RunType> storage(count); 14758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(storage.get(), runs, count * sizeof(RunType)); 14768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->setRuns(storage.get(), count); 14778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 1480