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