1 | /* |
2 | * Copyright 2015 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 "include/utils/SkPaintFilterCanvas.h" |
9 | |
10 | #include "include/core/SkPaint.h" |
11 | #include "include/core/SkPixmap.h" |
12 | #include "include/core/SkSurface.h" |
13 | #include "src/core/SkTLazy.h" |
14 | |
15 | class SkPaintFilterCanvas::AutoPaintFilter { |
16 | public: |
17 | AutoPaintFilter(const SkPaintFilterCanvas* canvas, const SkPaint* paint) |
18 | : fPaint(paint ? *paint : SkPaint()) { |
19 | fShouldDraw = canvas->onFilter(fPaint); |
20 | } |
21 | |
22 | AutoPaintFilter(const SkPaintFilterCanvas* canvas, const SkPaint& paint) |
23 | : AutoPaintFilter(canvas, &paint) { } |
24 | |
25 | const SkPaint& paint() const { return fPaint; } |
26 | |
27 | bool shouldDraw() const { return fShouldDraw; } |
28 | |
29 | private: |
30 | SkPaint fPaint; |
31 | bool fShouldDraw; |
32 | }; |
33 | |
34 | SkPaintFilterCanvas::SkPaintFilterCanvas(SkCanvas *canvas) |
35 | : SkCanvasVirtualEnforcer<SkNWayCanvas>(canvas->imageInfo().width(), |
36 | canvas->imageInfo().height()) { |
37 | |
38 | // Transfer matrix & clip state before adding the target canvas. |
39 | this->clipRect(SkRect::Make(canvas->getDeviceClipBounds())); |
40 | this->setMatrix(canvas->getTotalMatrix()); |
41 | |
42 | this->addCanvas(canvas); |
43 | } |
44 | |
45 | void SkPaintFilterCanvas::onDrawPaint(const SkPaint& paint) { |
46 | AutoPaintFilter apf(this, paint); |
47 | if (apf.shouldDraw()) { |
48 | this->SkNWayCanvas::onDrawPaint(apf.paint()); |
49 | } |
50 | } |
51 | |
52 | void SkPaintFilterCanvas::onDrawBehind(const SkPaint& paint) { |
53 | AutoPaintFilter apf(this, paint); |
54 | if (apf.shouldDraw()) { |
55 | this->SkNWayCanvas::onDrawBehind(apf.paint()); |
56 | } |
57 | } |
58 | |
59 | void SkPaintFilterCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[], |
60 | const SkPaint& paint) { |
61 | AutoPaintFilter apf(this, paint); |
62 | if (apf.shouldDraw()) { |
63 | this->SkNWayCanvas::onDrawPoints(mode, count, pts, apf.paint()); |
64 | } |
65 | } |
66 | |
67 | void SkPaintFilterCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) { |
68 | AutoPaintFilter apf(this, paint); |
69 | if (apf.shouldDraw()) { |
70 | this->SkNWayCanvas::onDrawRect(rect, apf.paint()); |
71 | } |
72 | } |
73 | |
74 | void SkPaintFilterCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { |
75 | AutoPaintFilter apf(this, paint); |
76 | if (apf.shouldDraw()) { |
77 | this->SkNWayCanvas::onDrawRRect(rrect, apf.paint()); |
78 | } |
79 | } |
80 | |
81 | void SkPaintFilterCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, |
82 | const SkPaint& paint) { |
83 | AutoPaintFilter apf(this, paint); |
84 | if (apf.shouldDraw()) { |
85 | this->SkNWayCanvas::onDrawDRRect(outer, inner, apf.paint()); |
86 | } |
87 | } |
88 | |
89 | void SkPaintFilterCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) { |
90 | AutoPaintFilter apf(this, paint); |
91 | if (apf.shouldDraw()) { |
92 | this->SkNWayCanvas::onDrawRegion(region, apf.paint()); |
93 | } |
94 | } |
95 | |
96 | void SkPaintFilterCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) { |
97 | AutoPaintFilter apf(this, paint); |
98 | if (apf.shouldDraw()) { |
99 | this->SkNWayCanvas::onDrawOval(rect, apf.paint()); |
100 | } |
101 | } |
102 | |
103 | void SkPaintFilterCanvas::onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle, |
104 | bool useCenter, const SkPaint& paint) { |
105 | AutoPaintFilter apf(this, paint); |
106 | if (apf.shouldDraw()) { |
107 | this->SkNWayCanvas::onDrawArc(rect, startAngle, sweepAngle, useCenter, apf.paint()); |
108 | } |
109 | } |
110 | |
111 | void SkPaintFilterCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { |
112 | AutoPaintFilter apf(this, paint); |
113 | if (apf.shouldDraw()) { |
114 | this->SkNWayCanvas::onDrawPath(path, apf.paint()); |
115 | } |
116 | } |
117 | |
118 | void SkPaintFilterCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top, |
119 | const SkPaint* paint) { |
120 | AutoPaintFilter apf(this, paint); |
121 | if (apf.shouldDraw()) { |
122 | this->SkNWayCanvas::onDrawImage(image, left, top, &apf.paint()); |
123 | } |
124 | } |
125 | |
126 | void SkPaintFilterCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, |
127 | const SkRect& dst, const SkPaint* paint, |
128 | SrcRectConstraint constraint) { |
129 | AutoPaintFilter apf(this, paint); |
130 | if (apf.shouldDraw()) { |
131 | this->SkNWayCanvas::onDrawImageRect(image, src, dst, &apf.paint(), constraint); |
132 | } |
133 | } |
134 | |
135 | void SkPaintFilterCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, |
136 | const SkRect& dst, const SkPaint* paint) { |
137 | AutoPaintFilter apf(this, paint); |
138 | if (apf.shouldDraw()) { |
139 | this->SkNWayCanvas::onDrawImageNine(image, center, dst, &apf.paint()); |
140 | } |
141 | } |
142 | |
143 | void SkPaintFilterCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, |
144 | const SkRect& dst, const SkPaint* paint) { |
145 | AutoPaintFilter apf(this, paint); |
146 | if (apf.shouldDraw()) { |
147 | this->SkNWayCanvas::onDrawImageLattice(image, lattice, dst, &apf.paint()); |
148 | } |
149 | } |
150 | |
151 | void SkPaintFilterCanvas::onDrawVerticesObject(const SkVertices* vertices, |
152 | SkBlendMode bmode, const SkPaint& paint) { |
153 | AutoPaintFilter apf(this, paint); |
154 | if (apf.shouldDraw()) { |
155 | this->SkNWayCanvas::onDrawVerticesObject(vertices, bmode, apf.paint()); |
156 | } |
157 | } |
158 | |
159 | void SkPaintFilterCanvas::onDrawPatch(const SkPoint cubics[], const SkColor colors[], |
160 | const SkPoint texCoords[], SkBlendMode bmode, |
161 | const SkPaint& paint) { |
162 | AutoPaintFilter apf(this, paint); |
163 | if (apf.shouldDraw()) { |
164 | this->SkNWayCanvas::onDrawPatch(cubics, colors, texCoords, bmode, apf.paint()); |
165 | } |
166 | } |
167 | |
168 | void SkPaintFilterCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* m, |
169 | const SkPaint* paint) { |
170 | AutoPaintFilter apf(this, paint); |
171 | if (apf.shouldDraw()) { |
172 | this->SkNWayCanvas::onDrawPicture(picture, m, &apf.paint()); |
173 | } |
174 | } |
175 | |
176 | void SkPaintFilterCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) { |
177 | // There is no paint to filter in this case, but we can still filter on type. |
178 | // Subclasses need to unroll the drawable explicity (by overriding this method) in |
179 | // order to actually filter nested content. |
180 | AutoPaintFilter apf(this, nullptr); |
181 | if (apf.shouldDraw()) { |
182 | this->SkNWayCanvas::onDrawDrawable(drawable, matrix); |
183 | } |
184 | } |
185 | |
186 | void SkPaintFilterCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, |
187 | const SkPaint& paint) { |
188 | AutoPaintFilter apf(this, paint); |
189 | if (apf.shouldDraw()) { |
190 | this->SkNWayCanvas::onDrawTextBlob(blob, x, y, apf.paint()); |
191 | } |
192 | } |
193 | |
194 | void SkPaintFilterCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[], |
195 | const SkRect tex[], const SkColor colors[], int count, |
196 | SkBlendMode bmode, const SkRect* cull, const SkPaint* paint) { |
197 | AutoPaintFilter apf(this, paint); |
198 | if (apf.shouldDraw()) { |
199 | this->SkNWayCanvas::onDrawAtlas(image, xform, tex, colors, count, bmode, cull, &apf.paint()); |
200 | } |
201 | } |
202 | |
203 | void SkPaintFilterCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) { |
204 | this->SkNWayCanvas::onDrawAnnotation(rect, key, value); |
205 | } |
206 | |
207 | void SkPaintFilterCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) { |
208 | this->SkNWayCanvas::onDrawShadowRec(path, rec); |
209 | } |
210 | |
211 | void SkPaintFilterCanvas::onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], |
212 | QuadAAFlags aa, const SkColor4f& color, SkBlendMode mode) { |
213 | SkPaint paint; |
214 | paint.setColor(color); |
215 | paint.setBlendMode(mode); |
216 | AutoPaintFilter apf(this, paint); |
217 | if (apf.shouldDraw()) { |
218 | this->SkNWayCanvas::onDrawEdgeAAQuad(rect, clip, aa, apf.paint().getColor4f(), |
219 | apf.paint().getBlendMode()); |
220 | } |
221 | } |
222 | |
223 | void SkPaintFilterCanvas::onDrawEdgeAAImageSet(const ImageSetEntry set[], int count, |
224 | const SkPoint dstClips[], |
225 | const SkMatrix preViewMatrices[], |
226 | const SkPaint* paint, SrcRectConstraint constraint) { |
227 | AutoPaintFilter apf(this, paint); |
228 | if (apf.shouldDraw()) { |
229 | this->SkNWayCanvas::onDrawEdgeAAImageSet( |
230 | set, count, dstClips, preViewMatrices, &apf.paint(), constraint); |
231 | } |
232 | } |
233 | |
234 | sk_sp<SkSurface> SkPaintFilterCanvas::onNewSurface(const SkImageInfo& info, |
235 | const SkSurfaceProps& props) { |
236 | return proxy()->makeSurface(info, &props); |
237 | } |
238 | |
239 | bool SkPaintFilterCanvas::onPeekPixels(SkPixmap* pixmap) { |
240 | return proxy()->peekPixels(pixmap); |
241 | } |
242 | |
243 | bool SkPaintFilterCanvas::onAccessTopLayerPixels(SkPixmap* pixmap) { |
244 | SkImageInfo info; |
245 | size_t rowBytes; |
246 | |
247 | void* addr = proxy()->accessTopLayerPixels(&info, &rowBytes); |
248 | if (!addr) { |
249 | return false; |
250 | } |
251 | |
252 | pixmap->reset(info, addr, rowBytes); |
253 | return true; |
254 | } |
255 | |
256 | SkImageInfo SkPaintFilterCanvas::onImageInfo() const { |
257 | return proxy()->imageInfo(); |
258 | } |
259 | |
260 | bool SkPaintFilterCanvas::onGetProps(SkSurfaceProps* props) const { |
261 | return proxy()->getProps(props); |
262 | } |
263 | |