1 /*
2  * Copyright 2016 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 "SkDeferredCanvas.h"
9 #include "SkDrawable.h"
10 #include "SkPath.h"
11 #include "SkRRect.h"
12 #include "SkSurface.h"
13 #include "SkTextBlob.h"
14 
isConcat(SkMatrix * m) const15 bool SkDeferredCanvas::Rec::isConcat(SkMatrix* m) const {
16     switch (fType) {
17         case kTrans_Type:
18             m->setTranslate(fData.fTranslate.x(), fData.fTranslate.y());
19             return true;
20         case kScaleTrans_Type:
21             m->setScaleTranslate(fData.fScaleTrans.fScale.x(),
22                                  fData.fScaleTrans.fScale.y(),
23                                  fData.fScaleTrans.fTrans.x(),
24                                  fData.fScaleTrans.fTrans.y());
25             return true;
26         default:
27             break;
28     }
29     return false;
30 }
31 
setConcat(const SkMatrix & m)32 void SkDeferredCanvas::Rec::setConcat(const SkMatrix& m) {
33     SkASSERT(m.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask));
34 
35     if (m.getType() <= SkMatrix::kTranslate_Mask) {
36         fType = kTrans_Type;
37         fData.fTranslate.set(m.getTranslateX(), m.getTranslateY());
38     } else {
39         fType = kScaleTrans_Type;
40         fData.fScaleTrans.fScale.set(m.getScaleX(), m.getScaleY());
41         fData.fScaleTrans.fTrans.set(m.getTranslateX(), m.getTranslateY());
42     }
43 }
44 
45 ///////////////////////////////////////////////////////////////////////////////////////////////////
46 
SkDeferredCanvas(SkCanvas * canvas)47 SkDeferredCanvas::SkDeferredCanvas(SkCanvas* canvas)
48     : INHERITED(canvas->getBaseLayerSize().width(), canvas->getBaseLayerSize().height())
49     , fCanvas(canvas)
50 {}
51 
~SkDeferredCanvas()52 SkDeferredCanvas::~SkDeferredCanvas() {}
53 
push_save()54 void SkDeferredCanvas::push_save() {
55     Rec* r = fRecs.append();
56     r->fType = kSave_Type;
57 }
58 
push_cliprect(const SkRect & bounds)59 void SkDeferredCanvas::push_cliprect(const SkRect& bounds) {
60     int index = fRecs.count() - 1;
61     if (index >= 0 && fRecs[index].fType == kClipRect_Type) {
62         if (!fRecs[index].fData.fBounds.intersect(bounds)) {
63             fRecs[index].fData.fBounds.setEmpty();
64         }
65     } else {
66         Rec* r = fRecs.append();
67         r->fType = kClipRect_Type;
68         r->fData.fBounds = bounds;
69     }
70 }
71 
push_concat(const SkMatrix & mat)72 bool SkDeferredCanvas::push_concat(const SkMatrix& mat) {
73     if (mat.getType() > (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) {
74         return false;
75     }
76     // At the moment, we don't know which ops can scale and which can also flip, so
77     // we reject negative scales for now
78     if (mat.getScaleX() < 0 || mat.getScaleY() < 0) {
79         return false;
80     }
81 
82     int index = fRecs.count() - 1;
83     SkMatrix m;
84     if (index >= 0 && fRecs[index].isConcat(&m)) {
85         m.preConcat(mat);
86         fRecs[index].setConcat(m);
87     } else {
88         fRecs.append()->setConcat(mat);
89     }
90     return true;
91 }
92 
emit(const Rec & rec)93 void SkDeferredCanvas::emit(const Rec& rec) {
94     switch (rec.fType) {
95         case kSave_Type:
96             fCanvas->save();
97             this->INHERITED::willSave();
98             break;
99         case kClipRect_Type:
100             fCanvas->clipRect(rec.fData.fBounds);
101             this->INHERITED::onClipRect(rec.fData.fBounds,
102                                         kIntersect_Op, kHard_ClipEdgeStyle);
103             break;
104         case kTrans_Type:
105         case kScaleTrans_Type: {
106             SkMatrix mat;
107             rec.getConcat(&mat);
108             fCanvas->concat(mat);
109             this->INHERITED::didConcat(mat);
110         } break;
111     }
112 }
113 
flush_le(int index)114 void SkDeferredCanvas::flush_le(int index) {
115     SkASSERT(index >= -1 && index < fRecs.count());
116 
117     int count = index + 1;
118     for (int i = 0; i < count; ++i) {
119         this->emit(fRecs[i]);
120     }
121     fRecs.remove(0, count);
122 }
123 
flush_all()124 void SkDeferredCanvas::flush_all() {
125     this->flush_le(fRecs.count() - 1);
126 }
127 
flush_before_saves()128 void SkDeferredCanvas::flush_before_saves() {
129     int i;
130     for (i = fRecs.count() - 1; i >= 0; --i) {
131         if (kSave_Type != fRecs[i].fType) {
132             break;
133         }
134     }
135     this->flush_le(i);
136 }
137 
138 enum Flags {
139     kNoTranslate_Flag   = 1 << 0,
140     kNoClip_Flag        = 1 << 1,
141     kNoCull_Flag        = 1 << 2,
142     kNoScale_Flag       = 1 << 3,
143 };
144 
flush_check(SkRect * bounds,const SkPaint * paint,unsigned flags)145 void SkDeferredCanvas::flush_check(SkRect* bounds, const SkPaint* paint, unsigned flags) {
146     if (paint) {
147         if (paint->getShader() || paint->getImageFilter()) {
148             flags |= kNoTranslate_Flag | kNoScale_Flag;
149         }
150         // TODO: replace these with code to enlarge the bounds conservatively?
151         if (paint->getStyle() != SkPaint::kFill_Style || paint->getMaskFilter() ||
152             paint->getImageFilter() || paint->getPathEffect())
153         {
154             flags |= kNoCull_Flag | kNoScale_Flag | kNoClip_Flag;
155         }
156         if (paint->getLooper()) {
157             // to be conservative, we disable both, since embedded layers could have shaders
158             // or strokes etc.
159             flags |= kNoTranslate_Flag | kNoCull_Flag | kNoScale_Flag;
160         }
161     }
162     bool canClip = !(flags & kNoClip_Flag);
163     bool canTranslate = !(flags & kNoTranslate_Flag);
164     bool canCull = !(flags & kNoCull_Flag);
165     bool canScale = !(flags & kNoScale_Flag);
166 
167     int i;
168     for (i = fRecs.count() - 1; i >= 0; --i) {
169         const Rec& rec = fRecs[i];
170         switch (rec.fType) {
171             case kSave_Type:
172                 // continue to the next rec
173                 break;
174             case kClipRect_Type:
175                 if (!canCull) {
176                     goto STOP;
177                 }
178                 if (canClip) {
179                     if (!bounds->intersect(rec.fData.fBounds)) {
180                         bounds->setEmpty();
181                         return;
182                     }
183                     // continue to the next rec
184                 } else {
185                     if (!rec.fData.fBounds.contains(*bounds)) {
186                         goto STOP;
187                     }
188                     // continue to the next rec
189                 }
190                 break;
191             case kTrans_Type:
192                 if (canTranslate) {
193                     bounds->offset(rec.fData.fTranslate.x(), rec.fData.fTranslate.y());
194                     // continue to the next rec
195                 } else {
196                     goto STOP;
197                 }
198                 break;
199             case kScaleTrans_Type:
200                 if (canScale) {
201                     SkMatrix m;
202                     rec.getConcat(&m);
203                     m.mapRectScaleTranslate(bounds, *bounds);
204                 } else {
205                     goto STOP;
206                 }
207                 break;
208         }
209     }
210 STOP:
211     this->flush_le(i);
212 }
213 
flush_translate(SkScalar * x,SkScalar * y,const SkRect & bounds,const SkPaint * paint)214 void SkDeferredCanvas::flush_translate(SkScalar* x, SkScalar* y, const SkRect& bounds,
215                                        const SkPaint* paint) {
216     SkRect tmp = bounds;
217     this->flush_check(&tmp, paint, kNoClip_Flag | kNoScale_Flag);
218     *x += tmp.x() - bounds.x();
219     *y += tmp.y() - bounds.y();
220 }
221 
flush_translate(SkScalar * x,SkScalar * y,const SkPaint & paint)222 void SkDeferredCanvas::flush_translate(SkScalar* x, SkScalar* y, const SkPaint& paint) {
223     SkRect tmp = SkRect::MakeXYWH(*x, *y, 1, 1);
224     this->flush_check(&tmp, &paint, kNoClip_Flag | kNoCull_Flag | kNoScale_Flag);
225     *x = tmp.x();
226     *y = tmp.y();
227 }
228 
229 ///////////////////////////////////////////////////////////////////////////////////////////////////
230 
willSave()231 void SkDeferredCanvas::willSave() {
232     this->push_save();
233 }
234 
getSaveLayerStrategy(const SaveLayerRec & rec)235 SkCanvas::SaveLayerStrategy SkDeferredCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
236     this->flush_all();
237     fCanvas->saveLayer(rec);
238     this->INHERITED::getSaveLayerStrategy(rec);
239     // No need for a layer.
240     return kNoLayer_SaveLayerStrategy;
241 }
242 
willRestore()243 void SkDeferredCanvas::willRestore() {
244     for (int i = fRecs.count() - 1; i >= 0; --i) {
245         if (kSave_Type == fRecs[i].fType) {
246             fRecs.setCount(i);  // pop off everything here and later
247             return;
248         }
249     }
250     for (int i = 0; i < fRecs.count(); ++i) {
251         SkASSERT(kSave_Type != fRecs[i].fType);
252     }
253     fRecs.setCount(0);
254     fCanvas->restore();
255     this->INHERITED::willRestore();
256 }
257 
didConcat(const SkMatrix & matrix)258 void SkDeferredCanvas::didConcat(const SkMatrix& matrix) {
259     if (matrix.isIdentity()) {
260         return;
261     }
262     if (!this->push_concat(matrix)) {
263         this->flush_all();
264         fCanvas->concat(matrix);
265         this->INHERITED::didConcat(matrix);
266     }
267 }
268 
didSetMatrix(const SkMatrix & matrix)269 void SkDeferredCanvas::didSetMatrix(const SkMatrix& matrix) {
270     this->flush_all();
271     fCanvas->setMatrix(matrix);
272     this->INHERITED::didSetMatrix(matrix);
273 }
274 
onClipRect(const SkRect & rect,ClipOp op,ClipEdgeStyle edgeStyle)275 void SkDeferredCanvas::onClipRect(const SkRect& rect, ClipOp op, ClipEdgeStyle edgeStyle) {
276     if (kIntersect_Op == op) {
277         this->push_cliprect(rect);
278     } else {
279         this->flush_all();
280         fCanvas->clipRect(rect, op, kSoft_ClipEdgeStyle == edgeStyle);
281         this->INHERITED::onClipRect(rect, op, edgeStyle);
282     }
283 }
284 
onClipRRect(const SkRRect & rrect,ClipOp op,ClipEdgeStyle edgeStyle)285 void SkDeferredCanvas::onClipRRect(const SkRRect& rrect, ClipOp op, ClipEdgeStyle edgeStyle) {
286     this->flush_all();
287     fCanvas->clipRRect(rrect, op, kSoft_ClipEdgeStyle == edgeStyle);
288     this->INHERITED::onClipRRect(rrect, op, edgeStyle);
289 }
290 
onClipPath(const SkPath & path,ClipOp op,ClipEdgeStyle edgeStyle)291 void SkDeferredCanvas::onClipPath(const SkPath& path, ClipOp op, ClipEdgeStyle edgeStyle) {
292     this->flush_all();
293     fCanvas->clipPath(path, op, kSoft_ClipEdgeStyle == edgeStyle);
294     this->INHERITED::onClipPath(path, op, edgeStyle);
295 }
296 
onClipRegion(const SkRegion & deviceRgn,ClipOp op)297 void SkDeferredCanvas::onClipRegion(const SkRegion& deviceRgn, ClipOp op) {
298     this->flush_all();
299     fCanvas->clipRegion(deviceRgn, op);
300     this->INHERITED::onClipRegion(deviceRgn, op);
301 }
302 
onDrawPaint(const SkPaint & paint)303 void SkDeferredCanvas::onDrawPaint(const SkPaint& paint) {
304     // TODO: Can we turn this into drawRect?
305     this->flush_all();
306     fCanvas->drawPaint(paint);
307 }
308 
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)309 void SkDeferredCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
310                                 const SkPaint& paint) {
311     this->flush_all();
312     fCanvas->drawPoints(mode, count, pts, paint);
313 }
314 
onDrawRect(const SkRect & rect,const SkPaint & paint)315 void SkDeferredCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
316     SkRect modRect = rect;
317     this->flush_check(&modRect, &paint);
318     fCanvas->drawRect(modRect, paint);
319 }
320 
onDrawRegion(const SkRegion & region,const SkPaint & paint)321 void SkDeferredCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
322     this->flush_all();  // can we do better?
323     fCanvas->drawRegion(region, paint);
324 }
325 
onDrawOval(const SkRect & rect,const SkPaint & paint)326 void SkDeferredCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
327     SkRect modRect = rect;
328     this->flush_check(&modRect, &paint, kNoClip_Flag);
329     fCanvas->drawOval(modRect, paint);
330 }
331 
onDrawArc(const SkRect & rect,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)332 void SkDeferredCanvas::onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
333                                  bool useCenter, const SkPaint& paint) {
334     SkRect modRect = rect;
335     this->flush_check(&modRect, &paint, kNoClip_Flag);
336     fCanvas->drawArc(modRect, startAngle, sweepAngle, useCenter, paint);
337 }
338 
make_offset(const SkRRect & src,SkScalar dx,SkScalar dy)339 static SkRRect make_offset(const SkRRect& src, SkScalar dx, SkScalar dy) {
340     SkRRect dst = src;
341     dst.offset(dx, dy);
342     return dst;
343 }
344 
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)345 void SkDeferredCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
346     SkRect modRect = rrect.getBounds();
347     this->flush_check(&modRect, &paint, kNoClip_Flag);
348     fCanvas->drawRRect(make_offset(rrect,
349                                    modRect.x() - rrect.getBounds().x(),
350                                    modRect.y() - rrect.getBounds().y()), paint);
351 }
352 
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)353 void SkDeferredCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
354     this->flush_all();
355     fCanvas->drawDRRect(outer, inner, paint);
356 }
357 
onDrawPath(const SkPath & path,const SkPaint & paint)358 void SkDeferredCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
359     if (path.isInverseFillType()) {
360         this->flush_before_saves();
361     } else {
362         SkRect modRect = path.getBounds();
363         this->flush_check(&modRect, &paint, kNoClip_Flag | kNoTranslate_Flag | kNoScale_Flag);
364     }
365     fCanvas->drawPath(path, paint);
366 }
367 
onDrawBitmap(const SkBitmap & bitmap,SkScalar x,SkScalar y,const SkPaint * paint)368 void SkDeferredCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
369                                 const SkPaint* paint) {
370     const SkScalar w = SkIntToScalar(bitmap.width());
371     const SkScalar h = SkIntToScalar(bitmap.height());
372     SkRect bounds = SkRect::MakeXYWH(x, y, w, h);
373     this->flush_check(&bounds, paint, kNoClip_Flag);
374     if (bounds.width() == w && bounds.height() == h) {
375         fCanvas->drawBitmap(bitmap, bounds.x(), bounds.y(), paint);
376     } else {
377         fCanvas->drawBitmapRect(bitmap, bounds, paint);
378     }
379 }
380 
onDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)381 void SkDeferredCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
382                                     const SkPaint* paint, SrcRectConstraint constraint) {
383     SkRect modRect = dst;
384     this->flush_check(&modRect, paint, kNoClip_Flag);
385     fCanvas->legacy_drawBitmapRect(bitmap, src, modRect, paint, constraint);
386 }
387 
onDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)388 void SkDeferredCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
389                                     const SkRect& dst, const SkPaint* paint) {
390     SkRect modRect = dst;
391     this->flush_check(&modRect, paint, kNoClip_Flag);
392     fCanvas->drawBitmapNine(bitmap, center, modRect, paint);
393 }
394 
onDrawBitmapLattice(const SkBitmap & bitmap,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)395 void SkDeferredCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
396                                            const SkRect& dst, const SkPaint* paint) {
397     SkRect modRect = dst;
398     this->flush_check(&modRect, paint, kNoClip_Flag);
399     fCanvas->drawBitmapLattice(bitmap, lattice, modRect, paint);
400 }
401 
onDrawImageNine(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)402 void SkDeferredCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center,
403                                        const SkRect& dst, const SkPaint* paint) {
404     SkRect modRect = dst;
405     this->flush_check(&modRect, paint, kNoClip_Flag);
406     fCanvas->drawImageNine(image, center, modRect, paint);
407 }
408 
onDrawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)409 void SkDeferredCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y,
410                                    const SkPaint* paint) {
411     const SkScalar w = SkIntToScalar(image->width());
412     const SkScalar h = SkIntToScalar(image->height());
413     SkRect bounds = SkRect::MakeXYWH(x, y, w, h);
414     this->flush_check(&bounds, paint, kNoClip_Flag);
415     if (bounds.width() == w && bounds.height() == h) {
416         fCanvas->drawImage(image, bounds.x(), bounds.y(), paint);
417     } else {
418         fCanvas->drawImageRect(image, bounds, paint);
419     }
420 }
421 
onDrawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)422 void SkDeferredCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
423                                    const SkPaint* paint, SrcRectConstraint constraint) {
424     SkRect modRect = dst;
425     this->flush_check(&modRect, paint, kNoClip_Flag);
426     fCanvas->legacy_drawImageRect(image, src, modRect, paint, constraint);
427 }
428 
onDrawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)429 void SkDeferredCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice,
430                                           const SkRect& dst, const SkPaint* paint) {
431     SkRect modRect = dst;
432     this->flush_check(&modRect, paint, kNoClip_Flag);
433     fCanvas->drawImageLattice(image, lattice, modRect, paint);
434 }
435 
onDrawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)436 void SkDeferredCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
437                               const SkPaint& paint) {
438     this->flush_translate(&x, &y, paint);
439     fCanvas->drawText(text, byteLength, x, y, paint);
440 }
441 
onDrawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)442 void SkDeferredCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
443                                  const SkPaint& paint) {
444     this->flush_before_saves();
445     fCanvas->drawPosText(text, byteLength, pos, paint);
446 }
447 
onDrawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)448 void SkDeferredCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
449                                   SkScalar constY, const SkPaint& paint) {
450     this->flush_before_saves();
451     fCanvas->drawPosTextH(text, byteLength, xpos, constY, paint);
452 }
453 
onDrawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)454 void SkDeferredCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
455                                     const SkMatrix* matrix, const SkPaint& paint) {
456     this->flush_before_saves();
457     fCanvas->drawTextOnPath(text, byteLength, path, matrix, paint);
458 }
459 
onDrawTextRSXform(const void * text,size_t byteLength,const SkRSXform xform[],const SkRect * cullRect,const SkPaint & paint)460 void SkDeferredCanvas::onDrawTextRSXform(const void* text, size_t byteLength,
461                                          const SkRSXform xform[], const SkRect* cullRect,
462                                          const SkPaint& paint) {
463     if (cullRect) {
464         SkRect modRect = *cullRect;
465         // only allow culling
466         this->flush_check(&modRect, &paint, kNoClip_Flag | kNoScale_Flag | kNoTranslate_Flag);
467     } else {
468         this->flush_before_saves();
469     }
470     fCanvas->drawTextRSXform(text, byteLength, xform, cullRect, paint);
471 }
472 
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)473 void SkDeferredCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
474                                   const SkPaint &paint) {
475     this->flush_translate(&x, &y, blob->bounds(), &paint);
476     fCanvas->drawTextBlob(blob, x, y, paint);
477 }
478 
479 #include "SkPicture.h"
480 #include "SkCanvasPriv.h"
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)481 void SkDeferredCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
482                                  const SkPaint* paint) {
483 #if 1
484     SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
485     picture->playback(this);
486 #else
487     this->flush_before_saves();
488     fCanvas->drawPicture(picture, matrix, paint);
489 #endif
490 }
491 
onDrawDrawable(SkDrawable * drawable,const SkMatrix * matrix)492 void SkDeferredCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
493     // TODO: investigate culling and applying concat to the matrix
494 #if 1
495     drawable->draw(this, matrix);
496 #else
497     this->flush_before_saves();
498     fCanvas->drawDrawable(drawable, matrix);
499 #endif
500 }
501 
onDrawAtlas(const SkImage * image,const SkRSXform xform[],const SkRect rects[],const SkColor colors[],int count,SkXfermode::Mode mode,const SkRect * cull,const SkPaint * paint)502 void SkDeferredCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[],
503                                    const SkRect rects[], const SkColor colors[],
504                                    int count, SkXfermode::Mode mode,
505                                    const SkRect* cull, const SkPaint* paint) {
506     this->flush_before_saves();
507     fCanvas->drawAtlas(image, xform, rects, colors, count, mode, cull, paint);
508 }
509 
onDrawVertices(VertexMode vmode,int vertexCount,const SkPoint vertices[],const SkPoint texs[],const SkColor colors[],SkXfermode * xmode,const uint16_t indices[],int indexCount,const SkPaint & paint)510 void SkDeferredCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
511                                   const SkPoint vertices[], const SkPoint texs[],
512                                   const SkColor colors[], SkXfermode* xmode,
513                                   const uint16_t indices[], int indexCount,
514                                   const SkPaint& paint) {
515     this->flush_before_saves();
516     fCanvas->drawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
517                            indices, indexCount, paint);
518 }
519 
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkXfermode * xmode,const SkPaint & paint)520 void SkDeferredCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
521                                const SkPoint texCoords[4], SkXfermode* xmode,
522                                const SkPaint& paint) {
523     this->flush_before_saves();
524     fCanvas->drawPatch(cubics, colors, texCoords, xmode, paint);
525 }
526 
onDrawAnnotation(const SkRect & rect,const char key[],SkData * data)527 void SkDeferredCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* data) {
528     fCanvas->drawAnnotation(rect, key, data);
529 }
530 
531 #ifdef SK_SUPPORT_LEGACY_DRAWFILTER
setDrawFilter(SkDrawFilter * filter)532 SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
533     fCanvas->setDrawFilter(filter);
534     return this->INHERITED::setDrawFilter(filter);
535 }
536 #endif
537 
538 ///////////////////////////////////////////////////////////////////////////////////////////////////
539 
onNewSurface(const SkImageInfo & info,const SkSurfaceProps & props)540 sk_sp<SkSurface> SkDeferredCanvas::onNewSurface(const SkImageInfo& info,
541                                                 const SkSurfaceProps& props) {
542     return fCanvas->makeSurface(info, &props);
543 }
getBaseLayerSize() const544 SkISize SkDeferredCanvas::getBaseLayerSize() const { return fCanvas->getBaseLayerSize(); }
getClipBounds(SkRect * bounds) const545 bool SkDeferredCanvas::getClipBounds(SkRect* bounds) const {
546     return fCanvas->getClipBounds(bounds);
547 }
getClipDeviceBounds(SkIRect * bounds) const548 bool SkDeferredCanvas::getClipDeviceBounds(SkIRect* bounds) const {
549     return fCanvas->getClipDeviceBounds(bounds);
550 }
isClipEmpty() const551 bool SkDeferredCanvas::isClipEmpty() const { return fCanvas->isClipEmpty(); }
isClipRect() const552 bool SkDeferredCanvas::isClipRect() const { return fCanvas->isClipRect(); }
onPeekPixels(SkPixmap * pixmap)553 bool SkDeferredCanvas::onPeekPixels(SkPixmap* pixmap) { return fCanvas->peekPixels(pixmap); }
onAccessTopLayerPixels(SkPixmap * pixmap)554 bool SkDeferredCanvas::onAccessTopLayerPixels(SkPixmap* pixmap) {
555     SkImageInfo info;
556     size_t rowBytes;
557     SkIPoint* origin = nullptr;
558     void* addr = fCanvas->accessTopLayerPixels(&info, &rowBytes, origin);
559     if (addr) {
560         *pixmap = SkPixmap(info, addr, rowBytes);
561         return true;
562     }
563     return false;
564 }
onImageInfo() const565 SkImageInfo SkDeferredCanvas::onImageInfo() const { return fCanvas->imageInfo(); }
onGetProps(SkSurfaceProps * props) const566 bool SkDeferredCanvas::onGetProps(SkSurfaceProps* props) const { return fCanvas->getProps(props); }
onFlush()567 void SkDeferredCanvas::onFlush() {
568     this->flush_all();
569     return fCanvas->flush();
570 }
571