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