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