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