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