SkRegion.cpp revision 9221e8085d77b0850a07c6585275ec7bb7e0931a
10910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* libs/corecg/SkRegion.cpp
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
30910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** Copyright 2006, The Android Open Source Project
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
50910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
60910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** you may not use this file except in compliance with the License.
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** You may obtain a copy of the License at
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project**
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** See the License for the specific language governing permissions and
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project** limitations under the License.
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkRegionPriv.h"
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTemplates.h"
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkThread.h"
219221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato#include <stdio.h>
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkDEBUGCODE(int32_t gRgnAllocCounter;)
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////////////////////////
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*  Pass in a scanline, beginning with the Left value of the pair (i.e. not the Y beginning)
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkRegion::RunType* skip_scanline(const SkRegion::RunType runs[])
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (runs[0] != SkRegion::kRunTypeSentinel)
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(runs[0] < runs[1]);    // valid span
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        runs += 2;
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (SkRegion::RunType*)(runs + 1);  // return past the X-sentinel
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkRegion::RunType* find_y(const SkRegion::RunType runs[], int y)
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int top = *runs++;
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (top <= y)
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        for (;;)
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int bot = *runs++;
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (bot > y)
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (bot == SkRegion::kRunTypeSentinel || *runs == SkRegion::kRunTypeSentinel)
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    break;
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                return (SkRegion::RunType*)runs;
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            top = bot;
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            runs = skip_scanline(runs);
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return NULL;
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// returns true if runs are just a rect
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::ComputeRunBounds(const SkRegion::RunType runs[], int count, SkIRect* bounds)
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    assert_sentinel(runs[0], false);    // top
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (count == kRectRegionRuns)
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_sentinel(runs[1], false);    // bottom
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_sentinel(runs[2], false);    // left
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_sentinel(runs[3], false);    // right
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_sentinel(runs[4], true);
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_sentinel(runs[5], true);
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(runs[0] < runs[1]);    // valid height
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(runs[2] < runs[3]);    // valid width
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bounds->set(runs[2], runs[0], runs[3], runs[1]);
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int left = SK_MaxS32;
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int rite = SK_MinS32;
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int bot;
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bounds->fTop = *runs++;
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do {
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bot = *runs++;
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (*runs < SkRegion::kRunTypeSentinel)
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (left > *runs)
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                left = *runs;
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            runs = skip_scanline(runs);
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (rite < runs[-2])
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                rite = runs[-2];
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            runs += 1;  // skip X-sentinel
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } while (runs[0] < SkRegion::kRunTypeSentinel);
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bounds->fLeft = left;
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bounds->fRight = rite;
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bounds->fBottom = bot;
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return false;
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkRegion::SkRegion()
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBounds.set(0, 0, 0, 0);
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRunHead = SkRegion_gEmptyRunHeadPtr;
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkRegion::SkRegion(const SkRegion& src)
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRunHead = SkRegion_gEmptyRunHeadPtr;   // just need a value that won't trigger sk_free(fRunHead)
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->setRegion(src);
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkRegion::SkRegion(const SkIRect& rect)
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRunHead = SkRegion_gEmptyRunHeadPtr;   // just need a value that won't trigger sk_free(fRunHead)
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->setRect(rect);
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkRegion::~SkRegion()
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->freeRuns();
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkRegion::freeRuns()
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fRunHead->isComplex())
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(fRunHead->fRefCnt >= 1);
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (sk_atomic_dec(&fRunHead->fRefCnt) == 1)
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            //SkASSERT(gRgnAllocCounter > 0);
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            //SkDEBUGCODE(sk_atomic_dec(&gRgnAllocCounter));
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            //SkDEBUGF(("************** gRgnAllocCounter::free %d\n", gRgnAllocCounter));
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            sk_free(fRunHead);
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkRegion::allocateRuns(int count)
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRunHead = RunHead::Alloc(count);
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkRegion& SkRegion::operator=(const SkRegion& src)
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    (void)this->setRegion(src);
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return *this;
1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkRegion::swap(SkRegion& other)
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTSwap<SkIRect>(fBounds, other.fBounds);
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTSwap<RunHead*>(fRunHead, other.fRunHead);
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::setEmpty()
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->freeRuns();
1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBounds.set(0, 0, 0, 0);
1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRunHead = SkRegion_gEmptyRunHeadPtr;
1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return false;
1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::setRect(int32_t left, int32_t top, int32_t right, int32_t bottom)
1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (left >= right || top >= bottom)
1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->setEmpty();
1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->freeRuns();
1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBounds.set(left, top, right, bottom);
1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRunHead = SkRegion_gRectRunHeadPtr;
1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return true;
1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::setRect(const SkIRect& r)
1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return this->setRect(r.fLeft, r.fTop, r.fRight, r.fBottom);
1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::setRegion(const SkRegion& src)
1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this != &src)
1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->freeRuns();
1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fBounds = src.fBounds;
1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRunHead = src.fRunHead;
1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fRunHead->isComplex())
1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            sk_atomic_inc(&fRunHead->fRefCnt);
1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return fRunHead != SkRegion_gEmptyRunHeadPtr;
1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::op(const SkIRect& rect, const SkRegion& rgn, Op op)
2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion tmp(rect);
2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return this->op(tmp, rgn, op);
2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::op(const SkRegion& rgn, const SkIRect& rect, Op op)
2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion tmp(rect);
2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return this->op(rgn, tmp, op);
2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////////////////
2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2159221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onoratochar* SkRegion::toString()
2169221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato{
2179221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    Iterator iter(*this);
2189221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    int count = 0;
2199221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    while (!iter.done()) {
2209221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato        count++;
2219221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato        iter.next();
2229221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    }
2239221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    // 4 ints, up to 10 digits each plus sign, 3 commas, '(', ')', SkRegion() and '\0'
2249221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    const int max = (count*((11*4)+5))+11+1;
2259221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    char* result = (char*)malloc(max);
2269221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    if (result == NULL) {
2279221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato        return NULL;
2289221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    }
2299221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    count = sprintf(result, "SkRegion(");
2309221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    iter.reset(*this);
2319221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    while (!iter.done()) {
2329221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato        const SkIRect& r = iter.rect();
2339221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato        count += sprintf(result+count, "(%d,%d,%d,%d)", r.fLeft, r.fTop, r.fRight, r.fBottom);
2349221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato        iter.next();
2359221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    }
2369221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    count += sprintf(result+count, ")");
2379221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato    return result;
2389221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato}
2399221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato
2409221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato//////////////////////////////////////////////////////////////////////////////////////
2419221e8085d77b0850a07c6585275ec7bb7e0931aJoe Onorato
2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint SkRegion::count_runtype_values(int* itop, int* ibot) const
2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this == NULL)
2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *itop = SK_MinS32;
2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *ibot = SK_MaxS32;
2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int maxT;
2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isRect())
2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        maxT = 2;
2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else
2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(this->isComplex());
2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // skip the top
2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const RunType*  runs = fRunHead->readonly_runs() + 1;
2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        maxT = 0;
2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        do {
2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const RunType* next = skip_scanline(runs + 1);
2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(next > runs);
2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int         T = (int)(next - runs - 1);
2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (maxT < T)
2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                maxT = T;
2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            runs = next;
2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } while (runs[0] < SkRegion::kRunTypeSentinel);
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *itop = fBounds.fTop;
2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *ibot = fBounds.fBottom;
2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return maxT;
2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::setRuns(RunType runs[], int count)
2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(this->validate();)
2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(count > 0);
2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (count <= 2)
2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
2830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //  SkDEBUGF(("setRuns: empty\n"));
2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_sentinel(runs[count-1], true);
2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->setEmpty();
2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // trim off any empty spans from the top and bottom
2890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // weird I should need this, perhaps op() could be smarter...
2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (count > kRectRegionRuns)
2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
2920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        RunType* stop = runs + count;
2930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_sentinel(runs[0], false);    // top
2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_sentinel(runs[1], false);    // bottom
2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (runs[2] == SkRegion::kRunTypeSentinel)    // should be first left...
2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            runs += 2;  // skip empty initial span
2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            runs[0] = runs[-1]; // set new top to prev bottom
2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            assert_sentinel(runs[1], false);    // bot: a sentinal would mean two in a row
3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            assert_sentinel(runs[2], false);    // left
3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            assert_sentinel(runs[3], false);    // right
3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // now check for a trailing empty span
3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_sentinel(stop[-1], true);
3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_sentinel(stop[-2], true);
3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_sentinel(stop[-3], false);   // should be last right
3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (stop[-4] == SkRegion::kRunTypeSentinel)   // eek, stop[-3] was a bottom with no x-runs
3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stop[-3] = SkRegion::kRunTypeSentinel;    // kill empty last span
3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            stop -= 2;
3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            assert_sentinel(stop[-1], true);
3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            assert_sentinel(stop[-2], true);
3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            assert_sentinel(stop[-3], false);
3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            assert_sentinel(stop[-4], false);
3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            assert_sentinel(stop[-5], false);
3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        count = (int)(stop - runs);
3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(count >= kRectRegionRuns);
3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (ComputeRunBounds(runs, count, &fBounds))
3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //  SkDEBUGF(("setRuns: rect[%d %d %d %d]\n", fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom));
3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->setRect(fBounds);
3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //  if we get here, we need to become a complex region
3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (!fRunHead->isComplex() || fRunHead->fRunCount != count)
3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUGx
3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkDebugf("setRuns: rgn [");
3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const RunType* r = runs;
3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkDebugf(" top: %d\n", *r++);
3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (*r < SkRegion::kRunTypeSentinel)
3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkDebugf(" bottom: %d", *r++);
3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                while (*r < SkRegion::kRunTypeSentinel)
3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                {
3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkDebugf(" [%d %d]", r[0], r[1]);
3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    r += 2;
3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkDebugf("\n");
3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->freeRuns();
3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->allocateRuns(count);
3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // must call this before we can write directly into runs()
3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // in case we are sharing the buffer with another region (copy on write)
3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRunHead = fRunHead->ensureWritable();
3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    memcpy(fRunHead->writable_runs(), runs, count * sizeof(RunType));
3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(this->validate();)
3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return true;
3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkRegion::BuildRectRuns(const SkIRect& bounds,
3660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                             RunType runs[kRectRegionRuns])
3670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
3680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    runs[0] = bounds.fTop;
3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    runs[1] = bounds.fBottom;
3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    runs[2] = bounds.fLeft;
3710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    runs[3] = bounds.fRight;
3720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    runs[4] = kRunTypeSentinel;
3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    runs[5] = kRunTypeSentinel;
3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkRegion::RunType* find_scanline(const SkRegion::RunType runs[], int y)
3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(y >= runs[0]); // if this fails, we didn't do a quick check on the boudns
3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    runs += 1;  // skip top-Y
3810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (;;)
3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (runs[0] == SkRegion::kRunTypeSentinel)
3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (y < runs[0])
3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return (SkRegion::RunType*)&runs[1];
3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        runs = skip_scanline(runs + 1); // skip the Y value before calling
3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return NULL;
3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3922c497e64d20a73267eb92ae88fdc51ba2a356b55Mike Reedbool SkRegion::contains(int32_t x, int32_t y) const
3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (!fBounds.contains(x, y))
3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
3960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isRect())
3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(this->isComplex());
4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const RunType* runs = find_scanline(fRunHead->readonly_runs(), y);
4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (runs)
4040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {   for (;;)
4050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {   if (x < runs[0])
4060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
4070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (x < runs[1])
4080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                return true;
4090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            runs += 2;
4100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return false;
4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::contains(const SkIRect& r) const
4160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
4170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion tmp(r);
4180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return this->contains(tmp);
4200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::contains(const SkRegion& rgn) const
4230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
4240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isEmpty() || rgn.isEmpty() || !fBounds.contains(rgn.fBounds))
4250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
4260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isRect())
4280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
4290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion    tmp;
4310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    tmp.op(*this, rgn, kUnion_Op);
4330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return tmp == *this;
4340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst SkRegion::RunType* SkRegion::getRuns(RunType tmpStorage[], int* count) const
4370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
4380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(tmpStorage && count);
4390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const RunType* runs = tmpStorage;
4400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isEmpty())
4420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
4430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        tmpStorage[0] = kRunTypeSentinel;
4440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *count = 1;
4450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else if (this->isRect())
4470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
4480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        BuildRectRuns(fBounds, tmpStorage);
4490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *count = kRectRegionRuns;
4500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else
4520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
4530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *count = fRunHead->fRunCount;
4540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        runs = fRunHead->readonly_runs();
4550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return runs;
4570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////////////
4600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::intersects(const SkIRect& r) const {
4620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isEmpty() || r.isEmpty()) {
4630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
4640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (!SkIRect::Intersects(fBounds, r)) {
4670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
4680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isRect()) {
4710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
4720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // we are complex
4750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion tmp;
4760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return tmp.op(*this, r, kIntersect_Op);
4770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::intersects(const SkRegion& rgn) const {
4800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isEmpty() || rgn.isEmpty()) {
4810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
4820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (!SkIRect::Intersects(fBounds, rgn.fBounds)) {
4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isRect() && rgn.isRect()) {
4890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
4900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // one or both of us is complex
4930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // TODO: write a faster version that aborts as soon as we write the first
4940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //       non-empty span, to avoid build the entire result
4950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion tmp;
4960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return tmp.op(*this, rgn, kIntersect_Op);
4970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////////////
5000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint operator==(const SkRegion& a, const SkRegion& b)
5020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(a.validate();)
5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(b.validate();)
5050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (&a == &b)
5070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
5080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (a.fBounds != b.fBounds)
5090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
5100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkRegion::RunHead* ah = a.fRunHead;
5120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkRegion::RunHead* bh = b.fRunHead;
5130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // this catches empties and rects being equal
5150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (ah == bh)
5160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
5170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // now we insist that both are complex (but different ptrs)
5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (!ah->isComplex() || !bh->isComplex())
5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return  ah->fRunCount == bh->fRunCount &&
5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            !memcmp(ah->readonly_runs(), bh->readonly_runs(),
5240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    ah->fRunCount * sizeof(SkRegion::RunType));
5250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkRegion::translate(int dx, int dy, SkRegion* dst) const
5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(this->validate();)
5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (NULL == dst)
5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isEmpty())
5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        dst->setEmpty();
5360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else if (this->isRect())
5370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        dst->setRect(fBounds.fLeft + dx, fBounds.fTop + dy,
5380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                     fBounds.fRight + dx, fBounds.fBottom + dy);
5390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else
5400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
5410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (this == dst)
5420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
5430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            dst->fRunHead = dst->fRunHead->ensureWritable();
5440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else
5460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
5470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkRegion    tmp;
5480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            tmp.allocateRuns(fRunHead->fRunCount);
5490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            tmp.fBounds = fBounds;
5500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            dst->swap(tmp);
5510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        dst->fBounds.offset(dx, dy);
5540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const RunType*  sruns = fRunHead->readonly_runs();
5560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        RunType*        druns = dst->fRunHead->writable_runs();
5570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *druns++ = (SkRegion::RunType)(*sruns++ + dy);    // top
5590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        for (;;)
5600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
5610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int bottom = *sruns++;
5620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (bottom == kRunTypeSentinel)
5630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
5640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *druns++ = (SkRegion::RunType)(bottom + dy);  // bottom;
5650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            for (;;)
5660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
5670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                int x = *sruns++;
5680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (x == kRunTypeSentinel)
5690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    break;
5700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *druns++ = (SkRegion::RunType)(x + dx);
5710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *druns++ = (SkRegion::RunType)(*sruns++ + dx);
5720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *druns++ = kRunTypeSentinel;    // x sentinel
5740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *druns++ = kRunTypeSentinel;    // y sentinel
5760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(sruns - fRunHead->readonly_runs() == fRunHead->fRunCount);
5780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(druns - dst->fRunHead->readonly_runs() == dst->fRunHead->fRunCount);
5790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(this->validate();)
5820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////////////
5850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if defined _WIN32 && _MSC_VER >= 1300  // disable warning : local variable used without having been initialized
5870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#pragma warning ( push )
5880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#pragma warning ( disable : 4701 )
5890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
5900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
5920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void assert_valid_pair(int left, int rite)
5930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
5940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(left == SkRegion::kRunTypeSentinel || left < rite);
5950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else
5970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    #define assert_valid_pair(left, rite)
5980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
5990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstruct spanRec {
6010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkRegion::RunType*    fA_runs;
6020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkRegion::RunType*    fB_runs;
6030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int                         fA_left, fA_rite, fB_left, fB_rite;
6040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int                         fLeft, fRite, fInside;
6050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void init(const SkRegion::RunType a_runs[], const SkRegion::RunType b_runs[])
6070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
6080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fA_left = *a_runs++;
6090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fA_rite = *a_runs++;
6100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fB_left = *b_runs++;
6110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fB_rite = *b_runs++;
6120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fA_runs = a_runs;
6140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fB_runs = b_runs;
6150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
6160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool done() const
6180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
6190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(fA_left <= SkRegion::kRunTypeSentinel);
6200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(fB_left <= SkRegion::kRunTypeSentinel);
6210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return fA_left == SkRegion::kRunTypeSentinel && fB_left == SkRegion::kRunTypeSentinel;
6220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
6230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void next()
6250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
6260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_valid_pair(fA_left, fA_rite);
6270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        assert_valid_pair(fB_left, fB_rite);
6280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int     inside, left, rite SK_INIT_TO_AVOID_WARNING;
6300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool    a_flush = false;
6310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool    b_flush = false;
6320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int a_left = fA_left;
6340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int a_rite = fA_rite;
6350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int b_left = fB_left;
6360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int b_rite = fB_rite;
6370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (a_left < b_left)
6390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
6400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            inside = 1;
6410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            left = a_left;
6420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (a_rite <= b_left)   // [...] <...>
6430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
6440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                rite = a_rite;
6450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                a_flush = true;
6460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
6470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else // [...<..]...> or [...<...>...]
6480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                rite = a_left = b_left;
6490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else if (b_left < a_left)
6510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
6520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            inside = 2;
6530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            left = b_left;
6540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (b_rite <= a_left)   // [...] <...>
6550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
6560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                rite = b_rite;
6570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                b_flush = true;
6580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
6590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else // [...<..]...> or [...<...>...]
6600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                rite = b_left = a_left;
6610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else    // a_left == b_left
6630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
6640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            inside = 3;
6650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            left = a_left;  // or b_left
6660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (a_rite <= b_rite)
6670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
6680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                rite = b_left = a_rite;
6690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                a_flush = true;
6700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
6710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (b_rite <= a_rite)
6720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
6730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                rite = a_left = b_rite;
6740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                b_flush = true;
6750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
6760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (a_flush)
6790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
6800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            a_left = *fA_runs++;
6810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            a_rite = *fA_runs++;
6820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (b_flush)
6840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
6850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            b_left = *fB_runs++;
6860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            b_rite = *fB_runs++;
6870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(left <= rite);
6900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // now update our state
6920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fA_left = a_left;
6930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fA_rite = a_rite;
6940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fB_left = b_left;
6950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fB_rite = b_rite;
6960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fLeft = left;
6980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRite = rite;
6990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fInside = inside;
7000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
7020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkRegion::RunType* operate_on_span(const SkRegion::RunType a_runs[],
7040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                          const SkRegion::RunType b_runs[],
7050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                          SkRegion::RunType dst[],
7060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                          int min, int max)
7070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
7080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    spanRec rec;
7090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool    firstInterval = true;
7100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    rec.init(a_runs, b_runs);
7120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (!rec.done())
7140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
7150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        rec.next();
7160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int left = rec.fLeft;
7180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int rite = rec.fRite;
7190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // add left,rite to our dst buffer (checking for coincidence
7210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if ((unsigned)(rec.fInside - min) <= (unsigned)(max - min) &&
7220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            left < rite)    // skip if equal
7230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
7240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (firstInterval || dst[-1] < left)
7250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
7260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *dst++ = (SkRegion::RunType)(left);
7270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *dst++ = (SkRegion::RunType)(rite);
7280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                firstInterval = false;
7290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
7300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else    // update the right edge
7310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                dst[-1] = (SkRegion::RunType)(rite);
7320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
7330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *dst++ = SkRegion::kRunTypeSentinel;
7360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return dst;
7370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if defined _WIN32 && _MSC_VER >= 1300
7400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#pragma warning ( pop )
7410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
7420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const struct {
7440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint8_t fMin;
7450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint8_t fMax;
7460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} gOpMinMax[] = {
7470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { 1, 1 },   // Difference
7480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { 3, 3 },   // Intersection
7490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { 1, 3 },   // Union
7500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    { 1, 2 }    // XOR
7510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
7520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass RgnOper {
7540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
7550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    RgnOper(int top, SkRegion::RunType dst[], SkRegion::Op op)
7560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
7570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // need to ensure that the op enum lines up with our minmax array
7580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(SkRegion::kDifference_Op == 0);
7590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(SkRegion::kIntersect_Op == 1);
7600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(SkRegion::kUnion_Op == 2);
7610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(SkRegion::kXOR_Op == 3);
7620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT((unsigned)op <= 3);
7630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fStartDst = dst;
7650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPrevDst = dst + 1;
7660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPrevLen = 0;       // will never match a length from operate_on_span
7670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fTop = (SkRegion::RunType)(top);    // just a first guess, we might update this
7680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fMin = gOpMinMax[op].fMin;
7700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fMax = gOpMinMax[op].fMax;
7710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void addSpan(int bottom, const SkRegion::RunType a_runs[], const SkRegion::RunType b_runs[])
7740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
7750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkRegion::RunType*  start = fPrevDst + fPrevLen + 1;    // skip X values and slot for the next Y
7760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkRegion::RunType*  stop = operate_on_span(a_runs, b_runs, start, fMin, fMax);
7770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        size_t              len = stop - start;
7780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fPrevLen == len && !memcmp(fPrevDst, start, len * sizeof(SkRegion::RunType)))   // update Y value
7800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fPrevDst[-1] = (SkRegion::RunType)(bottom);
7810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else    // accept the new span
7820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
7830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (len == 1 && fPrevLen == 0) {
7840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fTop = (SkRegion::RunType)(bottom); // just update our bottom
7850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
7860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                start[-1] = (SkRegion::RunType)(bottom);
7870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fPrevDst = start;
7880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fPrevLen = len;
7890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
7900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
7910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int flush()
7940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
7950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fStartDst[0] = fTop;
7960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fPrevDst[fPrevLen] = SkRegion::kRunTypeSentinel;
7970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return (int)(fPrevDst - fStartDst + fPrevLen + 1);
7980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint8_t fMin, fMax;
8010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate:
8030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion::RunType*  fStartDst;
8040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion::RunType*  fPrevDst;
8050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t              fPrevLen;
8060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion::RunType   fTop;
8070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
8080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic int operate( const SkRegion::RunType a_runs[],
8100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    const SkRegion::RunType b_runs[],
8110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkRegion::RunType dst[],
8120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkRegion::Op op)
8130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
8144c1037238c8ebcef8c75b5d43730ed308a11102cMike Reed    const SkRegion::RunType gSentinel[] = {
8154c1037238c8ebcef8c75b5d43730ed308a11102cMike Reed        SkRegion::kRunTypeSentinel,
8164c1037238c8ebcef8c75b5d43730ed308a11102cMike Reed        // just need a 2nd value, since spanRec.init() reads 2 values, even
8174c1037238c8ebcef8c75b5d43730ed308a11102cMike Reed        // though if the first value is the sentinel, it ignores the 2nd value.
8184c1037238c8ebcef8c75b5d43730ed308a11102cMike Reed        // w/o the 2nd value here, we might read uninitialized memory.
8194c1037238c8ebcef8c75b5d43730ed308a11102cMike Reed        0,
8204c1037238c8ebcef8c75b5d43730ed308a11102cMike Reed    };
8210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int a_top = *a_runs++;
8230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int a_bot = *a_runs++;
8240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int b_top = *b_runs++;
8250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int b_bot = *b_runs++;
8260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    assert_sentinel(a_top, false);
8280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    assert_sentinel(a_bot, false);
8290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    assert_sentinel(b_top, false);
8300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    assert_sentinel(b_bot, false);
8310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    RgnOper oper(SkMin32(a_top, b_top), dst, op);
8330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool firstInterval = true;
8350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int prevBot = SkRegion::kRunTypeSentinel; // so we fail the first test
8360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (a_bot < SkRegion::kRunTypeSentinel || b_bot < SkRegion::kRunTypeSentinel)
8380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
8390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int         top, bot SK_INIT_TO_AVOID_WARNING;
8404c1037238c8ebcef8c75b5d43730ed308a11102cMike Reed        const SkRegion::RunType*    run0 = gSentinel;
8414c1037238c8ebcef8c75b5d43730ed308a11102cMike Reed        const SkRegion::RunType*    run1 = gSentinel;
8420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool        a_flush = false;
8430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool        b_flush = false;
8440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int         inside;
8450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (a_top < b_top)
8470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
8480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            inside = 1;
8490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            top = a_top;
8500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            run0 = a_runs;
8510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (a_bot <= b_top) // [...] <...>
8520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
8530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bot = a_bot;
8540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                a_flush = true;
8550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
8560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else // [...<..]...> or [...<...>...]
8570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bot = a_top = b_top;
8580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
8590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else if (b_top < a_top)
8600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
8610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            inside = 2;
8620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            top = b_top;
8630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            run1 = b_runs;
8640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (b_bot <= a_top) // [...] <...>
8650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
8660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bot = b_bot;
8670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                b_flush = true;
8680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
8690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else // [...<..]...> or [...<...>...]
8700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bot = b_top = a_top;
8710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
8720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else    // a_top == b_top
8730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
8740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            inside = 3;
8750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            top = a_top;    // or b_top
8760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            run0 = a_runs;
8770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            run1 = b_runs;
8780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (a_bot <= b_bot)
8790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
8800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bot = b_top = a_bot;
8810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                a_flush = true;
8820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
8830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (b_bot <= a_bot)
8840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
8850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bot = a_top = b_bot;
8860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                b_flush = true;
8870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
8880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
8890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (top > prevBot)
8914c1037238c8ebcef8c75b5d43730ed308a11102cMike Reed            oper.addSpan(top, gSentinel, gSentinel);
8920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//      if ((unsigned)(inside - oper.fMin) <= (unsigned)(oper.fMax - oper.fMin))
8940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
8950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            oper.addSpan(bot, run0, run1);
8960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            firstInterval = false;
8970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
8980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (a_flush)
9000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
9010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            a_runs = skip_scanline(a_runs);
9020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            a_top = a_bot;
9030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            a_bot = *a_runs++;
9040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (a_bot == SkRegion::kRunTypeSentinel)
9050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                a_top = a_bot;
9060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
9070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (b_flush)
9080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
9090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            b_runs = skip_scanline(b_runs);
9100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            b_top = b_bot;
9110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            b_bot = *b_runs++;
9120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (b_bot == SkRegion::kRunTypeSentinel)
9130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                b_top = b_bot;
9140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
9150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        prevBot = bot;
9170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return oper.flush();
9190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
9220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*  Given count RunTypes in a complex region, return the worst case number of
9240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    logical intervals that represents (i.e. number of rects that would be
9250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    returned from the iterator).
9260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    We could just return count/2, since there must be at least 2 values per
9280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    interval, but we can first trim off the const overhead of the initial TOP
9290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    value, plus the final BOTTOM + 2 sentinels.
9300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
9310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic int count_to_intervals(int count) {
9320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(count >= 6);   // a single rect is 6 values
9330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (count - 4) >> 1;
9340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*  Given a number of intervals, what is the worst case representation of that
9370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    many intervals?
9380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Worst case (from a storage perspective), is a vertical stack of single
9400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    intervals:  TOP + N * (BOTTOM LEFT RIGHT SENTINEL) + SENTINEL
9410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
9420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic int intervals_to_count(int intervals) {
9430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return 1 + intervals * 4 + 1;
9440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*  Given the counts of RunTypes in two regions, return the worst-case number
9470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    of RunTypes need to store the result after a region-op.
9480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
9490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic int compute_worst_case_count(int a_count, int b_count) {
9500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int a_intervals = count_to_intervals(a_count);
9510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int b_intervals = count_to_intervals(b_count);
9520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // Our heuristic worst case is ai * (bi + 1) + bi * (ai + 1)
9530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int intervals = 2 * a_intervals * b_intervals + a_intervals + b_intervals;
9540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // convert back to number of RunType values
9550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return intervals_to_count(intervals);
9560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::op(const SkRegion& rgnaOrig, const SkRegion& rgnbOrig, Op op)
9590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
9600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(this->validate();)
9610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((unsigned)op < kOpCount);
9630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (kReplace_Op == op)
9650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return this->set(rgnbOrig);
9660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // swith to using pointers, so we can swap them as needed
9680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkRegion* rgna = &rgnaOrig;
9690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkRegion* rgnb = &rgnbOrig;
9700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // after this point, do not refer to rgnaOrig or rgnbOrig!!!
9710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // collaps difference and reverse-difference into just difference
9730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (kReverseDifference_Op == op)
9740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
9750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkTSwap<const SkRegion*>(rgna, rgnb);
9760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        op = kDifference_Op;
9770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkIRect bounds;
9800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool    a_empty = rgna->isEmpty();
9810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool    b_empty = rgnb->isEmpty();
9820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool    a_rect = rgna->isRect();
9830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool    b_rect = rgnb->isRect();
9840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (op) {
9860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    case kDifference_Op:
9870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (a_empty)
9880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return this->setEmpty();
9890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (b_empty || !SkIRect::Intersects(rgna->fBounds, rgnb->fBounds))
9900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return this->setRegion(*rgna);
9910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        break;
9920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    case kIntersect_Op:
9940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if ((a_empty | b_empty)
9950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                || !bounds.intersect(rgna->fBounds, rgnb->fBounds))
9960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return this->setEmpty();
9970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (a_rect & b_rect)
9980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return this->setRect(bounds);
9990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        break;
10000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    case kUnion_Op:
10020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (a_empty)
10030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return this->setRegion(*rgnb);
10040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (b_empty)
10050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return this->setRegion(*rgna);
10060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (a_rect && rgna->fBounds.contains(rgnb->fBounds))
10070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return this->setRegion(*rgna);
10080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (b_rect && rgnb->fBounds.contains(rgna->fBounds))
10090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return this->setRegion(*rgnb);
10100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        break;
10110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    case kXOR_Op:
10130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (a_empty)
10140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return this->setRegion(*rgnb);
10150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (b_empty)
10160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return this->setRegion(*rgna);
10170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        break;
10180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    default:
10190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(!"unknown region op");
10200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return !this->isEmpty();
10210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
10220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    RunType tmpA[kRectRegionRuns];
10240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    RunType tmpB[kRectRegionRuns];
10250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int a_count, b_count;
10270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const RunType* a_runs = rgna->getRuns(tmpA, &a_count);
10280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const RunType* b_runs = rgnb->getRuns(tmpB, &b_count);
10290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int dstCount = compute_worst_case_count(a_count, b_count);
10310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoSTMalloc<32, RunType> array(dstCount);
10320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int count = operate(a_runs, b_runs, array.get(), op);
10340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(count <= dstCount);
10350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return this->setRuns(array.get(), count);
10360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////////////////////////////////////
10390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBuffer.h"
10410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectuint32_t SkRegion::flatten(void* storage) const {
10430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (NULL == storage) {
10440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        uint32_t size = sizeof(int32_t); // -1 (empty), 0 (rect), runCount
10450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (!this->isEmpty()) {
10460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            size += sizeof(fBounds);
10470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (this->isComplex()) {
10480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                size += fRunHead->fRunCount * sizeof(RunType);
10490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
10500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
10510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return size;
10520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
10530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkWBuffer   buffer(storage);
10550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isEmpty()) {
10570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        buffer.write32(-1);
10580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {
10590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool isRect = this->isRect();
10600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        buffer.write32(isRect ? 0 : fRunHead->fRunCount);
10620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        buffer.write(&fBounds, sizeof(fBounds));
10630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (!isRect) {
10650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            buffer.write(fRunHead->readonly_runs(),
10660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                         fRunHead->fRunCount * sizeof(RunType));
10670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
10680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
10690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return buffer.pos();
10700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectuint32_t SkRegion::unflatten(const void* storage) {
10730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRBuffer   buffer(storage);
10740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkRegion    tmp;
10750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int32_t     count;
10760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    count = buffer.readS32();
10780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (count >= 0) {
10790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        buffer.read(&tmp.fBounds, sizeof(tmp.fBounds));
10800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (count == 0) {
10810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            tmp.fRunHead = SkRegion_gRectRunHeadPtr;
10820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
10830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            tmp.allocateRuns(count);
10840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            buffer.read(tmp.fRunHead->writable_runs(), count * sizeof(RunType));
10850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
10860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
10870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->swap(tmp);
10880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return buffer.pos();
10890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////////////////////////////////////
10920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
10940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const SkRegion::RunType* validate_line(const SkRegion::RunType run[], const SkIRect& bounds)
10960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
10970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // *run is the bottom of the current span
10980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(*run > bounds.fTop);
10990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(*run <= bounds.fBottom);
11000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    run += 1;
11010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // check for empty span
11030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (*run != SkRegion::kRunTypeSentinel)
11040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
11050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int prevRite = bounds.fLeft - 1;
11060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        do {
11070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int left = *run++;
11080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int rite = *run++;
11090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(left < rite);
11100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(left > prevRite);
11110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(rite <= bounds.fRight);
11120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            prevRite = rite;
11130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } while (*run < SkRegion::kRunTypeSentinel);
11140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return run + 1; // skip sentinel
11160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkRegion::validate() const
11190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
11200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isEmpty())
11210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
11220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // check for explicit empty (the zero rect), so we can compare rects to know when
11230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // two regions are equal (i.e. emptyRectA == emptyRectB)
11240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // this is stricter than just asserting fBounds.isEmpty()
11250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(fBounds.fLeft == 0 && fBounds.fTop == 0 && fBounds.fRight == 0 && fBounds.fBottom == 0);
11260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else
11280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
11290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(!fBounds.isEmpty());
11300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (!this->isRect())
11310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
11320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(fRunHead->fRefCnt >= 1);
11330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(fRunHead->fRunCount >= kRectRegionRuns);
11340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const RunType* run = fRunHead->readonly_runs();
11360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const RunType* stop = run + fRunHead->fRunCount;
11370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // check that our bounds match our runs
11390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
11400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkIRect bounds;
11410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bool isARect = ComputeRunBounds(run, stop - run, &bounds);
11420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(!isARect);
11430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(bounds == fBounds);
11440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
11450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(*run == fBounds.fTop);
11470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            run++;
11480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            do {
11490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                run = validate_line(run, fBounds);
11500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } while (*run < kRunTypeSentinel);
11510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(run + 1 == stop);
11520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
11530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkRegion::dump() const
11570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
11580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->isEmpty())
11590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkDebugf("  rgn: empty\n");
11600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else
11610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
11620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkDebugf("  rgn: [%d %d %d %d]", fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
11630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (this->isComplex())
11640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
11650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const RunType* runs = fRunHead->readonly_runs();
11660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            for (int i = 0; i < fRunHead->fRunCount; i++)
11670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkDebugf(" %d", runs[i]);
11680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
11690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkDebugf("\n");
11700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
11740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////////////
11760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkRegion::Iterator::Iterator(const SkRegion& rgn) {
11780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    this->reset(rgn);
11790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::Iterator::rewind() {
11820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fRgn) {
11830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->reset(*fRgn);
11840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
11850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return false;
11870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkRegion::Iterator::reset(const SkRegion& rgn) {
11900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRgn = &rgn;
11910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (rgn.isEmpty()) {
11920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fDone = true;
11930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {
11940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fDone = false;
11950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (rgn.isRect()) {
11960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRect = rgn.fBounds;
11970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRuns = NULL;
11980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
11990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRuns = rgn.fRunHead->readonly_runs();
12000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRect.set(fRuns[2], fRuns[0], fRuns[3], fRuns[1]);
12010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRuns += 4;
12020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
12030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkRegion::Iterator::next() {
12070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fDone) {
12080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
12090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fRuns == NULL) {   // rect case
12120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fDone = true;
12130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
12140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const RunType* runs = fRuns;
12170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (runs[0] < kRunTypeSentinel) { // valid X value
12190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRect.fLeft = runs[0];
12200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fRect.fRight = runs[1];
12210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        runs += 2;
12220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {    // we're at the end of a line
12230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        runs += 1;
12240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (runs[0] < kRunTypeSentinel) { // valid Y value
12250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (runs[1] == kRunTypeSentinel) {    // empty line
12260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fRect.fTop = runs[0];
12270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                runs += 2;
12280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
12290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fRect.fTop = fRect.fBottom;
12300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRect.fBottom = runs[0];
12330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            assert_sentinel(runs[1], false);
12340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRect.fLeft = runs[1];
12350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRect.fRight = runs[2];
12360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            runs += 3;
12370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {    // end of rgn
12380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fDone = true;
12390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
12400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRuns = runs;
12420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkRegion::Cliperator::Cliperator(const SkRegion& rgn, const SkIRect& clip)
12450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        : fIter(rgn), fClip(clip), fDone(true) {
12460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkIRect& r = fIter.rect();
12470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (!fIter.done()) {
12490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (r.fTop >= clip.fBottom) {
12500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
12510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
12520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fRect.intersect(clip, r)) {
12530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fDone = false;
12540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
12550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
12560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fIter.next();
12570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkRegion::Cliperator::next() {
12610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fDone) {
12620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
12630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkIRect& r = fIter.rect();
12660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fDone = true;
12680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fIter.next();
12690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (!fIter.done()) {
12700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (r.fTop >= fClip.fBottom) {
12710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
12720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
12730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fRect.intersect(fClip, r)) {
12740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fDone = false;
12750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
12760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
12770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fIter.next();
12780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////
12820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkRegion::Spanerator::Spanerator(const SkRegion& rgn, int y, int left, int right)
12840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
12850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(rgn.validate();)
12860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkIRect& r = rgn.getBounds();
12880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fDone = true;
12900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (!rgn.isEmpty() && y >= r.fTop && y < r.fBottom && right > r.fLeft && left < r.fRight)
12910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
12920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (rgn.isRect())
12930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
12940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (left < r.fLeft)
12950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                left = r.fLeft;
12960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (right > r.fRight)
12970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                right = r.fRight;
12980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fLeft = left;
13000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRight = right;
13010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fRuns = NULL;    // means we're a rect, not a rgn
13020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fDone = false;
13030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
13040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else
13050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        {
13060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const SkRegion::RunType* runs = find_y(rgn.fRunHead->readonly_runs(), y);
13070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (runs)
13080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            {
13090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                for (;;)
13100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                {
13110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    if (runs[0] >= right)   // runs[0..1] is to the right of the span, so we're done
13120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        break;
13130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    if (runs[1] <= left)    // runs[0..1] is to the left of the span, so continue
13140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    {
13150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        runs += 2;
13160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        continue;
13170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    }
13180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    // runs[0..1] intersects the span
13190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    fRuns = runs;
13200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    fLeft = left;
13210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    fRight = right;
13220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    fDone = false;
13230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    break;
13240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
13250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
13260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
13270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
13280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
13290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::Spanerator::next(int* left, int* right)
13310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
13320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fDone) return false;
13330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fRuns == NULL)   // we're a rect
13350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
13360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fDone = true;   // ok, now we're done
13370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (left) *left = fLeft;
13380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (right) *right = fRight;
13390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;    // this interval is legal
13400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
13410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkRegion::RunType* runs = fRuns;
13430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (runs[0] >= fRight)
13450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
13460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fDone = true;
13470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
13480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
13490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(runs[1] > fLeft);
13510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (left)
13530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *left = SkMax32(fLeft, runs[0]);
13540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (right)
13550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *right = SkMin32(fRight, runs[1]);
13560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fRuns = runs + 2;
13570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return true;
13580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
13590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
13610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
13630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkRegion::debugSetRuns(const RunType runs[], int count) {
13650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // we need to make a copy, since the real method may modify the array, and
13660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // so it cannot be const.
13670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkAutoTArray<RunType> storage(count);
13690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    memcpy(storage.get(), runs, count * sizeof(RunType));
13700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return this->setRuns(storage.get(), count);
13710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
13720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
13730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1374