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