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:
AutoPaintFilter(const SkPaintFilterCanvas * canvas,const SkPaint * paint)17 AutoPaintFilter(const SkPaintFilterCanvas* canvas, const SkPaint* paint)
18 : fPaint(paint ? *paint : SkPaint()) {
19 fShouldDraw = canvas->onFilter(fPaint);
20 }
21
AutoPaintFilter(const SkPaintFilterCanvas * canvas,const SkPaint & paint)22 AutoPaintFilter(const SkPaintFilterCanvas* canvas, const SkPaint& paint)
23 : AutoPaintFilter(canvas, &paint) { }
24
paint() const25 const SkPaint& paint() const { return fPaint; }
26
shouldDraw() const27 bool shouldDraw() const { return fShouldDraw; }
28
29 private:
30 SkPaint fPaint;
31 bool fShouldDraw;
32 };
33
SkPaintFilterCanvas(SkCanvas * canvas)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
onDrawPaint(const SkPaint & paint)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
onDrawBehind(const SkPaint & paint)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
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)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
onDrawRect(const SkRect & rect,const SkPaint & paint)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
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)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
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)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
onDrawRegion(const SkRegion & region,const SkPaint & paint)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
onDrawOval(const SkRect & rect,const SkPaint & paint)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
onDrawArc(const SkRect & rect,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)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
onDrawPath(const SkPath & path,const SkPaint & paint)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
onDrawBitmap(const SkBitmap & bm,SkScalar left,SkScalar top,const SkPaint * paint)118 void SkPaintFilterCanvas::onDrawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
119 const SkPaint* paint) {
120 AutoPaintFilter apf(this, paint);
121 if (apf.shouldDraw()) {
122 this->SkNWayCanvas::onDrawBitmap(bm, left, top, &apf.paint());
123 }
124 }
125
onDrawBitmapRect(const SkBitmap & bm,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)126 void SkPaintFilterCanvas::onDrawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRect& dst,
127 const SkPaint* paint, SrcRectConstraint constraint) {
128 AutoPaintFilter apf(this, paint);
129 if (apf.shouldDraw()) {
130 this->SkNWayCanvas::onDrawBitmapRect(bm, src, dst, &apf.paint(), constraint);
131 }
132 }
133
onDrawBitmapNine(const SkBitmap & bm,const SkIRect & center,const SkRect & dst,const SkPaint * paint)134 void SkPaintFilterCanvas::onDrawBitmapNine(const SkBitmap& bm, const SkIRect& center,
135 const SkRect& dst, const SkPaint* paint) {
136 AutoPaintFilter apf(this, paint);
137 if (apf.shouldDraw()) {
138 this->SkNWayCanvas::onDrawBitmapNine(bm, center, dst, &apf.paint());
139 }
140 }
141
onDrawBitmapLattice(const SkBitmap & bitmap,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)142 void SkPaintFilterCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
143 const SkRect& dst, const SkPaint* paint) {
144 AutoPaintFilter apf(this, paint);
145 if (apf.shouldDraw()) {
146 this->SkNWayCanvas::onDrawBitmapLattice(bitmap, lattice, dst, &apf.paint());
147 }
148 }
149
onDrawImage(const SkImage * image,SkScalar left,SkScalar top,const SkPaint * paint)150 void SkPaintFilterCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
151 const SkPaint* paint) {
152 AutoPaintFilter apf(this, paint);
153 if (apf.shouldDraw()) {
154 this->SkNWayCanvas::onDrawImage(image, left, top, &apf.paint());
155 }
156 }
157
onDrawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)158 void SkPaintFilterCanvas::onDrawImageRect(const SkImage* image, const SkRect* src,
159 const SkRect& dst, const SkPaint* paint,
160 SrcRectConstraint constraint) {
161 AutoPaintFilter apf(this, paint);
162 if (apf.shouldDraw()) {
163 this->SkNWayCanvas::onDrawImageRect(image, src, dst, &apf.paint(), constraint);
164 }
165 }
166
onDrawImageNine(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)167 void SkPaintFilterCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center,
168 const SkRect& dst, const SkPaint* paint) {
169 AutoPaintFilter apf(this, paint);
170 if (apf.shouldDraw()) {
171 this->SkNWayCanvas::onDrawImageNine(image, center, dst, &apf.paint());
172 }
173 }
174
onDrawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)175 void SkPaintFilterCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
176 const SkRect& dst, const SkPaint* paint) {
177 AutoPaintFilter apf(this, paint);
178 if (apf.shouldDraw()) {
179 this->SkNWayCanvas::onDrawImageLattice(image, lattice, dst, &apf.paint());
180 }
181 }
182
onDrawVerticesObject(const SkVertices * vertices,const SkVertices::Bone bones[],int boneCount,SkBlendMode bmode,const SkPaint & paint)183 void SkPaintFilterCanvas::onDrawVerticesObject(const SkVertices* vertices,
184 const SkVertices::Bone bones[], int boneCount,
185 SkBlendMode bmode, const SkPaint& paint) {
186 AutoPaintFilter apf(this, paint);
187 if (apf.shouldDraw()) {
188 this->SkNWayCanvas::onDrawVerticesObject(vertices, bones, boneCount, bmode, apf.paint());
189 }
190 }
191
onDrawPatch(const SkPoint cubics[],const SkColor colors[],const SkPoint texCoords[],SkBlendMode bmode,const SkPaint & paint)192 void SkPaintFilterCanvas::onDrawPatch(const SkPoint cubics[], const SkColor colors[],
193 const SkPoint texCoords[], SkBlendMode bmode,
194 const SkPaint& paint) {
195 AutoPaintFilter apf(this, paint);
196 if (apf.shouldDraw()) {
197 this->SkNWayCanvas::onDrawPatch(cubics, colors, texCoords, bmode, apf.paint());
198 }
199 }
200
onDrawPicture(const SkPicture * picture,const SkMatrix * m,const SkPaint * paint)201 void SkPaintFilterCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* m,
202 const SkPaint* paint) {
203 AutoPaintFilter apf(this, paint);
204 if (apf.shouldDraw()) {
205 this->SkNWayCanvas::onDrawPicture(picture, m, &apf.paint());
206 }
207 }
208
onDrawDrawable(SkDrawable * drawable,const SkMatrix * matrix)209 void SkPaintFilterCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
210 // There is no paint to filter in this case, but we can still filter on type.
211 // Subclasses need to unroll the drawable explicity (by overriding this method) in
212 // order to actually filter nested content.
213 AutoPaintFilter apf(this, nullptr);
214 if (apf.shouldDraw()) {
215 this->SkNWayCanvas::onDrawDrawable(drawable, matrix);
216 }
217 }
218
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)219 void SkPaintFilterCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
220 const SkPaint& paint) {
221 AutoPaintFilter apf(this, paint);
222 if (apf.shouldDraw()) {
223 this->SkNWayCanvas::onDrawTextBlob(blob, x, y, apf.paint());
224 }
225 }
226
onDrawAtlas(const SkImage * image,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode bmode,const SkRect * cull,const SkPaint * paint)227 void SkPaintFilterCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[],
228 const SkRect tex[], const SkColor colors[], int count,
229 SkBlendMode bmode, const SkRect* cull, const SkPaint* paint) {
230 AutoPaintFilter apf(this, paint);
231 if (apf.shouldDraw()) {
232 this->SkNWayCanvas::onDrawAtlas(image, xform, tex, colors, count, bmode, cull, &apf.paint());
233 }
234 }
235
onDrawAnnotation(const SkRect & rect,const char key[],SkData * value)236 void SkPaintFilterCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
237 this->SkNWayCanvas::onDrawAnnotation(rect, key, value);
238 }
239
onDrawShadowRec(const SkPath & path,const SkDrawShadowRec & rec)240 void SkPaintFilterCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
241 this->SkNWayCanvas::onDrawShadowRec(path, rec);
242 }
243
onDrawEdgeAAQuad(const SkRect & rect,const SkPoint clip[4],QuadAAFlags aa,const SkColor4f & color,SkBlendMode mode)244 void SkPaintFilterCanvas::onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
245 QuadAAFlags aa, const SkColor4f& color, SkBlendMode mode) {
246 SkPaint paint;
247 paint.setColor(color);
248 paint.setBlendMode(mode);
249 AutoPaintFilter apf(this, paint);
250 if (apf.shouldDraw()) {
251 this->SkNWayCanvas::onDrawEdgeAAQuad(rect, clip, aa, apf.paint().getColor4f(),
252 apf.paint().getBlendMode());
253 }
254 }
255
onDrawEdgeAAImageSet(const ImageSetEntry set[],int count,const SkPoint dstClips[],const SkMatrix preViewMatrices[],const SkPaint * paint,SrcRectConstraint constraint)256 void SkPaintFilterCanvas::onDrawEdgeAAImageSet(const ImageSetEntry set[], int count,
257 const SkPoint dstClips[],
258 const SkMatrix preViewMatrices[],
259 const SkPaint* paint, SrcRectConstraint constraint) {
260 AutoPaintFilter apf(this, paint);
261 if (apf.shouldDraw()) {
262 this->SkNWayCanvas::onDrawEdgeAAImageSet(
263 set, count, dstClips, preViewMatrices, &apf.paint(), constraint);
264 }
265 }
266
onNewSurface(const SkImageInfo & info,const SkSurfaceProps & props)267 sk_sp<SkSurface> SkPaintFilterCanvas::onNewSurface(const SkImageInfo& info,
268 const SkSurfaceProps& props) {
269 return proxy()->makeSurface(info, &props);
270 }
271
onPeekPixels(SkPixmap * pixmap)272 bool SkPaintFilterCanvas::onPeekPixels(SkPixmap* pixmap) {
273 return proxy()->peekPixels(pixmap);
274 }
275
onAccessTopLayerPixels(SkPixmap * pixmap)276 bool SkPaintFilterCanvas::onAccessTopLayerPixels(SkPixmap* pixmap) {
277 SkImageInfo info;
278 size_t rowBytes;
279
280 void* addr = proxy()->accessTopLayerPixels(&info, &rowBytes);
281 if (!addr) {
282 return false;
283 }
284
285 pixmap->reset(info, addr, rowBytes);
286 return true;
287 }
288
onImageInfo() const289 SkImageInfo SkPaintFilterCanvas::onImageInfo() const {
290 return proxy()->imageInfo();
291 }
292
onGetProps(SkSurfaceProps * props) const293 bool SkPaintFilterCanvas::onGetProps(SkSurfaceProps* props) const {
294 return proxy()->getProps(props);
295 }
296