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