blob: 5588dfbc5c2f489b6bed549129561d2e2b1274db [file] [log] [blame]
reed@google.comd1e3c5f2011-10-10 19:36:25 +00001/*
2 * Copyright 2010 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkRasterClip.h"
9
10
11SkRasterClip::SkRasterClip() {
12 fIsBW = true;
13}
14
reed@google.com34f7e472011-10-13 15:11:59 +000015SkRasterClip::SkRasterClip(const SkRasterClip& src) {
16 fIsBW = src.fIsBW;
17 if (fIsBW) {
18 fBW = src.fBW;
19 } else {
20 fAA = src.fAA;
21 }
22}
23
reed@google.comba16da92011-10-11 13:15:03 +000024SkRasterClip::SkRasterClip(const SkIRect& bounds) : fBW(bounds) {
25 fIsBW = true;
26}
27
28SkRasterClip::~SkRasterClip() {}
29
reed@google.comd1e3c5f2011-10-10 19:36:25 +000030bool SkRasterClip::isEmpty() const {
31 return fIsBW ? fBW.isEmpty() : fAA.isEmpty();
32}
33
34bool SkRasterClip::isRect() const {
35 return fIsBW ? fBW.isRect() : false;
36}
37
38bool SkRasterClip::isComplex() const {
39 return fIsBW ? fBW.isComplex() : !fAA.isEmpty();
40}
41
42const SkIRect& SkRasterClip::getBounds() const {
43 return fIsBW ? fBW.getBounds() : fAA.getBounds();
44}
45
46bool SkRasterClip::setEmpty() {
47 fIsBW = true;
48 fBW.setEmpty();
49 fAA.setEmpty();
50 return false;
51}
52
reed@google.comba16da92011-10-11 13:15:03 +000053bool SkRasterClip::setRect(const SkIRect& rect) {
reed@google.comd1e3c5f2011-10-10 19:36:25 +000054 fIsBW = true;
55 fAA.setEmpty();
56 return fBW.setRect(rect);
57}
58
59bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) {
60 if (this->isBW() && !doAA) {
61 return fBW.setPath(path, clip);
62 } else {
63 if (this->isBW()) {
64 this->convertToAA();
65 }
66 return fAA.setPath(path, &clip, doAA);
67 }
68}
69
70bool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) {
71 SkRegion tmp;
72 tmp.setRect(clip);
73 return this->setPath(path, tmp, doAA);
74}
75
76bool SkRasterClip::setPath(const SkPath& path, const SkRasterClip& clip,
77 bool doAA) {
78 if (clip.isBW()) {
79 return this->setPath(path, clip.bwRgn(), doAA);
80 } else {
81 SkRegion tmp;
82 tmp.setRect(clip.getBounds());
83 if (!this->setPath(path, clip, doAA)) {
84 return false;
85 }
86 return this->op(clip, SkRegion::kIntersect_Op);
87 }
88}
89
90bool SkRasterClip::op(const SkIRect& rect, SkRegion::Op op) {
91 return fIsBW ? fBW.op(rect, op) : fAA.op(rect, op);
92}
93
reed@google.comba16da92011-10-11 13:15:03 +000094bool SkRasterClip::op(const SkRegion& rgn, SkRegion::Op op) {
95 if (fIsBW) {
96 return fBW.op(rgn, op);
97 } else {
98 SkAAClip tmp;
99 tmp.setRegion(rgn);
100 return fAA.op(tmp, op);
101 }
102}
103
reed@google.comd1e3c5f2011-10-10 19:36:25 +0000104bool SkRasterClip::op(const SkRasterClip& clip, SkRegion::Op op) {
105 if (this->isBW() && clip.isBW()) {
106 return fBW.op(clip.fBW, op);
107 } else {
108 SkAAClip tmp;
109 const SkAAClip* other;
110
111 if (this->isBW()) {
112 this->convertToAA();
113 }
114 if (clip.isBW()) {
115 tmp.setRegion(clip.bwRgn());
116 other = &tmp;
117 } else {
118 other = &clip.aaRgn();
119 }
120 return fAA.op(*other, op);
121 }
122}
123
reed@google.com00177082011-10-12 14:34:30 +0000124// return true if x is nearly integral (within 1/256) since that is the highest
125// precision our aa code can have.
126static bool is_integral(SkScalar x) {
127 int ix = SkScalarRoundToInt(x);
128 SkScalar sx = SkIntToScalar(ix);
129 return SkScalarAbs(sx - x) < (SK_Scalar1 / 256);
130}
131
132bool SkRasterClip::op(const SkRect& r, SkRegion::Op op, bool doAA) {
133 if (doAA) {
134 // check that the rect really needs aa
135 if (is_integral(r.fLeft) && is_integral(r.fTop) &&
136 is_integral(r.fRight) && is_integral(r.fBottom)) {
137 doAA = false;
138 }
139 }
140
141 if (fIsBW && !doAA) {
142 SkIRect ir;
143 r.round(&ir);
reed@google.com56074222011-10-12 15:11:14 +0000144 return fBW.op(ir, op);
reed@google.com00177082011-10-12 14:34:30 +0000145 } else {
146 if (fIsBW) {
147 this->convertToAA();
148 }
reed@google.com56074222011-10-12 15:11:14 +0000149 return fAA.op(r, op, doAA);
reed@google.com00177082011-10-12 14:34:30 +0000150 }
151}
152
reed@google.com34f7e472011-10-13 15:11:59 +0000153void SkRasterClip::translate(int dx, int dy, SkRasterClip* dst) const {
154 if (NULL == dst) {
155 return;
156 }
157
158 if (this->isEmpty()) {
159 dst->setEmpty();
160 return;
161 }
162 if (0 == (dx | dy)) {
163 *dst = *this;
164 return;
165 }
166
167 dst->fIsBW = fIsBW;
168 if (fIsBW) {
169 fBW.translate(dx, dy, &dst->fBW);
170 dst->fAA.setEmpty();
171 } else {
172 fAA.translate(dx, dy, &dst->fAA);
173 dst->fBW.setEmpty();
174 }
175}
176
177///////////////////////////////////////////////////////////////////////////////
178
reed@google.comba16da92011-10-11 13:15:03 +0000179const SkRegion& SkRasterClip::forceGetBW() {
180 if (!fIsBW) {
181 fBW.setRect(fAA.getBounds());
182 }
183 return fBW;
184}
185
reed@google.comd1e3c5f2011-10-10 19:36:25 +0000186void SkRasterClip::convertToAA() {
187 SkASSERT(fIsBW);
188 fAA.setRegion(fBW);
189 fIsBW = false;
190}
191