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