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