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