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