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