1d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com/*
2d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com * Copyright 2010 Google Inc.
3d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com *
4d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com * Use of this source code is governed by a BSD-style license that can be
5d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com * found in the LICENSE file.
6d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com */
7d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
8d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com#include "SkRasterClip.h"
9d954498c01ccf0417feacf89e45d0c62a06a813breed#include "SkPath.h"
10d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
1134f7e47a3593911d03307a08e5af625b218ceec3reed@google.comSkRasterClip::SkRasterClip(const SkRasterClip& src) {
12045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_RASTERCLIP_VALIDATE(src);
13fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
14d954498c01ccf0417feacf89e45d0c62a06a813breed    fForceConservativeRects = src.fForceConservativeRects;
1534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    fIsBW = src.fIsBW;
1634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    if (fIsBW) {
1734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        fBW = src.fBW;
1834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    } else {
1934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        fAA = src.fAA;
2034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    }
21a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com
22a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    fIsEmpty = src.isEmpty();
23a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    fIsRect = src.isRect();
24a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    SkDEBUGCODE(this->validate();)
2534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com}
2634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
27d954498c01ccf0417feacf89e45d0c62a06a813breedSkRasterClip::SkRasterClip(const SkIRect& bounds, bool forceConservativeRects) : fBW(bounds) {
28d954498c01ccf0417feacf89e45d0c62a06a813breed    fForceConservativeRects = forceConservativeRects;
29ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com    fIsBW = true;
30a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    fIsEmpty = this->computeIsEmpty();  // bounds might be empty, so compute
31a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    fIsRect = !fIsEmpty;
32a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    SkDEBUGCODE(this->validate();)
33ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com}
34ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com
35d954498c01ccf0417feacf89e45d0c62a06a813breedSkRasterClip::SkRasterClip(bool forceConservativeRects) {
36d954498c01ccf0417feacf89e45d0c62a06a813breed    fForceConservativeRects = forceConservativeRects;
37d954498c01ccf0417feacf89e45d0c62a06a813breed    fIsBW = true;
38d954498c01ccf0417feacf89e45d0c62a06a813breed    fIsEmpty = true;
39d954498c01ccf0417feacf89e45d0c62a06a813breed    fIsRect = false;
40d954498c01ccf0417feacf89e45d0c62a06a813breed    SkDEBUGCODE(this->validate();)
41d954498c01ccf0417feacf89e45d0c62a06a813breed}
42d954498c01ccf0417feacf89e45d0c62a06a813breed
43045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comSkRasterClip::~SkRasterClip() {
44a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    SkDEBUGCODE(this->validate();)
45d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com}
46d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
47d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.combool SkRasterClip::isComplex() const {
48d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    return fIsBW ? fBW.isComplex() : !fAA.isEmpty();
49d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com}
50d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
51d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.comconst SkIRect& SkRasterClip::getBounds() const {
52d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    return fIsBW ? fBW.getBounds() : fAA.getBounds();
53d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com}
54d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
55d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.combool SkRasterClip::setEmpty() {
56045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_RASTERCLIP_VALIDATE(*this);
57045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
58d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    fIsBW = true;
59d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    fBW.setEmpty();
60d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    fAA.setEmpty();
61a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    fIsEmpty = true;
62a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    fIsRect = false;
63d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    return false;
64d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com}
65d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
66ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.combool SkRasterClip::setRect(const SkIRect& rect) {
67045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_RASTERCLIP_VALIDATE(*this);
68fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
69d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    fIsBW = true;
70d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    fAA.setEmpty();
71a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    fIsRect = fBW.setRect(rect);
72a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    fIsEmpty = !fIsRect;
73a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    return fIsRect;
74d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com}
75d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
76d954498c01ccf0417feacf89e45d0c62a06a813breed/////////////////////////////////////////////////////////////////////////////////////
77d954498c01ccf0417feacf89e45d0c62a06a813breed
78d954498c01ccf0417feacf89e45d0c62a06a813breedbool SkRasterClip::setConservativeRect(const SkRect& r, const SkIRect& clipR, bool isInverse) {
79d954498c01ccf0417feacf89e45d0c62a06a813breed    SkRegion::Op op;
80d954498c01ccf0417feacf89e45d0c62a06a813breed    if (isInverse) {
81d954498c01ccf0417feacf89e45d0c62a06a813breed        op = SkRegion::kDifference_Op;
82d954498c01ccf0417feacf89e45d0c62a06a813breed    } else {
83d954498c01ccf0417feacf89e45d0c62a06a813breed        op = SkRegion::kIntersect_Op;
84d954498c01ccf0417feacf89e45d0c62a06a813breed    }
85d954498c01ccf0417feacf89e45d0c62a06a813breed    fBW.setRect(clipR);
86b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed    fBW.op(r.roundOut(), op);
87d954498c01ccf0417feacf89e45d0c62a06a813breed    return this->updateCacheAndReturnNonEmpty();
88d954498c01ccf0417feacf89e45d0c62a06a813breed}
89d954498c01ccf0417feacf89e45d0c62a06a813breed
90d954498c01ccf0417feacf89e45d0c62a06a813breed/////////////////////////////////////////////////////////////////////////////////////
91d954498c01ccf0417feacf89e45d0c62a06a813breed
92d954498c01ccf0417feacf89e45d0c62a06a813breedenum MutateResult {
93d954498c01ccf0417feacf89e45d0c62a06a813breed    kDoNothing_MutateResult,
94d954498c01ccf0417feacf89e45d0c62a06a813breed    kReplaceClippedAgainstGlobalBounds_MutateResult,
95d954498c01ccf0417feacf89e45d0c62a06a813breed    kContinue_MutateResult,
96d954498c01ccf0417feacf89e45d0c62a06a813breed};
97d954498c01ccf0417feacf89e45d0c62a06a813breed
98d954498c01ccf0417feacf89e45d0c62a06a813breedstatic MutateResult mutate_conservative_op(SkRegion::Op* op, bool inverseFilled) {
99d954498c01ccf0417feacf89e45d0c62a06a813breed    if (inverseFilled) {
100d954498c01ccf0417feacf89e45d0c62a06a813breed        switch (*op) {
101d954498c01ccf0417feacf89e45d0c62a06a813breed            case SkRegion::kIntersect_Op:
102d954498c01ccf0417feacf89e45d0c62a06a813breed            case SkRegion::kDifference_Op:
103d954498c01ccf0417feacf89e45d0c62a06a813breed                // These ops can only shrink the current clip. So leaving
104d954498c01ccf0417feacf89e45d0c62a06a813breed                // the clip unchanged conservatively respects the contract.
105d954498c01ccf0417feacf89e45d0c62a06a813breed                return kDoNothing_MutateResult;
106d954498c01ccf0417feacf89e45d0c62a06a813breed            case SkRegion::kUnion_Op:
107d954498c01ccf0417feacf89e45d0c62a06a813breed            case SkRegion::kReplace_Op:
108d954498c01ccf0417feacf89e45d0c62a06a813breed            case SkRegion::kReverseDifference_Op:
109d954498c01ccf0417feacf89e45d0c62a06a813breed            case SkRegion::kXOR_Op: {
110d954498c01ccf0417feacf89e45d0c62a06a813breed                // These ops can grow the current clip up to the extents of
111d954498c01ccf0417feacf89e45d0c62a06a813breed                // the input clip, which is inverse filled, so we just set
112d954498c01ccf0417feacf89e45d0c62a06a813breed                // the current clip to the device bounds.
113d954498c01ccf0417feacf89e45d0c62a06a813breed                *op = SkRegion::kReplace_Op;
114d954498c01ccf0417feacf89e45d0c62a06a813breed                return kReplaceClippedAgainstGlobalBounds_MutateResult;
115d954498c01ccf0417feacf89e45d0c62a06a813breed            }
116d954498c01ccf0417feacf89e45d0c62a06a813breed        }
117d954498c01ccf0417feacf89e45d0c62a06a813breed    } else {
118d954498c01ccf0417feacf89e45d0c62a06a813breed        // Not inverse filled
119d954498c01ccf0417feacf89e45d0c62a06a813breed        switch (*op) {
120d954498c01ccf0417feacf89e45d0c62a06a813breed            case SkRegion::kIntersect_Op:
121d954498c01ccf0417feacf89e45d0c62a06a813breed            case SkRegion::kUnion_Op:
122d954498c01ccf0417feacf89e45d0c62a06a813breed            case SkRegion::kReplace_Op:
123d954498c01ccf0417feacf89e45d0c62a06a813breed                return kContinue_MutateResult;
124d954498c01ccf0417feacf89e45d0c62a06a813breed            case SkRegion::kDifference_Op:
125d954498c01ccf0417feacf89e45d0c62a06a813breed                // Difference can only shrink the current clip.
126d954498c01ccf0417feacf89e45d0c62a06a813breed                // Leaving clip unchanged conservatively fullfills the contract.
127d954498c01ccf0417feacf89e45d0c62a06a813breed                return kDoNothing_MutateResult;
128d954498c01ccf0417feacf89e45d0c62a06a813breed            case SkRegion::kReverseDifference_Op:
129d954498c01ccf0417feacf89e45d0c62a06a813breed                // To reverse, we swap in the bounds with a replace op.
130d954498c01ccf0417feacf89e45d0c62a06a813breed                // As with difference, leave it unchanged.
131d954498c01ccf0417feacf89e45d0c62a06a813breed                *op = SkRegion::kReplace_Op;
132d954498c01ccf0417feacf89e45d0c62a06a813breed                return kContinue_MutateResult;
133d954498c01ccf0417feacf89e45d0c62a06a813breed            case SkRegion::kXOR_Op:
134d954498c01ccf0417feacf89e45d0c62a06a813breed                // Be conservative, based on (A XOR B) always included in (A union B),
135d954498c01ccf0417feacf89e45d0c62a06a813breed                // which is always included in (bounds(A) union bounds(B))
136d954498c01ccf0417feacf89e45d0c62a06a813breed                *op = SkRegion::kUnion_Op;
137d954498c01ccf0417feacf89e45d0c62a06a813breed                return kContinue_MutateResult;
138d954498c01ccf0417feacf89e45d0c62a06a813breed        }
139d954498c01ccf0417feacf89e45d0c62a06a813breed    }
140d954498c01ccf0417feacf89e45d0c62a06a813breed    SkFAIL("should not get here");
141d954498c01ccf0417feacf89e45d0c62a06a813breed    return kDoNothing_MutateResult;
142d954498c01ccf0417feacf89e45d0c62a06a813breed}
143d954498c01ccf0417feacf89e45d0c62a06a813breed
144d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.combool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) {
145045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_RASTERCLIP_VALIDATE(*this);
146045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
147d954498c01ccf0417feacf89e45d0c62a06a813breed    if (fForceConservativeRects) {
148d954498c01ccf0417feacf89e45d0c62a06a813breed        return this->setConservativeRect(path.getBounds(), clip.getBounds(), path.isInverseFillType());
149d954498c01ccf0417feacf89e45d0c62a06a813breed    }
150d954498c01ccf0417feacf89e45d0c62a06a813breed
151d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    if (this->isBW() && !doAA) {
152a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com        (void)fBW.setPath(path, clip);
153d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    } else {
154897fc41934e6aecec62f89d093c93b917cfa5345reed@google.com        // TODO: since we are going to over-write fAA completely (aren't we?)
155897fc41934e6aecec62f89d093c93b917cfa5345reed@google.com        // we should just clear our BW data (if any) and set fIsAA=true
156d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com        if (this->isBW()) {
157d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com            this->convertToAA();
158d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com        }
159a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com        (void)fAA.setPath(path, &clip, doAA);
160d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    }
161a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    return this->updateCacheAndReturnNonEmpty();
162d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com}
163d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
164d64c9487135094c83f658319f53ea2005ecc08b2reedbool SkRasterClip::op(const SkPath& path, const SkISize& size, SkRegion::Op op, bool doAA) {
165d64c9487135094c83f658319f53ea2005ecc08b2reed    // base is used to limit the size (and therefore memory allocation) of the
166d64c9487135094c83f658319f53ea2005ecc08b2reed    // region that results from scan converting devPath.
167d64c9487135094c83f658319f53ea2005ecc08b2reed    SkRegion base;
168d954498c01ccf0417feacf89e45d0c62a06a813breed
169d954498c01ccf0417feacf89e45d0c62a06a813breed    if (fForceConservativeRects) {
170d954498c01ccf0417feacf89e45d0c62a06a813breed        SkIRect ir;
171d954498c01ccf0417feacf89e45d0c62a06a813breed        switch (mutate_conservative_op(&op, path.isInverseFillType())) {
172d954498c01ccf0417feacf89e45d0c62a06a813breed            case kDoNothing_MutateResult:
173d954498c01ccf0417feacf89e45d0c62a06a813breed                return !this->isEmpty();
174d954498c01ccf0417feacf89e45d0c62a06a813breed            case kReplaceClippedAgainstGlobalBounds_MutateResult:
175d954498c01ccf0417feacf89e45d0c62a06a813breed                ir = SkIRect::MakeSize(size);
176d954498c01ccf0417feacf89e45d0c62a06a813breed                break;
177d954498c01ccf0417feacf89e45d0c62a06a813breed            case kContinue_MutateResult:
178b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed                ir = path.getBounds().roundOut();
179d954498c01ccf0417feacf89e45d0c62a06a813breed                break;
180d954498c01ccf0417feacf89e45d0c62a06a813breed        }
181d954498c01ccf0417feacf89e45d0c62a06a813breed        return this->op(ir, op);
182d954498c01ccf0417feacf89e45d0c62a06a813breed    }
183d954498c01ccf0417feacf89e45d0c62a06a813breed
184d64c9487135094c83f658319f53ea2005ecc08b2reed    if (SkRegion::kIntersect_Op == op) {
185d64c9487135094c83f658319f53ea2005ecc08b2reed        // since we are intersect, we can do better (tighter) with currRgn's
186d64c9487135094c83f658319f53ea2005ecc08b2reed        // bounds, than just using the device. However, if currRgn is complex,
187d64c9487135094c83f658319f53ea2005ecc08b2reed        // our region blitter may hork, so we do that case in two steps.
188d64c9487135094c83f658319f53ea2005ecc08b2reed        if (this->isRect()) {
189d64c9487135094c83f658319f53ea2005ecc08b2reed            // FIXME: we should also be able to do this when this->isBW(),
190d64c9487135094c83f658319f53ea2005ecc08b2reed            // but relaxing the test above triggers GM asserts in
191d64c9487135094c83f658319f53ea2005ecc08b2reed            // SkRgnBuilder::blitH(). We need to investigate what's going on.
192d64c9487135094c83f658319f53ea2005ecc08b2reed            return this->setPath(path, this->bwRgn(), doAA);
193d64c9487135094c83f658319f53ea2005ecc08b2reed        } else {
194d64c9487135094c83f658319f53ea2005ecc08b2reed            base.setRect(this->getBounds());
195d954498c01ccf0417feacf89e45d0c62a06a813breed            SkRasterClip clip(fForceConservativeRects);
196d64c9487135094c83f658319f53ea2005ecc08b2reed            clip.setPath(path, base, doAA);
197d64c9487135094c83f658319f53ea2005ecc08b2reed            return this->op(clip, op);
198d64c9487135094c83f658319f53ea2005ecc08b2reed        }
199d64c9487135094c83f658319f53ea2005ecc08b2reed    } else {
200d64c9487135094c83f658319f53ea2005ecc08b2reed        base.setRect(0, 0, size.width(), size.height());
201d64c9487135094c83f658319f53ea2005ecc08b2reed
202d64c9487135094c83f658319f53ea2005ecc08b2reed        if (SkRegion::kReplace_Op == op) {
203d64c9487135094c83f658319f53ea2005ecc08b2reed            return this->setPath(path, base, doAA);
204d64c9487135094c83f658319f53ea2005ecc08b2reed        } else {
205d954498c01ccf0417feacf89e45d0c62a06a813breed            SkRasterClip clip(fForceConservativeRects);
206d64c9487135094c83f658319f53ea2005ecc08b2reed            clip.setPath(path, base, doAA);
207d64c9487135094c83f658319f53ea2005ecc08b2reed            return this->op(clip, op);
208d64c9487135094c83f658319f53ea2005ecc08b2reed        }
209d64c9487135094c83f658319f53ea2005ecc08b2reed    }
210d64c9487135094c83f658319f53ea2005ecc08b2reed}
211d64c9487135094c83f658319f53ea2005ecc08b2reed
212d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.combool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) {
213d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    SkRegion tmp;
214d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    tmp.setRect(clip);
215d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    return this->setPath(path, tmp, doAA);
216d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com}
217d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
218d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.combool SkRasterClip::op(const SkIRect& rect, SkRegion::Op op) {
219045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_RASTERCLIP_VALIDATE(*this);
220fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
221a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    fIsBW ? fBW.op(rect, op) : fAA.op(rect, op);
222a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    return this->updateCacheAndReturnNonEmpty();
223d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com}
224d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
225ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.combool SkRasterClip::op(const SkRegion& rgn, SkRegion::Op op) {
226045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_RASTERCLIP_VALIDATE(*this);
227fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
228ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com    if (fIsBW) {
229a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com        (void)fBW.op(rgn, op);
230ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com    } else {
231ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com        SkAAClip tmp;
232ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com        tmp.setRegion(rgn);
233a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com        (void)fAA.op(tmp, op);
234ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com    }
235a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    return this->updateCacheAndReturnNonEmpty();
236ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com}
237ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com
238d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.combool SkRasterClip::op(const SkRasterClip& clip, SkRegion::Op op) {
239045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_RASTERCLIP_VALIDATE(*this);
240045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    clip.validate();
241045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
242d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    if (this->isBW() && clip.isBW()) {
243a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com        (void)fBW.op(clip.fBW, op);
244d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    } else {
245d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com        SkAAClip tmp;
246d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com        const SkAAClip* other;
247d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
248d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com        if (this->isBW()) {
249d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com            this->convertToAA();
250d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com        }
251d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com        if (clip.isBW()) {
252d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com            tmp.setRegion(clip.bwRgn());
253d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com            other = &tmp;
254d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com        } else {
255d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com            other = &clip.aaRgn();
256d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com        }
257a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com        (void)fAA.op(*other, op);
258d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    }
259a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    return this->updateCacheAndReturnNonEmpty();
260d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com}
261d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
26218c464b460d062142ab7198724431a4d2ad7070dreed@google.com/**
26318c464b460d062142ab7198724431a4d2ad7070dreed@google.com *  Our antialiasing currently has a granularity of 1/4 of a pixel along each
26418c464b460d062142ab7198724431a4d2ad7070dreed@google.com *  axis. Thus we can treat an axis coordinate as an integer if it differs
26518c464b460d062142ab7198724431a4d2ad7070dreed@google.com *  from its nearest int by < half of that value (1.8 in this case).
26618c464b460d062142ab7198724431a4d2ad7070dreed@google.com */
26718c464b460d062142ab7198724431a4d2ad7070dreed@google.comstatic bool nearly_integral(SkScalar x) {
26818c464b460d062142ab7198724431a4d2ad7070dreed@google.com    static const SkScalar domain = SK_Scalar1 / 4;
26918c464b460d062142ab7198724431a4d2ad7070dreed@google.com    static const SkScalar halfDomain = domain / 2;
27018c464b460d062142ab7198724431a4d2ad7070dreed@google.com
27118c464b460d062142ab7198724431a4d2ad7070dreed@google.com    x += halfDomain;
27218c464b460d062142ab7198724431a4d2ad7070dreed@google.com    return x - SkScalarFloorToScalar(x) < domain;
2730017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com}
2740017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com
275d954498c01ccf0417feacf89e45d0c62a06a813breedbool SkRasterClip::op(const SkRect& r, const SkISize& size, SkRegion::Op op, bool doAA) {
276045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_RASTERCLIP_VALIDATE(*this);
277fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
278d954498c01ccf0417feacf89e45d0c62a06a813breed    if (fForceConservativeRects) {
279d954498c01ccf0417feacf89e45d0c62a06a813breed        SkIRect ir;
280d954498c01ccf0417feacf89e45d0c62a06a813breed        switch (mutate_conservative_op(&op, false)) {
281d954498c01ccf0417feacf89e45d0c62a06a813breed            case kDoNothing_MutateResult:
282d954498c01ccf0417feacf89e45d0c62a06a813breed                return !this->isEmpty();
283d954498c01ccf0417feacf89e45d0c62a06a813breed            case kReplaceClippedAgainstGlobalBounds_MutateResult:
284d954498c01ccf0417feacf89e45d0c62a06a813breed                ir = SkIRect::MakeSize(size);
285d954498c01ccf0417feacf89e45d0c62a06a813breed                break;
286d954498c01ccf0417feacf89e45d0c62a06a813breed            case kContinue_MutateResult:
287b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed                ir = r.roundOut();
288d954498c01ccf0417feacf89e45d0c62a06a813breed                break;
289d954498c01ccf0417feacf89e45d0c62a06a813breed        }
290d954498c01ccf0417feacf89e45d0c62a06a813breed        return this->op(ir, op);
291d954498c01ccf0417feacf89e45d0c62a06a813breed    }
292d954498c01ccf0417feacf89e45d0c62a06a813breed
293420f74fa720272b1164eae55d7b6c10e07d41601reed@google.com    if (fIsBW && doAA) {
29418c464b460d062142ab7198724431a4d2ad7070dreed@google.com        // check that the rect really needs aa, or is it close enought to
29518c464b460d062142ab7198724431a4d2ad7070dreed@google.com        // integer boundaries that we can just treat it as a BW rect?
29618c464b460d062142ab7198724431a4d2ad7070dreed@google.com        if (nearly_integral(r.fLeft) && nearly_integral(r.fTop) &&
29718c464b460d062142ab7198724431a4d2ad7070dreed@google.com            nearly_integral(r.fRight) && nearly_integral(r.fBottom)) {
2980017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            doAA = false;
2990017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        }
3000017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    }
3010017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com
3020017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    if (fIsBW && !doAA) {
3030017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        SkIRect ir;
3040017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        r.round(&ir);
305a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com        (void)fBW.op(ir, op);
3060017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    } else {
3070017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        if (fIsBW) {
3080017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com            this->convertToAA();
3090017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com        }
310a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com        (void)fAA.op(r, op, doAA);
3110017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com    }
312a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    return this->updateCacheAndReturnNonEmpty();
3130017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com}
3140017708a5bcb6d0fbff0fac565085bef65de7433reed@google.com
31534f7e47a3593911d03307a08e5af625b218ceec3reed@google.comvoid SkRasterClip::translate(int dx, int dy, SkRasterClip* dst) const {
31634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    if (NULL == dst) {
31734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        return;
31834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    }
31934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
320045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_RASTERCLIP_VALIDATE(*this);
321fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
32234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    if (this->isEmpty()) {
32334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        dst->setEmpty();
32434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        return;
32534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    }
32634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    if (0 == (dx | dy)) {
32734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        *dst = *this;
32834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        return;
32934f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    }
33034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
33134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    dst->fIsBW = fIsBW;
33234f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    if (fIsBW) {
33334f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        fBW.translate(dx, dy, &dst->fBW);
33434f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        dst->fAA.setEmpty();
33534f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    } else {
33634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        fAA.translate(dx, dy, &dst->fAA);
33734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com        dst->fBW.setEmpty();
33834f7e47a3593911d03307a08e5af625b218ceec3reed@google.com    }
339a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    dst->updateCacheAndReturnNonEmpty();
34034f7e47a3593911d03307a08e5af625b218ceec3reed@google.com}
34134f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
342045e62d715f5ee9b03deb5af3c750f8318096179reed@google.combool SkRasterClip::quickContains(const SkIRect& ir) const {
343045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    return fIsBW ? fBW.quickContains(ir) : fAA.quickContains(ir);
344045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
345045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
34634f7e47a3593911d03307a08e5af625b218ceec3reed@google.com///////////////////////////////////////////////////////////////////////////////
34734f7e47a3593911d03307a08e5af625b218ceec3reed@google.com
348ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.comconst SkRegion& SkRasterClip::forceGetBW() {
349045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_RASTERCLIP_VALIDATE(*this);
350fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
351ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com    if (!fIsBW) {
352ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com        fBW.setRect(fAA.getBounds());
353ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com    }
354ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com    return fBW;
355ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com}
356ba16da97e82e7ec9b73caa752b00504206ff516dreed@google.com
357d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.comvoid SkRasterClip::convertToAA() {
358045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    AUTO_RASTERCLIP_VALIDATE(*this);
359d954498c01ccf0417feacf89e45d0c62a06a813breed
360d954498c01ccf0417feacf89e45d0c62a06a813breed    SkASSERT(!fForceConservativeRects);
361d954498c01ccf0417feacf89e45d0c62a06a813breed
362d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    SkASSERT(fIsBW);
363d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    fAA.setRegion(fBW);
364d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com    fIsBW = false;
365202ab2a5cabaf25a1e6ec47c0003da3213a79864reed
366202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    // since we are being explicitly asked to convert-to-aa, we pass false so we don't "optimize"
367202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    // ourselves back to BW.
368202ab2a5cabaf25a1e6ec47c0003da3213a79864reed    (void)this->updateCacheAndReturnNonEmpty(false);
369d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com}
370d1e3c5fde3f2ed309273cb08dbba2309b13e527freed@google.com
371045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#ifdef SK_DEBUG
372045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkRasterClip::validate() const {
373045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // can't ever assert that fBW is empty, since we may have called forceGetBW
374045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (fIsBW) {
375045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        SkASSERT(fAA.isEmpty());
376045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
377045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
378045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    fBW.validate();
379045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    fAA.validate();
380a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com
381a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    SkASSERT(this->computeIsEmpty() == fIsEmpty);
382a1c6ff4922251065c45e3323e17e985a62931fc7reed@google.com    SkASSERT(this->computeIsRect() == fIsRect);
383045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
384045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#endif
385045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
386045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com///////////////////////////////////////////////////////////////////////////////
387045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
388045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comSkAAClipBlitterWrapper::SkAAClipBlitterWrapper() {
389045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkDEBUGCODE(fClipRgn = NULL;)
390045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkDEBUGCODE(fBlitter = NULL;)
391045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
392045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
393045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comSkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkRasterClip& clip,
394045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                                               SkBlitter* blitter) {
395045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    this->init(clip, blitter);
396045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
397045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
398045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comSkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkAAClip* aaclip,
399045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com                                               SkBlitter* blitter) {
400045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(blitter);
401045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(aaclip);
402045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    fBWRgn.setRect(aaclip->getBounds());
403045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    fAABlitter.init(blitter, aaclip);
404045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    // now our return values
405045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    fClipRgn = &fBWRgn;
406045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    fBlitter = &fAABlitter;
407045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
408045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com
409045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comvoid SkAAClipBlitterWrapper::init(const SkRasterClip& clip, SkBlitter* blitter) {
410045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    SkASSERT(blitter);
411045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    if (clip.isBW()) {
412045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClipRgn = &clip.bwRgn();
413045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fBlitter = blitter;
414045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    } else {
415045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        const SkAAClip& aaclip = clip.aaRgn();
416045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fBWRgn.setRect(aaclip.getBounds());
417045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fAABlitter.init(blitter, &aaclip);
418045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        // now our return values
419045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fClipRgn = &fBWRgn;
420045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com        fBlitter = &fAABlitter;
421045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com    }
422045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com}
423