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