• Home
  • History
  • Annotate
  • 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     do {
1159         --ySpanCount;
1160         if (ySpanCount < 0) {
1161             return false;  // too many yspans
1162         }
1163         rect.fBottom = *runs++;
1164         if (rect.fBottom == SkRegion::kRunTypeSentinel) {
1165             return false;
1166         }
1167         int32_t xIntervals = *runs++;
1168         SkASSERT(runs < end);
1169         if (xIntervals < 0 || runs + 1 + 2 * xIntervals > end) {
1170             return false;
1171         }
1172         intervalCount -= xIntervals;
1173         if (intervalCount < 0) {
1174             return false;  // too many intervals
1175         }
1176         while (xIntervals-- > 0) {
1177             rect.fLeft = *runs++;
1178             rect.fRight = *runs++;
1179             if (rect.fLeft == SkRegion::kRunTypeSentinel ||
1180                 rect.fRight == SkRegion::kRunTypeSentinel || rect.isEmpty()) {
1181                 return false;
1182             }
1183             bounds.join(rect);
1184         }
1185         if (*runs++ != SkRegion::kRunTypeSentinel) {
1186             return false;  // required check sentinal.
1187         }
1188         rect.fTop = rect.fBottom;
1189         SkASSERT(runs < end);
1190     } while (*runs != SkRegion::kRunTypeSentinel);
1191     ++runs;
1192     if (ySpanCount != 0 || intervalCount != 0 || givenBounds != bounds) {
1193         return false;
1194     }
1195     SkASSERT(runs == end);  // if ySpanCount && intervalCount are right, must be correct length.
1196     return true;
1197 }
readFromMemory(const void * storage,size_t length)1198 size_t SkRegion::readFromMemory(const void* storage, size_t length) {
1199     SkRBuffer   buffer(storage, length);
1200     SkRegion    tmp;
1201     int32_t     count;
1202 
1203     // Serialized Region Format:
1204     //    Empty:
1205     //       -1
1206     //    Simple Rect:
1207     //       0  LEFT TOP RIGHT BOTTOM
1208     //    Complex Region:
1209     //       COUNT LEFT TOP RIGHT BOTTOM Y_SPAN_COUNT TOTAL_INTERVAL_COUNT [RUNS....]
1210     if (!buffer.readS32(&count) || count < -1) {
1211         return 0;
1212     }
1213     if (count >= 0) {
1214         if (!buffer.read(&tmp.fBounds, sizeof(tmp.fBounds)) || tmp.fBounds.isEmpty()) {
1215             return 0;  // Short buffer or bad bounds for non-empty region; report failure.
1216         }
1217         if (count == 0) {
1218             tmp.fRunHead = SkRegion_gRectRunHeadPtr;
1219         } else {
1220             int32_t ySpanCount, intervalCount;
1221             if (!buffer.readS32(&ySpanCount) ||
1222                 !buffer.readS32(&intervalCount) ||
1223                 buffer.available() < count * sizeof(int32_t)) {
1224                 return 0;
1225             }
1226             if (!validate_run((const int32_t*)((const char*)storage + buffer.pos()), count,
1227                               tmp.fBounds, ySpanCount, intervalCount)) {
1228                 return 0;  // invalid runs, don't even allocate
1229             }
1230             tmp.allocateRuns(count, ySpanCount, intervalCount);
1231             SkASSERT(tmp.isComplex());
1232             SkAssertResult(buffer.read(tmp.fRunHead->writable_runs(), count * sizeof(int32_t)));
1233         }
1234     }
1235     SkASSERT(tmp.isValid());
1236     SkASSERT(buffer.isValid());
1237     this->swap(tmp);
1238     return buffer.pos();
1239 }
1240 
1241 ///////////////////////////////////////////////////////////////////////////////
1242 
GetEmptyRegion()1243 const SkRegion& SkRegion::GetEmptyRegion() {
1244     static SkRegion gEmpty;
1245     return gEmpty;
1246 }
1247 
1248 ///////////////////////////////////////////////////////////////////////////////
1249 
isValid() const1250 bool SkRegion::isValid() const {
1251     if (this->isEmpty()) {
1252         return fBounds == SkIRect{0, 0, 0, 0};
1253     }
1254     if (fBounds.isEmpty()) {
1255         return false;
1256     }
1257     if (this->isRect()) {
1258         return true;
1259     }
1260     return fRunHead && fRunHead->fRefCnt > 0 &&
1261            validate_run(fRunHead->readonly_runs(), fRunHead->fRunCount, fBounds,
1262                         fRunHead->getYSpanCount(), fRunHead->getIntervalCount());
1263 }
1264 
1265 #ifdef SK_DEBUG
validate() const1266 void SkRegion::validate() const { SkASSERT(this->isValid()); }
1267 
dump() const1268 void SkRegion::dump() const {
1269     if (this->isEmpty()) {
1270         SkDebugf("  rgn: empty\n");
1271     } else {
1272         SkDebugf("  rgn: [%d %d %d %d]", fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
1273         if (this->isComplex()) {
1274             const RunType* runs = fRunHead->readonly_runs();
1275             for (int i = 0; i < fRunHead->fRunCount; i++)
1276                 SkDebugf(" %d", runs[i]);
1277         }
1278         SkDebugf("\n");
1279     }
1280 }
1281 
1282 #endif
1283 
1284 ///////////////////////////////////////////////////////////////////////////////
1285 
Iterator(const SkRegion & rgn)1286 SkRegion::Iterator::Iterator(const SkRegion& rgn) {
1287     this->reset(rgn);
1288 }
1289 
rewind()1290 bool SkRegion::Iterator::rewind() {
1291     if (fRgn) {
1292         this->reset(*fRgn);
1293         return true;
1294     }
1295     return false;
1296 }
1297 
reset(const SkRegion & rgn)1298 void SkRegion::Iterator::reset(const SkRegion& rgn) {
1299     fRgn = &rgn;
1300     if (rgn.isEmpty()) {
1301         fDone = true;
1302     } else {
1303         fDone = false;
1304         if (rgn.isRect()) {
1305             fRect = rgn.fBounds;
1306             fRuns = nullptr;
1307         } else {
1308             fRuns = rgn.fRunHead->readonly_runs();
1309             fRect.set(fRuns[3], fRuns[0], fRuns[4], fRuns[1]);
1310             fRuns += 5;
1311             // Now fRuns points to the 2nd interval (or x-sentinel)
1312         }
1313     }
1314 }
1315 
next()1316 void SkRegion::Iterator::next() {
1317     if (fDone) {
1318         return;
1319     }
1320 
1321     if (fRuns == nullptr) {   // rect case
1322         fDone = true;
1323         return;
1324     }
1325 
1326     const RunType* runs = fRuns;
1327 
1328     if (runs[0] < kRunTypeSentinel) { // valid X value
1329         fRect.fLeft = runs[0];
1330         fRect.fRight = runs[1];
1331         runs += 2;
1332     } else {    // we're at the end of a line
1333         runs += 1;
1334         if (runs[0] < kRunTypeSentinel) { // valid Y value
1335             int intervals = runs[1];
1336             if (0 == intervals) {    // empty line
1337                 fRect.fTop = runs[0];
1338                 runs += 3;
1339             } else {
1340                 fRect.fTop = fRect.fBottom;
1341             }
1342 
1343             fRect.fBottom = runs[0];
1344             assert_sentinel(runs[2], false);
1345             assert_sentinel(runs[3], false);
1346             fRect.fLeft = runs[2];
1347             fRect.fRight = runs[3];
1348             runs += 4;
1349         } else {    // end of rgn
1350             fDone = true;
1351         }
1352     }
1353     fRuns = runs;
1354 }
1355 
Cliperator(const SkRegion & rgn,const SkIRect & clip)1356 SkRegion::Cliperator::Cliperator(const SkRegion& rgn, const SkIRect& clip)
1357         : fIter(rgn), fClip(clip), fDone(true) {
1358     const SkIRect& r = fIter.rect();
1359 
1360     while (!fIter.done()) {
1361         if (r.fTop >= clip.fBottom) {
1362             break;
1363         }
1364         if (fRect.intersect(clip, r)) {
1365             fDone = false;
1366             break;
1367         }
1368         fIter.next();
1369     }
1370 }
1371 
next()1372 void SkRegion::Cliperator::next() {
1373     if (fDone) {
1374         return;
1375     }
1376 
1377     const SkIRect& r = fIter.rect();
1378 
1379     fDone = true;
1380     fIter.next();
1381     while (!fIter.done()) {
1382         if (r.fTop >= fClip.fBottom) {
1383             break;
1384         }
1385         if (fRect.intersect(fClip, r)) {
1386             fDone = false;
1387             break;
1388         }
1389         fIter.next();
1390     }
1391 }
1392 
1393 ///////////////////////////////////////////////////////////////////////////////
1394 
Spanerator(const SkRegion & rgn,int y,int left,int right)1395 SkRegion::Spanerator::Spanerator(const SkRegion& rgn, int y, int left,
1396                                  int right) {
1397     SkDEBUGCODE(rgn.validate();)
1398 
1399     const SkIRect& r = rgn.getBounds();
1400 
1401     fDone = true;
1402     if (!rgn.isEmpty() && y >= r.fTop && y < r.fBottom &&
1403             right > r.fLeft && left < r.fRight) {
1404         if (rgn.isRect()) {
1405             if (left < r.fLeft) {
1406                 left = r.fLeft;
1407             }
1408             if (right > r.fRight) {
1409                 right = r.fRight;
1410             }
1411             fLeft = left;
1412             fRight = right;
1413             fRuns = nullptr;    // means we're a rect, not a rgn
1414             fDone = false;
1415         } else {
1416             const SkRegion::RunType* runs = rgn.fRunHead->findScanline(y);
1417             runs += 2;  // skip Bottom and IntervalCount
1418             for (;;) {
1419                 // runs[0..1] is to the right of the span, so we're done
1420                 if (runs[0] >= right) {
1421                     break;
1422                 }
1423                 // runs[0..1] is to the left of the span, so continue
1424                 if (runs[1] <= left) {
1425                     runs += 2;
1426                     continue;
1427                 }
1428                 // runs[0..1] intersects the span
1429                 fRuns = runs;
1430                 fLeft = left;
1431                 fRight = right;
1432                 fDone = false;
1433                 break;
1434             }
1435         }
1436     }
1437 }
1438 
next(int * left,int * right)1439 bool SkRegion::Spanerator::next(int* left, int* right) {
1440     if (fDone) {
1441         return false;
1442     }
1443 
1444     if (fRuns == nullptr) {   // we're a rect
1445         fDone = true;   // ok, now we're done
1446         if (left) {
1447             *left = fLeft;
1448         }
1449         if (right) {
1450             *right = fRight;
1451         }
1452         return true;    // this interval is legal
1453     }
1454 
1455     const SkRegion::RunType* runs = fRuns;
1456 
1457     if (runs[0] >= fRight) {
1458         fDone = true;
1459         return false;
1460     }
1461 
1462     SkASSERT(runs[1] > fLeft);
1463 
1464     if (left) {
1465         *left = SkMax32(fLeft, runs[0]);
1466     }
1467     if (right) {
1468         *right = SkMin32(fRight, runs[1]);
1469     }
1470     fRuns = runs + 2;
1471     return true;
1472 }
1473 
1474 ///////////////////////////////////////////////////////////////////////////////
1475 
1476 #ifdef SK_DEBUG
1477 
debugSetRuns(const RunType runs[],int count)1478 bool SkRegion::debugSetRuns(const RunType runs[], int count) {
1479     // we need to make a copy, since the real method may modify the array, and
1480     // so it cannot be const.
1481 
1482     SkAutoTArray<RunType> storage(count);
1483     memcpy(storage.get(), runs, count * sizeof(RunType));
1484     return this->setRuns(storage.get(), count);
1485 }
1486 
1487 #endif
1488