1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkRegion.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/private/SkMacros.h" 11cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h" 12cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 13cb93a386Sopenharmony_ci#include "src/core/SkRegionPriv.h" 14cb93a386Sopenharmony_ci#include "src/core/SkSafeMath.h" 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ci#include <utility> 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci/* Region Layout 19cb93a386Sopenharmony_ci * 20cb93a386Sopenharmony_ci * TOP 21cb93a386Sopenharmony_ci * 22cb93a386Sopenharmony_ci * [ Bottom, X-Intervals, [Left, Right]..., X-Sentinel ] 23cb93a386Sopenharmony_ci * ... 24cb93a386Sopenharmony_ci * 25cb93a386Sopenharmony_ci * Y-Sentinel 26cb93a386Sopenharmony_ci */ 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////// 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci#define SkRegion_gEmptyRunHeadPtr ((SkRegionPriv::RunHead*)-1) 31cb93a386Sopenharmony_ci#define SkRegion_gRectRunHeadPtr nullptr 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ciconstexpr int kRunArrayStackCount = 256; 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci// This is a simple data structure which is like a SkSTArray<N,T,true>, except that: 36cb93a386Sopenharmony_ci// - It does not initialize memory. 37cb93a386Sopenharmony_ci// - It does not distinguish between reserved space and initialized space. 38cb93a386Sopenharmony_ci// - resizeToAtLeast() instead of resize() 39cb93a386Sopenharmony_ci// - Uses sk_realloc_throw() 40cb93a386Sopenharmony_ci// - Can never be made smaller. 41cb93a386Sopenharmony_ci// Measurement: for the `region_union_16` benchmark, this is 6% faster. 42cb93a386Sopenharmony_ciclass RunArray { 43cb93a386Sopenharmony_cipublic: 44cb93a386Sopenharmony_ci RunArray() { fPtr = fStack; } 45cb93a386Sopenharmony_ci #ifdef SK_DEBUG 46cb93a386Sopenharmony_ci int count() const { return fCount; } 47cb93a386Sopenharmony_ci #endif 48cb93a386Sopenharmony_ci SkRegionPriv::RunType& operator[](int i) { 49cb93a386Sopenharmony_ci SkASSERT((unsigned)i < (unsigned)fCount); 50cb93a386Sopenharmony_ci return fPtr[i]; 51cb93a386Sopenharmony_ci } 52cb93a386Sopenharmony_ci /** Resize the array to a size greater-than-or-equal-to count. */ 53cb93a386Sopenharmony_ci void resizeToAtLeast(int count) { 54cb93a386Sopenharmony_ci if (count > fCount) { 55cb93a386Sopenharmony_ci // leave at least 50% extra space for future growth. 56cb93a386Sopenharmony_ci count += count >> 1; 57cb93a386Sopenharmony_ci fMalloc.realloc(count); 58cb93a386Sopenharmony_ci if (fPtr == fStack) { 59cb93a386Sopenharmony_ci memcpy(fMalloc.get(), fStack, fCount * sizeof(SkRegionPriv::RunType)); 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci fPtr = fMalloc.get(); 62cb93a386Sopenharmony_ci fCount = count; 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci } 65cb93a386Sopenharmony_ciprivate: 66cb93a386Sopenharmony_ci SkRegionPriv::RunType fStack[kRunArrayStackCount]; 67cb93a386Sopenharmony_ci SkAutoTMalloc<SkRegionPriv::RunType> fMalloc; 68cb93a386Sopenharmony_ci int fCount = kRunArrayStackCount; 69cb93a386Sopenharmony_ci SkRegionPriv::RunType* fPtr; // non-owning pointer 70cb93a386Sopenharmony_ci}; 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci/* Pass in the beginning with the intervals. 73cb93a386Sopenharmony_ci * We back up 1 to read the interval-count. 74cb93a386Sopenharmony_ci * Return the beginning of the next scanline (i.e. the next Y-value) 75cb93a386Sopenharmony_ci */ 76cb93a386Sopenharmony_cistatic SkRegionPriv::RunType* skip_intervals(const SkRegionPriv::RunType runs[]) { 77cb93a386Sopenharmony_ci int intervals = runs[-1]; 78cb93a386Sopenharmony_ci#ifdef SK_DEBUG 79cb93a386Sopenharmony_ci if (intervals > 0) { 80cb93a386Sopenharmony_ci SkASSERT(runs[0] < runs[1]); 81cb93a386Sopenharmony_ci SkASSERT(runs[1] < SkRegion_kRunTypeSentinel); 82cb93a386Sopenharmony_ci } else { 83cb93a386Sopenharmony_ci SkASSERT(0 == intervals); 84cb93a386Sopenharmony_ci SkASSERT(SkRegion_kRunTypeSentinel == runs[0]); 85cb93a386Sopenharmony_ci } 86cb93a386Sopenharmony_ci#endif 87cb93a386Sopenharmony_ci runs += intervals * 2 + 1; 88cb93a386Sopenharmony_ci return const_cast<SkRegionPriv::RunType*>(runs); 89cb93a386Sopenharmony_ci} 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_cibool SkRegion::RunsAreARect(const SkRegion::RunType runs[], int count, 92cb93a386Sopenharmony_ci SkIRect* bounds) { 93cb93a386Sopenharmony_ci assert_sentinel(runs[0], false); // top 94cb93a386Sopenharmony_ci SkASSERT(count >= kRectRegionRuns); 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci if (count == kRectRegionRuns) { 97cb93a386Sopenharmony_ci assert_sentinel(runs[1], false); // bottom 98cb93a386Sopenharmony_ci SkASSERT(1 == runs[2]); 99cb93a386Sopenharmony_ci assert_sentinel(runs[3], false); // left 100cb93a386Sopenharmony_ci assert_sentinel(runs[4], false); // right 101cb93a386Sopenharmony_ci assert_sentinel(runs[5], true); 102cb93a386Sopenharmony_ci assert_sentinel(runs[6], true); 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci SkASSERT(runs[0] < runs[1]); // valid height 105cb93a386Sopenharmony_ci SkASSERT(runs[3] < runs[4]); // valid width 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci bounds->setLTRB(runs[3], runs[0], runs[4], runs[1]); 108cb93a386Sopenharmony_ci return true; 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci return false; 111cb93a386Sopenharmony_ci} 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////// 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_ciSkRegion::SkRegion() { 116cb93a386Sopenharmony_ci fBounds.setEmpty(); 117cb93a386Sopenharmony_ci fRunHead = SkRegion_gEmptyRunHeadPtr; 118cb93a386Sopenharmony_ci} 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ciSkRegion::SkRegion(const SkRegion& src) { 121cb93a386Sopenharmony_ci fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead) 122cb93a386Sopenharmony_ci this->setRegion(src); 123cb93a386Sopenharmony_ci} 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ciSkRegion::SkRegion(const SkIRect& rect) { 126cb93a386Sopenharmony_ci fRunHead = SkRegion_gEmptyRunHeadPtr; // just need a value that won't trigger sk_free(fRunHead) 127cb93a386Sopenharmony_ci this->setRect(rect); 128cb93a386Sopenharmony_ci} 129cb93a386Sopenharmony_ci 130cb93a386Sopenharmony_ciSkRegion::~SkRegion() { 131cb93a386Sopenharmony_ci this->freeRuns(); 132cb93a386Sopenharmony_ci} 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_civoid SkRegion::freeRuns() { 135cb93a386Sopenharmony_ci if (this->isComplex()) { 136cb93a386Sopenharmony_ci SkASSERT(fRunHead->fRefCnt >= 1); 137cb93a386Sopenharmony_ci if (--fRunHead->fRefCnt == 0) { 138cb93a386Sopenharmony_ci sk_free(fRunHead); 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci } 141cb93a386Sopenharmony_ci} 142cb93a386Sopenharmony_ci 143cb93a386Sopenharmony_civoid SkRegion::allocateRuns(int count, int ySpanCount, int intervalCount) { 144cb93a386Sopenharmony_ci fRunHead = RunHead::Alloc(count, ySpanCount, intervalCount); 145cb93a386Sopenharmony_ci} 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_civoid SkRegion::allocateRuns(int count) { 148cb93a386Sopenharmony_ci fRunHead = RunHead::Alloc(count); 149cb93a386Sopenharmony_ci} 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_civoid SkRegion::allocateRuns(const RunHead& head) { 152cb93a386Sopenharmony_ci fRunHead = RunHead::Alloc(head.fRunCount, 153cb93a386Sopenharmony_ci head.getYSpanCount(), 154cb93a386Sopenharmony_ci head.getIntervalCount()); 155cb93a386Sopenharmony_ci} 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_ciSkRegion& SkRegion::operator=(const SkRegion& src) { 158cb93a386Sopenharmony_ci (void)this->setRegion(src); 159cb93a386Sopenharmony_ci return *this; 160cb93a386Sopenharmony_ci} 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_civoid SkRegion::swap(SkRegion& other) { 163cb93a386Sopenharmony_ci using std::swap; 164cb93a386Sopenharmony_ci swap(fBounds, other.fBounds); 165cb93a386Sopenharmony_ci swap(fRunHead, other.fRunHead); 166cb93a386Sopenharmony_ci} 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_ciint SkRegion::computeRegionComplexity() const { 169cb93a386Sopenharmony_ci if (this->isEmpty()) { 170cb93a386Sopenharmony_ci return 0; 171cb93a386Sopenharmony_ci } else if (this->isRect()) { 172cb93a386Sopenharmony_ci return 1; 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci return fRunHead->getIntervalCount(); 175cb93a386Sopenharmony_ci} 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_cibool SkRegion::setEmpty() { 178cb93a386Sopenharmony_ci this->freeRuns(); 179cb93a386Sopenharmony_ci fBounds.setEmpty(); 180cb93a386Sopenharmony_ci fRunHead = SkRegion_gEmptyRunHeadPtr; 181cb93a386Sopenharmony_ci return false; 182cb93a386Sopenharmony_ci} 183cb93a386Sopenharmony_ci 184cb93a386Sopenharmony_cibool SkRegion::setRect(const SkIRect& r) { 185cb93a386Sopenharmony_ci if (r.isEmpty() || 186cb93a386Sopenharmony_ci SkRegion_kRunTypeSentinel == r.right() || 187cb93a386Sopenharmony_ci SkRegion_kRunTypeSentinel == r.bottom()) { 188cb93a386Sopenharmony_ci return this->setEmpty(); 189cb93a386Sopenharmony_ci } 190cb93a386Sopenharmony_ci this->freeRuns(); 191cb93a386Sopenharmony_ci fBounds = r; 192cb93a386Sopenharmony_ci fRunHead = SkRegion_gRectRunHeadPtr; 193cb93a386Sopenharmony_ci return true; 194cb93a386Sopenharmony_ci} 195cb93a386Sopenharmony_ci 196cb93a386Sopenharmony_cibool SkRegion::setRegion(const SkRegion& src) { 197cb93a386Sopenharmony_ci if (this != &src) { 198cb93a386Sopenharmony_ci this->freeRuns(); 199cb93a386Sopenharmony_ci 200cb93a386Sopenharmony_ci fBounds = src.fBounds; 201cb93a386Sopenharmony_ci fRunHead = src.fRunHead; 202cb93a386Sopenharmony_ci if (this->isComplex()) { 203cb93a386Sopenharmony_ci fRunHead->fRefCnt++; 204cb93a386Sopenharmony_ci } 205cb93a386Sopenharmony_ci } 206cb93a386Sopenharmony_ci return fRunHead != SkRegion_gEmptyRunHeadPtr; 207cb93a386Sopenharmony_ci} 208cb93a386Sopenharmony_ci 209cb93a386Sopenharmony_cibool SkRegion::op(const SkIRect& rect, const SkRegion& rgn, Op op) { 210cb93a386Sopenharmony_ci SkRegion tmp(rect); 211cb93a386Sopenharmony_ci 212cb93a386Sopenharmony_ci return this->op(tmp, rgn, op); 213cb93a386Sopenharmony_ci} 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_cibool SkRegion::op(const SkRegion& rgn, const SkIRect& rect, Op op) { 216cb93a386Sopenharmony_ci SkRegion tmp(rect); 217cb93a386Sopenharmony_ci 218cb93a386Sopenharmony_ci return this->op(rgn, tmp, op); 219cb93a386Sopenharmony_ci} 220cb93a386Sopenharmony_ci 221cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 222cb93a386Sopenharmony_ci 223cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 224cb93a386Sopenharmony_ci#include <stdio.h> 225cb93a386Sopenharmony_cichar* SkRegion::toString() { 226cb93a386Sopenharmony_ci Iterator iter(*this); 227cb93a386Sopenharmony_ci int count = 0; 228cb93a386Sopenharmony_ci while (!iter.done()) { 229cb93a386Sopenharmony_ci count++; 230cb93a386Sopenharmony_ci iter.next(); 231cb93a386Sopenharmony_ci } 232cb93a386Sopenharmony_ci // 4 ints, up to 10 digits each plus sign, 3 commas, '(', ')', SkRegion() and '\0' 233cb93a386Sopenharmony_ci const int max = (count*((11*4)+5))+11+1; 234cb93a386Sopenharmony_ci char* result = (char*)sk_malloc_throw(max); 235cb93a386Sopenharmony_ci if (result == nullptr) { 236cb93a386Sopenharmony_ci return nullptr; 237cb93a386Sopenharmony_ci } 238cb93a386Sopenharmony_ci count = snprintf(result, max, "SkRegion("); 239cb93a386Sopenharmony_ci iter.reset(*this); 240cb93a386Sopenharmony_ci while (!iter.done()) { 241cb93a386Sopenharmony_ci const SkIRect& r = iter.rect(); 242cb93a386Sopenharmony_ci count += snprintf(result+count, max - count, 243cb93a386Sopenharmony_ci "(%d,%d,%d,%d)", r.fLeft, r.fTop, r.fRight, r.fBottom); 244cb93a386Sopenharmony_ci iter.next(); 245cb93a386Sopenharmony_ci } 246cb93a386Sopenharmony_ci count += snprintf(result+count, max - count, ")"); 247cb93a386Sopenharmony_ci return result; 248cb93a386Sopenharmony_ci} 249cb93a386Sopenharmony_ci#endif 250cb93a386Sopenharmony_ci 251cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_ciint SkRegion::count_runtype_values(int* itop, int* ibot) const { 254cb93a386Sopenharmony_ci int maxT; 255cb93a386Sopenharmony_ci 256cb93a386Sopenharmony_ci if (this->isRect()) { 257cb93a386Sopenharmony_ci maxT = 2; 258cb93a386Sopenharmony_ci } else { 259cb93a386Sopenharmony_ci SkASSERT(this->isComplex()); 260cb93a386Sopenharmony_ci maxT = fRunHead->getIntervalCount() * 2; 261cb93a386Sopenharmony_ci } 262cb93a386Sopenharmony_ci *itop = fBounds.fTop; 263cb93a386Sopenharmony_ci *ibot = fBounds.fBottom; 264cb93a386Sopenharmony_ci return maxT; 265cb93a386Sopenharmony_ci} 266cb93a386Sopenharmony_ci 267cb93a386Sopenharmony_cistatic bool isRunCountEmpty(int count) { 268cb93a386Sopenharmony_ci return count <= 2; 269cb93a386Sopenharmony_ci} 270cb93a386Sopenharmony_ci 271cb93a386Sopenharmony_cibool SkRegion::setRuns(RunType runs[], int count) { 272cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(*this)); 273cb93a386Sopenharmony_ci SkASSERT(count > 0); 274cb93a386Sopenharmony_ci 275cb93a386Sopenharmony_ci if (isRunCountEmpty(count)) { 276cb93a386Sopenharmony_ci // SkDEBUGF("setRuns: empty\n"); 277cb93a386Sopenharmony_ci assert_sentinel(runs[count-1], true); 278cb93a386Sopenharmony_ci return this->setEmpty(); 279cb93a386Sopenharmony_ci } 280cb93a386Sopenharmony_ci 281cb93a386Sopenharmony_ci // trim off any empty spans from the top and bottom 282cb93a386Sopenharmony_ci // weird I should need this, perhaps op() could be smarter... 283cb93a386Sopenharmony_ci if (count > kRectRegionRuns) { 284cb93a386Sopenharmony_ci RunType* stop = runs + count; 285cb93a386Sopenharmony_ci assert_sentinel(runs[0], false); // top 286cb93a386Sopenharmony_ci assert_sentinel(runs[1], false); // bottom 287cb93a386Sopenharmony_ci // runs[2] is uncomputed intervalCount 288cb93a386Sopenharmony_ci 289cb93a386Sopenharmony_ci if (runs[3] == SkRegion_kRunTypeSentinel) { // should be first left... 290cb93a386Sopenharmony_ci runs += 3; // skip empty initial span 291cb93a386Sopenharmony_ci runs[0] = runs[-2]; // set new top to prev bottom 292cb93a386Sopenharmony_ci assert_sentinel(runs[1], false); // bot: a sentinal would mean two in a row 293cb93a386Sopenharmony_ci assert_sentinel(runs[2], false); // intervalcount 294cb93a386Sopenharmony_ci assert_sentinel(runs[3], false); // left 295cb93a386Sopenharmony_ci assert_sentinel(runs[4], false); // right 296cb93a386Sopenharmony_ci } 297cb93a386Sopenharmony_ci 298cb93a386Sopenharmony_ci assert_sentinel(stop[-1], true); 299cb93a386Sopenharmony_ci assert_sentinel(stop[-2], true); 300cb93a386Sopenharmony_ci 301cb93a386Sopenharmony_ci // now check for a trailing empty span 302cb93a386Sopenharmony_ci if (stop[-5] == SkRegion_kRunTypeSentinel) { // eek, stop[-4] was a bottom with no x-runs 303cb93a386Sopenharmony_ci stop[-4] = SkRegion_kRunTypeSentinel; // kill empty last span 304cb93a386Sopenharmony_ci stop -= 3; 305cb93a386Sopenharmony_ci assert_sentinel(stop[-1], true); // last y-sentinel 306cb93a386Sopenharmony_ci assert_sentinel(stop[-2], true); // last x-sentinel 307cb93a386Sopenharmony_ci assert_sentinel(stop[-3], false); // last right 308cb93a386Sopenharmony_ci assert_sentinel(stop[-4], false); // last left 309cb93a386Sopenharmony_ci assert_sentinel(stop[-5], false); // last interval-count 310cb93a386Sopenharmony_ci assert_sentinel(stop[-6], false); // last bottom 311cb93a386Sopenharmony_ci } 312cb93a386Sopenharmony_ci count = (int)(stop - runs); 313cb93a386Sopenharmony_ci } 314cb93a386Sopenharmony_ci 315cb93a386Sopenharmony_ci SkASSERT(count >= kRectRegionRuns); 316cb93a386Sopenharmony_ci 317cb93a386Sopenharmony_ci if (SkRegion::RunsAreARect(runs, count, &fBounds)) { 318cb93a386Sopenharmony_ci return this->setRect(fBounds); 319cb93a386Sopenharmony_ci } 320cb93a386Sopenharmony_ci 321cb93a386Sopenharmony_ci // if we get here, we need to become a complex region 322cb93a386Sopenharmony_ci 323cb93a386Sopenharmony_ci if (!this->isComplex() || fRunHead->fRunCount != count) { 324cb93a386Sopenharmony_ci this->freeRuns(); 325cb93a386Sopenharmony_ci this->allocateRuns(count); 326cb93a386Sopenharmony_ci SkASSERT(this->isComplex()); 327cb93a386Sopenharmony_ci } 328cb93a386Sopenharmony_ci 329cb93a386Sopenharmony_ci // must call this before we can write directly into runs() 330cb93a386Sopenharmony_ci // in case we are sharing the buffer with another region (copy on write) 331cb93a386Sopenharmony_ci fRunHead = fRunHead->ensureWritable(); 332cb93a386Sopenharmony_ci memcpy(fRunHead->writable_runs(), runs, count * sizeof(RunType)); 333cb93a386Sopenharmony_ci fRunHead->computeRunBounds(&fBounds); 334cb93a386Sopenharmony_ci 335cb93a386Sopenharmony_ci // Our computed bounds might be too large, so we have to check here. 336cb93a386Sopenharmony_ci if (fBounds.isEmpty()) { 337cb93a386Sopenharmony_ci return this->setEmpty(); 338cb93a386Sopenharmony_ci } 339cb93a386Sopenharmony_ci 340cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(*this)); 341cb93a386Sopenharmony_ci 342cb93a386Sopenharmony_ci return true; 343cb93a386Sopenharmony_ci} 344cb93a386Sopenharmony_ci 345cb93a386Sopenharmony_civoid SkRegion::BuildRectRuns(const SkIRect& bounds, 346cb93a386Sopenharmony_ci RunType runs[kRectRegionRuns]) { 347cb93a386Sopenharmony_ci runs[0] = bounds.fTop; 348cb93a386Sopenharmony_ci runs[1] = bounds.fBottom; 349cb93a386Sopenharmony_ci runs[2] = 1; // 1 interval for this scanline 350cb93a386Sopenharmony_ci runs[3] = bounds.fLeft; 351cb93a386Sopenharmony_ci runs[4] = bounds.fRight; 352cb93a386Sopenharmony_ci runs[5] = SkRegion_kRunTypeSentinel; 353cb93a386Sopenharmony_ci runs[6] = SkRegion_kRunTypeSentinel; 354cb93a386Sopenharmony_ci} 355cb93a386Sopenharmony_ci 356cb93a386Sopenharmony_cibool SkRegion::contains(int32_t x, int32_t y) const { 357cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(*this)); 358cb93a386Sopenharmony_ci 359cb93a386Sopenharmony_ci if (!fBounds.contains(x, y)) { 360cb93a386Sopenharmony_ci return false; 361cb93a386Sopenharmony_ci } 362cb93a386Sopenharmony_ci if (this->isRect()) { 363cb93a386Sopenharmony_ci return true; 364cb93a386Sopenharmony_ci } 365cb93a386Sopenharmony_ci SkASSERT(this->isComplex()); 366cb93a386Sopenharmony_ci 367cb93a386Sopenharmony_ci const RunType* runs = fRunHead->findScanline(y); 368cb93a386Sopenharmony_ci 369cb93a386Sopenharmony_ci // Skip the Bottom and IntervalCount 370cb93a386Sopenharmony_ci runs += 2; 371cb93a386Sopenharmony_ci 372cb93a386Sopenharmony_ci // Just walk this scanline, checking each interval. The X-sentinel will 373cb93a386Sopenharmony_ci // appear as a left-inteval (runs[0]) and should abort the search. 374cb93a386Sopenharmony_ci // 375cb93a386Sopenharmony_ci // We could do a bsearch, using interval-count (runs[1]), but need to time 376cb93a386Sopenharmony_ci // when that would be worthwhile. 377cb93a386Sopenharmony_ci // 378cb93a386Sopenharmony_ci for (;;) { 379cb93a386Sopenharmony_ci if (x < runs[0]) { 380cb93a386Sopenharmony_ci break; 381cb93a386Sopenharmony_ci } 382cb93a386Sopenharmony_ci if (x < runs[1]) { 383cb93a386Sopenharmony_ci return true; 384cb93a386Sopenharmony_ci } 385cb93a386Sopenharmony_ci runs += 2; 386cb93a386Sopenharmony_ci } 387cb93a386Sopenharmony_ci return false; 388cb93a386Sopenharmony_ci} 389cb93a386Sopenharmony_ci 390cb93a386Sopenharmony_cistatic SkRegionPriv::RunType scanline_bottom(const SkRegionPriv::RunType runs[]) { 391cb93a386Sopenharmony_ci return runs[0]; 392cb93a386Sopenharmony_ci} 393cb93a386Sopenharmony_ci 394cb93a386Sopenharmony_cistatic const SkRegionPriv::RunType* scanline_next(const SkRegionPriv::RunType runs[]) { 395cb93a386Sopenharmony_ci // skip [B N [L R]... S] 396cb93a386Sopenharmony_ci return runs + 2 + runs[1] * 2 + 1; 397cb93a386Sopenharmony_ci} 398cb93a386Sopenharmony_ci 399cb93a386Sopenharmony_cistatic bool scanline_contains(const SkRegionPriv::RunType runs[], 400cb93a386Sopenharmony_ci SkRegionPriv::RunType L, SkRegionPriv::RunType R) { 401cb93a386Sopenharmony_ci runs += 2; // skip Bottom and IntervalCount 402cb93a386Sopenharmony_ci for (;;) { 403cb93a386Sopenharmony_ci if (L < runs[0]) { 404cb93a386Sopenharmony_ci break; 405cb93a386Sopenharmony_ci } 406cb93a386Sopenharmony_ci if (R <= runs[1]) { 407cb93a386Sopenharmony_ci return true; 408cb93a386Sopenharmony_ci } 409cb93a386Sopenharmony_ci runs += 2; 410cb93a386Sopenharmony_ci } 411cb93a386Sopenharmony_ci return false; 412cb93a386Sopenharmony_ci} 413cb93a386Sopenharmony_ci 414cb93a386Sopenharmony_cibool SkRegion::contains(const SkIRect& r) const { 415cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(*this)); 416cb93a386Sopenharmony_ci 417cb93a386Sopenharmony_ci if (!fBounds.contains(r)) { 418cb93a386Sopenharmony_ci return false; 419cb93a386Sopenharmony_ci } 420cb93a386Sopenharmony_ci if (this->isRect()) { 421cb93a386Sopenharmony_ci return true; 422cb93a386Sopenharmony_ci } 423cb93a386Sopenharmony_ci SkASSERT(this->isComplex()); 424cb93a386Sopenharmony_ci 425cb93a386Sopenharmony_ci const RunType* scanline = fRunHead->findScanline(r.fTop); 426cb93a386Sopenharmony_ci for (;;) { 427cb93a386Sopenharmony_ci if (!scanline_contains(scanline, r.fLeft, r.fRight)) { 428cb93a386Sopenharmony_ci return false; 429cb93a386Sopenharmony_ci } 430cb93a386Sopenharmony_ci if (r.fBottom <= scanline_bottom(scanline)) { 431cb93a386Sopenharmony_ci break; 432cb93a386Sopenharmony_ci } 433cb93a386Sopenharmony_ci scanline = scanline_next(scanline); 434cb93a386Sopenharmony_ci } 435cb93a386Sopenharmony_ci return true; 436cb93a386Sopenharmony_ci} 437cb93a386Sopenharmony_ci 438cb93a386Sopenharmony_cibool SkRegion::contains(const SkRegion& rgn) const { 439cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(*this)); 440cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(rgn)); 441cb93a386Sopenharmony_ci 442cb93a386Sopenharmony_ci if (this->isEmpty() || rgn.isEmpty() || !fBounds.contains(rgn.fBounds)) { 443cb93a386Sopenharmony_ci return false; 444cb93a386Sopenharmony_ci } 445cb93a386Sopenharmony_ci if (this->isRect()) { 446cb93a386Sopenharmony_ci return true; 447cb93a386Sopenharmony_ci } 448cb93a386Sopenharmony_ci if (rgn.isRect()) { 449cb93a386Sopenharmony_ci return this->contains(rgn.getBounds()); 450cb93a386Sopenharmony_ci } 451cb93a386Sopenharmony_ci 452cb93a386Sopenharmony_ci /* 453cb93a386Sopenharmony_ci * A contains B is equivalent to 454cb93a386Sopenharmony_ci * B - A == 0 455cb93a386Sopenharmony_ci */ 456cb93a386Sopenharmony_ci return !Oper(rgn, *this, kDifference_Op, nullptr); 457cb93a386Sopenharmony_ci} 458cb93a386Sopenharmony_ci 459cb93a386Sopenharmony_ciconst SkRegion::RunType* SkRegion::getRuns(RunType tmpStorage[], 460cb93a386Sopenharmony_ci int* intervals) const { 461cb93a386Sopenharmony_ci SkASSERT(tmpStorage && intervals); 462cb93a386Sopenharmony_ci const RunType* runs = tmpStorage; 463cb93a386Sopenharmony_ci 464cb93a386Sopenharmony_ci if (this->isEmpty()) { 465cb93a386Sopenharmony_ci tmpStorage[0] = SkRegion_kRunTypeSentinel; 466cb93a386Sopenharmony_ci *intervals = 0; 467cb93a386Sopenharmony_ci } else if (this->isRect()) { 468cb93a386Sopenharmony_ci BuildRectRuns(fBounds, tmpStorage); 469cb93a386Sopenharmony_ci *intervals = 1; 470cb93a386Sopenharmony_ci } else { 471cb93a386Sopenharmony_ci runs = fRunHead->readonly_runs(); 472cb93a386Sopenharmony_ci *intervals = fRunHead->getIntervalCount(); 473cb93a386Sopenharmony_ci } 474cb93a386Sopenharmony_ci return runs; 475cb93a386Sopenharmony_ci} 476cb93a386Sopenharmony_ci 477cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 478cb93a386Sopenharmony_ci 479cb93a386Sopenharmony_cistatic bool scanline_intersects(const SkRegionPriv::RunType runs[], 480cb93a386Sopenharmony_ci SkRegionPriv::RunType L, SkRegionPriv::RunType R) { 481cb93a386Sopenharmony_ci runs += 2; // skip Bottom and IntervalCount 482cb93a386Sopenharmony_ci for (;;) { 483cb93a386Sopenharmony_ci if (R <= runs[0]) { 484cb93a386Sopenharmony_ci break; 485cb93a386Sopenharmony_ci } 486cb93a386Sopenharmony_ci if (L < runs[1]) { 487cb93a386Sopenharmony_ci return true; 488cb93a386Sopenharmony_ci } 489cb93a386Sopenharmony_ci runs += 2; 490cb93a386Sopenharmony_ci } 491cb93a386Sopenharmony_ci return false; 492cb93a386Sopenharmony_ci} 493cb93a386Sopenharmony_ci 494cb93a386Sopenharmony_cibool SkRegion::intersects(const SkIRect& r) const { 495cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(*this)); 496cb93a386Sopenharmony_ci 497cb93a386Sopenharmony_ci if (this->isEmpty() || r.isEmpty()) { 498cb93a386Sopenharmony_ci return false; 499cb93a386Sopenharmony_ci } 500cb93a386Sopenharmony_ci 501cb93a386Sopenharmony_ci SkIRect sect; 502cb93a386Sopenharmony_ci if (!sect.intersect(fBounds, r)) { 503cb93a386Sopenharmony_ci return false; 504cb93a386Sopenharmony_ci } 505cb93a386Sopenharmony_ci if (this->isRect()) { 506cb93a386Sopenharmony_ci return true; 507cb93a386Sopenharmony_ci } 508cb93a386Sopenharmony_ci SkASSERT(this->isComplex()); 509cb93a386Sopenharmony_ci 510cb93a386Sopenharmony_ci const RunType* scanline = fRunHead->findScanline(sect.fTop); 511cb93a386Sopenharmony_ci for (;;) { 512cb93a386Sopenharmony_ci if (scanline_intersects(scanline, sect.fLeft, sect.fRight)) { 513cb93a386Sopenharmony_ci return true; 514cb93a386Sopenharmony_ci } 515cb93a386Sopenharmony_ci if (sect.fBottom <= scanline_bottom(scanline)) { 516cb93a386Sopenharmony_ci break; 517cb93a386Sopenharmony_ci } 518cb93a386Sopenharmony_ci scanline = scanline_next(scanline); 519cb93a386Sopenharmony_ci } 520cb93a386Sopenharmony_ci return false; 521cb93a386Sopenharmony_ci} 522cb93a386Sopenharmony_ci 523cb93a386Sopenharmony_cibool SkRegion::intersects(const SkRegion& rgn) const { 524cb93a386Sopenharmony_ci if (this->isEmpty() || rgn.isEmpty()) { 525cb93a386Sopenharmony_ci return false; 526cb93a386Sopenharmony_ci } 527cb93a386Sopenharmony_ci 528cb93a386Sopenharmony_ci if (!SkIRect::Intersects(fBounds, rgn.fBounds)) { 529cb93a386Sopenharmony_ci return false; 530cb93a386Sopenharmony_ci } 531cb93a386Sopenharmony_ci 532cb93a386Sopenharmony_ci bool weAreARect = this->isRect(); 533cb93a386Sopenharmony_ci bool theyAreARect = rgn.isRect(); 534cb93a386Sopenharmony_ci 535cb93a386Sopenharmony_ci if (weAreARect && theyAreARect) { 536cb93a386Sopenharmony_ci return true; 537cb93a386Sopenharmony_ci } 538cb93a386Sopenharmony_ci if (weAreARect) { 539cb93a386Sopenharmony_ci return rgn.intersects(this->getBounds()); 540cb93a386Sopenharmony_ci } 541cb93a386Sopenharmony_ci if (theyAreARect) { 542cb93a386Sopenharmony_ci return this->intersects(rgn.getBounds()); 543cb93a386Sopenharmony_ci } 544cb93a386Sopenharmony_ci 545cb93a386Sopenharmony_ci // both of us are complex 546cb93a386Sopenharmony_ci return Oper(*this, rgn, kIntersect_Op, nullptr); 547cb93a386Sopenharmony_ci} 548cb93a386Sopenharmony_ci 549cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 550cb93a386Sopenharmony_ci 551cb93a386Sopenharmony_cibool SkRegion::operator==(const SkRegion& b) const { 552cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(*this)); 553cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(b)); 554cb93a386Sopenharmony_ci 555cb93a386Sopenharmony_ci if (this == &b) { 556cb93a386Sopenharmony_ci return true; 557cb93a386Sopenharmony_ci } 558cb93a386Sopenharmony_ci if (fBounds != b.fBounds) { 559cb93a386Sopenharmony_ci return false; 560cb93a386Sopenharmony_ci } 561cb93a386Sopenharmony_ci 562cb93a386Sopenharmony_ci const SkRegion::RunHead* ah = fRunHead; 563cb93a386Sopenharmony_ci const SkRegion::RunHead* bh = b.fRunHead; 564cb93a386Sopenharmony_ci 565cb93a386Sopenharmony_ci // this catches empties and rects being equal 566cb93a386Sopenharmony_ci if (ah == bh) { 567cb93a386Sopenharmony_ci return true; 568cb93a386Sopenharmony_ci } 569cb93a386Sopenharmony_ci // now we insist that both are complex (but different ptrs) 570cb93a386Sopenharmony_ci if (!this->isComplex() || !b.isComplex()) { 571cb93a386Sopenharmony_ci return false; 572cb93a386Sopenharmony_ci } 573cb93a386Sopenharmony_ci return ah->fRunCount == bh->fRunCount && 574cb93a386Sopenharmony_ci !memcmp(ah->readonly_runs(), bh->readonly_runs(), 575cb93a386Sopenharmony_ci ah->fRunCount * sizeof(SkRegion::RunType)); 576cb93a386Sopenharmony_ci} 577cb93a386Sopenharmony_ci 578cb93a386Sopenharmony_ci// Return a (new) offset such that when applied (+=) to min and max, we don't overflow/underflow 579cb93a386Sopenharmony_cistatic int32_t pin_offset_s32(int32_t min, int32_t max, int32_t offset) { 580cb93a386Sopenharmony_ci SkASSERT(min <= max); 581cb93a386Sopenharmony_ci const int32_t lo = -SK_MaxS32-1, 582cb93a386Sopenharmony_ci hi = +SK_MaxS32; 583cb93a386Sopenharmony_ci if ((int64_t)min + offset < lo) { offset = lo - min; } 584cb93a386Sopenharmony_ci if ((int64_t)max + offset > hi) { offset = hi - max; } 585cb93a386Sopenharmony_ci return offset; 586cb93a386Sopenharmony_ci} 587cb93a386Sopenharmony_ci 588cb93a386Sopenharmony_civoid SkRegion::translate(int dx, int dy, SkRegion* dst) const { 589cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(*this)); 590cb93a386Sopenharmony_ci 591cb93a386Sopenharmony_ci if (nullptr == dst) { 592cb93a386Sopenharmony_ci return; 593cb93a386Sopenharmony_ci } 594cb93a386Sopenharmony_ci if (this->isEmpty()) { 595cb93a386Sopenharmony_ci dst->setEmpty(); 596cb93a386Sopenharmony_ci return; 597cb93a386Sopenharmony_ci } 598cb93a386Sopenharmony_ci // pin dx and dy so we don't overflow our existing bounds 599cb93a386Sopenharmony_ci dx = pin_offset_s32(fBounds.fLeft, fBounds.fRight, dx); 600cb93a386Sopenharmony_ci dy = pin_offset_s32(fBounds.fTop, fBounds.fBottom, dy); 601cb93a386Sopenharmony_ci 602cb93a386Sopenharmony_ci if (this->isRect()) { 603cb93a386Sopenharmony_ci dst->setRect(fBounds.makeOffset(dx, dy)); 604cb93a386Sopenharmony_ci } else { 605cb93a386Sopenharmony_ci if (this == dst) { 606cb93a386Sopenharmony_ci dst->fRunHead = dst->fRunHead->ensureWritable(); 607cb93a386Sopenharmony_ci } else { 608cb93a386Sopenharmony_ci SkRegion tmp; 609cb93a386Sopenharmony_ci tmp.allocateRuns(*fRunHead); 610cb93a386Sopenharmony_ci SkASSERT(tmp.isComplex()); 611cb93a386Sopenharmony_ci tmp.fBounds = fBounds; 612cb93a386Sopenharmony_ci dst->swap(tmp); 613cb93a386Sopenharmony_ci } 614cb93a386Sopenharmony_ci 615cb93a386Sopenharmony_ci dst->fBounds.offset(dx, dy); 616cb93a386Sopenharmony_ci 617cb93a386Sopenharmony_ci const RunType* sruns = fRunHead->readonly_runs(); 618cb93a386Sopenharmony_ci RunType* druns = dst->fRunHead->writable_runs(); 619cb93a386Sopenharmony_ci 620cb93a386Sopenharmony_ci *druns++ = (SkRegion::RunType)(*sruns++ + dy); // top 621cb93a386Sopenharmony_ci for (;;) { 622cb93a386Sopenharmony_ci int bottom = *sruns++; 623cb93a386Sopenharmony_ci if (bottom == SkRegion_kRunTypeSentinel) { 624cb93a386Sopenharmony_ci break; 625cb93a386Sopenharmony_ci } 626cb93a386Sopenharmony_ci *druns++ = (SkRegion::RunType)(bottom + dy); // bottom; 627cb93a386Sopenharmony_ci *druns++ = *sruns++; // copy intervalCount; 628cb93a386Sopenharmony_ci for (;;) { 629cb93a386Sopenharmony_ci int x = *sruns++; 630cb93a386Sopenharmony_ci if (x == SkRegion_kRunTypeSentinel) { 631cb93a386Sopenharmony_ci break; 632cb93a386Sopenharmony_ci } 633cb93a386Sopenharmony_ci *druns++ = (SkRegion::RunType)(x + dx); 634cb93a386Sopenharmony_ci *druns++ = (SkRegion::RunType)(*sruns++ + dx); 635cb93a386Sopenharmony_ci } 636cb93a386Sopenharmony_ci *druns++ = SkRegion_kRunTypeSentinel; // x sentinel 637cb93a386Sopenharmony_ci } 638cb93a386Sopenharmony_ci *druns++ = SkRegion_kRunTypeSentinel; // y sentinel 639cb93a386Sopenharmony_ci 640cb93a386Sopenharmony_ci SkASSERT(sruns - fRunHead->readonly_runs() == fRunHead->fRunCount); 641cb93a386Sopenharmony_ci SkASSERT(druns - dst->fRunHead->readonly_runs() == dst->fRunHead->fRunCount); 642cb93a386Sopenharmony_ci } 643cb93a386Sopenharmony_ci 644cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(*this)); 645cb93a386Sopenharmony_ci} 646cb93a386Sopenharmony_ci 647cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 648cb93a386Sopenharmony_ci 649cb93a386Sopenharmony_cibool SkRegion::setRects(const SkIRect rects[], int count) { 650cb93a386Sopenharmony_ci if (0 == count) { 651cb93a386Sopenharmony_ci this->setEmpty(); 652cb93a386Sopenharmony_ci } else { 653cb93a386Sopenharmony_ci this->setRect(rects[0]); 654cb93a386Sopenharmony_ci for (int i = 1; i < count; i++) { 655cb93a386Sopenharmony_ci this->op(rects[i], kUnion_Op); 656cb93a386Sopenharmony_ci } 657cb93a386Sopenharmony_ci } 658cb93a386Sopenharmony_ci return !this->isEmpty(); 659cb93a386Sopenharmony_ci} 660cb93a386Sopenharmony_ci 661cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 662cb93a386Sopenharmony_ci 663cb93a386Sopenharmony_ci#if defined _WIN32 // disable warning : local variable used without having been initialized 664cb93a386Sopenharmony_ci#pragma warning ( push ) 665cb93a386Sopenharmony_ci#pragma warning ( disable : 4701 ) 666cb93a386Sopenharmony_ci#endif 667cb93a386Sopenharmony_ci 668cb93a386Sopenharmony_ci#ifdef SK_DEBUG 669cb93a386Sopenharmony_cistatic void assert_valid_pair(int left, int rite) 670cb93a386Sopenharmony_ci{ 671cb93a386Sopenharmony_ci SkASSERT(left == SkRegion_kRunTypeSentinel || left < rite); 672cb93a386Sopenharmony_ci} 673cb93a386Sopenharmony_ci#else 674cb93a386Sopenharmony_ci #define assert_valid_pair(left, rite) 675cb93a386Sopenharmony_ci#endif 676cb93a386Sopenharmony_ci 677cb93a386Sopenharmony_cistruct spanRec { 678cb93a386Sopenharmony_ci const SkRegionPriv::RunType* fA_runs; 679cb93a386Sopenharmony_ci const SkRegionPriv::RunType* fB_runs; 680cb93a386Sopenharmony_ci int fA_left, fA_rite, fB_left, fB_rite; 681cb93a386Sopenharmony_ci int fLeft, fRite, fInside; 682cb93a386Sopenharmony_ci 683cb93a386Sopenharmony_ci void init(const SkRegionPriv::RunType a_runs[], 684cb93a386Sopenharmony_ci const SkRegionPriv::RunType b_runs[]) { 685cb93a386Sopenharmony_ci fA_left = *a_runs++; 686cb93a386Sopenharmony_ci fA_rite = *a_runs++; 687cb93a386Sopenharmony_ci fB_left = *b_runs++; 688cb93a386Sopenharmony_ci fB_rite = *b_runs++; 689cb93a386Sopenharmony_ci 690cb93a386Sopenharmony_ci fA_runs = a_runs; 691cb93a386Sopenharmony_ci fB_runs = b_runs; 692cb93a386Sopenharmony_ci } 693cb93a386Sopenharmony_ci 694cb93a386Sopenharmony_ci bool done() const { 695cb93a386Sopenharmony_ci SkASSERT(fA_left <= SkRegion_kRunTypeSentinel); 696cb93a386Sopenharmony_ci SkASSERT(fB_left <= SkRegion_kRunTypeSentinel); 697cb93a386Sopenharmony_ci return fA_left == SkRegion_kRunTypeSentinel && 698cb93a386Sopenharmony_ci fB_left == SkRegion_kRunTypeSentinel; 699cb93a386Sopenharmony_ci } 700cb93a386Sopenharmony_ci 701cb93a386Sopenharmony_ci void next() { 702cb93a386Sopenharmony_ci assert_valid_pair(fA_left, fA_rite); 703cb93a386Sopenharmony_ci assert_valid_pair(fB_left, fB_rite); 704cb93a386Sopenharmony_ci 705cb93a386Sopenharmony_ci int inside, left, rite SK_INIT_TO_AVOID_WARNING; 706cb93a386Sopenharmony_ci bool a_flush = false; 707cb93a386Sopenharmony_ci bool b_flush = false; 708cb93a386Sopenharmony_ci 709cb93a386Sopenharmony_ci int a_left = fA_left; 710cb93a386Sopenharmony_ci int a_rite = fA_rite; 711cb93a386Sopenharmony_ci int b_left = fB_left; 712cb93a386Sopenharmony_ci int b_rite = fB_rite; 713cb93a386Sopenharmony_ci 714cb93a386Sopenharmony_ci if (a_left < b_left) { 715cb93a386Sopenharmony_ci inside = 1; 716cb93a386Sopenharmony_ci left = a_left; 717cb93a386Sopenharmony_ci if (a_rite <= b_left) { // [...] <...> 718cb93a386Sopenharmony_ci rite = a_rite; 719cb93a386Sopenharmony_ci a_flush = true; 720cb93a386Sopenharmony_ci } else { // [...<..]...> or [...<...>...] 721cb93a386Sopenharmony_ci rite = a_left = b_left; 722cb93a386Sopenharmony_ci } 723cb93a386Sopenharmony_ci } else if (b_left < a_left) { 724cb93a386Sopenharmony_ci inside = 2; 725cb93a386Sopenharmony_ci left = b_left; 726cb93a386Sopenharmony_ci if (b_rite <= a_left) { // [...] <...> 727cb93a386Sopenharmony_ci rite = b_rite; 728cb93a386Sopenharmony_ci b_flush = true; 729cb93a386Sopenharmony_ci } else { // [...<..]...> or [...<...>...] 730cb93a386Sopenharmony_ci rite = b_left = a_left; 731cb93a386Sopenharmony_ci } 732cb93a386Sopenharmony_ci } else { // a_left == b_left 733cb93a386Sopenharmony_ci inside = 3; 734cb93a386Sopenharmony_ci left = a_left; // or b_left 735cb93a386Sopenharmony_ci if (a_rite <= b_rite) { 736cb93a386Sopenharmony_ci rite = b_left = a_rite; 737cb93a386Sopenharmony_ci a_flush = true; 738cb93a386Sopenharmony_ci } 739cb93a386Sopenharmony_ci if (b_rite <= a_rite) { 740cb93a386Sopenharmony_ci rite = a_left = b_rite; 741cb93a386Sopenharmony_ci b_flush = true; 742cb93a386Sopenharmony_ci } 743cb93a386Sopenharmony_ci } 744cb93a386Sopenharmony_ci 745cb93a386Sopenharmony_ci if (a_flush) { 746cb93a386Sopenharmony_ci a_left = *fA_runs++; 747cb93a386Sopenharmony_ci a_rite = *fA_runs++; 748cb93a386Sopenharmony_ci } 749cb93a386Sopenharmony_ci if (b_flush) { 750cb93a386Sopenharmony_ci b_left = *fB_runs++; 751cb93a386Sopenharmony_ci b_rite = *fB_runs++; 752cb93a386Sopenharmony_ci } 753cb93a386Sopenharmony_ci 754cb93a386Sopenharmony_ci SkASSERT(left <= rite); 755cb93a386Sopenharmony_ci 756cb93a386Sopenharmony_ci // now update our state 757cb93a386Sopenharmony_ci fA_left = a_left; 758cb93a386Sopenharmony_ci fA_rite = a_rite; 759cb93a386Sopenharmony_ci fB_left = b_left; 760cb93a386Sopenharmony_ci fB_rite = b_rite; 761cb93a386Sopenharmony_ci 762cb93a386Sopenharmony_ci fLeft = left; 763cb93a386Sopenharmony_ci fRite = rite; 764cb93a386Sopenharmony_ci fInside = inside; 765cb93a386Sopenharmony_ci } 766cb93a386Sopenharmony_ci}; 767cb93a386Sopenharmony_ci 768cb93a386Sopenharmony_cistatic int distance_to_sentinel(const SkRegionPriv::RunType* runs) { 769cb93a386Sopenharmony_ci const SkRegionPriv::RunType* ptr = runs; 770cb93a386Sopenharmony_ci while (*ptr != SkRegion_kRunTypeSentinel) { ptr += 2; } 771cb93a386Sopenharmony_ci return ptr - runs; 772cb93a386Sopenharmony_ci} 773cb93a386Sopenharmony_ci 774cb93a386Sopenharmony_cistatic int operate_on_span(const SkRegionPriv::RunType a_runs[], 775cb93a386Sopenharmony_ci const SkRegionPriv::RunType b_runs[], 776cb93a386Sopenharmony_ci RunArray* array, int dstOffset, 777cb93a386Sopenharmony_ci int min, int max) { 778cb93a386Sopenharmony_ci // This is a worst-case for this span plus two for TWO terminating sentinels. 779cb93a386Sopenharmony_ci array->resizeToAtLeast( 780cb93a386Sopenharmony_ci dstOffset + distance_to_sentinel(a_runs) + distance_to_sentinel(b_runs) + 2); 781cb93a386Sopenharmony_ci SkRegionPriv::RunType* dst = &(*array)[dstOffset]; // get pointer AFTER resizing. 782cb93a386Sopenharmony_ci 783cb93a386Sopenharmony_ci spanRec rec; 784cb93a386Sopenharmony_ci bool firstInterval = true; 785cb93a386Sopenharmony_ci 786cb93a386Sopenharmony_ci rec.init(a_runs, b_runs); 787cb93a386Sopenharmony_ci 788cb93a386Sopenharmony_ci while (!rec.done()) { 789cb93a386Sopenharmony_ci rec.next(); 790cb93a386Sopenharmony_ci 791cb93a386Sopenharmony_ci int left = rec.fLeft; 792cb93a386Sopenharmony_ci int rite = rec.fRite; 793cb93a386Sopenharmony_ci 794cb93a386Sopenharmony_ci // add left,rite to our dst buffer (checking for coincidence 795cb93a386Sopenharmony_ci if ((unsigned)(rec.fInside - min) <= (unsigned)(max - min) && 796cb93a386Sopenharmony_ci left < rite) { // skip if equal 797cb93a386Sopenharmony_ci if (firstInterval || *(dst - 1) < left) { 798cb93a386Sopenharmony_ci *dst++ = (SkRegionPriv::RunType)(left); 799cb93a386Sopenharmony_ci *dst++ = (SkRegionPriv::RunType)(rite); 800cb93a386Sopenharmony_ci firstInterval = false; 801cb93a386Sopenharmony_ci } else { 802cb93a386Sopenharmony_ci // update the right edge 803cb93a386Sopenharmony_ci *(dst - 1) = (SkRegionPriv::RunType)(rite); 804cb93a386Sopenharmony_ci } 805cb93a386Sopenharmony_ci } 806cb93a386Sopenharmony_ci } 807cb93a386Sopenharmony_ci SkASSERT(dst < &(*array)[array->count() - 1]); 808cb93a386Sopenharmony_ci *dst++ = SkRegion_kRunTypeSentinel; 809cb93a386Sopenharmony_ci return dst - &(*array)[0]; 810cb93a386Sopenharmony_ci} 811cb93a386Sopenharmony_ci 812cb93a386Sopenharmony_ci#if defined _WIN32 813cb93a386Sopenharmony_ci#pragma warning ( pop ) 814cb93a386Sopenharmony_ci#endif 815cb93a386Sopenharmony_ci 816cb93a386Sopenharmony_cistatic const struct { 817cb93a386Sopenharmony_ci uint8_t fMin; 818cb93a386Sopenharmony_ci uint8_t fMax; 819cb93a386Sopenharmony_ci} gOpMinMax[] = { 820cb93a386Sopenharmony_ci { 1, 1 }, // Difference 821cb93a386Sopenharmony_ci { 3, 3 }, // Intersection 822cb93a386Sopenharmony_ci { 1, 3 }, // Union 823cb93a386Sopenharmony_ci { 1, 2 } // XOR 824cb93a386Sopenharmony_ci}; 825cb93a386Sopenharmony_ci// need to ensure that the op enum lines up with our minmax array 826cb93a386Sopenharmony_cistatic_assert(0 == SkRegion::kDifference_Op, ""); 827cb93a386Sopenharmony_cistatic_assert(1 == SkRegion::kIntersect_Op, ""); 828cb93a386Sopenharmony_cistatic_assert(2 == SkRegion::kUnion_Op, ""); 829cb93a386Sopenharmony_cistatic_assert(3 == SkRegion::kXOR_Op, ""); 830cb93a386Sopenharmony_ci 831cb93a386Sopenharmony_ciclass RgnOper { 832cb93a386Sopenharmony_cipublic: 833cb93a386Sopenharmony_ci RgnOper(int top, RunArray* array, SkRegion::Op op) 834cb93a386Sopenharmony_ci : fMin(gOpMinMax[op].fMin) 835cb93a386Sopenharmony_ci , fMax(gOpMinMax[op].fMax) 836cb93a386Sopenharmony_ci , fArray(array) 837cb93a386Sopenharmony_ci , fTop((SkRegionPriv::RunType)top) // just a first guess, we might update this 838cb93a386Sopenharmony_ci { SkASSERT((unsigned)op <= 3); } 839cb93a386Sopenharmony_ci 840cb93a386Sopenharmony_ci void addSpan(int bottom, const SkRegionPriv::RunType a_runs[], 841cb93a386Sopenharmony_ci const SkRegionPriv::RunType b_runs[]) { 842cb93a386Sopenharmony_ci // skip X values and slots for the next Y+intervalCount 843cb93a386Sopenharmony_ci int start = fPrevDst + fPrevLen + 2; 844cb93a386Sopenharmony_ci // start points to beginning of dst interval 845cb93a386Sopenharmony_ci int stop = operate_on_span(a_runs, b_runs, fArray, start, fMin, fMax); 846cb93a386Sopenharmony_ci size_t len = SkToSizeT(stop - start); 847cb93a386Sopenharmony_ci SkASSERT(len >= 1 && (len & 1) == 1); 848cb93a386Sopenharmony_ci SkASSERT(SkRegion_kRunTypeSentinel == (*fArray)[stop - 1]); 849cb93a386Sopenharmony_ci 850cb93a386Sopenharmony_ci // Assert memcmp won't exceed fArray->count(). 851cb93a386Sopenharmony_ci SkASSERT(fArray->count() >= SkToInt(start + len - 1)); 852cb93a386Sopenharmony_ci if (fPrevLen == len && 853cb93a386Sopenharmony_ci (1 == len || !memcmp(&(*fArray)[fPrevDst], 854cb93a386Sopenharmony_ci &(*fArray)[start], 855cb93a386Sopenharmony_ci (len - 1) * sizeof(SkRegionPriv::RunType)))) { 856cb93a386Sopenharmony_ci // update Y value 857cb93a386Sopenharmony_ci (*fArray)[fPrevDst - 2] = (SkRegionPriv::RunType)bottom; 858cb93a386Sopenharmony_ci } else { // accept the new span 859cb93a386Sopenharmony_ci if (len == 1 && fPrevLen == 0) { 860cb93a386Sopenharmony_ci fTop = (SkRegionPriv::RunType)bottom; // just update our bottom 861cb93a386Sopenharmony_ci } else { 862cb93a386Sopenharmony_ci (*fArray)[start - 2] = (SkRegionPriv::RunType)bottom; 863cb93a386Sopenharmony_ci (*fArray)[start - 1] = SkToS32(len >> 1); 864cb93a386Sopenharmony_ci fPrevDst = start; 865cb93a386Sopenharmony_ci fPrevLen = len; 866cb93a386Sopenharmony_ci } 867cb93a386Sopenharmony_ci } 868cb93a386Sopenharmony_ci } 869cb93a386Sopenharmony_ci 870cb93a386Sopenharmony_ci int flush() { 871cb93a386Sopenharmony_ci (*fArray)[fStartDst] = fTop; 872cb93a386Sopenharmony_ci // Previously reserved enough for TWO sentinals. 873cb93a386Sopenharmony_ci SkASSERT(fArray->count() > SkToInt(fPrevDst + fPrevLen)); 874cb93a386Sopenharmony_ci (*fArray)[fPrevDst + fPrevLen] = SkRegion_kRunTypeSentinel; 875cb93a386Sopenharmony_ci return (int)(fPrevDst - fStartDst + fPrevLen + 1); 876cb93a386Sopenharmony_ci } 877cb93a386Sopenharmony_ci 878cb93a386Sopenharmony_ci bool isEmpty() const { return 0 == fPrevLen; } 879cb93a386Sopenharmony_ci 880cb93a386Sopenharmony_ci uint8_t fMin, fMax; 881cb93a386Sopenharmony_ci 882cb93a386Sopenharmony_ciprivate: 883cb93a386Sopenharmony_ci RunArray* fArray; 884cb93a386Sopenharmony_ci int fStartDst = 0; 885cb93a386Sopenharmony_ci int fPrevDst = 1; 886cb93a386Sopenharmony_ci size_t fPrevLen = 0; // will never match a length from operate_on_span 887cb93a386Sopenharmony_ci SkRegionPriv::RunType fTop; 888cb93a386Sopenharmony_ci}; 889cb93a386Sopenharmony_ci 890cb93a386Sopenharmony_ci// want a unique value to signal that we exited due to quickExit 891cb93a386Sopenharmony_ci#define QUICK_EXIT_TRUE_COUNT (-1) 892cb93a386Sopenharmony_ci 893cb93a386Sopenharmony_cistatic int operate(const SkRegionPriv::RunType a_runs[], 894cb93a386Sopenharmony_ci const SkRegionPriv::RunType b_runs[], 895cb93a386Sopenharmony_ci RunArray* dst, 896cb93a386Sopenharmony_ci SkRegion::Op op, 897cb93a386Sopenharmony_ci bool quickExit) { 898cb93a386Sopenharmony_ci const SkRegionPriv::RunType gEmptyScanline[] = { 899cb93a386Sopenharmony_ci 0, // fake bottom value 900cb93a386Sopenharmony_ci 0, // zero intervals 901cb93a386Sopenharmony_ci SkRegion_kRunTypeSentinel, 902cb93a386Sopenharmony_ci // just need a 2nd value, since spanRec.init() reads 2 values, even 903cb93a386Sopenharmony_ci // though if the first value is the sentinel, it ignores the 2nd value. 904cb93a386Sopenharmony_ci // w/o the 2nd value here, we might read uninitialized memory. 905cb93a386Sopenharmony_ci // This happens when we are using gSentinel, which is pointing at 906cb93a386Sopenharmony_ci // our sentinel value. 907cb93a386Sopenharmony_ci 0 908cb93a386Sopenharmony_ci }; 909cb93a386Sopenharmony_ci const SkRegionPriv::RunType* const gSentinel = &gEmptyScanline[2]; 910cb93a386Sopenharmony_ci 911cb93a386Sopenharmony_ci int a_top = *a_runs++; 912cb93a386Sopenharmony_ci int a_bot = *a_runs++; 913cb93a386Sopenharmony_ci int b_top = *b_runs++; 914cb93a386Sopenharmony_ci int b_bot = *b_runs++; 915cb93a386Sopenharmony_ci 916cb93a386Sopenharmony_ci a_runs += 1; // skip the intervalCount; 917cb93a386Sopenharmony_ci b_runs += 1; // skip the intervalCount; 918cb93a386Sopenharmony_ci 919cb93a386Sopenharmony_ci // Now a_runs and b_runs to their intervals (or sentinel) 920cb93a386Sopenharmony_ci 921cb93a386Sopenharmony_ci assert_sentinel(a_top, false); 922cb93a386Sopenharmony_ci assert_sentinel(a_bot, false); 923cb93a386Sopenharmony_ci assert_sentinel(b_top, false); 924cb93a386Sopenharmony_ci assert_sentinel(b_bot, false); 925cb93a386Sopenharmony_ci 926cb93a386Sopenharmony_ci RgnOper oper(std::min(a_top, b_top), dst, op); 927cb93a386Sopenharmony_ci 928cb93a386Sopenharmony_ci int prevBot = SkRegion_kRunTypeSentinel; // so we fail the first test 929cb93a386Sopenharmony_ci 930cb93a386Sopenharmony_ci while (a_bot < SkRegion_kRunTypeSentinel || 931cb93a386Sopenharmony_ci b_bot < SkRegion_kRunTypeSentinel) { 932cb93a386Sopenharmony_ci int top, bot SK_INIT_TO_AVOID_WARNING; 933cb93a386Sopenharmony_ci const SkRegionPriv::RunType* run0 = gSentinel; 934cb93a386Sopenharmony_ci const SkRegionPriv::RunType* run1 = gSentinel; 935cb93a386Sopenharmony_ci bool a_flush = false; 936cb93a386Sopenharmony_ci bool b_flush = false; 937cb93a386Sopenharmony_ci 938cb93a386Sopenharmony_ci if (a_top < b_top) { 939cb93a386Sopenharmony_ci top = a_top; 940cb93a386Sopenharmony_ci run0 = a_runs; 941cb93a386Sopenharmony_ci if (a_bot <= b_top) { // [...] <...> 942cb93a386Sopenharmony_ci bot = a_bot; 943cb93a386Sopenharmony_ci a_flush = true; 944cb93a386Sopenharmony_ci } else { // [...<..]...> or [...<...>...] 945cb93a386Sopenharmony_ci bot = a_top = b_top; 946cb93a386Sopenharmony_ci } 947cb93a386Sopenharmony_ci } else if (b_top < a_top) { 948cb93a386Sopenharmony_ci top = b_top; 949cb93a386Sopenharmony_ci run1 = b_runs; 950cb93a386Sopenharmony_ci if (b_bot <= a_top) { // [...] <...> 951cb93a386Sopenharmony_ci bot = b_bot; 952cb93a386Sopenharmony_ci b_flush = true; 953cb93a386Sopenharmony_ci } else { // [...<..]...> or [...<...>...] 954cb93a386Sopenharmony_ci bot = b_top = a_top; 955cb93a386Sopenharmony_ci } 956cb93a386Sopenharmony_ci } else { // a_top == b_top 957cb93a386Sopenharmony_ci top = a_top; // or b_top 958cb93a386Sopenharmony_ci run0 = a_runs; 959cb93a386Sopenharmony_ci run1 = b_runs; 960cb93a386Sopenharmony_ci if (a_bot <= b_bot) { 961cb93a386Sopenharmony_ci bot = b_top = a_bot; 962cb93a386Sopenharmony_ci a_flush = true; 963cb93a386Sopenharmony_ci } 964cb93a386Sopenharmony_ci if (b_bot <= a_bot) { 965cb93a386Sopenharmony_ci bot = a_top = b_bot; 966cb93a386Sopenharmony_ci b_flush = true; 967cb93a386Sopenharmony_ci } 968cb93a386Sopenharmony_ci } 969cb93a386Sopenharmony_ci 970cb93a386Sopenharmony_ci if (top > prevBot) { 971cb93a386Sopenharmony_ci oper.addSpan(top, gSentinel, gSentinel); 972cb93a386Sopenharmony_ci } 973cb93a386Sopenharmony_ci oper.addSpan(bot, run0, run1); 974cb93a386Sopenharmony_ci 975cb93a386Sopenharmony_ci if (quickExit && !oper.isEmpty()) { 976cb93a386Sopenharmony_ci return QUICK_EXIT_TRUE_COUNT; 977cb93a386Sopenharmony_ci } 978cb93a386Sopenharmony_ci 979cb93a386Sopenharmony_ci if (a_flush) { 980cb93a386Sopenharmony_ci a_runs = skip_intervals(a_runs); 981cb93a386Sopenharmony_ci a_top = a_bot; 982cb93a386Sopenharmony_ci a_bot = *a_runs++; 983cb93a386Sopenharmony_ci a_runs += 1; // skip uninitialized intervalCount 984cb93a386Sopenharmony_ci if (a_bot == SkRegion_kRunTypeSentinel) { 985cb93a386Sopenharmony_ci a_top = a_bot; 986cb93a386Sopenharmony_ci } 987cb93a386Sopenharmony_ci } 988cb93a386Sopenharmony_ci if (b_flush) { 989cb93a386Sopenharmony_ci b_runs = skip_intervals(b_runs); 990cb93a386Sopenharmony_ci b_top = b_bot; 991cb93a386Sopenharmony_ci b_bot = *b_runs++; 992cb93a386Sopenharmony_ci b_runs += 1; // skip uninitialized intervalCount 993cb93a386Sopenharmony_ci if (b_bot == SkRegion_kRunTypeSentinel) { 994cb93a386Sopenharmony_ci b_top = b_bot; 995cb93a386Sopenharmony_ci } 996cb93a386Sopenharmony_ci } 997cb93a386Sopenharmony_ci 998cb93a386Sopenharmony_ci prevBot = bot; 999cb93a386Sopenharmony_ci } 1000cb93a386Sopenharmony_ci return oper.flush(); 1001cb93a386Sopenharmony_ci} 1002cb93a386Sopenharmony_ci 1003cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1004cb93a386Sopenharmony_ci 1005cb93a386Sopenharmony_ci/* Given count RunTypes in a complex region, return the worst case number of 1006cb93a386Sopenharmony_ci logical intervals that represents (i.e. number of rects that would be 1007cb93a386Sopenharmony_ci returned from the iterator). 1008cb93a386Sopenharmony_ci 1009cb93a386Sopenharmony_ci We could just return count/2, since there must be at least 2 values per 1010cb93a386Sopenharmony_ci interval, but we can first trim off the const overhead of the initial TOP 1011cb93a386Sopenharmony_ci value, plus the final BOTTOM + 2 sentinels. 1012cb93a386Sopenharmony_ci */ 1013cb93a386Sopenharmony_ci#if 0 // UNUSED 1014cb93a386Sopenharmony_cistatic int count_to_intervals(int count) { 1015cb93a386Sopenharmony_ci SkASSERT(count >= 6); // a single rect is 6 values 1016cb93a386Sopenharmony_ci return (count - 4) >> 1; 1017cb93a386Sopenharmony_ci} 1018cb93a386Sopenharmony_ci#endif 1019cb93a386Sopenharmony_ci 1020cb93a386Sopenharmony_cistatic bool setEmptyCheck(SkRegion* result) { 1021cb93a386Sopenharmony_ci return result ? result->setEmpty() : false; 1022cb93a386Sopenharmony_ci} 1023cb93a386Sopenharmony_ci 1024cb93a386Sopenharmony_cistatic bool setRectCheck(SkRegion* result, const SkIRect& rect) { 1025cb93a386Sopenharmony_ci return result ? result->setRect(rect) : !rect.isEmpty(); 1026cb93a386Sopenharmony_ci} 1027cb93a386Sopenharmony_ci 1028cb93a386Sopenharmony_cistatic bool setRegionCheck(SkRegion* result, const SkRegion& rgn) { 1029cb93a386Sopenharmony_ci return result ? result->setRegion(rgn) : !rgn.isEmpty(); 1030cb93a386Sopenharmony_ci} 1031cb93a386Sopenharmony_ci 1032cb93a386Sopenharmony_cibool SkRegion::Oper(const SkRegion& rgnaOrig, const SkRegion& rgnbOrig, Op op, 1033cb93a386Sopenharmony_ci SkRegion* result) { 1034cb93a386Sopenharmony_ci SkASSERT((unsigned)op < kOpCount); 1035cb93a386Sopenharmony_ci 1036cb93a386Sopenharmony_ci if (kReplace_Op == op) { 1037cb93a386Sopenharmony_ci return setRegionCheck(result, rgnbOrig); 1038cb93a386Sopenharmony_ci } 1039cb93a386Sopenharmony_ci 1040cb93a386Sopenharmony_ci // swith to using pointers, so we can swap them as needed 1041cb93a386Sopenharmony_ci const SkRegion* rgna = &rgnaOrig; 1042cb93a386Sopenharmony_ci const SkRegion* rgnb = &rgnbOrig; 1043cb93a386Sopenharmony_ci // after this point, do not refer to rgnaOrig or rgnbOrig!!! 1044cb93a386Sopenharmony_ci 1045cb93a386Sopenharmony_ci // collaps difference and reverse-difference into just difference 1046cb93a386Sopenharmony_ci if (kReverseDifference_Op == op) { 1047cb93a386Sopenharmony_ci using std::swap; 1048cb93a386Sopenharmony_ci swap(rgna, rgnb); 1049cb93a386Sopenharmony_ci op = kDifference_Op; 1050cb93a386Sopenharmony_ci } 1051cb93a386Sopenharmony_ci 1052cb93a386Sopenharmony_ci SkIRect bounds; 1053cb93a386Sopenharmony_ci bool a_empty = rgna->isEmpty(); 1054cb93a386Sopenharmony_ci bool b_empty = rgnb->isEmpty(); 1055cb93a386Sopenharmony_ci bool a_rect = rgna->isRect(); 1056cb93a386Sopenharmony_ci bool b_rect = rgnb->isRect(); 1057cb93a386Sopenharmony_ci 1058cb93a386Sopenharmony_ci switch (op) { 1059cb93a386Sopenharmony_ci case kDifference_Op: 1060cb93a386Sopenharmony_ci if (a_empty) { 1061cb93a386Sopenharmony_ci return setEmptyCheck(result); 1062cb93a386Sopenharmony_ci } 1063cb93a386Sopenharmony_ci if (b_empty || !SkIRect::Intersects(rgna->fBounds, rgnb->fBounds)) { 1064cb93a386Sopenharmony_ci return setRegionCheck(result, *rgna); 1065cb93a386Sopenharmony_ci } 1066cb93a386Sopenharmony_ci if (b_rect && rgnb->fBounds.containsNoEmptyCheck(rgna->fBounds)) { 1067cb93a386Sopenharmony_ci return setEmptyCheck(result); 1068cb93a386Sopenharmony_ci } 1069cb93a386Sopenharmony_ci break; 1070cb93a386Sopenharmony_ci 1071cb93a386Sopenharmony_ci case kIntersect_Op: 1072cb93a386Sopenharmony_ci if ((a_empty | b_empty) 1073cb93a386Sopenharmony_ci || !bounds.intersect(rgna->fBounds, rgnb->fBounds)) { 1074cb93a386Sopenharmony_ci return setEmptyCheck(result); 1075cb93a386Sopenharmony_ci } 1076cb93a386Sopenharmony_ci if (a_rect & b_rect) { 1077cb93a386Sopenharmony_ci return setRectCheck(result, bounds); 1078cb93a386Sopenharmony_ci } 1079cb93a386Sopenharmony_ci if (a_rect && rgna->fBounds.contains(rgnb->fBounds)) { 1080cb93a386Sopenharmony_ci return setRegionCheck(result, *rgnb); 1081cb93a386Sopenharmony_ci } 1082cb93a386Sopenharmony_ci if (b_rect && rgnb->fBounds.contains(rgna->fBounds)) { 1083cb93a386Sopenharmony_ci return setRegionCheck(result, *rgna); 1084cb93a386Sopenharmony_ci } 1085cb93a386Sopenharmony_ci break; 1086cb93a386Sopenharmony_ci 1087cb93a386Sopenharmony_ci case kUnion_Op: 1088cb93a386Sopenharmony_ci if (a_empty) { 1089cb93a386Sopenharmony_ci return setRegionCheck(result, *rgnb); 1090cb93a386Sopenharmony_ci } 1091cb93a386Sopenharmony_ci if (b_empty) { 1092cb93a386Sopenharmony_ci return setRegionCheck(result, *rgna); 1093cb93a386Sopenharmony_ci } 1094cb93a386Sopenharmony_ci if (a_rect && rgna->fBounds.contains(rgnb->fBounds)) { 1095cb93a386Sopenharmony_ci return setRegionCheck(result, *rgna); 1096cb93a386Sopenharmony_ci } 1097cb93a386Sopenharmony_ci if (b_rect && rgnb->fBounds.contains(rgna->fBounds)) { 1098cb93a386Sopenharmony_ci return setRegionCheck(result, *rgnb); 1099cb93a386Sopenharmony_ci } 1100cb93a386Sopenharmony_ci break; 1101cb93a386Sopenharmony_ci 1102cb93a386Sopenharmony_ci case kXOR_Op: 1103cb93a386Sopenharmony_ci if (a_empty) { 1104cb93a386Sopenharmony_ci return setRegionCheck(result, *rgnb); 1105cb93a386Sopenharmony_ci } 1106cb93a386Sopenharmony_ci if (b_empty) { 1107cb93a386Sopenharmony_ci return setRegionCheck(result, *rgna); 1108cb93a386Sopenharmony_ci } 1109cb93a386Sopenharmony_ci break; 1110cb93a386Sopenharmony_ci default: 1111cb93a386Sopenharmony_ci SkDEBUGFAIL("unknown region op"); 1112cb93a386Sopenharmony_ci return false; 1113cb93a386Sopenharmony_ci } 1114cb93a386Sopenharmony_ci 1115cb93a386Sopenharmony_ci RunType tmpA[kRectRegionRuns]; 1116cb93a386Sopenharmony_ci RunType tmpB[kRectRegionRuns]; 1117cb93a386Sopenharmony_ci 1118cb93a386Sopenharmony_ci int a_intervals, b_intervals; 1119cb93a386Sopenharmony_ci const RunType* a_runs = rgna->getRuns(tmpA, &a_intervals); 1120cb93a386Sopenharmony_ci const RunType* b_runs = rgnb->getRuns(tmpB, &b_intervals); 1121cb93a386Sopenharmony_ci 1122cb93a386Sopenharmony_ci RunArray array; 1123cb93a386Sopenharmony_ci int count = operate(a_runs, b_runs, &array, op, nullptr == result); 1124cb93a386Sopenharmony_ci SkASSERT(count <= array.count()); 1125cb93a386Sopenharmony_ci 1126cb93a386Sopenharmony_ci if (result) { 1127cb93a386Sopenharmony_ci SkASSERT(count >= 0); 1128cb93a386Sopenharmony_ci return result->setRuns(&array[0], count); 1129cb93a386Sopenharmony_ci } else { 1130cb93a386Sopenharmony_ci return (QUICK_EXIT_TRUE_COUNT == count) || !isRunCountEmpty(count); 1131cb93a386Sopenharmony_ci } 1132cb93a386Sopenharmony_ci} 1133cb93a386Sopenharmony_ci 1134cb93a386Sopenharmony_cibool SkRegion::op(const SkRegion& rgna, const SkRegion& rgnb, Op op) { 1135cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(*this)); 1136cb93a386Sopenharmony_ci return SkRegion::Oper(rgna, rgnb, op, this); 1137cb93a386Sopenharmony_ci} 1138cb93a386Sopenharmony_ci 1139cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1140cb93a386Sopenharmony_ci 1141cb93a386Sopenharmony_ci#include "src/core/SkBuffer.h" 1142cb93a386Sopenharmony_ci 1143cb93a386Sopenharmony_cisize_t SkRegion::writeToMemory(void* storage) const { 1144cb93a386Sopenharmony_ci if (nullptr == storage) { 1145cb93a386Sopenharmony_ci size_t size = sizeof(int32_t); // -1 (empty), 0 (rect), runCount 1146cb93a386Sopenharmony_ci if (!this->isEmpty()) { 1147cb93a386Sopenharmony_ci size += sizeof(fBounds); 1148cb93a386Sopenharmony_ci if (this->isComplex()) { 1149cb93a386Sopenharmony_ci size += 2 * sizeof(int32_t); // ySpanCount + intervalCount 1150cb93a386Sopenharmony_ci size += fRunHead->fRunCount * sizeof(RunType); 1151cb93a386Sopenharmony_ci } 1152cb93a386Sopenharmony_ci } 1153cb93a386Sopenharmony_ci return size; 1154cb93a386Sopenharmony_ci } 1155cb93a386Sopenharmony_ci 1156cb93a386Sopenharmony_ci SkWBuffer buffer(storage); 1157cb93a386Sopenharmony_ci 1158cb93a386Sopenharmony_ci if (this->isEmpty()) { 1159cb93a386Sopenharmony_ci buffer.write32(-1); 1160cb93a386Sopenharmony_ci } else { 1161cb93a386Sopenharmony_ci bool isRect = this->isRect(); 1162cb93a386Sopenharmony_ci 1163cb93a386Sopenharmony_ci buffer.write32(isRect ? 0 : fRunHead->fRunCount); 1164cb93a386Sopenharmony_ci buffer.write(&fBounds, sizeof(fBounds)); 1165cb93a386Sopenharmony_ci 1166cb93a386Sopenharmony_ci if (!isRect) { 1167cb93a386Sopenharmony_ci buffer.write32(fRunHead->getYSpanCount()); 1168cb93a386Sopenharmony_ci buffer.write32(fRunHead->getIntervalCount()); 1169cb93a386Sopenharmony_ci buffer.write(fRunHead->readonly_runs(), 1170cb93a386Sopenharmony_ci fRunHead->fRunCount * sizeof(RunType)); 1171cb93a386Sopenharmony_ci } 1172cb93a386Sopenharmony_ci } 1173cb93a386Sopenharmony_ci return buffer.pos(); 1174cb93a386Sopenharmony_ci} 1175cb93a386Sopenharmony_ci 1176cb93a386Sopenharmony_cistatic bool validate_run_count(int ySpanCount, int intervalCount, int runCount) { 1177cb93a386Sopenharmony_ci // return 2 + 3 * ySpanCount + 2 * intervalCount; 1178cb93a386Sopenharmony_ci if (ySpanCount < 1 || intervalCount < 2) { 1179cb93a386Sopenharmony_ci return false; 1180cb93a386Sopenharmony_ci } 1181cb93a386Sopenharmony_ci SkSafeMath safeMath; 1182cb93a386Sopenharmony_ci int sum = 2; 1183cb93a386Sopenharmony_ci sum = safeMath.addInt(sum, ySpanCount); 1184cb93a386Sopenharmony_ci sum = safeMath.addInt(sum, ySpanCount); 1185cb93a386Sopenharmony_ci sum = safeMath.addInt(sum, ySpanCount); 1186cb93a386Sopenharmony_ci sum = safeMath.addInt(sum, intervalCount); 1187cb93a386Sopenharmony_ci sum = safeMath.addInt(sum, intervalCount); 1188cb93a386Sopenharmony_ci return safeMath && sum == runCount; 1189cb93a386Sopenharmony_ci} 1190cb93a386Sopenharmony_ci 1191cb93a386Sopenharmony_ci// Validate that a memory sequence is a valid region. 1192cb93a386Sopenharmony_ci// Try to check all possible errors. 1193cb93a386Sopenharmony_ci// never read beyond &runs[runCount-1]. 1194cb93a386Sopenharmony_cistatic bool validate_run(const int32_t* runs, 1195cb93a386Sopenharmony_ci int runCount, 1196cb93a386Sopenharmony_ci const SkIRect& givenBounds, 1197cb93a386Sopenharmony_ci int32_t ySpanCount, 1198cb93a386Sopenharmony_ci int32_t intervalCount) { 1199cb93a386Sopenharmony_ci // Region Layout: 1200cb93a386Sopenharmony_ci // Top ( Bottom Span_Interval_Count ( Left Right )* Sentinel )+ Sentinel 1201cb93a386Sopenharmony_ci if (!validate_run_count(SkToInt(ySpanCount), SkToInt(intervalCount), runCount)) { 1202cb93a386Sopenharmony_ci return false; 1203cb93a386Sopenharmony_ci } 1204cb93a386Sopenharmony_ci SkASSERT(runCount >= 7); // 7==SkRegion::kRectRegionRuns 1205cb93a386Sopenharmony_ci // quick safety check: 1206cb93a386Sopenharmony_ci if (runs[runCount - 1] != SkRegion_kRunTypeSentinel || 1207cb93a386Sopenharmony_ci runs[runCount - 2] != SkRegion_kRunTypeSentinel) { 1208cb93a386Sopenharmony_ci return false; 1209cb93a386Sopenharmony_ci } 1210cb93a386Sopenharmony_ci const int32_t* const end = runs + runCount; 1211cb93a386Sopenharmony_ci SkIRect bounds = {0, 0, 0 ,0}; // calulated bounds 1212cb93a386Sopenharmony_ci SkIRect rect = {0, 0, 0, 0}; // current rect 1213cb93a386Sopenharmony_ci rect.fTop = *runs++; 1214cb93a386Sopenharmony_ci if (rect.fTop == SkRegion_kRunTypeSentinel) { 1215cb93a386Sopenharmony_ci return false; // no rect can contain SkRegion_kRunTypeSentinel 1216cb93a386Sopenharmony_ci } 1217cb93a386Sopenharmony_ci if (rect.fTop != givenBounds.fTop) { 1218cb93a386Sopenharmony_ci return false; // Must not begin with empty span that does not contribute to bounds. 1219cb93a386Sopenharmony_ci } 1220cb93a386Sopenharmony_ci do { 1221cb93a386Sopenharmony_ci --ySpanCount; 1222cb93a386Sopenharmony_ci if (ySpanCount < 0) { 1223cb93a386Sopenharmony_ci return false; // too many yspans 1224cb93a386Sopenharmony_ci } 1225cb93a386Sopenharmony_ci rect.fBottom = *runs++; 1226cb93a386Sopenharmony_ci if (rect.fBottom == SkRegion_kRunTypeSentinel) { 1227cb93a386Sopenharmony_ci return false; 1228cb93a386Sopenharmony_ci } 1229cb93a386Sopenharmony_ci if (rect.fBottom > givenBounds.fBottom) { 1230cb93a386Sopenharmony_ci return false; // Must not end with empty span that does not contribute to bounds. 1231cb93a386Sopenharmony_ci } 1232cb93a386Sopenharmony_ci if (rect.fBottom <= rect.fTop) { 1233cb93a386Sopenharmony_ci return false; // y-intervals must be ordered; rects must be non-empty. 1234cb93a386Sopenharmony_ci } 1235cb93a386Sopenharmony_ci 1236cb93a386Sopenharmony_ci int32_t xIntervals = *runs++; 1237cb93a386Sopenharmony_ci SkASSERT(runs < end); 1238cb93a386Sopenharmony_ci if (xIntervals < 0 || xIntervals > intervalCount || runs + 1 + 2 * xIntervals > end) { 1239cb93a386Sopenharmony_ci return false; 1240cb93a386Sopenharmony_ci } 1241cb93a386Sopenharmony_ci intervalCount -= xIntervals; 1242cb93a386Sopenharmony_ci bool firstInterval = true; 1243cb93a386Sopenharmony_ci int32_t lastRight = 0; // check that x-intervals are distinct and ordered. 1244cb93a386Sopenharmony_ci while (xIntervals-- > 0) { 1245cb93a386Sopenharmony_ci rect.fLeft = *runs++; 1246cb93a386Sopenharmony_ci rect.fRight = *runs++; 1247cb93a386Sopenharmony_ci if (rect.fLeft == SkRegion_kRunTypeSentinel || 1248cb93a386Sopenharmony_ci rect.fRight == SkRegion_kRunTypeSentinel || 1249cb93a386Sopenharmony_ci rect.fLeft >= rect.fRight || // check non-empty rect 1250cb93a386Sopenharmony_ci (!firstInterval && rect.fLeft <= lastRight)) { 1251cb93a386Sopenharmony_ci return false; 1252cb93a386Sopenharmony_ci } 1253cb93a386Sopenharmony_ci lastRight = rect.fRight; 1254cb93a386Sopenharmony_ci firstInterval = false; 1255cb93a386Sopenharmony_ci bounds.join(rect); 1256cb93a386Sopenharmony_ci } 1257cb93a386Sopenharmony_ci if (*runs++ != SkRegion_kRunTypeSentinel) { 1258cb93a386Sopenharmony_ci return false; // required check sentinal. 1259cb93a386Sopenharmony_ci } 1260cb93a386Sopenharmony_ci rect.fTop = rect.fBottom; 1261cb93a386Sopenharmony_ci SkASSERT(runs < end); 1262cb93a386Sopenharmony_ci } while (*runs != SkRegion_kRunTypeSentinel); 1263cb93a386Sopenharmony_ci ++runs; 1264cb93a386Sopenharmony_ci if (ySpanCount != 0 || intervalCount != 0 || givenBounds != bounds) { 1265cb93a386Sopenharmony_ci return false; 1266cb93a386Sopenharmony_ci } 1267cb93a386Sopenharmony_ci SkASSERT(runs == end); // if ySpanCount && intervalCount are right, must be correct length. 1268cb93a386Sopenharmony_ci return true; 1269cb93a386Sopenharmony_ci} 1270cb93a386Sopenharmony_cisize_t SkRegion::readFromMemory(const void* storage, size_t length) { 1271cb93a386Sopenharmony_ci SkRBuffer buffer(storage, length); 1272cb93a386Sopenharmony_ci SkRegion tmp; 1273cb93a386Sopenharmony_ci int32_t count; 1274cb93a386Sopenharmony_ci 1275cb93a386Sopenharmony_ci // Serialized Region Format: 1276cb93a386Sopenharmony_ci // Empty: 1277cb93a386Sopenharmony_ci // -1 1278cb93a386Sopenharmony_ci // Simple Rect: 1279cb93a386Sopenharmony_ci // 0 LEFT TOP RIGHT BOTTOM 1280cb93a386Sopenharmony_ci // Complex Region: 1281cb93a386Sopenharmony_ci // COUNT LEFT TOP RIGHT BOTTOM Y_SPAN_COUNT TOTAL_INTERVAL_COUNT [RUNS....] 1282cb93a386Sopenharmony_ci if (!buffer.readS32(&count) || count < -1) { 1283cb93a386Sopenharmony_ci return 0; 1284cb93a386Sopenharmony_ci } 1285cb93a386Sopenharmony_ci if (count >= 0) { 1286cb93a386Sopenharmony_ci if (!buffer.read(&tmp.fBounds, sizeof(tmp.fBounds)) || tmp.fBounds.isEmpty()) { 1287cb93a386Sopenharmony_ci return 0; // Short buffer or bad bounds for non-empty region; report failure. 1288cb93a386Sopenharmony_ci } 1289cb93a386Sopenharmony_ci if (count == 0) { 1290cb93a386Sopenharmony_ci tmp.fRunHead = SkRegion_gRectRunHeadPtr; 1291cb93a386Sopenharmony_ci } else { 1292cb93a386Sopenharmony_ci int32_t ySpanCount, intervalCount; 1293cb93a386Sopenharmony_ci if (!buffer.readS32(&ySpanCount) || 1294cb93a386Sopenharmony_ci !buffer.readS32(&intervalCount) || 1295cb93a386Sopenharmony_ci buffer.available() < count * sizeof(int32_t)) { 1296cb93a386Sopenharmony_ci return 0; 1297cb93a386Sopenharmony_ci } 1298cb93a386Sopenharmony_ci if (!validate_run((const int32_t*)((const char*)storage + buffer.pos()), count, 1299cb93a386Sopenharmony_ci tmp.fBounds, ySpanCount, intervalCount)) { 1300cb93a386Sopenharmony_ci return 0; // invalid runs, don't even allocate 1301cb93a386Sopenharmony_ci } 1302cb93a386Sopenharmony_ci tmp.allocateRuns(count, ySpanCount, intervalCount); 1303cb93a386Sopenharmony_ci SkASSERT(tmp.isComplex()); 1304cb93a386Sopenharmony_ci SkAssertResult(buffer.read(tmp.fRunHead->writable_runs(), count * sizeof(int32_t))); 1305cb93a386Sopenharmony_ci } 1306cb93a386Sopenharmony_ci } 1307cb93a386Sopenharmony_ci SkASSERT(tmp.isValid()); 1308cb93a386Sopenharmony_ci SkASSERT(buffer.isValid()); 1309cb93a386Sopenharmony_ci this->swap(tmp); 1310cb93a386Sopenharmony_ci return buffer.pos(); 1311cb93a386Sopenharmony_ci} 1312cb93a386Sopenharmony_ci 1313cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1314cb93a386Sopenharmony_ci 1315cb93a386Sopenharmony_cibool SkRegion::isValid() const { 1316cb93a386Sopenharmony_ci if (this->isEmpty()) { 1317cb93a386Sopenharmony_ci return fBounds == SkIRect{0, 0, 0, 0}; 1318cb93a386Sopenharmony_ci } 1319cb93a386Sopenharmony_ci if (fBounds.isEmpty()) { 1320cb93a386Sopenharmony_ci return false; 1321cb93a386Sopenharmony_ci } 1322cb93a386Sopenharmony_ci if (this->isRect()) { 1323cb93a386Sopenharmony_ci return true; 1324cb93a386Sopenharmony_ci } 1325cb93a386Sopenharmony_ci return fRunHead && fRunHead->fRefCnt > 0 && 1326cb93a386Sopenharmony_ci validate_run(fRunHead->readonly_runs(), fRunHead->fRunCount, fBounds, 1327cb93a386Sopenharmony_ci fRunHead->getYSpanCount(), fRunHead->getIntervalCount()); 1328cb93a386Sopenharmony_ci} 1329cb93a386Sopenharmony_ci 1330cb93a386Sopenharmony_civoid SkRegion::dump(std::string& desc, int depth) const { 1331cb93a386Sopenharmony_ci std::string split(depth, '\t'); 1332cb93a386Sopenharmony_ci desc += split + "\n SkRegion:{ \n"; 1333cb93a386Sopenharmony_ci if (this->isEmpty()) { 1334cb93a386Sopenharmony_ci desc += split + " rgn: empty\n"; 1335cb93a386Sopenharmony_ci } else { 1336cb93a386Sopenharmony_ci desc += split + " rgn:\n"; 1337cb93a386Sopenharmony_ci desc += split + "\t fBounds.fLeft:" + std::to_string(fBounds.fLeft) + "\n"; 1338cb93a386Sopenharmony_ci desc += split + "\t fBounds.fTop:" + std::to_string(fBounds.fTop) + "\n"; 1339cb93a386Sopenharmony_ci desc += split + "\t fBounds.fRight:" + std::to_string(fBounds.fRight) + "\n"; 1340cb93a386Sopenharmony_ci desc += split + "\t fBounds.fBottom:" + std::to_string(fBounds.fBottom) + "\n"; 1341cb93a386Sopenharmony_ci 1342cb93a386Sopenharmony_ci if (this->isComplex()) { 1343cb93a386Sopenharmony_ci desc += split + "\t fRunHead->readonly_runs():"; 1344cb93a386Sopenharmony_ci const RunType* runs = fRunHead->readonly_runs(); 1345cb93a386Sopenharmony_ci for (int i = 0; i < fRunHead->fRunCount; i++) { 1346cb93a386Sopenharmony_ci desc += " " + std::to_string(runs[i]); 1347cb93a386Sopenharmony_ci } 1348cb93a386Sopenharmony_ci desc += "\n"; 1349cb93a386Sopenharmony_ci } 1350cb93a386Sopenharmony_ci } 1351cb93a386Sopenharmony_ci desc += split + "}\n"; 1352cb93a386Sopenharmony_ci} 1353cb93a386Sopenharmony_ci 1354cb93a386Sopenharmony_ci#ifdef SK_DEBUG 1355cb93a386Sopenharmony_civoid SkRegionPriv::Validate(const SkRegion& rgn) { SkASSERT(rgn.isValid()); } 1356cb93a386Sopenharmony_ci 1357cb93a386Sopenharmony_civoid SkRegion::dump() const { 1358cb93a386Sopenharmony_ci if (this->isEmpty()) { 1359cb93a386Sopenharmony_ci SkDebugf(" rgn: empty\n"); 1360cb93a386Sopenharmony_ci } else { 1361cb93a386Sopenharmony_ci SkDebugf(" rgn: [%d %d %d %d]", fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom); 1362cb93a386Sopenharmony_ci if (this->isComplex()) { 1363cb93a386Sopenharmony_ci const RunType* runs = fRunHead->readonly_runs(); 1364cb93a386Sopenharmony_ci for (int i = 0; i < fRunHead->fRunCount; i++) 1365cb93a386Sopenharmony_ci SkDebugf(" %d", runs[i]); 1366cb93a386Sopenharmony_ci } 1367cb93a386Sopenharmony_ci SkDebugf("\n"); 1368cb93a386Sopenharmony_ci } 1369cb93a386Sopenharmony_ci} 1370cb93a386Sopenharmony_ci 1371cb93a386Sopenharmony_ci#endif 1372cb93a386Sopenharmony_ci 1373cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1374cb93a386Sopenharmony_ci 1375cb93a386Sopenharmony_ciSkRegion::Iterator::Iterator(const SkRegion& rgn) { 1376cb93a386Sopenharmony_ci this->reset(rgn); 1377cb93a386Sopenharmony_ci} 1378cb93a386Sopenharmony_ci 1379cb93a386Sopenharmony_cibool SkRegion::Iterator::rewind() { 1380cb93a386Sopenharmony_ci if (fRgn) { 1381cb93a386Sopenharmony_ci this->reset(*fRgn); 1382cb93a386Sopenharmony_ci return true; 1383cb93a386Sopenharmony_ci } 1384cb93a386Sopenharmony_ci return false; 1385cb93a386Sopenharmony_ci} 1386cb93a386Sopenharmony_ci 1387cb93a386Sopenharmony_civoid SkRegion::Iterator::reset(const SkRegion& rgn) { 1388cb93a386Sopenharmony_ci fRgn = &rgn; 1389cb93a386Sopenharmony_ci if (rgn.isEmpty()) { 1390cb93a386Sopenharmony_ci fDone = true; 1391cb93a386Sopenharmony_ci } else { 1392cb93a386Sopenharmony_ci fDone = false; 1393cb93a386Sopenharmony_ci if (rgn.isRect()) { 1394cb93a386Sopenharmony_ci fRect = rgn.fBounds; 1395cb93a386Sopenharmony_ci fRuns = nullptr; 1396cb93a386Sopenharmony_ci } else { 1397cb93a386Sopenharmony_ci fRuns = rgn.fRunHead->readonly_runs(); 1398cb93a386Sopenharmony_ci fRect.setLTRB(fRuns[3], fRuns[0], fRuns[4], fRuns[1]); 1399cb93a386Sopenharmony_ci fRuns += 5; 1400cb93a386Sopenharmony_ci // Now fRuns points to the 2nd interval (or x-sentinel) 1401cb93a386Sopenharmony_ci } 1402cb93a386Sopenharmony_ci } 1403cb93a386Sopenharmony_ci} 1404cb93a386Sopenharmony_ci 1405cb93a386Sopenharmony_civoid SkRegion::Iterator::next() { 1406cb93a386Sopenharmony_ci if (fDone) { 1407cb93a386Sopenharmony_ci return; 1408cb93a386Sopenharmony_ci } 1409cb93a386Sopenharmony_ci 1410cb93a386Sopenharmony_ci if (fRuns == nullptr) { // rect case 1411cb93a386Sopenharmony_ci fDone = true; 1412cb93a386Sopenharmony_ci return; 1413cb93a386Sopenharmony_ci } 1414cb93a386Sopenharmony_ci 1415cb93a386Sopenharmony_ci const RunType* runs = fRuns; 1416cb93a386Sopenharmony_ci 1417cb93a386Sopenharmony_ci if (runs[0] < SkRegion_kRunTypeSentinel) { // valid X value 1418cb93a386Sopenharmony_ci fRect.fLeft = runs[0]; 1419cb93a386Sopenharmony_ci fRect.fRight = runs[1]; 1420cb93a386Sopenharmony_ci runs += 2; 1421cb93a386Sopenharmony_ci } else { // we're at the end of a line 1422cb93a386Sopenharmony_ci runs += 1; 1423cb93a386Sopenharmony_ci if (runs[0] < SkRegion_kRunTypeSentinel) { // valid Y value 1424cb93a386Sopenharmony_ci int intervals = runs[1]; 1425cb93a386Sopenharmony_ci if (0 == intervals) { // empty line 1426cb93a386Sopenharmony_ci fRect.fTop = runs[0]; 1427cb93a386Sopenharmony_ci runs += 3; 1428cb93a386Sopenharmony_ci } else { 1429cb93a386Sopenharmony_ci fRect.fTop = fRect.fBottom; 1430cb93a386Sopenharmony_ci } 1431cb93a386Sopenharmony_ci 1432cb93a386Sopenharmony_ci fRect.fBottom = runs[0]; 1433cb93a386Sopenharmony_ci assert_sentinel(runs[2], false); 1434cb93a386Sopenharmony_ci assert_sentinel(runs[3], false); 1435cb93a386Sopenharmony_ci fRect.fLeft = runs[2]; 1436cb93a386Sopenharmony_ci fRect.fRight = runs[3]; 1437cb93a386Sopenharmony_ci runs += 4; 1438cb93a386Sopenharmony_ci } else { // end of rgn 1439cb93a386Sopenharmony_ci fDone = true; 1440cb93a386Sopenharmony_ci } 1441cb93a386Sopenharmony_ci } 1442cb93a386Sopenharmony_ci fRuns = runs; 1443cb93a386Sopenharmony_ci} 1444cb93a386Sopenharmony_ci 1445cb93a386Sopenharmony_ciSkRegion::Cliperator::Cliperator(const SkRegion& rgn, const SkIRect& clip) 1446cb93a386Sopenharmony_ci : fIter(rgn), fClip(clip), fDone(true) { 1447cb93a386Sopenharmony_ci const SkIRect& r = fIter.rect(); 1448cb93a386Sopenharmony_ci 1449cb93a386Sopenharmony_ci while (!fIter.done()) { 1450cb93a386Sopenharmony_ci if (r.fTop >= clip.fBottom) { 1451cb93a386Sopenharmony_ci break; 1452cb93a386Sopenharmony_ci } 1453cb93a386Sopenharmony_ci if (fRect.intersect(clip, r)) { 1454cb93a386Sopenharmony_ci fDone = false; 1455cb93a386Sopenharmony_ci break; 1456cb93a386Sopenharmony_ci } 1457cb93a386Sopenharmony_ci fIter.next(); 1458cb93a386Sopenharmony_ci } 1459cb93a386Sopenharmony_ci} 1460cb93a386Sopenharmony_ci 1461cb93a386Sopenharmony_civoid SkRegion::Cliperator::next() { 1462cb93a386Sopenharmony_ci if (fDone) { 1463cb93a386Sopenharmony_ci return; 1464cb93a386Sopenharmony_ci } 1465cb93a386Sopenharmony_ci 1466cb93a386Sopenharmony_ci const SkIRect& r = fIter.rect(); 1467cb93a386Sopenharmony_ci 1468cb93a386Sopenharmony_ci fDone = true; 1469cb93a386Sopenharmony_ci fIter.next(); 1470cb93a386Sopenharmony_ci while (!fIter.done()) { 1471cb93a386Sopenharmony_ci if (r.fTop >= fClip.fBottom) { 1472cb93a386Sopenharmony_ci break; 1473cb93a386Sopenharmony_ci } 1474cb93a386Sopenharmony_ci if (fRect.intersect(fClip, r)) { 1475cb93a386Sopenharmony_ci fDone = false; 1476cb93a386Sopenharmony_ci break; 1477cb93a386Sopenharmony_ci } 1478cb93a386Sopenharmony_ci fIter.next(); 1479cb93a386Sopenharmony_ci } 1480cb93a386Sopenharmony_ci} 1481cb93a386Sopenharmony_ci 1482cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////// 1483cb93a386Sopenharmony_ci 1484cb93a386Sopenharmony_ciSkRegion::Spanerator::Spanerator(const SkRegion& rgn, int y, int left, 1485cb93a386Sopenharmony_ci int right) { 1486cb93a386Sopenharmony_ci SkDEBUGCODE(SkRegionPriv::Validate(rgn)); 1487cb93a386Sopenharmony_ci 1488cb93a386Sopenharmony_ci const SkIRect& r = rgn.getBounds(); 1489cb93a386Sopenharmony_ci 1490cb93a386Sopenharmony_ci fDone = true; 1491cb93a386Sopenharmony_ci if (!rgn.isEmpty() && y >= r.fTop && y < r.fBottom && 1492cb93a386Sopenharmony_ci right > r.fLeft && left < r.fRight) { 1493cb93a386Sopenharmony_ci if (rgn.isRect()) { 1494cb93a386Sopenharmony_ci if (left < r.fLeft) { 1495cb93a386Sopenharmony_ci left = r.fLeft; 1496cb93a386Sopenharmony_ci } 1497cb93a386Sopenharmony_ci if (right > r.fRight) { 1498cb93a386Sopenharmony_ci right = r.fRight; 1499cb93a386Sopenharmony_ci } 1500cb93a386Sopenharmony_ci fLeft = left; 1501cb93a386Sopenharmony_ci fRight = right; 1502cb93a386Sopenharmony_ci fRuns = nullptr; // means we're a rect, not a rgn 1503cb93a386Sopenharmony_ci fDone = false; 1504cb93a386Sopenharmony_ci } else { 1505cb93a386Sopenharmony_ci const SkRegion::RunType* runs = rgn.fRunHead->findScanline(y); 1506cb93a386Sopenharmony_ci runs += 2; // skip Bottom and IntervalCount 1507cb93a386Sopenharmony_ci for (;;) { 1508cb93a386Sopenharmony_ci // runs[0..1] is to the right of the span, so we're done 1509cb93a386Sopenharmony_ci if (runs[0] >= right) { 1510cb93a386Sopenharmony_ci break; 1511cb93a386Sopenharmony_ci } 1512cb93a386Sopenharmony_ci // runs[0..1] is to the left of the span, so continue 1513cb93a386Sopenharmony_ci if (runs[1] <= left) { 1514cb93a386Sopenharmony_ci runs += 2; 1515cb93a386Sopenharmony_ci continue; 1516cb93a386Sopenharmony_ci } 1517cb93a386Sopenharmony_ci // runs[0..1] intersects the span 1518cb93a386Sopenharmony_ci fRuns = runs; 1519cb93a386Sopenharmony_ci fLeft = left; 1520cb93a386Sopenharmony_ci fRight = right; 1521cb93a386Sopenharmony_ci fDone = false; 1522cb93a386Sopenharmony_ci break; 1523cb93a386Sopenharmony_ci } 1524cb93a386Sopenharmony_ci } 1525cb93a386Sopenharmony_ci } 1526cb93a386Sopenharmony_ci} 1527cb93a386Sopenharmony_ci 1528cb93a386Sopenharmony_cibool SkRegion::Spanerator::next(int* left, int* right) { 1529cb93a386Sopenharmony_ci if (fDone) { 1530cb93a386Sopenharmony_ci return false; 1531cb93a386Sopenharmony_ci } 1532cb93a386Sopenharmony_ci 1533cb93a386Sopenharmony_ci if (fRuns == nullptr) { // we're a rect 1534cb93a386Sopenharmony_ci fDone = true; // ok, now we're done 1535cb93a386Sopenharmony_ci if (left) { 1536cb93a386Sopenharmony_ci *left = fLeft; 1537cb93a386Sopenharmony_ci } 1538cb93a386Sopenharmony_ci if (right) { 1539cb93a386Sopenharmony_ci *right = fRight; 1540cb93a386Sopenharmony_ci } 1541cb93a386Sopenharmony_ci return true; // this interval is legal 1542cb93a386Sopenharmony_ci } 1543cb93a386Sopenharmony_ci 1544cb93a386Sopenharmony_ci const SkRegion::RunType* runs = fRuns; 1545cb93a386Sopenharmony_ci 1546cb93a386Sopenharmony_ci if (runs[0] >= fRight) { 1547cb93a386Sopenharmony_ci fDone = true; 1548cb93a386Sopenharmony_ci return false; 1549cb93a386Sopenharmony_ci } 1550cb93a386Sopenharmony_ci 1551cb93a386Sopenharmony_ci SkASSERT(runs[1] > fLeft); 1552cb93a386Sopenharmony_ci 1553cb93a386Sopenharmony_ci if (left) { 1554cb93a386Sopenharmony_ci *left = std::max(fLeft, runs[0]); 1555cb93a386Sopenharmony_ci } 1556cb93a386Sopenharmony_ci if (right) { 1557cb93a386Sopenharmony_ci *right = std::min(fRight, runs[1]); 1558cb93a386Sopenharmony_ci } 1559cb93a386Sopenharmony_ci fRuns = runs + 2; 1560cb93a386Sopenharmony_ci return true; 1561cb93a386Sopenharmony_ci} 1562cb93a386Sopenharmony_ci 1563cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////////////////////////// 1564cb93a386Sopenharmony_ci 1565cb93a386Sopenharmony_cistatic void visit_pairs(int pairCount, int y, const int32_t pairs[], 1566cb93a386Sopenharmony_ci const std::function<void(const SkIRect&)>& visitor) { 1567cb93a386Sopenharmony_ci for (int i = 0; i < pairCount; ++i) { 1568cb93a386Sopenharmony_ci visitor({ pairs[0], y, pairs[1], y + 1 }); 1569cb93a386Sopenharmony_ci pairs += 2; 1570cb93a386Sopenharmony_ci } 1571cb93a386Sopenharmony_ci} 1572cb93a386Sopenharmony_ci 1573cb93a386Sopenharmony_civoid SkRegionPriv::VisitSpans(const SkRegion& rgn, 1574cb93a386Sopenharmony_ci const std::function<void(const SkIRect&)>& visitor) { 1575cb93a386Sopenharmony_ci if (rgn.isEmpty()) { 1576cb93a386Sopenharmony_ci return; 1577cb93a386Sopenharmony_ci } 1578cb93a386Sopenharmony_ci if (rgn.isRect()) { 1579cb93a386Sopenharmony_ci visitor(rgn.getBounds()); 1580cb93a386Sopenharmony_ci } else { 1581cb93a386Sopenharmony_ci const int32_t* p = rgn.fRunHead->readonly_runs(); 1582cb93a386Sopenharmony_ci int32_t top = *p++; 1583cb93a386Sopenharmony_ci int32_t bot = *p++; 1584cb93a386Sopenharmony_ci do { 1585cb93a386Sopenharmony_ci int pairCount = *p++; 1586cb93a386Sopenharmony_ci if (pairCount == 1) { 1587cb93a386Sopenharmony_ci visitor({ p[0], top, p[1], bot }); 1588cb93a386Sopenharmony_ci p += 2; 1589cb93a386Sopenharmony_ci } else if (pairCount > 1) { 1590cb93a386Sopenharmony_ci // we have to loop repeated in Y, sending each interval in Y -> X order 1591cb93a386Sopenharmony_ci for (int y = top; y < bot; ++y) { 1592cb93a386Sopenharmony_ci visit_pairs(pairCount, y, p, visitor); 1593cb93a386Sopenharmony_ci } 1594cb93a386Sopenharmony_ci p += pairCount * 2; 1595cb93a386Sopenharmony_ci } 1596cb93a386Sopenharmony_ci assert_sentinel(*p, true); 1597cb93a386Sopenharmony_ci p += 1; // skip sentinel 1598cb93a386Sopenharmony_ci 1599cb93a386Sopenharmony_ci // read next bottom or sentinel 1600cb93a386Sopenharmony_ci top = bot; 1601cb93a386Sopenharmony_ci bot = *p++; 1602cb93a386Sopenharmony_ci } while (!SkRegionValueIsSentinel(bot)); 1603cb93a386Sopenharmony_ci } 1604cb93a386Sopenharmony_ci} 1605cb93a386Sopenharmony_ci 1606