• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(int32_t x,int32_t y) const364 bool SkRegion::contains(int32_t x, int32_t 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