• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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