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