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 "SkPaintFilterCanvas.h"
9
10#include "SkPaint.h"
11#include "SkTLazy.h"
12
13class SkPaintFilterCanvas::AutoPaintFilter {
14public:
15    AutoPaintFilter(const SkPaintFilterCanvas* canvas, Type type, const SkPaint* paint)
16        : fPaint(paint) {
17        fShouldDraw = canvas->onFilter(&fPaint, type);
18    }
19
20    AutoPaintFilter(const SkPaintFilterCanvas* canvas, Type type, const SkPaint& paint)
21        : AutoPaintFilter(canvas, type, &paint) { }
22
23    const SkPaint* paint() const { return fPaint; }
24
25    bool shouldDraw() const { return fShouldDraw; }
26
27private:
28    SkTCopyOnFirstWrite<SkPaint> fPaint;
29    bool                         fShouldDraw;
30};
31
32SkPaintFilterCanvas::SkPaintFilterCanvas(SkCanvas *canvas)
33    : INHERITED(canvas->imageInfo().width(), canvas->imageInfo().height()) {
34
35    // Transfer matrix & clip state before adding the target canvas.
36    this->clipRect(SkRect::Make(canvas->getDeviceClipBounds()));
37    this->setMatrix(canvas->getTotalMatrix());
38
39    this->addCanvas(canvas);
40}
41
42void SkPaintFilterCanvas::onDrawPaint(const SkPaint& paint) {
43    AutoPaintFilter apf(this, kPaint_Type, paint);
44    if (apf.shouldDraw()) {
45        this->INHERITED::onDrawPaint(*apf.paint());
46    }
47}
48
49void SkPaintFilterCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
50                                       const SkPaint& paint) {
51    AutoPaintFilter apf(this, kPoint_Type, paint);
52    if (apf.shouldDraw()) {
53        this->INHERITED::onDrawPoints(mode, count, pts, *apf.paint());
54    }
55}
56
57void SkPaintFilterCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
58    AutoPaintFilter apf(this, kRect_Type, paint);
59    if (apf.shouldDraw()) {
60        this->INHERITED::onDrawRect(rect, *apf.paint());
61    }
62}
63
64void SkPaintFilterCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
65    AutoPaintFilter apf(this, kRRect_Type, paint);
66    if (apf.shouldDraw()) {
67        this->INHERITED::onDrawRRect(rrect, *apf.paint());
68    }
69}
70
71void SkPaintFilterCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
72                                       const SkPaint& paint) {
73    AutoPaintFilter apf(this, kDRRect_Type, paint);
74    if (apf.shouldDraw()) {
75        this->INHERITED::onDrawDRRect(outer, inner, *apf.paint());
76    }
77}
78
79void SkPaintFilterCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
80    AutoPaintFilter apf(this, kOval_Type, paint);
81    if (apf.shouldDraw()) {
82        this->INHERITED::onDrawOval(rect, *apf.paint());
83    }
84}
85
86void SkPaintFilterCanvas::onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
87                                    bool useCenter, const SkPaint& paint) {
88    AutoPaintFilter apf(this, kArc_Type, paint);
89    if (apf.shouldDraw()) {
90        this->INHERITED::onDrawArc(rect, startAngle, sweepAngle, useCenter, *apf.paint());
91    }
92}
93
94void SkPaintFilterCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
95    AutoPaintFilter apf(this, kPath_Type, paint);
96    if (apf.shouldDraw()) {
97        this->INHERITED::onDrawPath(path, *apf.paint());
98    }
99}
100
101void SkPaintFilterCanvas::onDrawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
102                                       const SkPaint* paint) {
103    AutoPaintFilter apf(this, kBitmap_Type, paint);
104    if (apf.shouldDraw()) {
105        this->INHERITED::onDrawBitmap(bm, left, top, apf.paint());
106    }
107}
108
109void SkPaintFilterCanvas::onDrawBitmapRect(const SkBitmap& bm, const SkRect* src, const SkRect& dst,
110                                           const SkPaint* paint, SrcRectConstraint constraint) {
111    AutoPaintFilter apf(this, kBitmap_Type, paint);
112    if (apf.shouldDraw()) {
113        this->INHERITED::onDrawBitmapRect(bm, src, dst, apf.paint(), constraint);
114    }
115}
116
117void SkPaintFilterCanvas::onDrawBitmapNine(const SkBitmap& bm, const SkIRect& center,
118                                           const SkRect& dst, const SkPaint* paint) {
119    AutoPaintFilter apf(this, kBitmap_Type, paint);
120    if (apf.shouldDraw()) {
121        this->INHERITED::onDrawBitmapNine(bm, center, dst, apf.paint());
122    }
123}
124
125void SkPaintFilterCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top,
126                                      const SkPaint* paint) {
127    AutoPaintFilter apf(this, kBitmap_Type, paint);
128    if (apf.shouldDraw()) {
129        this->INHERITED::onDrawImage(image, left, top, apf.paint());
130    }
131}
132
133void SkPaintFilterCanvas::onDrawImageRect(const SkImage* image, const SkRect* src,
134                                          const SkRect& dst, const SkPaint* paint,
135                                          SrcRectConstraint constraint) {
136    AutoPaintFilter apf(this, kBitmap_Type, paint);
137    if (apf.shouldDraw()) {
138        this->INHERITED::onDrawImageRect(image, src, dst, apf.paint(), constraint);
139    }
140}
141
142void SkPaintFilterCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center,
143                                               const SkRect& dst, const SkPaint* paint) {
144    AutoPaintFilter apf(this, kBitmap_Type, paint);
145    if (apf.shouldDraw()) {
146        this->INHERITED::onDrawImageNine(image, center, dst, apf.paint());
147    }
148}
149
150void SkPaintFilterCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
151                                               const SkPaint& paint) {
152    AutoPaintFilter apf(this, kVertices_Type, paint);
153    if (apf.shouldDraw()) {
154        this->INHERITED::onDrawVerticesObject(vertices, bmode, *apf.paint());
155    }
156}
157
158void SkPaintFilterCanvas::onDrawPatch(const SkPoint cubics[], const SkColor colors[],
159                                      const SkPoint texCoords[], SkBlendMode bmode,
160                                      const SkPaint& paint) {
161    AutoPaintFilter apf(this, kPatch_Type, paint);
162    if (apf.shouldDraw()) {
163        this->INHERITED::onDrawPatch(cubics, colors, texCoords, bmode, *apf.paint());
164    }
165}
166
167void SkPaintFilterCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* m,
168                                        const SkPaint* paint) {
169    AutoPaintFilter apf(this, kPicture_Type, paint);
170    if (apf.shouldDraw()) {
171        this->INHERITED::onDrawPicture(picture, m, apf.paint());
172    }
173}
174
175void SkPaintFilterCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
176                                     const SkPaint& paint) {
177    AutoPaintFilter apf(this, kText_Type, paint);
178    if (apf.shouldDraw()) {
179        this->INHERITED::onDrawText(text, byteLength, x, y, *apf.paint());
180    }
181}
182
183void SkPaintFilterCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
184                                        const SkPaint& paint) {
185    AutoPaintFilter apf(this, kText_Type, paint);
186    if (apf.shouldDraw()) {
187        this->INHERITED::onDrawPosText(text, byteLength, pos, *apf.paint());
188    }
189}
190
191void SkPaintFilterCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
192                                         SkScalar constY, const SkPaint& paint) {
193    AutoPaintFilter apf(this, kText_Type, paint);
194    if (apf.shouldDraw()) {
195        this->INHERITED::onDrawPosTextH(text, byteLength, xpos, constY, *apf.paint());
196    }
197}
198
199void SkPaintFilterCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
200                                           const SkMatrix* matrix, const SkPaint& paint) {
201    AutoPaintFilter apf(this, kText_Type, paint);
202    if (apf.shouldDraw()) {
203        this->INHERITED::onDrawTextOnPath(text, byteLength, path, matrix, *apf.paint());
204    }
205}
206
207void SkPaintFilterCanvas::onDrawTextRSXform(const void* text, size_t byteLength,
208                                            const SkRSXform xform[], const SkRect* cull,
209                                            const SkPaint& paint) {
210    AutoPaintFilter apf(this, kText_Type, paint);
211    if (apf.shouldDraw()) {
212        this->INHERITED::onDrawTextRSXform(text, byteLength, xform, cull, *apf.paint());
213    }
214}
215
216void SkPaintFilterCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
217                                         const SkPaint& paint) {
218    AutoPaintFilter apf(this, kTextBlob_Type, paint);
219    if (apf.shouldDraw()) {
220        this->INHERITED::onDrawTextBlob(blob, x, y, *apf.paint());
221    }
222}
223