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