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