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