1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRegionPriv.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplates.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkThread.h"
139c36a76102453db964cb6e51078a3d74d4126b2creed@google.com#include "SkUtils.h"
149c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
159c36a76102453db964cb6e51078a3d74d4126b2creed@google.com/* Region Layout
169c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *
179c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *  TOP
189c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *
199c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *  [ Bottom, X-Intervals, [Left, Right]..., X-Sentinel ]
209c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *  ...
219c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *
229c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *  Y-Sentinel
239c36a76102453db964cb6e51078a3d74d4126b2creed@google.com */
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDEBUGCODE(int32_t gRgnAllocCounter;)
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////////////////////////
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
299c36a76102453db964cb6e51078a3d74d4126b2creed@google.com/*  Pass in the beginning with the intervals.
309c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *  We back up 1 to read the interval-count.
319c36a76102453db964cb6e51078a3d74d4126b2creed@google.com *  Return the beginning of the next scanline (i.e. the next Y-value)
329c36a76102453db964cb6e51078a3d74d4126b2creed@google.com */
339c36a76102453db964cb6e51078a3d74d4126b2creed@google.comstatic SkRegion::RunType* skip_intervals(const SkRegion::RunType runs[]) {
349c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    int intervals = runs[-1];
359c36a76102453db964cb6e51078a3d74d4126b2creed@google.com#ifdef SK_DEBUG
369c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    if (intervals > 0) {
379c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(runs[0] < runs[1]);
389c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(runs[1] < SkRegion::kRunTypeSentinel);
399c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    } else {
409c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(0 == intervals);
419c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(SkRegion::kRunTypeSentinel == runs[0]);
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
439c36a76102453db964cb6e51078a3d74d4126b2creed@google.com#endif
449c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    runs += intervals * 2 + 1;
459c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    return const_cast<SkRegion::RunType*>(runs);
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
489c36a76102453db964cb6e51078a3d74d4126b2creed@google.combool SkRegion::RunsAreARect(const SkRegion::RunType runs[], int count,
499c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                            SkIRect* bounds) {
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    assert_sentinel(runs[0], false);    // top
519c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    SkASSERT(count >= kRectRegionRuns);
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    if (count == kRectRegionRuns) {
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        assert_sentinel(runs[1], false);    // bottom
559c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(1 == runs[2]);
569c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        assert_sentinel(runs[3], false);    // left
579c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        assert_sentinel(runs[4], false);    // right
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        assert_sentinel(runs[5], true);
599c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        assert_sentinel(runs[6], true);
60fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(runs[0] < runs[1]);    // valid height
629c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(runs[3] < runs[4]);    // valid width
63fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
649c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        bounds->set(runs[3], runs[0], runs[4], runs[1]);
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
720a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comSkRegion::SkRegion() {
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBounds.set(0, 0, 0, 0);
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRunHead = SkRegion_gEmptyRunHeadPtr;
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
770a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comSkRegion::SkRegion(const SkRegion& src) {
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRunHead = SkRegion_gEmptyRunHeadPtr;   // just need a value that won't trigger sk_free(fRunHead)
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setRegion(src);
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
820a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comSkRegion::SkRegion(const SkIRect& rect) {
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRunHead = SkRegion_gEmptyRunHeadPtr;   // just need a value that won't trigger sk_free(fRunHead)
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->setRect(rect);
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
870a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comSkRegion::~SkRegion() {
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->freeRuns();
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
910a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comvoid SkRegion::freeRuns() {
92b77b69f89f2551a4a14a30b1a44dd93ea5927bb1bungeman@google.com    if (this->isComplex()) {
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fRunHead->fRefCnt >= 1);
940a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com        if (sk_atomic_dec(&fRunHead->fRefCnt) == 1) {
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            //SkASSERT(gRgnAllocCounter > 0);
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            //SkDEBUGCODE(sk_atomic_dec(&gRgnAllocCounter));
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            //SkDEBUGF(("************** gRgnAllocCounter::free %d\n", gRgnAllocCounter));
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            sk_free(fRunHead);
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
103af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.comvoid SkRegion::allocateRuns(int count, int ySpanCount, int intervalCount) {
104af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com    fRunHead = RunHead::Alloc(count, ySpanCount, intervalCount);
105af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com}
106af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com
1079c36a76102453db964cb6e51078a3d74d4126b2creed@google.comvoid SkRegion::allocateRuns(int count) {
1089c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    fRunHead = RunHead::Alloc(count);
1099c36a76102453db964cb6e51078a3d74d4126b2creed@google.com}
1109c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
111af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.comvoid SkRegion::allocateRuns(const RunHead& head) {
112af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com    fRunHead = RunHead::Alloc(head.fRunCount,
113af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com                              head.getYSpanCount(),
114af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com                              head.getIntervalCount());
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1170a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comSkRegion& SkRegion::operator=(const SkRegion& src) {
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    (void)this->setRegion(src);
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return *this;
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1220a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comvoid SkRegion::swap(SkRegion& other) {
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkTSwap<SkIRect>(fBounds, other.fBounds);
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkTSwap<RunHead*>(fRunHead, other.fRunHead);
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1275dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.orgint SkRegion::computeRegionComplexity() const {
1285dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org  if (this->isEmpty()) {
1295dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org    return 0;
1305dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org  } else if (this->isRect()) {
1315dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org    return 1;
1325dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org  }
1335dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org  return fRunHead->getIntervalCount();
1345dd567c2a55c16c8bc2668902cdfce1734dfae8fcommit-bot@chromium.org}
135f7d01ce1849aa029743e9e0b810a8f955ad99f28skia.committer@gmail.com
1360a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.combool SkRegion::setEmpty() {
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->freeRuns();
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBounds.set(0, 0, 0, 0);
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRunHead = SkRegion_gEmptyRunHeadPtr;
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1430a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.combool SkRegion::setRect(int32_t left, int32_t top,
1440a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com                       int32_t right, int32_t bottom) {
1450a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com    if (left >= right || top >= bottom) {
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->setEmpty();
1470a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com    }
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->freeRuns();
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBounds.set(left, top, right, bottom);
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRunHead = SkRegion_gRectRunHeadPtr;
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1540a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.combool SkRegion::setRect(const SkIRect& r) {
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->setRect(r.fLeft, r.fTop, r.fRight, r.fBottom);
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1580a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.combool SkRegion::setRegion(const SkRegion& src) {
1590a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com    if (this != &src) {
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->freeRuns();
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBounds = src.fBounds;
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRunHead = src.fRunHead;
164b77b69f89f2551a4a14a30b1a44dd93ea5927bb1bungeman@google.com        if (this->isComplex()) {
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            sk_atomic_inc(&fRunHead->fRefCnt);
1660a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com        }
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fRunHead != SkRegion_gEmptyRunHeadPtr;
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1710a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.combool SkRegion::op(const SkIRect& rect, const SkRegion& rgn, Op op) {
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion tmp(rect);
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->op(tmp, rgn, op);
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1770a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.combool SkRegion::op(const SkRegion& rgn, const SkIRect& rect, Op op) {
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion tmp(rect);
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->op(rgn, tmp, op);
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1830a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com///////////////////////////////////////////////////////////////////////////////
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18556c69773aea56c6c6bd47bc7e7970dd081205184djsollen@google.com#ifdef SK_BUILD_FOR_ANDROID
1862c8e9d40a42ef24e811c3a2614b361cad1036110bungeman@google.com#include <stdio.h>
187c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.comchar* SkRegion::toString() {
188cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    Iterator iter(*this);
189cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    int count = 0;
190cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    while (!iter.done()) {
191cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        count++;
192cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        iter.next();
193cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    }
194cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    // 4 ints, up to 10 digits each plus sign, 3 commas, '(', ')', SkRegion() and '\0'
195cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    const int max = (count*((11*4)+5))+11+1;
196cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    char* result = (char*)malloc(max);
197cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    if (result == NULL) {
198cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        return NULL;
199cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    }
200cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    count = sprintf(result, "SkRegion(");
201cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    iter.reset(*this);
202cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    while (!iter.done()) {
203cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        const SkIRect& r = iter.rect();
204cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        count += sprintf(result+count, "(%d,%d,%d,%d)", r.fLeft, r.fTop, r.fRight, r.fBottom);
205cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com        iter.next();
206cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    }
207cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    count += sprintf(result+count, ")");
208cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com    return result;
209cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com}
210cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com#endif
211cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com
212c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com///////////////////////////////////////////////////////////////////////////////
213cd9d69b9ce7eb301a9fd8d91b9f95fd99b07bae5djsollen@google.com
214c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.comint SkRegion::count_runtype_values(int* itop, int* ibot) const {
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int maxT;
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
217c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    if (this->isRect()) {
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        maxT = 2;
219c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    } else {
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(this->isComplex());
221af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com        maxT = fRunHead->getIntervalCount() * 2;
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *itop = fBounds.fTop;
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *ibot = fBounds.fBottom;
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return maxT;
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2287d4aee34e23e536e1115f132d20a20fb629bb66areed@google.comstatic bool isRunCountEmpty(int count) {
2297d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    return count <= 2;
2307d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com}
2317d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com
232c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.combool SkRegion::setRuns(RunType runs[], int count) {
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(count > 0);
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
236c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    if (isRunCountEmpty(count)) {
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    //  SkDEBUGF(("setRuns: empty\n"));
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        assert_sentinel(runs[count-1], true);
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->setEmpty();
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // trim off any empty spans from the top and bottom
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // weird I should need this, perhaps op() could be smarter...
244c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    if (count > kRectRegionRuns) {
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        RunType* stop = runs + count;
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        assert_sentinel(runs[0], false);    // top
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        assert_sentinel(runs[1], false);    // bottom
2489c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        // runs[2] is uncomputed intervalCount
249fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2509c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        if (runs[3] == SkRegion::kRunTypeSentinel) {  // should be first left...
2519c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            runs += 3;  // skip empty initial span
2529c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            runs[0] = runs[-2]; // set new top to prev bottom
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            assert_sentinel(runs[1], false);    // bot: a sentinal would mean two in a row
2549c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            assert_sentinel(runs[2], false);    // intervalcount
2559c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            assert_sentinel(runs[3], false);    // left
2569c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            assert_sentinel(runs[4], false);    // right
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        assert_sentinel(stop[-1], true);
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        assert_sentinel(stop[-2], true);
2619c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
2629c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        // now check for a trailing empty span
2639c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        if (stop[-5] == SkRegion::kRunTypeSentinel) { // eek, stop[-4] was a bottom with no x-runs
2649c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            stop[-4] = SkRegion::kRunTypeSentinel;    // kill empty last span
2659c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            stop -= 3;
2669c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            assert_sentinel(stop[-1], true);    // last y-sentinel
2679c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            assert_sentinel(stop[-2], true);    // last x-sentinel
2689c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            assert_sentinel(stop[-3], false);   // last right
2699c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            assert_sentinel(stop[-4], false);   // last left
2709c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            assert_sentinel(stop[-5], false);   // last interval-count
2719c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            assert_sentinel(stop[-6], false);   // last bottom
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        count = (int)(stop - runs);
2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(count >= kRectRegionRuns);
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2789c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    if (SkRegion::RunsAreARect(runs, count, &fBounds)) {
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return this->setRect(fBounds);
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
281fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    //  if we get here, we need to become a complex region
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
284b77b69f89f2551a4a14a30b1a44dd93ea5927bb1bungeman@google.com    if (!this->isComplex() || fRunHead->fRunCount != count) {
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->freeRuns();
2869c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        this->allocateRuns(count);
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
288fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // must call this before we can write directly into runs()
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // in case we are sharing the buffer with another region (copy on write)
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRunHead = fRunHead->ensureWritable();
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    memcpy(fRunHead->writable_runs(), runs, count * sizeof(RunType));
2939c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    fRunHead->computeRunBounds(&fBounds);
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRegion::BuildRectRuns(const SkIRect& bounds,
301c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com                             RunType runs[kRectRegionRuns]) {
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    runs[0] = bounds.fTop;
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    runs[1] = bounds.fBottom;
3049c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    runs[2] = 1;    // 1 interval for this scanline
3059c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    runs[3] = bounds.fLeft;
3069c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    runs[4] = bounds.fRight;
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    runs[5] = kRunTypeSentinel;
3089c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    runs[6] = kRunTypeSentinel;
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
311c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.combool SkRegion::contains(int32_t x, int32_t y) const {
3129c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    SkDEBUGCODE(this->validate();)
3139c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
314c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    if (!fBounds.contains(x, y)) {
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
316c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    }
317c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    if (this->isRect()) {
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
319c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    }
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(this->isComplex());
321bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com
3229c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    const RunType* runs = fRunHead->findScanline(y);
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3249c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    // Skip the Bottom and IntervalCount
3259c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    runs += 2;
326fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
3279c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    // Just walk this scanline, checking each interval. The X-sentinel will
3289c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    // appear as a left-inteval (runs[0]) and should abort the search.
3299c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    //
3309c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    // We could do a bsearch, using interval-count (runs[1]), but need to time
3319c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    // when that would be worthwhile.
3329c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    //
3339c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    for (;;) {
3349c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        if (x < runs[0]) {
3359c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            break;
3369c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        }
3379c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        if (x < runs[1]) {
3389c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            return true;
3399c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        }
3409c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        runs += 2;
3419c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    }
3429c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    return false;
3439c36a76102453db964cb6e51078a3d74d4126b2creed@google.com}
3449c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
345796a1753d96eb0c76e742c8288617d758ddf33dfmike@reedtribe.orgstatic SkRegion::RunType scanline_bottom(const SkRegion::RunType runs[]) {
346796a1753d96eb0c76e742c8288617d758ddf33dfmike@reedtribe.org    return runs[0];
347796a1753d96eb0c76e742c8288617d758ddf33dfmike@reedtribe.org}
348796a1753d96eb0c76e742c8288617d758ddf33dfmike@reedtribe.org
3499c36a76102453db964cb6e51078a3d74d4126b2creed@google.comstatic const SkRegion::RunType* scanline_next(const SkRegion::RunType runs[]) {
3509c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    // skip [B N [L R]... S]
3519c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    return runs + 2 + runs[1] * 2 + 1;
3529c36a76102453db964cb6e51078a3d74d4126b2creed@google.com}
3539c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
3549c36a76102453db964cb6e51078a3d74d4126b2creed@google.comstatic bool scanline_contains(const SkRegion::RunType runs[],
3559c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                              SkRegion::RunType L, SkRegion::RunType R) {
3569c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    runs += 2;  // skip Bottom and IntervalCount
3579c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    for (;;) {
3589c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        if (L < runs[0]) {
3599c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            break;
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3619c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        if (R <= runs[1]) {
3629c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            return true;
3639c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        }
3649c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        runs += 2;
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
369c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.combool SkRegion::contains(const SkIRect& r) const {
3709c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    SkDEBUGCODE(this->validate();)
3719c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
3729c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    if (!fBounds.contains(r)) {
3739c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        return false;
3749c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    }
3759c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    if (this->isRect()) {
3769c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        return true;
3779c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    }
3789c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    SkASSERT(this->isComplex());
379bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com
3809c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    const RunType* scanline = fRunHead->findScanline(r.fTop);
381bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com    for (;;) {
3829c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        if (!scanline_contains(scanline, r.fLeft, r.fRight)) {
3839c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            return false;
3849c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        }
385bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com        if (r.fBottom <= scanline_bottom(scanline)) {
386bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com            break;
387bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com        }
3889c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        scanline = scanline_next(scanline);
389bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com    }
3909c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    return true;
3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
393c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.combool SkRegion::contains(const SkRegion& rgn) const {
3949c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    SkDEBUGCODE(this->validate();)
3959c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    SkDEBUGCODE(rgn.validate();)
3969c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
397c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    if (this->isEmpty() || rgn.isEmpty() || !fBounds.contains(rgn.fBounds)) {
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
399c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    }
400c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    if (this->isRect()) {
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
402c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    }
4039c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    if (rgn.isRect()) {
4049c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        return this->contains(rgn.getBounds());
4059c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    }
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4077d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    /*
4087d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com     *  A contains B is equivalent to
4097d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com     *  B - A == 0
4107d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com     */
4117d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    return !Oper(rgn, *this, kDifference_Op, NULL);
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
414c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.comconst SkRegion::RunType* SkRegion::getRuns(RunType tmpStorage[],
415af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com                                           int* intervals) const {
416af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com    SkASSERT(tmpStorage && intervals);
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const RunType* runs = tmpStorage;
4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
419c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    if (this->isEmpty()) {
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        tmpStorage[0] = kRunTypeSentinel;
421af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com        *intervals = 0;
422c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    } else if (this->isRect()) {
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        BuildRectRuns(fBounds, tmpStorage);
424af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com        *intervals = 1;
425c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    } else {
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs = fRunHead->readonly_runs();
427af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com        *intervals = fRunHead->getIntervalCount();
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return runs;
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
432c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com///////////////////////////////////////////////////////////////////////////////
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4349c36a76102453db964cb6e51078a3d74d4126b2creed@google.comstatic bool scanline_intersects(const SkRegion::RunType runs[],
4359c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                                SkRegion::RunType L, SkRegion::RunType R) {
4369c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    runs += 2;  // skip Bottom and IntervalCount
4379c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    for (;;) {
4389c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        if (R <= runs[0]) {
4399c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            break;
4409c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        }
4419c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        if (L < runs[1]) {
4429c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            return true;
4439c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        }
4449c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        runs += 2;
4459c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    }
4469c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    return false;
4479c36a76102453db964cb6e51078a3d74d4126b2creed@google.com}
4489c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkRegion::intersects(const SkIRect& r) const {
4509c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    SkDEBUGCODE(this->validate();)
451fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (this->isEmpty() || r.isEmpty()) {
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
455fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4569c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    SkIRect sect;
4579c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    if (!sect.intersect(fBounds, r)) {
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (this->isRect()) {
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
463bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com    SkASSERT(this->isComplex());
464fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4659c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    const RunType* scanline = fRunHead->findScanline(sect.fTop);
466bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com    for (;;) {
4679c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        if (scanline_intersects(scanline, sect.fLeft, sect.fRight)) {
4689c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            return true;
4699c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        }
470bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com        if (sect.fBottom <= scanline_bottom(scanline)) {
471bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com            break;
472bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com        }
4739c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        scanline = scanline_next(scanline);
474bb094b947bb53374f5ad3df1b0cc71f41d43d9bfreed@google.com    }
4759c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    return false;
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkRegion::intersects(const SkRegion& rgn) const {
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (this->isEmpty() || rgn.isEmpty()) {
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
482fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (!SkIRect::Intersects(fBounds, rgn.fBounds)) {
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
486fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
4879c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    bool weAreARect = this->isRect();
4889c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    bool theyAreARect = rgn.isRect();
4899c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
4909c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    if (weAreARect && theyAreARect) {
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4939c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    if (weAreARect) {
4949c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        return rgn.intersects(this->getBounds());
4959c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    }
4969c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    if (theyAreARect) {
4979c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        return this->intersects(rgn.getBounds());
4989c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    }
499fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5009c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    // both of us are complex
5017d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    return Oper(*this, rgn, kIntersect_Op, NULL);
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
504c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com///////////////////////////////////////////////////////////////////////////////
5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5066d428d3e6e4238786a38caca6002dae92637958dreed@google.combool SkRegion::operator==(const SkRegion& b) const {
5076d428d3e6e4238786a38caca6002dae92637958dreed@google.com    SkDEBUGCODE(validate();)
5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(b.validate();)
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5106d428d3e6e4238786a38caca6002dae92637958dreed@google.com    if (this == &b) {
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
51297fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com    }
5136d428d3e6e4238786a38caca6002dae92637958dreed@google.com    if (fBounds != b.fBounds) {
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
51597fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com    }
516fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5176d428d3e6e4238786a38caca6002dae92637958dreed@google.com    const SkRegion::RunHead* ah = fRunHead;
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion::RunHead* bh = b.fRunHead;
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // this catches empties and rects being equal
52197fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com    if (ah == bh) {
5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
52397fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com    }
5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // now we insist that both are complex (but different ptrs)
525b77b69f89f2551a4a14a30b1a44dd93ea5927bb1bungeman@google.com    if (!this->isComplex() || !b.isComplex()) {
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
52797fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com    }
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return  ah->fRunCount == bh->fRunCount &&
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            !memcmp(ah->readonly_runs(), bh->readonly_runs(),
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    ah->fRunCount * sizeof(SkRegion::RunType));
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53397fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.comvoid SkRegion::translate(int dx, int dy, SkRegion* dst) const {
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53697fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com    if (NULL == dst) {
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
53897fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com    }
53997fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com    if (this->isEmpty()) {
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst->setEmpty();
54197fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com    } else if (this->isRect()) {
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst->setRect(fBounds.fLeft + dx, fBounds.fTop + dy,
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                     fBounds.fRight + dx, fBounds.fBottom + dy);
54497fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com    } else {
54597fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com        if (this == dst) {
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst->fRunHead = dst->fRunHead->ensureWritable();
54797fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com        } else {
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkRegion    tmp;
549af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com            tmp.allocateRuns(*fRunHead);
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            tmp.fBounds = fBounds;
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            dst->swap(tmp);
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        dst->fBounds.offset(dx, dy);
555fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const RunType*  sruns = fRunHead->readonly_runs();
5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        RunType*        druns = dst->fRunHead->writable_runs();
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *druns++ = (SkRegion::RunType)(*sruns++ + dy);    // top
56097fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com        for (;;) {
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int bottom = *sruns++;
56297fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com            if (bottom == kRunTypeSentinel) {
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
56497fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com            }
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *druns++ = (SkRegion::RunType)(bottom + dy);  // bottom;
5669c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            *druns++ = *sruns++;    // copy intervalCount;
56797fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com            for (;;) {
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int x = *sruns++;
56997fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com                if (x == kRunTypeSentinel) {
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    break;
57197fa34c5f0079c4ae5fdf2c9f86772ff793d0133reed@google.com                }
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *druns++ = (SkRegion::RunType)(x + dx);
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *druns++ = (SkRegion::RunType)(*sruns++ + dx);
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            *druns++ = kRunTypeSentinel;    // x sentinel
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *druns++ = kRunTypeSentinel;    // y sentinel
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(sruns - fRunHead->readonly_runs() == fRunHead->fRunCount);
5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(druns - dst->fRunHead->readonly_runs() == dst->fRunHead->fRunCount);
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(this->validate();)
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
586097a3513535ad854c1b049c32c080ec875ab1411reed@android.com///////////////////////////////////////////////////////////////////////////////
587097a3513535ad854c1b049c32c080ec875ab1411reed@android.com
588097a3513535ad854c1b049c32c080ec875ab1411reed@android.combool SkRegion::setRects(const SkIRect rects[], int count) {
589097a3513535ad854c1b049c32c080ec875ab1411reed@android.com    if (0 == count) {
590cb34235f46b6259b612e72c416e850e26803250areed@android.com        this->setEmpty();
591cb34235f46b6259b612e72c416e850e26803250areed@android.com    } else {
592cb34235f46b6259b612e72c416e850e26803250areed@android.com        this->setRect(rects[0]);
593cb34235f46b6259b612e72c416e850e26803250areed@android.com        for (int i = 1; i < count; i++) {
594cb34235f46b6259b612e72c416e850e26803250areed@android.com            this->op(rects[i], kUnion_Op);
595097a3513535ad854c1b049c32c080ec875ab1411reed@android.com        }
596097a3513535ad854c1b049c32c080ec875ab1411reed@android.com    }
597cb34235f46b6259b612e72c416e850e26803250areed@android.com    return !this->isEmpty();
598097a3513535ad854c1b049c32c080ec875ab1411reed@android.com}
599097a3513535ad854c1b049c32c080ec875ab1411reed@android.com
600097a3513535ad854c1b049c32c080ec875ab1411reed@android.com///////////////////////////////////////////////////////////////////////////////
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300  // disable warning : local variable used without having been initialized
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( push )
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( disable : 4701 )
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void assert_valid_pair(int left, int rite)
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(left == SkRegion::kRunTypeSentinel || left < rite);
6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define assert_valid_pair(left, rite)
6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct spanRec {
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion::RunType*    fA_runs;
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion::RunType*    fB_runs;
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int                         fA_left, fA_rite, fB_left, fB_rite;
6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int                         fLeft, fRite, fInside;
621fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
622c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    void init(const SkRegion::RunType a_runs[],
623c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com              const SkRegion::RunType b_runs[]) {
6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fA_left = *a_runs++;
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fA_rite = *a_runs++;
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fB_left = *b_runs++;
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fB_rite = *b_runs++;
6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fA_runs = a_runs;
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fB_runs = b_runs;
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
632fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
633c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    bool done() const {
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fA_left <= SkRegion::kRunTypeSentinel);
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fB_left <= SkRegion::kRunTypeSentinel);
636c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com        return fA_left == SkRegion::kRunTypeSentinel &&
637c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com               fB_left == SkRegion::kRunTypeSentinel;
6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
640c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    void next() {
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        assert_valid_pair(fA_left, fA_rite);
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        assert_valid_pair(fB_left, fB_rite);
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int     inside, left, rite SK_INIT_TO_AVOID_WARNING;
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bool    a_flush = false;
6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bool    b_flush = false;
647fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int a_left = fA_left;
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int a_rite = fA_rite;
6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int b_left = fB_left;
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int b_rite = fB_rite;
6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
653c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com        if (a_left < b_left) {
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            inside = 1;
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            left = a_left;
656c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com            if (a_rite <= b_left) {   // [...] <...>
6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rite = a_rite;
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                a_flush = true;
659c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com            } else { // [...<..]...> or [...<...>...]
6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rite = a_left = b_left;
661c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com            }
662c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com        } else if (b_left < a_left) {
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            inside = 2;
6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            left = b_left;
665c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com            if (b_rite <= a_left) {   // [...] <...>
6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rite = b_rite;
6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                b_flush = true;
668c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com            } else {    // [...<..]...> or [...<...>...]
6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rite = b_left = a_left;
670c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com            }
671c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com        } else {    // a_left == b_left
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            inside = 3;
6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            left = a_left;  // or b_left
674c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com            if (a_rite <= b_rite) {
6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rite = b_left = a_rite;
6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                a_flush = true;
6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
678c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com            if (b_rite <= a_rite) {
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rite = a_left = b_rite;
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                b_flush = true;
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
684c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com        if (a_flush) {
6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            a_left = *fA_runs++;
6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            a_rite = *fA_runs++;
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
688c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com        if (b_flush) {
6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            b_left = *fB_runs++;
6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            b_rite = *fB_runs++;
6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(left <= rite);
694fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // now update our state
6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fA_left = a_left;
6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fA_rite = a_rite;
6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fB_left = b_left;
6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fB_rite = b_rite;
700fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fLeft = left;
7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRite = rite;
7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fInside = inside;
7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkRegion::RunType* operate_on_span(const SkRegion::RunType a_runs[],
7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                          const SkRegion::RunType b_runs[],
7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                          SkRegion::RunType dst[],
710c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com                                          int min, int max) {
7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    spanRec rec;
7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool    firstInterval = true;
713fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    rec.init(a_runs, b_runs);
7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
716c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    while (!rec.done()) {
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        rec.next();
718fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int left = rec.fLeft;
7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int rite = rec.fRite;
721fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // add left,rite to our dst buffer (checking for coincidence
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((unsigned)(rec.fInside - min) <= (unsigned)(max - min) &&
724c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com                left < rite) {    // skip if equal
725c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com            if (firstInterval || dst[-1] < left) {
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *dst++ = (SkRegion::RunType)(left);
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                *dst++ = (SkRegion::RunType)(rite);
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                firstInterval = false;
729c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com            } else {
730c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com                // update the right edge
7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                dst[-1] = (SkRegion::RunType)(rite);
732c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com            }
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    *dst++ = SkRegion::kRunTypeSentinel;
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return dst;
7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( pop )
7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const struct {
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint8_t fMin;
7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint8_t fMax;
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} gOpMinMax[] = {
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { 1, 1 },   // Difference
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { 3, 3 },   // Intersection
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { 1, 3 },   // Union
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    { 1, 2 }    // XOR
7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass RgnOper {
7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
756c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    RgnOper(int top, SkRegion::RunType dst[], SkRegion::Op op) {
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // need to ensure that the op enum lines up with our minmax array
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkRegion::kDifference_Op == 0);
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkRegion::kIntersect_Op == 1);
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkRegion::kUnion_Op == 2);
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(SkRegion::kXOR_Op == 3);
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((unsigned)op <= 3);
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStartDst = dst;
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPrevDst = dst + 1;
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPrevLen = 0;       // will never match a length from operate_on_span
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fTop = (SkRegion::RunType)(top);    // just a first guess, we might update this
7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMin = gOpMinMax[op].fMin;
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMax = gOpMinMax[op].fMax;
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
773c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    void addSpan(int bottom, const SkRegion::RunType a_runs[],
774c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com                 const SkRegion::RunType b_runs[]) {
7759c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        // skip X values and slots for the next Y+intervalCount
7769c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkRegion::RunType*  start = fPrevDst + fPrevLen + 2;
7779c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        // start points to beginning of dst interval
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkRegion::RunType*  stop = operate_on_span(a_runs, b_runs, start, fMin, fMax);
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        size_t              len = stop - start;
7809c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(len >= 1 && (len & 1) == 1);
7819c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(SkRegion::kRunTypeSentinel == stop[-1]);
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
783c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com        if (fPrevLen == len &&
7849c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            (1 == len || !memcmp(fPrevDst, start,
7859c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                                 (len - 1) * sizeof(SkRegion::RunType)))) {
786c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com            // update Y value
7879c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            fPrevDst[-2] = (SkRegion::RunType)(bottom);
788c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com        } else {    // accept the new span
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (len == 1 && fPrevLen == 0) {
7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fTop = (SkRegion::RunType)(bottom); // just update our bottom
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
7929c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                start[-2] = (SkRegion::RunType)(bottom);
793f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org                start[-1] = SkToS32(len >> 1);
7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fPrevDst = start;
7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fPrevLen = len;
7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
799fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
800c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    int flush() {
8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fStartDst[0] = fTop;
8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPrevDst[fPrevLen] = SkRegion::kRunTypeSentinel;
8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return (int)(fPrevDst - fStartDst + fPrevLen + 1);
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8067d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    bool isEmpty() const { return 0 == fPrevLen; }
8077d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint8_t fMin, fMax;
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::RunType*  fStartDst;
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::RunType*  fPrevDst;
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    size_t              fPrevLen;
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::RunType   fTop;
8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8177d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com// want a unique value to signal that we exited due to quickExit
8187d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com#define QUICK_EXIT_TRUE_COUNT   (-1)
8197d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com
8201deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.comstatic int operate(const SkRegion::RunType a_runs[],
8211deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com                   const SkRegion::RunType b_runs[],
8221deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com                   SkRegion::RunType dst[],
8237d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com                   SkRegion::Op op,
8247d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com                   bool quickExit) {
8259c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    const SkRegion::RunType gEmptyScanline[] = {
8269c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        0,  // dummy bottom value
8279c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        0,  // zero intervals
8285f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com        SkRegion::kRunTypeSentinel,
8295f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com        // just need a 2nd value, since spanRec.init() reads 2 values, even
8305f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com        // though if the first value is the sentinel, it ignores the 2nd value.
8315f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com        // w/o the 2nd value here, we might read uninitialized memory.
8325f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com        // This happens when we are using gSentinel, which is pointing at
8335f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com        // our sentinel value.
8345f7c8a55eeb6c15b563166b44b86484d9b039375reed@google.com        0
835fbb02e7e96745cec30c6c21ad58cc596b4e1c64dreed@android.com    };
8369c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    const SkRegion::RunType* const gSentinel = &gEmptyScanline[2];
8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int a_top = *a_runs++;
8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int a_bot = *a_runs++;
8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int b_top = *b_runs++;
8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int b_bot = *b_runs++;
8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8439c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    a_runs += 1;    // skip the intervalCount;
8449c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    b_runs += 1;    // skip the intervalCount;
8459c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
8469c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    // Now a_runs and b_runs to their intervals (or sentinel)
8479c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    assert_sentinel(a_top, false);
8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    assert_sentinel(a_bot, false);
8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    assert_sentinel(b_top, false);
8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    assert_sentinel(b_bot, false);
8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    RgnOper oper(SkMin32(a_top, b_top), dst, op);
854fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int prevBot = SkRegion::kRunTypeSentinel; // so we fail the first test
856fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
8571deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com    while (a_bot < SkRegion::kRunTypeSentinel ||
8581deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com           b_bot < SkRegion::kRunTypeSentinel) {
8591deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com        int                         top, bot SK_INIT_TO_AVOID_WARNING;
860fbb02e7e96745cec30c6c21ad58cc596b4e1c64dreed@android.com        const SkRegion::RunType*    run0 = gSentinel;
861fbb02e7e96745cec30c6c21ad58cc596b4e1c64dreed@android.com        const SkRegion::RunType*    run1 = gSentinel;
8621deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com        bool                        a_flush = false;
8631deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com        bool                        b_flush = false;
8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8651deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com        if (a_top < b_top) {
8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            top = a_top;
8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            run0 = a_runs;
8681deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com            if (a_bot <= b_top) {   // [...] <...>
8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bot = a_bot;
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                a_flush = true;
8711deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com            } else {  // [...<..]...> or [...<...>...]
8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bot = a_top = b_top;
8731deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com            }
8741deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com        } else if (b_top < a_top) {
8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            top = b_top;
8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            run1 = b_runs;
8771deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com            if (b_bot <= a_top) {   // [...] <...>
8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bot = b_bot;
8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                b_flush = true;
8801deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com            } else {    // [...<..]...> or [...<...>...]
8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bot = b_top = a_top;
8821deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com            }
8831deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com        } else {    // a_top == b_top
8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            top = a_top;    // or b_top
8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            run0 = a_runs;
8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            run1 = b_runs;
8871deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com            if (a_bot <= b_bot) {
8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bot = b_top = a_bot;
8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                a_flush = true;
8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
8911deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com            if (b_bot <= a_bot) {
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bot = a_top = b_bot;
8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                b_flush = true;
8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
896fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
8971deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com        if (top > prevBot) {
898fbb02e7e96745cec30c6c21ad58cc596b4e1c64dreed@android.com            oper.addSpan(top, gSentinel, gSentinel);
8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9001deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com        oper.addSpan(bot, run0, run1);
9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9027d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        if (quickExit && !oper.isEmpty()) {
9037d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com            return QUICK_EXIT_TRUE_COUNT;
9047d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        }
9057d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com
9061deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com        if (a_flush) {
9079c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            a_runs = skip_intervals(a_runs);
9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            a_top = a_bot;
9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            a_bot = *a_runs++;
9109c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            a_runs += 1;    // skip uninitialized intervalCount
9111deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com            if (a_bot == SkRegion::kRunTypeSentinel) {
9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                a_top = a_bot;
9131deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com            }
9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
9151deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com        if (b_flush) {
9169c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            b_runs = skip_intervals(b_runs);
9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            b_top = b_bot;
9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            b_bot = *b_runs++;
9199c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            b_runs += 1;    // skip uninitialized intervalCount
9201deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com            if (b_bot == SkRegion::kRunTypeSentinel) {
9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                b_top = b_bot;
9221deaab51e76848a60b9e8afd8be3fe32557f5374reed@google.com            }
9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
924fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        prevBot = bot;
9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return oper.flush();
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Given count RunTypes in a complex region, return the worst case number of
9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    logical intervals that represents (i.e. number of rects that would be
9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    returned from the iterator).
935fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    We could just return count/2, since there must be at least 2 values per
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    interval, but we can first trim off the const overhead of the initial TOP
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    value, plus the final BOTTOM + 2 sentinels.
9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
940803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#if 0 // UNUSED
9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int count_to_intervals(int count) {
9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(count >= 6);   // a single rect is 6 values
9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (count - 4) >> 1;
9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
945803eceb6afd13f07416df0b4a9bb714e9370f081caryclark@google.com#endif
9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  Given a number of intervals, what is the worst case representation of that
9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    many intervals?
949fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Worst case (from a storage perspective), is a vertical stack of single
9519c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    intervals:  TOP + N * (BOTTOM INTERVALCOUNT LEFT RIGHT SENTINEL) + SENTINEL
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int intervals_to_count(int intervals) {
9549c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    return 1 + intervals * 5 + 1;
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
957af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com/*  Given the intervalCounts of RunTypes in two regions, return the worst-case number
9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    of RunTypes need to store the result after a region-op.
9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
960af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.comstatic int compute_worst_case_count(int a_intervals, int b_intervals) {
9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // Our heuristic worst case is ai * (bi + 1) + bi * (ai + 1)
9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int intervals = 2 * a_intervals * b_intervals + a_intervals + b_intervals;
9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // convert back to number of RunType values
9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return intervals_to_count(intervals);
9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9677d4aee34e23e536e1115f132d20a20fb629bb66areed@google.comstatic bool setEmptyCheck(SkRegion* result) {
9687d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    return result ? result->setEmpty() : false;
9697d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com}
9707d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com
9717d4aee34e23e536e1115f132d20a20fb629bb66areed@google.comstatic bool setRectCheck(SkRegion* result, const SkIRect& rect) {
9727d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    return result ? result->setRect(rect) : !rect.isEmpty();
9737d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com}
9747d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com
9757d4aee34e23e536e1115f132d20a20fb629bb66areed@google.comstatic bool setRegionCheck(SkRegion* result, const SkRegion& rgn) {
9767d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    return result ? result->setRegion(rgn) : !rgn.isEmpty();
9777d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com}
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9797d4aee34e23e536e1115f132d20a20fb629bb66areed@google.combool SkRegion::Oper(const SkRegion& rgnaOrig, const SkRegion& rgnbOrig, Op op,
9807d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com                    SkRegion* result) {
9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT((unsigned)op < kOpCount);
982fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
9837d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    if (kReplace_Op == op) {
9847d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        return setRegionCheck(result, rgnbOrig);
9857d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    }
986fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // swith to using pointers, so we can swap them as needed
9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion* rgna = &rgnaOrig;
9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion* rgnb = &rgnbOrig;
9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // after this point, do not refer to rgnaOrig or rgnbOrig!!!
9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // collaps difference and reverse-difference into just difference
9937d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    if (kReverseDifference_Op == op) {
9948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkTSwap<const SkRegion*>(rgna, rgnb);
9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        op = kDifference_Op;
9968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect bounds;
9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool    a_empty = rgna->isEmpty();
10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool    b_empty = rgnb->isEmpty();
10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool    a_rect = rgna->isRect();
10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bool    b_rect = rgnb->isRect();
10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (op) {
10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case kDifference_Op:
10067d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        if (a_empty) {
10077d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com            return setEmptyCheck(result);
10087d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        }
10090d10280190c411b18feb569a2248552047d1aa93reed@google.com        if (b_empty || !SkIRect::IntersectsNoEmptyCheck(rgna->fBounds,
10100d10280190c411b18feb569a2248552047d1aa93reed@google.com                                                        rgnb->fBounds)) {
10117d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com            return setRegionCheck(result, *rgna);
10127d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        }
10130d10280190c411b18feb569a2248552047d1aa93reed@google.com        if (b_rect && rgnb->fBounds.containsNoEmptyCheck(rgna->fBounds)) {
10140d10280190c411b18feb569a2248552047d1aa93reed@google.com            return setEmptyCheck(result);
10150d10280190c411b18feb569a2248552047d1aa93reed@google.com        }
10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        break;
10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case kIntersect_Op:
10198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if ((a_empty | b_empty)
10207d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com                || !bounds.intersect(rgna->fBounds, rgnb->fBounds)) {
10217d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com            return setEmptyCheck(result);
10227d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        }
10237d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        if (a_rect & b_rect) {
10247d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com            return setRectCheck(result, bounds);
10257d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        }
1026633c32b13b5d199d797be669d3dc7981d603a945reed@google.com        if (a_rect && rgna->fBounds.contains(rgnb->fBounds)) {
1027633c32b13b5d199d797be669d3dc7981d603a945reed@google.com            return setRegionCheck(result, *rgnb);
1028633c32b13b5d199d797be669d3dc7981d603a945reed@google.com        }
1029633c32b13b5d199d797be669d3dc7981d603a945reed@google.com        if (b_rect && rgnb->fBounds.contains(rgna->fBounds)) {
1030633c32b13b5d199d797be669d3dc7981d603a945reed@google.com            return setRegionCheck(result, *rgna);
1031633c32b13b5d199d797be669d3dc7981d603a945reed@google.com        }
10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        break;
10338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case kUnion_Op:
10357d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        if (a_empty) {
10367d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com            return setRegionCheck(result, *rgnb);
10377d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        }
10387d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        if (b_empty) {
10397d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com            return setRegionCheck(result, *rgna);
10407d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        }
10417d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        if (a_rect && rgna->fBounds.contains(rgnb->fBounds)) {
10427d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com            return setRegionCheck(result, *rgna);
10437d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        }
10447d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        if (b_rect && rgnb->fBounds.contains(rgna->fBounds)) {
10457d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com            return setRegionCheck(result, *rgnb);
10467d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        }
10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        break;
10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    case kXOR_Op:
10507d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        if (a_empty) {
10517d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com            return setRegionCheck(result, *rgnb);
10527d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        }
10537d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        if (b_empty) {
10547d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com            return setRegionCheck(result, *rgna);
10557d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        }
10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        break;
10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    default:
10580c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com        SkDEBUGFAIL("unknown region op");
10597d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        return false;
10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    RunType tmpA[kRectRegionRuns];
10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    RunType tmpB[kRectRegionRuns];
10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1065af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com    int a_intervals, b_intervals;
1066af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com    const RunType* a_runs = rgna->getRuns(tmpA, &a_intervals);
1067af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com    const RunType* b_runs = rgnb->getRuns(tmpB, &b_intervals);
10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1069af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com    int dstCount = compute_worst_case_count(a_intervals, b_intervals);
1070af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com    SkAutoSTMalloc<256, RunType> array(dstCount);
10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10729c36a76102453db964cb6e51078a3d74d4126b2creed@google.com#ifdef SK_DEBUG
10739c36a76102453db964cb6e51078a3d74d4126b2creed@google.com//  Sometimes helpful to seed everything with a known value when debugging
10749c36a76102453db964cb6e51078a3d74d4126b2creed@google.com//  sk_memset32((uint32_t*)array.get(), 0x7FFFFFFF, dstCount);
10759c36a76102453db964cb6e51078a3d74d4126b2creed@google.com#endif
10769c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
10777d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    int count = operate(a_runs, b_runs, array.get(), op, NULL == result);
10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(count <= dstCount);
1079af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com
10807d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    if (result) {
10817d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        SkASSERT(count >= 0);
10827d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        return result->setRuns(array.get(), count);
10837d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    } else {
10847d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com        return (QUICK_EXIT_TRUE_COUNT == count) || !isRunCountEmpty(count);
10857d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    }
10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10887d4aee34e23e536e1115f132d20a20fb629bb66areed@google.combool SkRegion::op(const SkRegion& rgna, const SkRegion& rgnb, Op op) {
10897d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    SkDEBUGCODE(this->validate();)
10907d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com    return SkRegion::Oper(rgna, rgnb, op, this);
10917d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com}
10927d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com
10937d4aee34e23e536e1115f132d20a20fb629bb66areed@google.com///////////////////////////////////////////////////////////////////////////////
10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBuffer.h"
10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10974faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.orgsize_t SkRegion::writeToMemory(void* storage) const {
10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (NULL == storage) {
10994faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org        size_t size = sizeof(int32_t); // -1 (empty), 0 (rect), runCount
11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!this->isEmpty()) {
11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            size += sizeof(fBounds);
11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (this->isComplex()) {
1103af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com                size += 2 * sizeof(int32_t);    // ySpanCount + intervalCount
11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                size += fRunHead->fRunCount * sizeof(RunType);
11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return size;
11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkWBuffer   buffer(storage);
11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (this->isEmpty()) {
11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.write32(-1);
11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        bool isRect = this->isRect();
11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.write32(isRect ? 0 : fRunHead->fRunCount);
11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.write(&fBounds, sizeof(fBounds));
11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (!isRect) {
1121af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com            buffer.write32(fRunHead->getYSpanCount());
1122af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com            buffer.write32(fRunHead->getIntervalCount());
11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            buffer.write(fRunHead->readonly_runs(),
11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                         fRunHead->fRunCount * sizeof(RunType));
11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return buffer.pos();
11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11304faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.orgsize_t SkRegion::readFromMemory(const void* storage, size_t length) {
11314faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    SkRBufferWithSizeCheck  buffer(storage, length);
11324faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    SkRegion                tmp;
11334faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    int32_t                 count;
1134382fde3a3c5cb5e8e3dcdc4c549541453851d8d0skia.committer@gmail.com
11358f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org    if (buffer.readS32(&count) && (count >= 0) && buffer.read(&tmp.fBounds, sizeof(tmp.fBounds))) {
11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count == 0) {
11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            tmp.fRunHead = SkRegion_gRectRunHeadPtr;
11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
11398f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org            int32_t ySpanCount, intervalCount;
11408f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org            if (buffer.readS32(&ySpanCount) && buffer.readS32(&intervalCount)) {
11414faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org                tmp.allocateRuns(count, ySpanCount, intervalCount);
11424faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org                buffer.read(tmp.fRunHead->writable_runs(), count * sizeof(RunType));
11434faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org            }
11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
11464faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t sizeRead = 0;
11474faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    if (buffer.isValid()) {
11484faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org        this->swap(tmp);
11494faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org        sizeRead = buffer.pos();
11504faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    }
11514faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    return sizeRead;
11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11540a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com///////////////////////////////////////////////////////////////////////////////
11550a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com
11560a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comconst SkRegion& SkRegion::GetEmptyRegion() {
11570a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com    static SkRegion gEmpty;
11580a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com    return gEmpty;
11590a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com}
11600a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com
11610a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com///////////////////////////////////////////////////////////////////////////////
11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
11659c36a76102453db964cb6e51078a3d74d4126b2creed@google.com// Starts with first X-interval, and returns a ptr to the X-sentinel
11669c36a76102453db964cb6e51078a3d74d4126b2creed@google.comstatic const SkRegion::RunType* skip_intervals_slow(const SkRegion::RunType runs[]) {
11679c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    // want to track that our intevals are all disjoint, such that
11689c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    // prev-right < next-left. We rely on this optimization in places such as
11699c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    // contains().
11709c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    //
11719c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    SkRegion::RunType prevR = -SkRegion::kRunTypeSentinel;
1172fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
11739c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    while (runs[0] < SkRegion::kRunTypeSentinel) {
11749c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(prevR < runs[0]);
11759c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(runs[0] < runs[1]);
11769c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(runs[1] < SkRegion::kRunTypeSentinel);
11779c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        prevR = runs[1];
11789c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        runs += 2;
11799c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    }
11809c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    return runs;
11819c36a76102453db964cb6e51078a3d74d4126b2creed@google.com}
11829c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
1183e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.comstatic void compute_bounds(const SkRegion::RunType runs[],
11849c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                           SkIRect* bounds, int* ySpanCountPtr,
11859c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                           int* intervalCountPtr) {
11869c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    assert_sentinel(runs[0], false);    // top
1187fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
11889c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    int left = SK_MaxS32;
11899c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    int rite = SK_MinS32;
11909c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    int bot;
11919c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    int ySpanCount = 0;
11929c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    int intervalCount = 0;
1193fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
11949c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    bounds->fTop = *runs++;
11959c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    do {
11969c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        bot = *runs++;
11979c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(SkRegion::kRunTypeSentinel > bot);
11989c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
11999c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        ySpanCount += 1;
1200fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12019c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        runs += 1;  // skip intervalCount for now
12029c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        if (*runs < SkRegion::kRunTypeSentinel) {
12039c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            if (left > *runs) {
12049c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                left = *runs;
12059c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            }
1206fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12079c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            const SkRegion::RunType* prev = runs;
12089c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            runs = skip_intervals_slow(runs);
1209f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org            int intervals = SkToInt((runs - prev) >> 1);
12109c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            SkASSERT(prev[-1] == intervals);
12119c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            intervalCount += intervals;
1212fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12139c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            if (rite < runs[-1]) {
12149c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                rite = runs[-1];
12159c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            }
12169c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        } else {
12179c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            SkASSERT(0 == runs[-1]);    // no intervals
12189c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        }
12199c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        SkASSERT(SkRegion::kRunTypeSentinel == *runs);
12209c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        runs += 1;
12219c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    } while (SkRegion::kRunTypeSentinel != *runs);
1222fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
12239c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    bounds->fLeft = left;
12249c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    bounds->fRight = rite;
12259c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    bounds->fBottom = bot;
12269c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    *ySpanCountPtr = ySpanCount;
12279c36a76102453db964cb6e51078a3d74d4126b2creed@google.com    *intervalCountPtr = intervalCount;
12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1230c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.comvoid SkRegion::validate() const {
1231c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    if (this->isEmpty()) {
12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // check for explicit empty (the zero rect), so we can compare rects to know when
12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // two regions are equal (i.e. emptyRectA == emptyRectB)
12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // this is stricter than just asserting fBounds.isEmpty()
12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fBounds.fLeft == 0 && fBounds.fTop == 0 && fBounds.fRight == 0 && fBounds.fBottom == 0);
1236c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    } else {
12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(!fBounds.isEmpty());
1238c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com        if (!this->isRect()) {
12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(fRunHead->fRefCnt >= 1);
12409c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            SkASSERT(fRunHead->fRunCount > kRectRegionRuns);
12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const RunType* run = fRunHead->readonly_runs();
12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // check that our bounds match our runs
12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            {
12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkIRect bounds;
1247af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com                int ySpanCount, intervalCount;
1248e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.com                compute_bounds(run, &bounds, &ySpanCount, &intervalCount);
12499c36a76102453db964cb6e51078a3d74d4126b2creed@google.com
12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkASSERT(bounds == fBounds);
1251af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com                SkASSERT(ySpanCount > 0);
1252af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com                SkASSERT(fRunHead->getYSpanCount() == ySpanCount);
12539c36a76102453db964cb6e51078a3d74d4126b2creed@google.com           //     SkASSERT(intervalCount > 1);
1254af7e6943b74260ff9038bfbe0f8c50cf66657e83reed@google.com                SkASSERT(fRunHead->getIntervalCount() == intervalCount);
12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
12568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
12578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1260c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.comvoid SkRegion::dump() const {
1261c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    if (this->isEmpty()) {
12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("  rgn: empty\n");
1263c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com    } else {
12648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("  rgn: [%d %d %d %d]", fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
12659c36a76102453db964cb6e51078a3d74d4126b2creed@google.com        if (this->isComplex()) {
12668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            const RunType* runs = fRunHead->readonly_runs();
12678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            for (int i = 0; i < fRunHead->fRunCount; i++)
12688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkDebugf(" %d", runs[i]);
12698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkDebugf("\n");
12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
12758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1276c34f53db60d8d5312fb1a78ebb9f82224a9d70e5reed@google.com///////////////////////////////////////////////////////////////////////////////
12778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRegion::Iterator::Iterator(const SkRegion& rgn) {
12798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    this->reset(rgn);
12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkRegion::Iterator::rewind() {
12838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fRgn) {
12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->reset(*fRgn);
12858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;
12868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
12878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return false;
12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRegion::Iterator::reset(const SkRegion& rgn) {
12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRgn = &rgn;
12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (rgn.isEmpty()) {
12938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDone = true;
12948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
12958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDone = false;
12968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (rgn.isRect()) {
12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRect = rgn.fBounds;
12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRuns = NULL;
12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRuns = rgn.fRunHead->readonly_runs();
13019c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            fRect.set(fRuns[3], fRuns[0], fRuns[4], fRuns[1]);
13029c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            fRuns += 5;
13039c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            // Now fRuns points to the 2nd interval (or x-sentinel)
13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRegion::Iterator::next() {
13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDone) {
13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fRuns == NULL) {   // rect case
13148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDone = true;
13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const RunType* runs = fRuns;
13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (runs[0] < kRunTypeSentinel) { // valid X value
13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRect.fLeft = runs[0];
13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fRect.fRight = runs[1];
13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += 2;
13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {    // we're at the end of a line
13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += 1;
13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (runs[0] < kRunTypeSentinel) { // valid Y value
13279c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            int intervals = runs[1];
13289c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            if (0 == intervals) {    // empty line
13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRect.fTop = runs[0];
13309c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                runs += 3;
13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRect.fTop = fRect.fBottom;
13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1334fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRect.fBottom = runs[0];
13369c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            assert_sentinel(runs[2], false);
13379c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            assert_sentinel(runs[3], false);
13389c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            fRect.fLeft = runs[2];
13399c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            fRect.fRight = runs[3];
13409c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            runs += 4;
13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {    // end of rgn
13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDone = true;
13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRuns = runs;
13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRegion::Cliperator::Cliperator(const SkRegion& rgn, const SkIRect& clip)
13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : fIter(rgn), fClip(clip), fDone(true) {
13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkIRect& r = fIter.rect();
13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (!fIter.done()) {
13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (r.fTop >= clip.fBottom) {
13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fRect.intersect(clip, r)) {
13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDone = false;
13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fIter.next();
13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRegion::Cliperator::next() {
13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fDone) {
13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkIRect& r = fIter.rect();
13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = true;
13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fIter.next();
13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (!fIter.done()) {
13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (r.fTop >= fClip.fBottom) {
13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fRect.intersect(fClip, r)) {
13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDone = false;
13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fIter.next();
13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1385e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com///////////////////////////////////////////////////////////////////////////////
13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1387e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.comSkRegion::Spanerator::Spanerator(const SkRegion& rgn, int y, int left,
1388e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com                                 int right) {
13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(rgn.validate();)
13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkIRect& r = rgn.getBounds();
13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fDone = true;
1394e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com    if (!rgn.isEmpty() && y >= r.fTop && y < r.fBottom &&
1395e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com            right > r.fLeft && left < r.fRight) {
1396e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com        if (rgn.isRect()) {
1397e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com            if (left < r.fLeft) {
13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                left = r.fLeft;
1399e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com            }
1400e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com            if (right > r.fRight) {
14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                right = r.fRight;
1402e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com            }
14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fLeft = left;
14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRight = right;
14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRuns = NULL;    // means we're a rect, not a rgn
14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fDone = false;
1407e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com        } else {
14089c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            const SkRegion::RunType* runs = rgn.fRunHead->findScanline(y);
14099c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            runs += 2;  // skip Bottom and IntervalCount
14109c36a76102453db964cb6e51078a3d74d4126b2creed@google.com            for (;;) {
14119c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                // runs[0..1] is to the right of the span, so we're done
14129c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                if (runs[0] >= right) {
14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    break;
14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
14159c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                // runs[0..1] is to the left of the span, so continue
14169c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                if (runs[1] <= left) {
14179c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                    runs += 2;
14189c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                    continue;
14199c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                }
14209c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                // runs[0..1] intersects the span
14219c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                fRuns = runs;
14229c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                fLeft = left;
14239c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                fRight = right;
14249c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                fDone = false;
14259c36a76102453db964cb6e51078a3d74d4126b2creed@google.com                break;
14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
14288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1431e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.combool SkRegion::Spanerator::next(int* left, int* right) {
1432e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com    if (fDone) {
1433e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com        return false;
1434e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com    }
14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1436e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com    if (fRuns == NULL) {   // we're a rect
14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDone = true;   // ok, now we're done
1438e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com        if (left) {
1439e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com            *left = fLeft;
1440e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com        }
1441e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com        if (right) {
1442e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com            *right = fRight;
1443e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com        }
14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return true;    // this interval is legal
14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkRegion::RunType* runs = fRuns;
14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1449e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com    if (runs[0] >= fRight) {
14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fDone = true;
14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return false;
14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(runs[1] > fLeft);
14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1456e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com    if (left) {
14578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *left = SkMax32(fLeft, runs[0]);
1458e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com    }
1459e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com    if (right) {
14608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *right = SkMin32(fRight, runs[1]);
1461e72766fe02a4b6c75c9eb2d6ac6bfa8df796ddc5reed@google.com    }
14628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fRuns = runs + 2;
14638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return true;
14648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////
14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkRegion::debugSetRuns(const RunType runs[], int count) {
14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // we need to make a copy, since the real method may modify the array, and
14728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // so it cannot be const.
1473fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
14748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoTArray<RunType> storage(count);
14758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    memcpy(storage.get(), runs, count * sizeof(RunType));
14768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return this->setRuns(storage.get(), count);
14778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
14788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
14798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1480