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