1 /*
2 * Copyright 2011 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/SkNWayCanvas.h"
9
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkMatrix.h"
13 #include "include/core/SkPoint.h"
14 #include "include/core/SkRect.h"
15 #include "include/core/SkRefCnt.h"
16 #include "include/core/SkScalar.h"
17 #include "include/core/SkShader.h"
18 #include "include/core/SkTypes.h"
19 #include "include/private/base/SkTDArray.h"
20 #include "include/utils/SkNoDrawCanvas.h"
21 #include "src/core/SkCanvasPriv.h"
22
23 #include <algorithm>
24 #include <iterator>
25 #include <utility>
26
27 namespace sktext {
28 class GlyphRunList;
29 }
30
31 class SkData;
32 class SkDrawable;
33 class SkImage;
34 class SkPaint;
35 class SkPath;
36 class SkPicture;
37 class SkRRect;
38 class SkRegion;
39 class SkTextBlob;
40 class SkVertices;
41 enum class SkBlendMode;
42 enum class SkClipOp;
43 struct SkDrawShadowRec;
44
SkNWayCanvas(int width,int height)45 SkNWayCanvas::SkNWayCanvas(int width, int height) : INHERITED(width, height) {}
46
~SkNWayCanvas()47 SkNWayCanvas::~SkNWayCanvas() {
48 this->removeAll();
49 }
50
addCanvas(SkCanvas * canvas)51 void SkNWayCanvas::addCanvas(SkCanvas* canvas) {
52 if (!fList.empty()) {
53 // We are using the nway canvas as a wrapper for the originally added canvas, and the device
54 // on the nway may contradict calls for the device on this canvas. So, to add a second
55 // canvas, the devices on the first canvas, and the nway base device must be different.
56 SkASSERT(fList[0]->baseDevice() != this->baseDevice());
57 }
58 if (canvas) {
59 *fList.append() = canvas;
60 }
61 }
62
removeCanvas(SkCanvas * canvas)63 void SkNWayCanvas::removeCanvas(SkCanvas* canvas) {
64 auto found = std::find(fList.begin(), fList.end(), canvas);
65 if (found != fList.end()) {
66 fList.removeShuffle(std::distance(fList.begin(), found));
67 }
68 }
69
removeAll()70 void SkNWayCanvas::removeAll() {
71 fList.reset();
72 }
73
74 ///////////////////////////////////////////////////////////////////////////
75 // These are forwarded to the N canvases we're referencing
76
77 class SkNWayCanvas::Iter {
78 public:
Iter(const SkTDArray<SkCanvas * > & list)79 Iter(const SkTDArray<SkCanvas*>& list) : fList(list) {
80 fIndex = 0;
81 }
next()82 bool next() {
83 if (fIndex < fList.size()) {
84 fCanvas = fList[fIndex++];
85 return true;
86 }
87 return false;
88 }
operator ->()89 SkCanvas* operator->() { return fCanvas; }
get() const90 SkCanvas* get() const { return fCanvas; }
91
92 private:
93 const SkTDArray<SkCanvas*>& fList;
94 int fIndex;
95 SkCanvas* fCanvas;
96 };
97
willSave()98 void SkNWayCanvas::willSave() {
99 Iter iter(fList);
100 while (iter.next()) {
101 iter->save();
102 }
103
104 this->INHERITED::willSave();
105 }
106
getSaveLayerStrategy(const SaveLayerRec & rec)107 SkCanvas::SaveLayerStrategy SkNWayCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
108 Iter iter(fList);
109 while (iter.next()) {
110 iter->saveLayer(rec);
111 }
112
113 this->INHERITED::getSaveLayerStrategy(rec);
114 // No need for a layer.
115 return kNoLayer_SaveLayerStrategy;
116 }
117
onDoSaveBehind(const SkRect * bounds)118 bool SkNWayCanvas::onDoSaveBehind(const SkRect* bounds) {
119 Iter iter(fList);
120 while (iter.next()) {
121 SkCanvasPriv::SaveBehind(iter.get(), bounds);
122 }
123 this->INHERITED::onDoSaveBehind(bounds);
124 return false;
125 }
126
willRestore()127 void SkNWayCanvas::willRestore() {
128 Iter iter(fList);
129 while (iter.next()) {
130 iter->restore();
131 }
132 this->INHERITED::willRestore();
133 }
134
didConcat44(const SkM44 & m)135 void SkNWayCanvas::didConcat44(const SkM44& m) {
136 Iter iter(fList);
137 while (iter.next()) {
138 iter->concat(m);
139 }
140 }
141
didSetM44(const SkM44 & matrix)142 void SkNWayCanvas::didSetM44(const SkM44& matrix) {
143 Iter iter(fList);
144 while (iter.next()) {
145 iter->setMatrix(matrix);
146 }
147 }
148
didTranslate(SkScalar x,SkScalar y)149 void SkNWayCanvas::didTranslate(SkScalar x, SkScalar y) {
150 Iter iter(fList);
151 while (iter.next()) {
152 iter->translate(x, y);
153 }
154 }
155
didScale(SkScalar x,SkScalar y)156 void SkNWayCanvas::didScale(SkScalar x, SkScalar y) {
157 Iter iter(fList);
158 while (iter.next()) {
159 iter->scale(x, y);
160 }
161 }
162
onClipRect(const SkRect & rect,SkClipOp op,ClipEdgeStyle edgeStyle)163 void SkNWayCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
164 Iter iter(fList);
165 while (iter.next()) {
166 iter->clipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
167 }
168 this->INHERITED::onClipRect(rect, op, edgeStyle);
169 }
170
onClipRRect(const SkRRect & rrect,SkClipOp op,ClipEdgeStyle edgeStyle)171 void SkNWayCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
172 Iter iter(fList);
173 while (iter.next()) {
174 iter->clipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
175 }
176 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
177 }
178
onClipPath(const SkPath & path,SkClipOp op,ClipEdgeStyle edgeStyle)179 void SkNWayCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
180 Iter iter(fList);
181 while (iter.next()) {
182 iter->clipPath(path, op, kSoft_ClipEdgeStyle == edgeStyle);
183 }
184 this->INHERITED::onClipPath(path, op, edgeStyle);
185 }
186
onClipShader(sk_sp<SkShader> sh,SkClipOp op)187 void SkNWayCanvas::onClipShader(sk_sp<SkShader> sh, SkClipOp op) {
188 Iter iter(fList);
189 while (iter.next()) {
190 iter->clipShader(sh, op);
191 }
192 this->INHERITED::onClipShader(std::move(sh), op);
193 }
194
onClipRegion(const SkRegion & deviceRgn,SkClipOp op)195 void SkNWayCanvas::onClipRegion(const SkRegion& deviceRgn, SkClipOp op) {
196 Iter iter(fList);
197 while (iter.next()) {
198 iter->clipRegion(deviceRgn, op);
199 }
200 this->INHERITED::onClipRegion(deviceRgn, op);
201 }
202
onResetClip()203 void SkNWayCanvas::onResetClip() {
204 Iter iter(fList);
205 while (iter.next()) {
206 SkCanvasPriv::ResetClip(iter.get());
207 }
208 this->INHERITED::onResetClip();
209 }
210
onDrawPaint(const SkPaint & paint)211 void SkNWayCanvas::onDrawPaint(const SkPaint& paint) {
212 Iter iter(fList);
213 while (iter.next()) {
214 iter->drawPaint(paint);
215 }
216 }
217
onDrawBehind(const SkPaint & paint)218 void SkNWayCanvas::onDrawBehind(const SkPaint& paint) {
219 Iter iter(fList);
220 while (iter.next()) {
221 SkCanvasPriv::DrawBehind(iter.get(), paint);
222 }
223 }
224
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)225 void SkNWayCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
226 const SkPaint& paint) {
227 Iter iter(fList);
228 while (iter.next()) {
229 iter->drawPoints(mode, count, pts, paint);
230 }
231 }
232
onDrawRect(const SkRect & rect,const SkPaint & paint)233 void SkNWayCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
234 Iter iter(fList);
235 while (iter.next()) {
236 iter->drawRect(rect, paint);
237 }
238 }
239
onDrawRegion(const SkRegion & region,const SkPaint & paint)240 void SkNWayCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
241 Iter iter(fList);
242 while (iter.next()) {
243 iter->drawRegion(region, paint);
244 }
245 }
246
onDrawOval(const SkRect & rect,const SkPaint & paint)247 void SkNWayCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
248 Iter iter(fList);
249 while (iter.next()) {
250 iter->drawOval(rect, paint);
251 }
252 }
253
onDrawArc(const SkRect & rect,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)254 void SkNWayCanvas::onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
255 bool useCenter, const SkPaint& paint) {
256 Iter iter(fList);
257 while (iter.next()) {
258 iter->drawArc(rect, startAngle, sweepAngle, useCenter, paint);
259 }
260 }
261
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)262 void SkNWayCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
263 Iter iter(fList);
264 while (iter.next()) {
265 iter->drawRRect(rrect, paint);
266 }
267 }
268
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)269 void SkNWayCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
270 Iter iter(fList);
271 while (iter.next()) {
272 iter->drawDRRect(outer, inner, paint);
273 }
274 }
275
onDrawPath(const SkPath & path,const SkPaint & paint)276 void SkNWayCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
277 Iter iter(fList);
278 while (iter.next()) {
279 iter->drawPath(path, paint);
280 }
281 }
282
onDrawImage2(const SkImage * image,SkScalar left,SkScalar top,const SkSamplingOptions & sampling,const SkPaint * paint)283 void SkNWayCanvas::onDrawImage2(const SkImage* image, SkScalar left, SkScalar top,
284 const SkSamplingOptions& sampling, const SkPaint* paint) {
285 Iter iter(fList);
286 while (iter.next()) {
287 iter->drawImage(image, left, top, sampling, paint);
288 }
289 }
290
onDrawImageRect2(const SkImage * image,const SkRect & src,const SkRect & dst,const SkSamplingOptions & sampling,const SkPaint * paint,SrcRectConstraint constraint)291 void SkNWayCanvas::onDrawImageRect2(const SkImage* image, const SkRect& src, const SkRect& dst,
292 const SkSamplingOptions& sampling, const SkPaint* paint,
293 SrcRectConstraint constraint) {
294 Iter iter(fList);
295 while (iter.next()) {
296 iter->drawImageRect(image, src, dst, sampling, paint, constraint);
297 }
298 }
299
onDrawImageLattice2(const SkImage * image,const Lattice & lattice,const SkRect & dst,SkFilterMode filter,const SkPaint * paint)300 void SkNWayCanvas::onDrawImageLattice2(const SkImage* image, const Lattice& lattice,
301 const SkRect& dst, SkFilterMode filter,
302 const SkPaint* paint) {
303 Iter iter(fList);
304 while (iter.next()) {
305 iter->drawImageLattice(image, lattice, dst, filter, paint);
306 }
307 }
308
onDrawAtlas2(const SkImage * image,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode bmode,const SkSamplingOptions & sampling,const SkRect * cull,const SkPaint * paint)309 void SkNWayCanvas::onDrawAtlas2(const SkImage* image, const SkRSXform xform[], const SkRect tex[],
310 const SkColor colors[], int count, SkBlendMode bmode,
311 const SkSamplingOptions& sampling, const SkRect* cull,
312 const SkPaint* paint) {
313 Iter iter(fList);
314 while (iter.next()) {
315 iter->drawAtlas(image, xform, tex, colors, count, bmode, sampling, cull, paint);
316 }
317 }
318
onDrawGlyphRunList(const sktext::GlyphRunList & list,const SkPaint & paint)319 void SkNWayCanvas::onDrawGlyphRunList(const sktext::GlyphRunList& list,
320 const SkPaint &paint) {
321 Iter iter(fList);
322 while (iter.next()) {
323 iter->onDrawGlyphRunList(list, paint);
324 }
325 }
326
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)327 void SkNWayCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
328 const SkPaint &paint) {
329 Iter iter(fList);
330 while (iter.next()) {
331 iter->drawTextBlob(blob, x, y, paint);
332 }
333 }
334
335 #if defined(SK_GANESH)
onDrawSlug(const sktext::gpu::Slug * slug)336 void SkNWayCanvas::onDrawSlug(const sktext::gpu::Slug* slug) {
337 Iter iter(fList);
338 while (iter.next()) {
339 iter->drawSlug(slug);
340 }
341 }
342 #endif
343
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)344 void SkNWayCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
345 const SkPaint* paint) {
346 Iter iter(fList);
347 while (iter.next()) {
348 iter->drawPicture(picture, matrix, paint);
349 }
350 }
351
onDrawDrawable(SkDrawable * drawable,const SkMatrix * matrix)352 void SkNWayCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
353 Iter iter(fList);
354 while (iter.next()) {
355 iter->drawDrawable(drawable, matrix);
356 }
357 }
358
onDrawVerticesObject(const SkVertices * vertices,SkBlendMode bmode,const SkPaint & paint)359 void SkNWayCanvas::onDrawVerticesObject(const SkVertices* vertices,
360 SkBlendMode bmode, const SkPaint& paint) {
361 Iter iter(fList);
362 while (iter.next()) {
363 iter->drawVertices(vertices, bmode, paint);
364 }
365 }
366
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)367 void SkNWayCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
368 const SkPoint texCoords[4], SkBlendMode bmode,
369 const SkPaint& paint) {
370 Iter iter(fList);
371 while (iter.next()) {
372 iter->drawPatch(cubics, colors, texCoords, bmode, paint);
373 }
374 }
375
onDrawShadowRec(const SkPath & path,const SkDrawShadowRec & rec)376 void SkNWayCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
377 Iter iter(fList);
378 while (iter.next()) {
379 iter->private_draw_shadow_rec(path, rec);
380 }
381 }
382
onDrawAnnotation(const SkRect & rect,const char key[],SkData * data)383 void SkNWayCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) {
384 Iter iter(fList);
385 while (iter.next()) {
386 iter->drawAnnotation(rect, key, data);
387 }
388 }
389
onDrawEdgeAAQuad(const SkRect & rect,const SkPoint clip[4],QuadAAFlags aa,const SkColor4f & color,SkBlendMode mode)390 void SkNWayCanvas::onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4],
391 QuadAAFlags aa, const SkColor4f& color, SkBlendMode mode) {
392 Iter iter(fList);
393 while (iter.next()) {
394 iter->experimental_DrawEdgeAAQuad(rect, clip, aa, color, mode);
395 }
396 }
397
onDrawEdgeAAImageSet2(const ImageSetEntry set[],int count,const SkPoint dstClips[],const SkMatrix preViewMatrices[],const SkSamplingOptions & sampling,const SkPaint * paint,SrcRectConstraint constraint)398 void SkNWayCanvas::onDrawEdgeAAImageSet2(const ImageSetEntry set[], int count,
399 const SkPoint dstClips[], const SkMatrix preViewMatrices[],
400 const SkSamplingOptions& sampling, const SkPaint* paint,
401 SrcRectConstraint constraint) {
402 Iter iter(fList);
403 while (iter.next()) {
404 iter->experimental_DrawEdgeAAImageSet(
405 set, count, dstClips, preViewMatrices, sampling, paint, constraint);
406 }
407 }
408
onFlush()409 void SkNWayCanvas::onFlush() {
410 Iter iter(fList);
411 while (iter.next()) {
412 iter->flush();
413 }
414 }
415