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