blob: 004e3fcb6b5f987fe79fc47718d32503572cd2c0 [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.comba16da92011-10-11 13:15:03 +000015SkRasterClip::SkRasterClip(const SkIRect& bounds) : fBW(bounds) {
16 fIsBW = true;
17}
18
19SkRasterClip::~SkRasterClip() {}
20
reed@google.comd1e3c5f2011-10-10 19:36:25 +000021bool SkRasterClip::isEmpty() const {
22 return fIsBW ? fBW.isEmpty() : fAA.isEmpty();
23}
24
25bool SkRasterClip::isRect() const {
26 return fIsBW ? fBW.isRect() : false;
27}
28
29bool SkRasterClip::isComplex() const {
30 return fIsBW ? fBW.isComplex() : !fAA.isEmpty();
31}
32
33const SkIRect& SkRasterClip::getBounds() const {
34 return fIsBW ? fBW.getBounds() : fAA.getBounds();
35}
36
37bool SkRasterClip::setEmpty() {
38 fIsBW = true;
39 fBW.setEmpty();
40 fAA.setEmpty();
41 return false;
42}
43
reed@google.comba16da92011-10-11 13:15:03 +000044bool SkRasterClip::setRect(const SkIRect& rect) {
reed@google.comd1e3c5f2011-10-10 19:36:25 +000045 fIsBW = true;
46 fAA.setEmpty();
47 return fBW.setRect(rect);
48}
49
50bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) {
51 if (this->isBW() && !doAA) {
52 return fBW.setPath(path, clip);
53 } else {
54 if (this->isBW()) {
55 this->convertToAA();
56 }
57 return fAA.setPath(path, &clip, doAA);
58 }
59}
60
61bool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) {
62 SkRegion tmp;
63 tmp.setRect(clip);
64 return this->setPath(path, tmp, doAA);
65}
66
67bool SkRasterClip::setPath(const SkPath& path, const SkRasterClip& clip,
68 bool doAA) {
69 if (clip.isBW()) {
70 return this->setPath(path, clip.bwRgn(), doAA);
71 } else {
72 SkRegion tmp;
73 tmp.setRect(clip.getBounds());
74 if (!this->setPath(path, clip, doAA)) {
75 return false;
76 }
77 return this->op(clip, SkRegion::kIntersect_Op);
78 }
79}
80
81bool SkRasterClip::op(const SkIRect& rect, SkRegion::Op op) {
82 return fIsBW ? fBW.op(rect, op) : fAA.op(rect, op);
83}
84
reed@google.comba16da92011-10-11 13:15:03 +000085bool SkRasterClip::op(const SkRegion& rgn, SkRegion::Op op) {
86 if (fIsBW) {
87 return fBW.op(rgn, op);
88 } else {
89 SkAAClip tmp;
90 tmp.setRegion(rgn);
91 return fAA.op(tmp, op);
92 }
93}
94
reed@google.comd1e3c5f2011-10-10 19:36:25 +000095bool SkRasterClip::op(const SkRasterClip& clip, SkRegion::Op op) {
96 if (this->isBW() && clip.isBW()) {
97 return fBW.op(clip.fBW, op);
98 } else {
99 SkAAClip tmp;
100 const SkAAClip* other;
101
102 if (this->isBW()) {
103 this->convertToAA();
104 }
105 if (clip.isBW()) {
106 tmp.setRegion(clip.bwRgn());
107 other = &tmp;
108 } else {
109 other = &clip.aaRgn();
110 }
111 return fAA.op(*other, op);
112 }
113}
114
reed@google.com00177082011-10-12 14:34:30 +0000115// return true if x is nearly integral (within 1/256) since that is the highest
116// precision our aa code can have.
117static bool is_integral(SkScalar x) {
118 int ix = SkScalarRoundToInt(x);
119 SkScalar sx = SkIntToScalar(ix);
120 return SkScalarAbs(sx - x) < (SK_Scalar1 / 256);
121}
122
123bool SkRasterClip::op(const SkRect& r, SkRegion::Op op, bool doAA) {
124 if (doAA) {
125 // check that the rect really needs aa
126 if (is_integral(r.fLeft) && is_integral(r.fTop) &&
127 is_integral(r.fRight) && is_integral(r.fBottom)) {
128 doAA = false;
129 }
130 }
131
132 if (fIsBW && !doAA) {
133 SkIRect ir;
134 r.round(&ir);
135 fBW.op(ir, op);
136 } else {
137 if (fIsBW) {
138 this->convertToAA();
139 }
140 fAA.op(r, op, doAA);
141 }
142}
143
reed@google.comba16da92011-10-11 13:15:03 +0000144const SkRegion& SkRasterClip::forceGetBW() {
145 if (!fIsBW) {
146 fBW.setRect(fAA.getBounds());
147 }
148 return fBW;
149}
150
reed@google.comd1e3c5f2011-10-10 19:36:25 +0000151void SkRasterClip::convertToAA() {
152 SkASSERT(fIsBW);
153 fAA.setRegion(fBW);
154 fIsBW = false;
155}
156