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