Home | History | Annotate | Download | only in utils
      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 
     17 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 
     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 
     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 
     57 SkDeferredCanvas::~SkDeferredCanvas() {}
     58 
     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 
     72 void SkDeferredCanvas::push_save() {
     73     Rec* r = fRecs.append();
     74     r->fType = kSave_Type;
     75 }
     76 
     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 
     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 
    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 
    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 
    142 void SkDeferredCanvas::flush_all() {
    143     this->flush_le(fRecs.count() - 1);
    144 }
    145 
    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 
    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 
    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 
    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 
    249 void SkDeferredCanvas::willSave() {
    250     this->push_save();
    251 }
    252 
    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 
    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 
    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 
    287 void SkDeferredCanvas::didSetMatrix(const SkMatrix& matrix) {
    288     this->flush_all();
    289     fCanvas->setMatrix(matrix);
    290     this->INHERITED::didSetMatrix(matrix);
    291 }
    292 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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"
    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 
    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 
    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 
    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 
    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 
    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
    548 SkDrawFilter* SkDeferredCanvas::setDrawFilter(SkDrawFilter* filter) {
    549     fCanvas->setDrawFilter(filter);
    550     return this->INHERITED::setDrawFilter(filter);
    551 }
    552 #endif
    553 
    554 ///////////////////////////////////////////////////////////////////////////////////////////////////
    555 
    556 sk_sp<SkSurface> SkDeferredCanvas::onNewSurface(const SkImageInfo& info,
    557                                                 const SkSurfaceProps& props) {
    558     return fCanvas->makeSurface(info, &props);
    559 }
    560 SkISize SkDeferredCanvas::getBaseLayerSize() const { return fCanvas->getBaseLayerSize(); }
    561 SkRect SkDeferredCanvas::onGetLocalClipBounds() const {
    562     return fCanvas->getLocalClipBounds();
    563 }
    564 SkIRect SkDeferredCanvas::onGetDeviceClipBounds() const {
    565     return fCanvas->getDeviceClipBounds();
    566 }
    567 bool SkDeferredCanvas::isClipEmpty() const { return fCanvas->isClipEmpty(); }
    568 bool SkDeferredCanvas::isClipRect() const { return fCanvas->isClipRect(); }
    569 bool SkDeferredCanvas::onPeekPixels(SkPixmap* pixmap) { return fCanvas->peekPixels(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 }
    581 SkImageInfo SkDeferredCanvas::onImageInfo() const { return fCanvas->imageInfo(); }
    582 bool SkDeferredCanvas::onGetProps(SkSurfaceProps* props) const { return fCanvas->getProps(props); }
    583 void SkDeferredCanvas::onFlush() {
    584     this->flush_all();
    585     return fCanvas->flush();
    586 }
    587