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