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