Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2008 The Android Open Source Project
      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 "SkCanvas.h"
      9 
     10 #include "SkArenaAlloc.h"
     11 #include "SkBitmapDevice.h"
     12 #include "SkCanvasPriv.h"
     13 #include "SkClipOpPriv.h"
     14 #include "SkClipStack.h"
     15 #include "SkColorFilter.h"
     16 #include "SkDraw.h"
     17 #include "SkDrawLooper.h"
     18 #include "SkGlyphRun.h"
     19 #include "SkImage.h"
     20 #include "SkImageFilter.h"
     21 #include "SkImageFilterCache.h"
     22 #include "SkImage_Base.h"
     23 #include "SkLatticeIter.h"
     24 #include "SkMSAN.h"
     25 #include "SkMakeUnique.h"
     26 #include "SkMatrixUtils.h"
     27 #include "SkNoDrawCanvas.h"
     28 #include "SkNx.h"
     29 #include "SkPaintPriv.h"
     30 #include "SkPatchUtils.h"
     31 #include "SkPathEffect.h"
     32 #include "SkPicture.h"
     33 #include "SkRRect.h"
     34 #include "SkRasterClip.h"
     35 #include "SkRasterHandleAllocator.h"
     36 #include "SkSpecialImage.h"
     37 #include "SkStrikeCache.h"
     38 #include "SkString.h"
     39 #include "SkSurface_Base.h"
     40 #include "SkTLazy.h"
     41 #include "SkTextBlob.h"
     42 #include "SkTextFormatParams.h"
     43 #include "SkTo.h"
     44 #include "SkTraceEvent.h"
     45 #include "SkVertices.h"
     46 
     47 #include <new>
     48 
     49 #if SK_SUPPORT_GPU
     50 #include "GrContext.h"
     51 #include "SkGr.h"
     52 #endif
     53 
     54 #define RETURN_ON_NULL(ptr)     do { if (nullptr == (ptr)) return; } while (0)
     55 #define RETURN_ON_FALSE(pred)   do { if (!(pred)) return; } while (0)
     56 
     57 ///////////////////////////////////////////////////////////////////////////////////////////////////
     58 
     59 /*
     60  *  Return true if the drawing this rect would hit every pixels in the canvas.
     61  *
     62  *  Returns false if
     63  *  - rect does not contain the canvas' bounds
     64  *  - paint is not fill
     65  *  - paint would blur or otherwise change the coverage of the rect
     66  */
     67 bool SkCanvas::wouldOverwriteEntireSurface(const SkRect* rect, const SkPaint* paint,
     68                                            ShaderOverrideOpacity overrideOpacity) const {
     69     static_assert((int)SkPaintPriv::kNone_ShaderOverrideOpacity ==
     70                   (int)kNone_ShaderOverrideOpacity,
     71                   "need_matching_enums0");
     72     static_assert((int)SkPaintPriv::kOpaque_ShaderOverrideOpacity ==
     73                   (int)kOpaque_ShaderOverrideOpacity,
     74                   "need_matching_enums1");
     75     static_assert((int)SkPaintPriv::kNotOpaque_ShaderOverrideOpacity ==
     76                   (int)kNotOpaque_ShaderOverrideOpacity,
     77                   "need_matching_enums2");
     78 
     79     const SkISize size = this->getBaseLayerSize();
     80     const SkRect bounds = SkRect::MakeIWH(size.width(), size.height());
     81 
     82     // if we're clipped at all, we can't overwrite the entire surface
     83     {
     84         SkBaseDevice* base = this->getDevice();
     85         SkBaseDevice* top = this->getTopDevice();
     86         if (base != top) {
     87             return false;   // we're in a saveLayer, so conservatively don't assume we'll overwrite
     88         }
     89         if (!base->clipIsWideOpen()) {
     90             return false;
     91         }
     92     }
     93 
     94     if (rect) {
     95         if (!this->getTotalMatrix().isScaleTranslate()) {
     96             return false; // conservative
     97         }
     98 
     99         SkRect devRect;
    100         this->getTotalMatrix().mapRectScaleTranslate(&devRect, *rect);
    101         if (!devRect.contains(bounds)) {
    102             return false;
    103         }
    104     }
    105 
    106     if (paint) {
    107         SkPaint::Style paintStyle = paint->getStyle();
    108         if (!(paintStyle == SkPaint::kFill_Style ||
    109               paintStyle == SkPaint::kStrokeAndFill_Style)) {
    110             return false;
    111         }
    112         if (paint->getMaskFilter() || paint->getLooper()
    113             || paint->getPathEffect() || paint->getImageFilter()) {
    114             return false; // conservative
    115         }
    116     }
    117     return SkPaintPriv::Overwrites(paint, (SkPaintPriv::ShaderOverrideOpacity)overrideOpacity);
    118 }
    119 
    120 ///////////////////////////////////////////////////////////////////////////////////////////////////
    121 
    122 // experimental for faster tiled drawing...
    123 //#define SK_TRACE_SAVERESTORE
    124 
    125 #ifdef SK_TRACE_SAVERESTORE
    126     static int gLayerCounter;
    127     static void inc_layer() { ++gLayerCounter; printf("----- inc layer %d\n", gLayerCounter); }
    128     static void dec_layer() { --gLayerCounter; printf("----- dec layer %d\n", gLayerCounter); }
    129 
    130     static int gRecCounter;
    131     static void inc_rec() { ++gRecCounter; printf("----- inc rec %d\n", gRecCounter); }
    132     static void dec_rec() { --gRecCounter; printf("----- dec rec %d\n", gRecCounter); }
    133 
    134     static int gCanvasCounter;
    135     static void inc_canvas() { ++gCanvasCounter; printf("----- inc canvas %d\n", gCanvasCounter); }
    136     static void dec_canvas() { --gCanvasCounter; printf("----- dec canvas %d\n", gCanvasCounter); }
    137 #else
    138     #define inc_layer()
    139     #define dec_layer()
    140     #define inc_rec()
    141     #define dec_rec()
    142     #define inc_canvas()
    143     #define dec_canvas()
    144 #endif
    145 
    146 typedef SkTLazy<SkPaint> SkLazyPaint;
    147 
    148 void SkCanvas::predrawNotify(bool willOverwritesEntireSurface) {
    149     if (fSurfaceBase) {
    150         fSurfaceBase->aboutToDraw(willOverwritesEntireSurface
    151                                   ? SkSurface::kDiscard_ContentChangeMode
    152                                   : SkSurface::kRetain_ContentChangeMode);
    153     }
    154 }
    155 
    156 void SkCanvas::predrawNotify(const SkRect* rect, const SkPaint* paint,
    157                              ShaderOverrideOpacity overrideOpacity) {
    158     if (fSurfaceBase) {
    159         SkSurface::ContentChangeMode mode = SkSurface::kRetain_ContentChangeMode;
    160         // Since willOverwriteAllPixels() may not be complete free to call, we only do so if
    161         // there is an outstanding snapshot, since w/o that, there will be no copy-on-write
    162         // and therefore we don't care which mode we're in.
    163         //
    164         if (fSurfaceBase->outstandingImageSnapshot()) {
    165             if (this->wouldOverwriteEntireSurface(rect, paint, overrideOpacity)) {
    166                 mode = SkSurface::kDiscard_ContentChangeMode;
    167             }
    168         }
    169         fSurfaceBase->aboutToDraw(mode);
    170     }
    171 }
    172 
    173 ///////////////////////////////////////////////////////////////////////////////
    174 
    175 /*  This is the record we keep for each SkBaseDevice that the user installs.
    176     The clip/matrix/proc are fields that reflect the top of the save/restore
    177     stack. Whenever the canvas changes, it marks a dirty flag, and then before
    178     these are used (assuming we're not on a layer) we rebuild these cache
    179     values: they reflect the top of the save stack, but translated and clipped
    180     by the device's XY offset and bitmap-bounds.
    181 */
    182 struct DeviceCM {
    183     DeviceCM*                      fNext;
    184     sk_sp<SkBaseDevice>            fDevice;
    185     SkRasterClip                   fClip;
    186     std::unique_ptr<const SkPaint> fPaint; // may be null (in the future)
    187     SkMatrix                       fStashedMatrix; // original CTM; used by imagefilter in saveLayer
    188     sk_sp<SkImage>                 fClipImage;
    189     SkMatrix                       fClipMatrix;
    190 
    191     DeviceCM(sk_sp<SkBaseDevice> device, const SkPaint* paint, const SkMatrix& stashed,
    192              const SkImage* clipImage, const SkMatrix* clipMatrix)
    193         : fNext(nullptr)
    194         , fDevice(std::move(device))
    195         , fPaint(paint ? skstd::make_unique<SkPaint>(*paint) : nullptr)
    196         , fStashedMatrix(stashed)
    197         , fClipImage(sk_ref_sp(const_cast<SkImage*>(clipImage)))
    198         , fClipMatrix(clipMatrix ? *clipMatrix : SkMatrix::I())
    199     {}
    200 
    201     void reset(const SkIRect& bounds) {
    202         SkASSERT(!fPaint);
    203         SkASSERT(!fNext);
    204         SkASSERT(fDevice);
    205         fClip.setRect(bounds);
    206     }
    207 };
    208 
    209 namespace {
    210 // Encapsulate state needed to restore from saveBehind()
    211 struct BackImage {
    212     sk_sp<SkSpecialImage> fImage;
    213     SkIPoint              fLoc;
    214 };
    215 }
    216 
    217 /*  This is the record we keep for each save/restore level in the stack.
    218     Since a level optionally copies the matrix and/or stack, we have pointers
    219     for these fields. If the value is copied for this level, the copy is
    220     stored in the ...Storage field, and the pointer points to that. If the
    221     value is not copied for this level, we ignore ...Storage, and just point
    222     at the corresponding value in the previous level in the stack.
    223 */
    224 class SkCanvas::MCRec {
    225 public:
    226     DeviceCM* fLayer;
    227     /*  If there are any layers in the stack, this points to the top-most
    228         one that is at or below this level in the stack (so we know what
    229         bitmap/device to draw into from this level. This value is NOT
    230         reference counted, since the real owner is either our fLayer field,
    231         or a previous one in a lower level.)
    232     */
    233     DeviceCM* fTopLayer;
    234     std::unique_ptr<BackImage> fBackImage;
    235     SkConservativeClip fRasterClip;
    236     SkMatrix fMatrix;
    237     int fDeferredSaveCount;
    238 
    239     MCRec() {
    240         fLayer      = nullptr;
    241         fTopLayer   = nullptr;
    242         fMatrix.reset();
    243         fDeferredSaveCount = 0;
    244 
    245         // don't bother initializing fNext
    246         inc_rec();
    247     }
    248     MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
    249         fLayer = nullptr;
    250         fTopLayer = prev.fTopLayer;
    251         fDeferredSaveCount = 0;
    252 
    253         // don't bother initializing fNext
    254         inc_rec();
    255     }
    256     ~MCRec() {
    257         delete fLayer;
    258         dec_rec();
    259     }
    260 
    261     void reset(const SkIRect& bounds) {
    262         SkASSERT(fLayer);
    263         SkASSERT(fDeferredSaveCount == 0);
    264 
    265         fMatrix.reset();
    266         fRasterClip.setRect(bounds);
    267         fLayer->reset(bounds);
    268     }
    269 };
    270 
    271 class SkDrawIter {
    272 public:
    273     SkDrawIter(SkCanvas* canvas)
    274         : fDevice(nullptr), fCurrLayer(canvas->fMCRec->fTopLayer), fPaint(nullptr)
    275     {}
    276 
    277     bool next() {
    278         const DeviceCM* rec = fCurrLayer;
    279         if (rec && rec->fDevice) {
    280             fDevice = rec->fDevice.get();
    281             fPaint  = rec->fPaint.get();
    282             fCurrLayer = rec->fNext;
    283             // fCurrLayer may be nullptr now
    284             return true;
    285         }
    286         return false;
    287     }
    288 
    289     int getX() const { return fDevice->getOrigin().x(); }
    290     int getY() const { return fDevice->getOrigin().y(); }
    291     const SkPaint* getPaint() const { return fPaint; }
    292 
    293     SkBaseDevice*   fDevice;
    294 
    295 private:
    296     const DeviceCM* fCurrLayer;
    297     const SkPaint*  fPaint;     // May be null.
    298 };
    299 
    300 #define FOR_EACH_TOP_DEVICE( code )                       \
    301     do {                                                  \
    302         DeviceCM* layer = fMCRec->fTopLayer;              \
    303         while (layer) {                                   \
    304             SkBaseDevice* device = layer->fDevice.get();  \
    305             if (device) {                                 \
    306                 code;                                     \
    307             }                                             \
    308             layer = layer->fNext;                         \
    309         }                                                 \
    310     } while (0)
    311 
    312 /////////////////////////////////////////////////////////////////////////////
    313 
    314 static SkPaint* set_if_needed(SkLazyPaint* lazy, const SkPaint& orig) {
    315     return lazy->isValid() ? lazy->get() : lazy->set(orig);
    316 }
    317 
    318 /**
    319  *  If the paint has an imagefilter, but it can be simplified to just a colorfilter, return that
    320  *  colorfilter, else return nullptr.
    321  */
    322 static sk_sp<SkColorFilter> image_to_color_filter(const SkPaint& paint) {
    323     SkImageFilter* imgf = paint.getImageFilter();
    324     if (!imgf) {
    325         return nullptr;
    326     }
    327 
    328     SkColorFilter* imgCFPtr;
    329     if (!imgf->asAColorFilter(&imgCFPtr)) {
    330         return nullptr;
    331     }
    332     sk_sp<SkColorFilter> imgCF(imgCFPtr);
    333 
    334     SkColorFilter* paintCF = paint.getColorFilter();
    335     if (nullptr == paintCF) {
    336         // there is no existing paint colorfilter, so we can just return the imagefilter's
    337         return imgCF;
    338     }
    339 
    340     // The paint has both a colorfilter(paintCF) and an imagefilter-which-is-a-colorfilter(imgCF)
    341     // and we need to combine them into a single colorfilter.
    342     return imgCF->makeComposed(sk_ref_sp(paintCF));
    343 }
    344 
    345 /**
    346  * There are many bounds in skia. A circle's bounds is just its center extended by its radius.
    347  * However, if we stroke a circle, then the "bounds" of that is larger, since it will now draw
    348  * outside of its raw-bounds by 1/2 the stroke width.  SkPaint has lots of optional
    349  * effects/attributes that can modify the effective bounds of a given primitive -- maskfilters,
    350  * patheffects, stroking, etc.  This function takes a raw bounds and a paint, and returns the
    351  * conservative "effective" bounds based on the settings in the paint... with one exception. This
    352  * function does *not* look at the imagefilter, which can also modify the effective bounds. It is
    353  * deliberately ignored.
    354  */
    355 static const SkRect& apply_paint_to_bounds_sans_imagefilter(const SkPaint& paint,
    356                                                             const SkRect& rawBounds,
    357                                                             SkRect* storage) {
    358     SkPaint tmpUnfiltered(paint);
    359     tmpUnfiltered.setImageFilter(nullptr);
    360     if (tmpUnfiltered.canComputeFastBounds()) {
    361         return tmpUnfiltered.computeFastBounds(rawBounds, storage);
    362     } else {
    363         return rawBounds;
    364     }
    365 }
    366 
    367 class AutoDrawLooper {
    368 public:
    369     // "rawBounds" is the original bounds of the primitive about to be drawn, unmodified by the
    370     // paint. It's used to determine the size of the offscreen layer for filters.
    371     // If null, the clip will be used instead.
    372     AutoDrawLooper(SkCanvas* canvas, const SkPaint& paint, bool skipLayerForImageFilter = false,
    373                    const SkRect* rawBounds = nullptr) : fOrigPaint(paint) {
    374         fCanvas = canvas;
    375         fPaint = &fOrigPaint;
    376         fSaveCount = canvas->getSaveCount();
    377         fTempLayerForImageFilter = false;
    378         fDone = false;
    379 
    380         auto simplifiedCF = image_to_color_filter(fOrigPaint);
    381         if (simplifiedCF) {
    382             SkPaint* paint = set_if_needed(&fLazyPaintInit, fOrigPaint);
    383             paint->setColorFilter(std::move(simplifiedCF));
    384             paint->setImageFilter(nullptr);
    385             fPaint = paint;
    386         }
    387 
    388         if (!skipLayerForImageFilter && fPaint->getImageFilter()) {
    389             /**
    390              *  We implement ImageFilters for a given draw by creating a layer, then applying the
    391              *  imagefilter to the pixels of that layer (its backing surface/image), and then
    392              *  we call restore() to xfer that layer to the main canvas.
    393              *
    394              *  1. SaveLayer (with a paint containing the current imagefilter and xfermode)
    395              *  2. Generate the src pixels:
    396              *      Remove the imagefilter and the xfermode from the paint that we (AutoDrawLooper)
    397              *      return (fPaint). We then draw the primitive (using srcover) into a cleared
    398              *      buffer/surface.
    399              *  3. Restore the layer created in #1
    400              *      The imagefilter is passed the buffer/surface from the layer (now filled with the
    401              *      src pixels of the primitive). It returns a new "filtered" buffer, which we
    402              *      draw onto the previous layer using the xfermode from the original paint.
    403              */
    404             SkPaint tmp;
    405             tmp.setImageFilter(fPaint->refImageFilter());
    406             tmp.setBlendMode(fPaint->getBlendMode());
    407             SkRect storage;
    408             if (rawBounds) {
    409                 // Make rawBounds include all paint outsets except for those due to image filters.
    410                 rawBounds = &apply_paint_to_bounds_sans_imagefilter(*fPaint, *rawBounds, &storage);
    411             }
    412             (void)canvas->internalSaveLayer(SkCanvas::SaveLayerRec(rawBounds, &tmp),
    413                                             SkCanvas::kFullLayer_SaveLayerStrategy);
    414             fTempLayerForImageFilter = true;
    415             // we remove the imagefilter/xfermode inside doNext()
    416         }
    417 
    418         if (SkDrawLooper* looper = paint.getLooper()) {
    419             fLooperContext = looper->makeContext(canvas, &fAlloc);
    420             fIsSimple = false;
    421         } else {
    422             fLooperContext = nullptr;
    423             // can we be marked as simple?
    424             fIsSimple = !fTempLayerForImageFilter;
    425         }
    426     }
    427 
    428     ~AutoDrawLooper() {
    429         if (fTempLayerForImageFilter) {
    430             fCanvas->internalRestore();
    431         }
    432         SkASSERT(fCanvas->getSaveCount() == fSaveCount);
    433     }
    434 
    435     const SkPaint& paint() const {
    436         SkASSERT(fPaint);
    437         SkASSERT(fPaint->getDrawLooper() == nullptr);   // we should have cleared this
    438         return *fPaint;
    439     }
    440 
    441     bool next() {
    442         if (fDone) {
    443             return false;
    444         } else if (fIsSimple) {
    445             fDone = true;
    446             return !fPaint->nothingToDraw();
    447         } else {
    448             return this->doNext();
    449         }
    450     }
    451 
    452 private:
    453     SkLazyPaint     fLazyPaintInit;       // base paint storage in case we need to modify it
    454     SkLazyPaint     fLazyPaintPerLooper;  // per-draw-looper storage, so the looper can modify it
    455     SkCanvas*       fCanvas;
    456     const SkPaint&  fOrigPaint;
    457     const SkPaint*  fPaint;
    458     int             fSaveCount;
    459     bool            fTempLayerForImageFilter;
    460     bool            fDone;
    461     bool            fIsSimple;
    462     SkDrawLooper::Context* fLooperContext;
    463     SkSTArenaAlloc<48>     fAlloc;
    464 
    465     bool doNext();
    466 };
    467 
    468 bool AutoDrawLooper::doNext() {
    469     fPaint = nullptr;
    470     SkASSERT(!fIsSimple);
    471     SkASSERT(fLooperContext || fTempLayerForImageFilter);
    472 
    473     SkPaint* paint = fLazyPaintPerLooper.set(fLazyPaintInit.isValid() ?
    474                                              *fLazyPaintInit.get() : fOrigPaint);
    475     // never want our downstream clients (i.e. devices) to see loopers
    476     paint->setDrawLooper(nullptr);
    477 
    478     if (fTempLayerForImageFilter) {
    479         paint->setImageFilter(nullptr);
    480         paint->setBlendMode(SkBlendMode::kSrcOver);
    481     }
    482 
    483     if (fLooperContext && !fLooperContext->next(fCanvas, paint)) {
    484         fDone = true;
    485         return false;
    486     }
    487     fPaint = paint;
    488 
    489     // if we only came in here for the imagefilter, mark us as done
    490     if (!fLooperContext) {
    491         fDone = true;
    492     }
    493     return true;
    494 }
    495 
    496 ////////// macros to place around the internal draw calls //////////////////
    497 
    498 #define LOOPER_BEGIN_DRAWBITMAP(paint, skipLayerForFilter, bounds)  \
    499     this->predrawNotify();                                          \
    500     AutoDrawLooper looper(this, paint, skipLayerForFilter, bounds); \
    501     while (looper.next()) {                                         \
    502         SkDrawIter iter(this);
    503 
    504 
    505 #define LOOPER_BEGIN_DRAWDEVICE(paint)                              \
    506     this->predrawNotify();                                          \
    507     AutoDrawLooper  looper(this, paint, true);                      \
    508     while (looper.next()) {                                         \
    509         SkDrawIter          iter(this);
    510 
    511 #define LOOPER_BEGIN(paint, bounds)                                 \
    512     this->predrawNotify();                                          \
    513     AutoDrawLooper  looper(this, paint, false, bounds);             \
    514     while (looper.next()) {                                         \
    515         SkDrawIter          iter(this);
    516 
    517 #define LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, bounds, auxOpaque)  \
    518     this->predrawNotify(bounds, &paint, auxOpaque);                 \
    519     AutoDrawLooper  looper(this, paint, false, bounds);             \
    520     while (looper.next()) {                                         \
    521         SkDrawIter          iter(this);
    522 
    523 #define LOOPER_END    }
    524 
    525 ////////////////////////////////////////////////////////////////////////////
    526 
    527 static inline SkRect qr_clip_bounds(const SkIRect& bounds) {
    528     if (bounds.isEmpty()) {
    529         return SkRect::MakeEmpty();
    530     }
    531 
    532     // Expand bounds out by 1 in case we are anti-aliasing.  We store the
    533     // bounds as floats to enable a faster quick reject implementation.
    534     SkRect dst;
    535     SkNx_cast<float>(Sk4i::Load(&bounds.fLeft) + Sk4i(-1,-1,1,1)).store(&dst.fLeft);
    536     return dst;
    537 }
    538 
    539 void SkCanvas::resetForNextPicture(const SkIRect& bounds) {
    540     this->restoreToCount(1);
    541     fMCRec->reset(bounds);
    542 
    543     // We're peering through a lot of structs here.  Only at this scope do we
    544     // know that the device is a SkNoPixelsDevice.
    545     static_cast<SkNoPixelsDevice*>(fMCRec->fLayer->fDevice.get())->resetForNextPicture(bounds);
    546     fDeviceClipBounds = qr_clip_bounds(bounds);
    547     fIsScaleTranslate = true;
    548 }
    549 
    550 void SkCanvas::init(sk_sp<SkBaseDevice> device) {
    551     fAllowSimplifyClip = false;
    552     fSaveCount = 1;
    553 
    554     fMCRec = (MCRec*)fMCStack.push_back();
    555     new (fMCRec) MCRec;
    556     fMCRec->fRasterClip.setDeviceClipRestriction(&fClipRestrictionRect);
    557     fIsScaleTranslate = true;
    558 
    559     SkASSERT(sizeof(DeviceCM) <= sizeof(fDeviceCMStorage));
    560     fMCRec->fLayer = (DeviceCM*)fDeviceCMStorage;
    561     new (fDeviceCMStorage) DeviceCM(device, nullptr, fMCRec->fMatrix, nullptr, nullptr);
    562 
    563     fMCRec->fTopLayer = fMCRec->fLayer;
    564 
    565     fSurfaceBase = nullptr;
    566 
    567     if (device) {
    568         // The root device and the canvas should always have the same pixel geometry
    569         SkASSERT(fProps.pixelGeometry() == device->surfaceProps().pixelGeometry());
    570         fMCRec->fRasterClip.setRect(device->getGlobalBounds());
    571         fDeviceClipBounds = qr_clip_bounds(device->getGlobalBounds());
    572 
    573         device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
    574     }
    575 
    576     fScratchGlyphRunBuilder = skstd::make_unique<SkGlyphRunBuilder>();
    577 }
    578 
    579 SkCanvas::SkCanvas()
    580     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    581     , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
    582 {
    583     inc_canvas();
    584 
    585     this->init(nullptr);
    586 }
    587 
    588 SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
    589     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    590     , fProps(SkSurfacePropsCopyOrDefault(props))
    591 {
    592     inc_canvas();
    593     this->init(sk_make_sp<SkNoPixelsDevice>(
    594             SkIRect::MakeWH(SkTMax(width, 0), SkTMax(height, 0)), fProps));
    595 }
    596 
    597 SkCanvas::SkCanvas(const SkIRect& bounds)
    598     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    599     , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
    600 {
    601     inc_canvas();
    602 
    603     SkIRect r = bounds.isEmpty() ? SkIRect::MakeEmpty() : bounds;
    604     this->init(sk_make_sp<SkNoPixelsDevice>(r, fProps));
    605 }
    606 
    607 SkCanvas::SkCanvas(sk_sp<SkBaseDevice> device)
    608     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    609     , fProps(device->surfaceProps())
    610 {
    611     inc_canvas();
    612 
    613     this->init(device);
    614 }
    615 
    616 SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
    617     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    618     , fProps(props)
    619 {
    620     inc_canvas();
    621 
    622     sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps, nullptr, nullptr));
    623     this->init(device);
    624 }
    625 
    626 SkCanvas::SkCanvas(const SkBitmap& bitmap, std::unique_ptr<SkRasterHandleAllocator> alloc,
    627                    SkRasterHandleAllocator::Handle hndl)
    628     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    629     , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
    630     , fAllocator(std::move(alloc))
    631 {
    632     inc_canvas();
    633 
    634     sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps, hndl, nullptr));
    635     this->init(device);
    636 }
    637 
    638 SkCanvas::SkCanvas(const SkBitmap& bitmap) : SkCanvas(bitmap, nullptr, nullptr) {}
    639 
    640 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
    641 SkCanvas::SkCanvas(const SkBitmap& bitmap, ColorBehavior)
    642     : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
    643     , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
    644     , fAllocator(nullptr)
    645 {
    646     inc_canvas();
    647 
    648     SkBitmap tmp(bitmap);
    649     *const_cast<SkImageInfo*>(&tmp.info()) = tmp.info().makeColorSpace(nullptr);
    650     sk_sp<SkBaseDevice> device(new SkBitmapDevice(tmp, fProps, nullptr, nullptr));
    651     this->init(device);
    652 }
    653 #endif
    654 
    655 SkCanvas::~SkCanvas() {
    656     // free up the contents of our deque
    657     this->restoreToCount(1);    // restore everything but the last
    658 
    659     this->internalRestore();    // restore the last, since we're going away
    660 
    661     dec_canvas();
    662 }
    663 
    664 ///////////////////////////////////////////////////////////////////////////////
    665 
    666 void SkCanvas::flush() {
    667     this->onFlush();
    668 }
    669 
    670 void SkCanvas::onFlush() {
    671     SkBaseDevice* device = this->getDevice();
    672     if (device) {
    673         device->flush();
    674     }
    675 }
    676 
    677 SkISize SkCanvas::getBaseLayerSize() const {
    678     SkBaseDevice* d = this->getDevice();
    679     return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
    680 }
    681 
    682 SkIRect SkCanvas::getTopLayerBounds() const {
    683     SkBaseDevice* d = this->getTopDevice();
    684     if (!d) {
    685         return SkIRect::MakeEmpty();
    686     }
    687     return SkIRect::MakeXYWH(d->getOrigin().x(), d->getOrigin().y(), d->width(), d->height());
    688 }
    689 
    690 SkBaseDevice* SkCanvas::getDevice() const {
    691     // return root device
    692     MCRec* rec = (MCRec*) fMCStack.front();
    693     SkASSERT(rec && rec->fLayer);
    694     return rec->fLayer->fDevice.get();
    695 }
    696 
    697 SkBaseDevice* SkCanvas::getTopDevice() const {
    698     return fMCRec->fTopLayer->fDevice.get();
    699 }
    700 
    701 bool SkCanvas::readPixels(const SkPixmap& pm, int x, int y) {
    702     SkBaseDevice* device = this->getDevice();
    703     return device && pm.addr() && device->readPixels(pm, x, y);
    704 }
    705 
    706 bool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
    707     return this->readPixels({ dstInfo, dstP, rowBytes}, x, y);
    708 }
    709 
    710 bool SkCanvas::readPixels(const SkBitmap& bm, int x, int y) {
    711     SkPixmap pm;
    712     return bm.peekPixels(&pm) && this->readPixels(pm, x, y);
    713 }
    714 
    715 bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
    716     SkPixmap pm;
    717     if (bitmap.peekPixels(&pm)) {
    718         return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
    719     }
    720     return false;
    721 }
    722 
    723 bool SkCanvas::writePixels(const SkImageInfo& srcInfo, const void* pixels, size_t rowBytes,
    724                            int x, int y) {
    725     SkBaseDevice* device = this->getDevice();
    726     if (!device) {
    727         return false;
    728     }
    729 
    730     // This check gives us an early out and prevents generation ID churn on the surface.
    731     // This is purely optional: it is a subset of the checks performed by SkWritePixelsRec.
    732     SkIRect srcRect = SkIRect::MakeXYWH(x, y, srcInfo.width(), srcInfo.height());
    733     if (!srcRect.intersect(0, 0, device->width(), device->height())) {
    734         return false;
    735     }
    736 
    737     // Tell our owning surface to bump its generation ID.
    738     const bool completeOverwrite =
    739             srcRect.size() == SkISize::Make(device->width(), device->height());
    740     this->predrawNotify(completeOverwrite);
    741 
    742     // This can still fail, most notably in the case of a invalid color type or alpha type
    743     // conversion.  We could pull those checks into this function and avoid the unnecessary
    744     // generation ID bump.  But then we would be performing those checks twice, since they
    745     // are also necessary at the bitmap/pixmap entry points.
    746     return device->writePixels({srcInfo, pixels, rowBytes}, x, y);
    747 }
    748 
    749 //////////////////////////////////////////////////////////////////////////////
    750 
    751 void SkCanvas::checkForDeferredSave() {
    752     if (fMCRec->fDeferredSaveCount > 0) {
    753         this->doSave();
    754     }
    755 }
    756 
    757 int SkCanvas::getSaveCount() const {
    758 #ifdef SK_DEBUG
    759     int count = 0;
    760     SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
    761     for (;;) {
    762         const MCRec* rec = (const MCRec*)iter.next();
    763         if (!rec) {
    764             break;
    765         }
    766         count += 1 + rec->fDeferredSaveCount;
    767     }
    768     SkASSERT(count == fSaveCount);
    769 #endif
    770     return fSaveCount;
    771 }
    772 
    773 int SkCanvas::save() {
    774     fSaveCount += 1;
    775     fMCRec->fDeferredSaveCount += 1;
    776     return this->getSaveCount() - 1;  // return our prev value
    777 }
    778 
    779 void SkCanvas::doSave() {
    780     this->willSave();
    781 
    782     SkASSERT(fMCRec->fDeferredSaveCount > 0);
    783     fMCRec->fDeferredSaveCount -= 1;
    784     this->internalSave();
    785 }
    786 
    787 void SkCanvas::restore() {
    788     if (fMCRec->fDeferredSaveCount > 0) {
    789         SkASSERT(fSaveCount > 1);
    790         fSaveCount -= 1;
    791         fMCRec->fDeferredSaveCount -= 1;
    792     } else {
    793         // check for underflow
    794         if (fMCStack.count() > 1) {
    795             this->willRestore();
    796             SkASSERT(fSaveCount > 1);
    797             fSaveCount -= 1;
    798             this->internalRestore();
    799             this->didRestore();
    800         }
    801     }
    802 }
    803 
    804 void SkCanvas::restoreToCount(int count) {
    805     // sanity check
    806     if (count < 1) {
    807         count = 1;
    808     }
    809 
    810     int n = this->getSaveCount() - count;
    811     for (int i = 0; i < n; ++i) {
    812         this->restore();
    813     }
    814 }
    815 
    816 void SkCanvas::internalSave() {
    817     MCRec* newTop = (MCRec*)fMCStack.push_back();
    818     new (newTop) MCRec(*fMCRec);    // balanced in restore()
    819     fMCRec = newTop;
    820 
    821     FOR_EACH_TOP_DEVICE(device->save());
    822 }
    823 
    824 bool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) {
    825     return !(saveLayerFlags & SkCanvasPriv::kDontClipToLayer_SaveLayerFlag);
    826 }
    827 
    828 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlags,
    829                               SkIRect* intersection, const SkImageFilter* imageFilter) {
    830     SkIRect clipBounds = this->getDeviceClipBounds();
    831     if (clipBounds.isEmpty()) {
    832         return false;
    833     }
    834 
    835     const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
    836 
    837     if (imageFilter && bounds && !imageFilter->canComputeFastBounds()) {
    838         // If the image filter DAG affects transparent black then we will need to render
    839         // out to the clip bounds
    840         bounds = nullptr;
    841     }
    842 
    843     SkIRect inputSaveLayerBounds;
    844     if (bounds) {
    845         SkRect r;
    846         ctm.mapRect(&r, *bounds);
    847         r.roundOut(&inputSaveLayerBounds);
    848     } else {    // no user bounds, so just use the clip
    849         inputSaveLayerBounds = clipBounds;
    850     }
    851 
    852     if (imageFilter) {
    853         // expand the clip bounds by the image filter DAG to include extra content that might
    854         // be required by the image filters.
    855         clipBounds = imageFilter->filterBounds(clipBounds, ctm,
    856                                                SkImageFilter::kReverse_MapDirection,
    857                                                &inputSaveLayerBounds);
    858     }
    859 
    860     SkIRect clippedSaveLayerBounds;
    861     if (bounds) {
    862         // For better or for worse, user bounds currently act as a hard clip on the layer's
    863         // extent (i.e., they implement the CSS filter-effects 'filter region' feature).
    864         clippedSaveLayerBounds = inputSaveLayerBounds;
    865     } else {
    866         // If there are no user bounds, we don't want to artificially restrict the resulting
    867         // layer bounds, so allow the expanded clip bounds free reign.
    868         clippedSaveLayerBounds = clipBounds;
    869     }
    870 
    871     // early exit if the layer's bounds are clipped out
    872     if (!clippedSaveLayerBounds.intersect(clipBounds)) {
    873         if (BoundsAffectsClip(saveLayerFlags)) {
    874             fMCRec->fTopLayer->fDevice->clipRegion(SkRegion(), SkClipOp::kIntersect); // empty
    875             fMCRec->fRasterClip.setEmpty();
    876             fDeviceClipBounds.setEmpty();
    877         }
    878         return false;
    879     }
    880     SkASSERT(!clippedSaveLayerBounds.isEmpty());
    881 
    882     if (BoundsAffectsClip(saveLayerFlags)) {
    883         // Simplify the current clips since they will be applied properly during restore()
    884         fMCRec->fRasterClip.setRect(clippedSaveLayerBounds);
    885         fDeviceClipBounds = qr_clip_bounds(clippedSaveLayerBounds);
    886     }
    887 
    888     if (intersection) {
    889         *intersection = clippedSaveLayerBounds;
    890     }
    891 
    892     return true;
    893 }
    894 
    895 int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
    896     return this->saveLayer(SaveLayerRec(bounds, paint, 0));
    897 }
    898 
    899 int SkCanvas::saveLayer(const SaveLayerRec& rec) {
    900     TRACE_EVENT0("skia", TRACE_FUNC);
    901     if (rec.fPaint && rec.fPaint->nothingToDraw()) {
    902         // no need for the layer (or any of the draws until the matching restore()
    903         this->save();
    904         this->clipRect({0,0,0,0});
    905     } else {
    906         SaveLayerStrategy strategy = this->getSaveLayerStrategy(rec);
    907         fSaveCount += 1;
    908         this->internalSaveLayer(rec, strategy);
    909     }
    910     return this->getSaveCount() - 1;
    911 }
    912 
    913 int SkCanvas::only_axis_aligned_saveBehind(const SkRect* bounds) {
    914     if (bounds && !this->getLocalClipBounds().intersects(*bounds)) {
    915         // Assuming clips never expand, if the request bounds is outside of the current clip
    916         // there is no need to copy/restore the area, so just devolve back to a regular save.
    917         this->save();
    918     } else {
    919         bool doTheWork = this->onDoSaveBehind(bounds);
    920         fSaveCount += 1;
    921         this->internalSave();
    922         if (doTheWork) {
    923             this->internalSaveBehind(bounds);
    924         }
    925     }
    926     return this->getSaveCount() - 1;
    927 }
    928 
    929 void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
    930                                     SkBaseDevice* dst, const SkIPoint& dstOrigin,
    931                                     const SkMatrix& ctm) {
    932     SkDraw draw;
    933     SkRasterClip rc;
    934     rc.setRect(SkIRect::MakeWH(dst->width(), dst->height()));
    935     if (!dst->accessPixels(&draw.fDst)) {
    936         draw.fDst.reset(dst->imageInfo(), nullptr, 0);
    937     }
    938     draw.fMatrix = &SkMatrix::I();
    939     draw.fRC = &rc;
    940 
    941     SkPaint p;
    942     if (filter) {
    943         p.setImageFilter(filter->makeWithLocalMatrix(ctm));
    944     }
    945 
    946     int x = src->getOrigin().x() - dstOrigin.x();
    947     int y = src->getOrigin().y() - dstOrigin.y();
    948     auto special = src->snapSpecial();
    949     if (special) {
    950         dst->drawSpecial(special.get(), x, y, p, nullptr, SkMatrix::I());
    951     }
    952 }
    953 
    954 // This is shared by all backends, but contains raster-specific thoughts. Can we defer to the
    955 // device to perform this?
    956 static SkImageInfo make_layer_info(const SkImageInfo& prev, int w, int h, const SkPaint* paint) {
    957     // Need to force L32 for now if we have an image filter.
    958     // If filters ever support other colortypes, e.g. F16, we can modify this check.
    959     if (paint && paint->getImageFilter()) {
    960 #ifdef SK_SUPPORT_LEGACY_RASTERLAYERCOLORSPACE
    961         return SkImageInfo::MakeN32Premul(w, h);
    962 #else
    963         // TODO: can we query the imagefilter, to see if it can handle floats (so we don't always
    964         //       use N32 when the layer itself was float)?
    965         return SkImageInfo::MakeN32Premul(w, h, prev.refColorSpace());
    966 #endif
    967     }
    968 
    969     SkColorType ct = prev.colorType();
    970     if (prev.bytesPerPixel() <= 4) {
    971         // "Upgrade" A8, G8, 565, 4444, 1010102, 101010x, and 888x to 8888,
    972         // ensuring plenty of alpha bits for the layer, perhaps losing some color bits in return.
    973         ct = kN32_SkColorType;
    974     }
    975     return SkImageInfo::Make(w, h, ct, kPremul_SkAlphaType, prev.refColorSpace());
    976 }
    977 
    978 void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
    979     TRACE_EVENT0("skia", TRACE_FUNC);
    980     const SkRect* bounds = rec.fBounds;
    981     const SkPaint* paint = rec.fPaint;
    982     SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
    983 
    984     // If we have a backdrop filter, then we must apply it to the entire layer (clip-bounds)
    985     // regardless of any hint-rect from the caller. skbug.com/8783
    986     if (rec.fBackdrop) {
    987         bounds = nullptr;
    988     }
    989 
    990     SkLazyPaint lazyP;
    991     SkImageFilter* imageFilter = paint ? paint->getImageFilter() : nullptr;
    992     SkMatrix stashedMatrix = fMCRec->fMatrix;
    993     MCRec* modifiedRec = nullptr;
    994     SkMatrix remainder;
    995     SkSize scale;
    996     /*
    997      *  ImageFilters (so far) do not correctly handle matrices (CTM) that contain rotation/skew/etc.
    998      *  but they do handle scaling. To accommodate this, we do the following:
    999      *
   1000      *  1. Stash off the current CTM
   1001      *  2. Decompose the CTM into SCALE and REMAINDER
   1002      *  3. Wack the CTM to be just SCALE, and wrap the imagefilter with a MatrixImageFilter that
   1003      *     contains the REMAINDER
   1004      *  4. Proceed as usual, allowing the client to draw into the layer (now with a scale-only CTM)
   1005      *  5. During restore, we process the MatrixImageFilter, which applies REMAINDER to the output
   1006      *     of the original imagefilter, and draw that (via drawSprite)
   1007      *  6. Unwack the CTM to its original state (i.e. stashedMatrix)
   1008      *
   1009      *  Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
   1010      *  a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter.
   1011      */
   1012     if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() &&
   1013         stashedMatrix.decomposeScale(&scale, &remainder))
   1014     {
   1015         // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
   1016         modifiedRec = fMCRec;
   1017         this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height()));
   1018         SkPaint* p = lazyP.set(*paint);
   1019         p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder,
   1020                                                           SkFilterQuality::kLow_SkFilterQuality,
   1021                                                           sk_ref_sp(imageFilter)));
   1022         imageFilter = p->getImageFilter();
   1023         paint = p;
   1024     }
   1025 
   1026     // do this before we create the layer. We don't call the public save() since
   1027     // that would invoke a possibly overridden virtual
   1028     this->internalSave();
   1029 
   1030     SkIRect ir;
   1031     if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
   1032         if (modifiedRec) {
   1033             // In this case there will be no layer in which to stash the matrix so we need to
   1034             // revert the prior MCRec to its earlier state.
   1035             modifiedRec->fMatrix = stashedMatrix;
   1036         }
   1037         return;
   1038     }
   1039 
   1040     // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
   1041     // the clipRectBounds() call above?
   1042     if (kNoLayer_SaveLayerStrategy == strategy) {
   1043         return;
   1044     }
   1045 
   1046     SkPixelGeometry geo = fProps.pixelGeometry();
   1047     if (paint) {
   1048         // TODO: perhaps add a query to filters so we might preserve opaqueness...
   1049         if (paint->getImageFilter() || paint->getColorFilter()) {
   1050             geo = kUnknown_SkPixelGeometry;
   1051         }
   1052     }
   1053 
   1054     SkBaseDevice* priorDevice = this->getTopDevice();
   1055     if (nullptr == priorDevice) {   // Do we still need this check???
   1056         SkDebugf("Unable to find device for layer.");
   1057         return;
   1058     }
   1059 
   1060     SkImageInfo info = make_layer_info(priorDevice->imageInfo(), ir.width(), ir.height(), paint);
   1061 
   1062     sk_sp<SkBaseDevice> newDevice;
   1063     {
   1064         const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType();
   1065         const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
   1066         const bool trackCoverage =
   1067                 SkToBool(saveLayerFlags & kMaskAgainstCoverage_EXPERIMENTAL_DONT_USE_SaveLayerFlag);
   1068         const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
   1069                                                                              preserveLCDText,
   1070                                                                              trackCoverage,
   1071                                                                              fAllocator.get());
   1072         newDevice.reset(priorDevice->onCreateDevice(createInfo, paint));
   1073         if (!newDevice) {
   1074             return;
   1075         }
   1076     }
   1077     DeviceCM* layer = new DeviceCM(newDevice, paint, stashedMatrix, rec.fClipMask, rec.fClipMatrix);
   1078 
   1079     // only have a "next" if this new layer doesn't affect the clip (rare)
   1080     layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
   1081     fMCRec->fLayer = layer;
   1082     fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
   1083 
   1084     if ((rec.fSaveLayerFlags & kInitWithPrevious_SaveLayerFlag) || rec.fBackdrop) {
   1085         DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop },
   1086                              fMCRec->fMatrix);
   1087     }
   1088 
   1089     newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
   1090 
   1091     newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
   1092     if (layer->fNext) {
   1093         // need to punch a hole in the previous device, so we don't draw there, given that
   1094         // the new top-layer will allow drawing to happen "below" it.
   1095         SkRegion hole(ir);
   1096         do {
   1097             layer = layer->fNext;
   1098             layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
   1099         } while (layer->fNext);
   1100     }
   1101 }
   1102 
   1103 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
   1104     if (0xFF == alpha) {
   1105         return this->saveLayer(bounds, nullptr);
   1106     } else {
   1107         SkPaint tmpPaint;
   1108         tmpPaint.setAlpha(alpha);
   1109         return this->saveLayer(bounds, &tmpPaint);
   1110     }
   1111 }
   1112 
   1113 void SkCanvas::internalSaveBehind(const SkRect* localBounds) {
   1114     SkIRect devBounds;
   1115     if (localBounds) {
   1116         SkRect tmp;
   1117         fMCRec->fMatrix.mapRect(&tmp, *localBounds);
   1118         if (!devBounds.intersect(tmp.round(), this->getDeviceClipBounds())) {
   1119             devBounds.setEmpty();
   1120         }
   1121     } else {
   1122         devBounds = this->getDeviceClipBounds();
   1123     }
   1124     if (devBounds.isEmpty()) {
   1125         return;
   1126     }
   1127 
   1128     SkBaseDevice* device = this->getTopDevice();
   1129     if (nullptr == device) {   // Do we still need this check???
   1130         return;
   1131     }
   1132 
   1133     // need the bounds relative to the device itself
   1134     devBounds.offset(-device->fOrigin.fX, -device->fOrigin.fY);
   1135 
   1136     auto backImage = device->snapBackImage(devBounds);
   1137     if (!backImage) {
   1138         return;
   1139     }
   1140 
   1141     // we really need the save, so we can wack the fMCRec
   1142     this->checkForDeferredSave();
   1143 
   1144     fMCRec->fBackImage.reset(new BackImage{std::move(backImage), devBounds.topLeft()});
   1145 
   1146     SkPaint paint;
   1147     paint.setBlendMode(SkBlendMode::kClear);
   1148     this->drawClippedToSaveBehind(paint);
   1149 }
   1150 
   1151 void SkCanvas::internalRestore() {
   1152     SkASSERT(fMCStack.count() != 0);
   1153 
   1154     // reserve our layer (if any)
   1155     DeviceCM* layer = fMCRec->fLayer;   // may be null
   1156     // now detach it from fMCRec so we can pop(). Gets freed after its drawn
   1157     fMCRec->fLayer = nullptr;
   1158 
   1159     // move this out before we do the actual restore
   1160     auto backImage = std::move(fMCRec->fBackImage);
   1161 
   1162     // now do the normal restore()
   1163     fMCRec->~MCRec();       // balanced in save()
   1164     fMCStack.pop_back();
   1165     fMCRec = (MCRec*)fMCStack.back();
   1166 
   1167     if (fMCRec) {
   1168         FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
   1169     }
   1170 
   1171     if (backImage) {
   1172         SkPaint paint;
   1173         paint.setBlendMode(SkBlendMode::kDstOver);
   1174         const int x = backImage->fLoc.x();
   1175         const int y = backImage->fLoc.y();
   1176         this->getTopDevice()->drawSpecial(backImage->fImage.get(), x, y, paint,
   1177                                           nullptr, SkMatrix::I());
   1178     }
   1179 
   1180     /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
   1181         since if we're being recorded, we don't want to record this (the
   1182         recorder will have already recorded the restore).
   1183     */
   1184     if (layer) {
   1185         if (fMCRec) {
   1186             const SkIPoint& origin = layer->fDevice->getOrigin();
   1187             layer->fDevice->setImmutable();
   1188             this->internalDrawDevice(layer->fDevice.get(), origin.x(), origin.y(),
   1189                                      layer->fPaint.get(),
   1190                                      layer->fClipImage.get(), layer->fClipMatrix);
   1191             // restore what we smashed in internalSaveLayer
   1192             this->internalSetMatrix(layer->fStashedMatrix);
   1193             // reset this, since internalDrawDevice will have set it to true
   1194             delete layer;
   1195         } else {
   1196             // we're at the root
   1197             SkASSERT(layer == (void*)fDeviceCMStorage);
   1198             layer->~DeviceCM();
   1199             // no need to update fMCRec, 'cause we're killing the canvas
   1200         }
   1201     }
   1202 
   1203     if (fMCRec) {
   1204         fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
   1205         fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
   1206     }
   1207 }
   1208 
   1209 sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
   1210     if (nullptr == props) {
   1211         props = &fProps;
   1212     }
   1213     return this->onNewSurface(info, *props);
   1214 }
   1215 
   1216 sk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
   1217     SkBaseDevice* dev = this->getDevice();
   1218     return dev ? dev->makeSurface(info, props) : nullptr;
   1219 }
   1220 
   1221 SkImageInfo SkCanvas::imageInfo() const {
   1222     return this->onImageInfo();
   1223 }
   1224 
   1225 SkImageInfo SkCanvas::onImageInfo() const {
   1226     SkBaseDevice* dev = this->getDevice();
   1227     if (dev) {
   1228         return dev->imageInfo();
   1229     } else {
   1230         return SkImageInfo::MakeUnknown(0, 0);
   1231     }
   1232 }
   1233 
   1234 bool SkCanvas::getProps(SkSurfaceProps* props) const {
   1235     return this->onGetProps(props);
   1236 }
   1237 
   1238 bool SkCanvas::onGetProps(SkSurfaceProps* props) const {
   1239     SkBaseDevice* dev = this->getDevice();
   1240     if (dev) {
   1241         if (props) {
   1242             *props = fProps;
   1243         }
   1244         return true;
   1245     } else {
   1246         return false;
   1247     }
   1248 }
   1249 
   1250 bool SkCanvas::peekPixels(SkPixmap* pmap) {
   1251     return this->onPeekPixels(pmap);
   1252 }
   1253 
   1254 bool SkCanvas::onPeekPixels(SkPixmap* pmap) {
   1255     SkBaseDevice* dev = this->getDevice();
   1256     return dev && dev->peekPixels(pmap);
   1257 }
   1258 
   1259 void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
   1260     SkPixmap pmap;
   1261     if (!this->onAccessTopLayerPixels(&pmap)) {
   1262         return nullptr;
   1263     }
   1264     if (info) {
   1265         *info = pmap.info();
   1266     }
   1267     if (rowBytes) {
   1268         *rowBytes = pmap.rowBytes();
   1269     }
   1270     if (origin) {
   1271         *origin = this->getTopDevice()->getOrigin();
   1272     }
   1273     return pmap.writable_addr();
   1274 }
   1275 
   1276 bool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
   1277     SkBaseDevice* dev = this->getTopDevice();
   1278     return dev && dev->accessPixels(pmap);
   1279 }
   1280 
   1281 /////////////////////////////////////////////////////////////////////////////
   1282 
   1283 void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint,
   1284                                   SkImage* clipImage, const SkMatrix& clipMatrix) {
   1285     SkPaint tmp;
   1286     if (nullptr == paint) {
   1287         paint = &tmp;
   1288     }
   1289 
   1290     LOOPER_BEGIN_DRAWDEVICE(*paint)
   1291 
   1292     while (iter.next()) {
   1293         SkBaseDevice* dstDev = iter.fDevice;
   1294         paint = &looper.paint();
   1295         SkImageFilter* filter = paint->getImageFilter();
   1296         SkIPoint pos = { x - iter.getX(), y - iter.getY() };
   1297         if (filter || clipImage) {
   1298             sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
   1299             if (specialImage) {
   1300                 dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint,
   1301                                     clipImage, clipMatrix);
   1302             }
   1303         } else {
   1304             dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint);
   1305         }
   1306     }
   1307 
   1308     LOOPER_END
   1309 }
   1310 
   1311 /////////////////////////////////////////////////////////////////////////////
   1312 
   1313 void SkCanvas::translate(SkScalar dx, SkScalar dy) {
   1314     if (dx || dy) {
   1315         this->checkForDeferredSave();
   1316         fMCRec->fMatrix.preTranslate(dx,dy);
   1317 
   1318         // Translate shouldn't affect the is-scale-translateness of the matrix.
   1319         SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
   1320 
   1321         FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
   1322 
   1323         this->didTranslate(dx,dy);
   1324     }
   1325 }
   1326 
   1327 void SkCanvas::scale(SkScalar sx, SkScalar sy) {
   1328     SkMatrix m;
   1329     m.setScale(sx, sy);
   1330     this->concat(m);
   1331 }
   1332 
   1333 void SkCanvas::rotate(SkScalar degrees) {
   1334     SkMatrix m;
   1335     m.setRotate(degrees);
   1336     this->concat(m);
   1337 }
   1338 
   1339 void SkCanvas::rotate(SkScalar degrees, SkScalar px, SkScalar py) {
   1340     SkMatrix m;
   1341     m.setRotate(degrees, px, py);
   1342     this->concat(m);
   1343 }
   1344 
   1345 void SkCanvas::skew(SkScalar sx, SkScalar sy) {
   1346     SkMatrix m;
   1347     m.setSkew(sx, sy);
   1348     this->concat(m);
   1349 }
   1350 
   1351 void SkCanvas::concat(const SkMatrix& matrix) {
   1352     if (matrix.isIdentity()) {
   1353         return;
   1354     }
   1355 
   1356     this->checkForDeferredSave();
   1357     fMCRec->fMatrix.preConcat(matrix);
   1358     fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
   1359 
   1360     FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
   1361 
   1362     this->didConcat(matrix);
   1363 }
   1364 
   1365 void SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
   1366     fMCRec->fMatrix = matrix;
   1367     fIsScaleTranslate = matrix.isScaleTranslate();
   1368 
   1369     FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
   1370 }
   1371 
   1372 void SkCanvas::setMatrix(const SkMatrix& matrix) {
   1373     this->checkForDeferredSave();
   1374     this->internalSetMatrix(matrix);
   1375     this->didSetMatrix(matrix);
   1376 }
   1377 
   1378 void SkCanvas::resetMatrix() {
   1379     this->setMatrix(SkMatrix::I());
   1380 }
   1381 
   1382 //////////////////////////////////////////////////////////////////////////////
   1383 
   1384 void SkCanvas::clipRect(const SkRect& rect, SkClipOp op, bool doAA) {
   1385     if (!rect.isFinite()) {
   1386         return;
   1387     }
   1388     this->checkForDeferredSave();
   1389     ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
   1390     this->onClipRect(rect, op, edgeStyle);
   1391 }
   1392 
   1393 void SkCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
   1394     const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
   1395 
   1396     FOR_EACH_TOP_DEVICE(device->clipRect(rect, op, isAA));
   1397 
   1398     AutoValidateClip avc(this);
   1399     fMCRec->fRasterClip.opRect(rect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
   1400                                isAA);
   1401     fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
   1402 }
   1403 
   1404 void SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
   1405     fClipRestrictionRect = rect;
   1406     if (fClipRestrictionRect.isEmpty()) {
   1407         // we notify the device, but we *dont* resolve deferred saves (since we're just
   1408         // removing the restriction if the rect is empty. how I hate this api.
   1409         FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
   1410     } else {
   1411         this->checkForDeferredSave();
   1412         FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
   1413         AutoValidateClip avc(this);
   1414         fMCRec->fRasterClip.opIRect(fClipRestrictionRect, SkRegion::kIntersect_Op);
   1415         fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
   1416     }
   1417 }
   1418 
   1419 void SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
   1420     this->checkForDeferredSave();
   1421     ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
   1422     if (rrect.isRect()) {
   1423         this->onClipRect(rrect.getBounds(), op, edgeStyle);
   1424     } else {
   1425         this->onClipRRect(rrect, op, edgeStyle);
   1426     }
   1427 }
   1428 
   1429 void SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
   1430     AutoValidateClip avc(this);
   1431 
   1432     bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
   1433 
   1434     FOR_EACH_TOP_DEVICE(device->clipRRect(rrect, op, isAA));
   1435 
   1436     fMCRec->fRasterClip.opRRect(rrect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
   1437                                 isAA);
   1438     fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
   1439 }
   1440 
   1441 void SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
   1442     this->checkForDeferredSave();
   1443     ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
   1444 
   1445     if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) {
   1446         SkRect r;
   1447         if (path.isRect(&r)) {
   1448             this->onClipRect(r, op, edgeStyle);
   1449             return;
   1450         }
   1451         SkRRect rrect;
   1452         if (path.isOval(&r)) {
   1453             rrect.setOval(r);
   1454             this->onClipRRect(rrect, op, edgeStyle);
   1455             return;
   1456         }
   1457         if (path.isRRect(&rrect)) {
   1458             this->onClipRRect(rrect, op, edgeStyle);
   1459             return;
   1460         }
   1461     }
   1462 
   1463     this->onClipPath(path, op, edgeStyle);
   1464 }
   1465 
   1466 void SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
   1467     AutoValidateClip avc(this);
   1468 
   1469     bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
   1470 
   1471     FOR_EACH_TOP_DEVICE(device->clipPath(path, op, isAA));
   1472 
   1473     const SkPath* rasterClipPath = &path;
   1474     const SkMatrix* matrix = &fMCRec->fMatrix;
   1475     fMCRec->fRasterClip.opPath(*rasterClipPath, *matrix, this->getTopLayerBounds(),
   1476                                (SkRegion::Op)op, isAA);
   1477     fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
   1478 }
   1479 
   1480 void SkCanvas::clipRegion(const SkRegion& rgn, SkClipOp op) {
   1481     this->checkForDeferredSave();
   1482     this->onClipRegion(rgn, op);
   1483 }
   1484 
   1485 void SkCanvas::onClipRegion(const SkRegion& rgn, SkClipOp op) {
   1486     FOR_EACH_TOP_DEVICE(device->clipRegion(rgn, op));
   1487 
   1488     AutoValidateClip avc(this);
   1489 
   1490     fMCRec->fRasterClip.opRegion(rgn, (SkRegion::Op)op);
   1491     fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
   1492 }
   1493 
   1494 #ifdef SK_DEBUG
   1495 void SkCanvas::validateClip() const {
   1496     // construct clipRgn from the clipstack
   1497     const SkBaseDevice* device = this->getDevice();
   1498     if (!device) {
   1499         SkASSERT(this->isClipEmpty());
   1500         return;
   1501     }
   1502 }
   1503 #endif
   1504 
   1505 bool SkCanvas::androidFramework_isClipAA() const {
   1506     bool containsAA = false;
   1507 
   1508     FOR_EACH_TOP_DEVICE(containsAA |= device->onClipIsAA());
   1509 
   1510     return containsAA;
   1511 }
   1512 
   1513 class RgnAccumulator {
   1514     SkRegion* fRgn;
   1515 public:
   1516     RgnAccumulator(SkRegion* total) : fRgn(total) {}
   1517     void accumulate(SkBaseDevice* device, SkRegion* rgn) {
   1518         SkIPoint origin = device->getOrigin();
   1519         if (origin.x() | origin.y()) {
   1520             rgn->translate(origin.x(), origin.y());
   1521         }
   1522         fRgn->op(*rgn, SkRegion::kUnion_Op);
   1523     }
   1524 };
   1525 
   1526 void SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
   1527     RgnAccumulator accum(rgn);
   1528     SkRegion tmp;
   1529 
   1530     rgn->setEmpty();
   1531     FOR_EACH_TOP_DEVICE(device->onAsRgnClip(&tmp); accum.accumulate(device, &tmp));
   1532 }
   1533 
   1534 ///////////////////////////////////////////////////////////////////////////////
   1535 
   1536 bool SkCanvas::isClipEmpty() const {
   1537     return fMCRec->fRasterClip.isEmpty();
   1538 
   1539     // TODO: should we only use the conservative answer in a recording canvas?
   1540 #if 0
   1541     SkBaseDevice* dev = this->getTopDevice();
   1542     // if no device we return true
   1543     return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
   1544 #endif
   1545 }
   1546 
   1547 bool SkCanvas::isClipRect() const {
   1548     SkBaseDevice* dev = this->getTopDevice();
   1549     // if no device we return false
   1550     return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType;
   1551 }
   1552 
   1553 static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
   1554 #if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
   1555     __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec);
   1556     __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec);
   1557     __m128 mask = _mm_cmplt_ps(lLtT, RrBb);
   1558     return 0xF != _mm_movemask_ps(mask);
   1559 #elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
   1560     float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0];
   1561     float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1];
   1562     uint32x4_t mask = vcltq_f32(lLtT, RrBb);
   1563     return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask);
   1564 #else
   1565     SkRect devRectAsRect;
   1566     SkRect devClipAsRect;
   1567     devRect.store(&devRectAsRect.fLeft);
   1568     devClip.store(&devClipAsRect.fLeft);
   1569     return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect);
   1570 #endif
   1571 }
   1572 
   1573 // It's important for this function to not be inlined.  Otherwise the compiler will share code
   1574 // between the fast path and the slow path, resulting in two slow paths.
   1575 static SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip,
   1576                                                    const SkMatrix& matrix) {
   1577     SkRect deviceRect;
   1578     matrix.mapRect(&deviceRect, src);
   1579     return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip);
   1580 }
   1581 
   1582 bool SkCanvas::quickReject(const SkRect& src) const {
   1583 #ifdef SK_DEBUG
   1584     // Verify that fDeviceClipBounds are set properly.
   1585     SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
   1586     if (fMCRec->fRasterClip.isEmpty()) {
   1587         SkASSERT(fDeviceClipBounds.isEmpty());
   1588     } else {
   1589         SkASSERT(tmp == fDeviceClipBounds);
   1590     }
   1591 
   1592     // Verify that fIsScaleTranslate is set properly.
   1593     SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
   1594 #endif
   1595 
   1596     if (!fIsScaleTranslate) {
   1597         return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix);
   1598     }
   1599 
   1600     // We inline the implementation of mapScaleTranslate() for the fast path.
   1601     float sx = fMCRec->fMatrix.getScaleX();
   1602     float sy = fMCRec->fMatrix.getScaleY();
   1603     float tx = fMCRec->fMatrix.getTranslateX();
   1604     float ty = fMCRec->fMatrix.getTranslateY();
   1605     Sk4f scale(sx, sy, sx, sy);
   1606     Sk4f trans(tx, ty, tx, ty);
   1607 
   1608     // Apply matrix.
   1609     Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
   1610 
   1611     // Make sure left < right, top < bottom.
   1612     Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
   1613     Sk4f min = Sk4f::Min(ltrb, rblt);
   1614     Sk4f max = Sk4f::Max(ltrb, rblt);
   1615     // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
   1616     // ARM this sequence generates the fastest (a single instruction).
   1617     Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]);
   1618 
   1619     // Check if the device rect is NaN or outside the clip.
   1620     return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft));
   1621 }
   1622 
   1623 bool SkCanvas::quickReject(const SkPath& path) const {
   1624     return path.isEmpty() || this->quickReject(path.getBounds());
   1625 }
   1626 
   1627 SkRect SkCanvas::getLocalClipBounds() const {
   1628     SkIRect ibounds = this->getDeviceClipBounds();
   1629     if (ibounds.isEmpty()) {
   1630         return SkRect::MakeEmpty();
   1631     }
   1632 
   1633     SkMatrix inverse;
   1634     // if we can't invert the CTM, we can't return local clip bounds
   1635     if (!fMCRec->fMatrix.invert(&inverse)) {
   1636         return SkRect::MakeEmpty();
   1637     }
   1638 
   1639     SkRect bounds;
   1640     // adjust it outwards in case we are antialiasing
   1641     const int margin = 1;
   1642 
   1643     SkRect r = SkRect::Make(ibounds.makeOutset(margin, margin));
   1644     inverse.mapRect(&bounds, r);
   1645     return bounds;
   1646 }
   1647 
   1648 SkIRect SkCanvas::getDeviceClipBounds() const {
   1649     return fMCRec->fRasterClip.getBounds();
   1650 }
   1651 
   1652 const SkMatrix& SkCanvas::getTotalMatrix() const {
   1653     return fMCRec->fMatrix;
   1654 }
   1655 
   1656 GrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() {
   1657     SkBaseDevice* dev = this->getTopDevice();
   1658     return dev ? dev->accessRenderTargetContext() : nullptr;
   1659 }
   1660 
   1661 GrContext* SkCanvas::getGrContext() {
   1662     SkBaseDevice* device = this->getTopDevice();
   1663     return device ? device->context() : nullptr;
   1664 }
   1665 
   1666 void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
   1667                           const SkPaint& paint) {
   1668     TRACE_EVENT0("skia", TRACE_FUNC);
   1669     if (outer.isEmpty()) {
   1670         return;
   1671     }
   1672     if (inner.isEmpty()) {
   1673         this->drawRRect(outer, paint);
   1674         return;
   1675     }
   1676 
   1677     // We don't have this method (yet), but technically this is what we should
   1678     // be able to return ...
   1679     // if (!outer.contains(inner))) {
   1680     //
   1681     // For now at least check for containment of bounds
   1682     if (!outer.getBounds().contains(inner.getBounds())) {
   1683         return;
   1684     }
   1685 
   1686     this->onDrawDRRect(outer, inner, paint);
   1687 }
   1688 
   1689 void SkCanvas::drawPaint(const SkPaint& paint) {
   1690     TRACE_EVENT0("skia", TRACE_FUNC);
   1691     this->onDrawPaint(paint);
   1692 }
   1693 
   1694 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
   1695     TRACE_EVENT0("skia", TRACE_FUNC);
   1696     // To avoid redundant logic in our culling code and various backends, we always sort rects
   1697     // before passing them along.
   1698     this->onDrawRect(r.makeSorted(), paint);
   1699 }
   1700 
   1701 void SkCanvas::drawClippedToSaveBehind(const SkPaint& paint) {
   1702     TRACE_EVENT0("skia", TRACE_FUNC);
   1703     this->onDrawBehind(paint);
   1704 }
   1705 
   1706 void SkCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
   1707     TRACE_EVENT0("skia", TRACE_FUNC);
   1708     if (region.isEmpty()) {
   1709         return;
   1710     }
   1711 
   1712     if (region.isRect()) {
   1713         return this->drawIRect(region.getBounds(), paint);
   1714     }
   1715 
   1716     this->onDrawRegion(region, paint);
   1717 }
   1718 
   1719 void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
   1720     TRACE_EVENT0("skia", TRACE_FUNC);
   1721     // To avoid redundant logic in our culling code and various backends, we always sort rects
   1722     // before passing them along.
   1723     this->onDrawOval(r.makeSorted(), paint);
   1724 }
   1725 
   1726 void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
   1727     TRACE_EVENT0("skia", TRACE_FUNC);
   1728     this->onDrawRRect(rrect, paint);
   1729 }
   1730 
   1731 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
   1732     TRACE_EVENT0("skia", TRACE_FUNC);
   1733     this->onDrawPoints(mode, count, pts, paint);
   1734 }
   1735 
   1736 void SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode,
   1737                             const SkPaint& paint) {
   1738     TRACE_EVENT0("skia", TRACE_FUNC);
   1739     RETURN_ON_NULL(vertices);
   1740     // We expect fans to be converted to triangles when building or deserializing SkVertices.
   1741     SkASSERT(vertices->mode() != SkVertices::kTriangleFan_VertexMode);
   1742     this->onDrawVerticesObject(vertices.get(), nullptr, 0, mode, paint);
   1743 }
   1744 
   1745 void SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
   1746     TRACE_EVENT0("skia", TRACE_FUNC);
   1747     RETURN_ON_NULL(vertices);
   1748     this->onDrawVerticesObject(vertices, nullptr, 0, mode, paint);
   1749 }
   1750 
   1751 void SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, const SkVertices::Bone bones[],
   1752                             int boneCount, SkBlendMode mode, const SkPaint& paint) {
   1753     TRACE_EVENT0("skia", TRACE_FUNC);
   1754     RETURN_ON_NULL(vertices);
   1755     SkASSERT(boneCount <= 80);
   1756     this->onDrawVerticesObject(vertices.get(), bones, boneCount, mode, paint);
   1757 }
   1758 
   1759 void SkCanvas::drawVertices(const SkVertices* vertices, const SkVertices::Bone bones[],
   1760                             int boneCount, SkBlendMode mode, const SkPaint& paint) {
   1761     TRACE_EVENT0("skia", TRACE_FUNC);
   1762     RETURN_ON_NULL(vertices);
   1763     SkASSERT(boneCount <= 80);
   1764     this->onDrawVerticesObject(vertices, bones, boneCount, mode, paint);
   1765 }
   1766 
   1767 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
   1768     TRACE_EVENT0("skia", TRACE_FUNC);
   1769     this->onDrawPath(path, paint);
   1770 }
   1771 
   1772 void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
   1773     TRACE_EVENT0("skia", TRACE_FUNC);
   1774     RETURN_ON_NULL(image);
   1775     this->onDrawImage(image, x, y, paint);
   1776 }
   1777 
   1778 // Returns true if the rect can be "filled" : non-empty and finite
   1779 static bool fillable(const SkRect& r) {
   1780     SkScalar w = r.width();
   1781     SkScalar h = r.height();
   1782     return SkScalarIsFinite(w) && w > 0 && SkScalarIsFinite(h) && h > 0;
   1783 }
   1784 
   1785 void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
   1786                              const SkPaint* paint, SrcRectConstraint constraint) {
   1787     TRACE_EVENT0("skia", TRACE_FUNC);
   1788     RETURN_ON_NULL(image);
   1789     if (!fillable(dst) || !fillable(src)) {
   1790         return;
   1791     }
   1792     this->onDrawImageRect(image, &src, dst, paint, constraint);
   1793 }
   1794 
   1795 void SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
   1796                              const SkPaint* paint, SrcRectConstraint constraint) {
   1797     RETURN_ON_NULL(image);
   1798     this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
   1799 }
   1800 
   1801 void SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint) {
   1802     RETURN_ON_NULL(image);
   1803     this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
   1804                         kFast_SrcRectConstraint);
   1805 }
   1806 
   1807 namespace {
   1808 class LatticePaint : SkNoncopyable {
   1809 public:
   1810     LatticePaint(const SkPaint* origPaint) : fPaint(origPaint) {
   1811         if (!origPaint) {
   1812             return;
   1813         }
   1814         if (origPaint->getFilterQuality() > kLow_SkFilterQuality) {
   1815             fPaint.writable()->setFilterQuality(kLow_SkFilterQuality);
   1816         }
   1817         if (origPaint->getMaskFilter()) {
   1818             fPaint.writable()->setMaskFilter(nullptr);
   1819         }
   1820         if (origPaint->isAntiAlias()) {
   1821             fPaint.writable()->setAntiAlias(false);
   1822         }
   1823     }
   1824 
   1825     const SkPaint* get() const {
   1826         return fPaint;
   1827     }
   1828 
   1829 private:
   1830     SkTCopyOnFirstWrite<SkPaint> fPaint;
   1831 };
   1832 } // namespace
   1833 
   1834 void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
   1835                              const SkPaint* paint) {
   1836     TRACE_EVENT0("skia", TRACE_FUNC);
   1837     RETURN_ON_NULL(image);
   1838     if (dst.isEmpty()) {
   1839         return;
   1840     }
   1841     if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
   1842         LatticePaint latticePaint(paint);
   1843         this->onDrawImageNine(image, center, dst, latticePaint.get());
   1844     } else {
   1845         this->drawImageRect(image, dst, paint);
   1846     }
   1847 }
   1848 
   1849 void SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
   1850                                 const SkPaint* paint) {
   1851     TRACE_EVENT0("skia", TRACE_FUNC);
   1852     RETURN_ON_NULL(image);
   1853     if (dst.isEmpty()) {
   1854         return;
   1855     }
   1856 
   1857     SkIRect bounds;
   1858     Lattice latticePlusBounds = lattice;
   1859     if (!latticePlusBounds.fBounds) {
   1860         bounds = SkIRect::MakeWH(image->width(), image->height());
   1861         latticePlusBounds.fBounds = &bounds;
   1862     }
   1863 
   1864     if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
   1865         LatticePaint latticePaint(paint);
   1866         this->onDrawImageLattice(image, latticePlusBounds, dst, latticePaint.get());
   1867     } else {
   1868         this->drawImageRect(image, dst, paint);
   1869     }
   1870 }
   1871 
   1872 void SkCanvas::experimental_DrawImageSetV1(const ImageSetEntry imageSet[], int cnt,
   1873                                            SkFilterQuality filterQuality, SkBlendMode mode) {
   1874     TRACE_EVENT0("skia", TRACE_FUNC);
   1875     RETURN_ON_NULL(imageSet);
   1876     RETURN_ON_FALSE(cnt);
   1877 
   1878     this->onDrawImageSet(imageSet, cnt, filterQuality, mode);
   1879 }
   1880 
   1881 void SkCanvas::experimental_DrawEdgeAARectV1(const SkRect& r, QuadAAFlags edgeAA, SkColor color,
   1882                                              SkBlendMode mode) {
   1883     TRACE_EVENT0("skia", TRACE_FUNC);
   1884     // To avoid redundant logic in our culling code and various backends, we always sort rects
   1885     // before passing them along.
   1886     this->onDrawEdgeAARect(r.makeSorted(), edgeAA, color, mode);
   1887 }
   1888 
   1889 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
   1890     TRACE_EVENT0("skia", TRACE_FUNC);
   1891     if (bitmap.drawsNothing()) {
   1892         return;
   1893     }
   1894     this->onDrawBitmap(bitmap, dx, dy, paint);
   1895 }
   1896 
   1897 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
   1898                               const SkPaint* paint, SrcRectConstraint constraint) {
   1899     TRACE_EVENT0("skia", TRACE_FUNC);
   1900     if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
   1901         return;
   1902     }
   1903     this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
   1904 }
   1905 
   1906 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
   1907                               const SkPaint* paint, SrcRectConstraint constraint) {
   1908     this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
   1909 }
   1910 
   1911 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
   1912                               SrcRectConstraint constraint) {
   1913     this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
   1914                          constraint);
   1915 }
   1916 
   1917 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
   1918                               const SkPaint* paint) {
   1919     TRACE_EVENT0("skia", TRACE_FUNC);
   1920     if (bitmap.drawsNothing() || dst.isEmpty()) {
   1921         return;
   1922     }
   1923     if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
   1924         LatticePaint latticePaint(paint);
   1925         this->onDrawBitmapNine(bitmap, center, dst, latticePaint.get());
   1926     } else {
   1927         this->drawBitmapRect(bitmap, dst, paint);
   1928     }
   1929 }
   1930 
   1931 void SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
   1932                                  const SkPaint* paint) {
   1933     TRACE_EVENT0("skia", TRACE_FUNC);
   1934     if (bitmap.drawsNothing() || dst.isEmpty()) {
   1935         return;
   1936     }
   1937 
   1938     SkIRect bounds;
   1939     Lattice latticePlusBounds = lattice;
   1940     if (!latticePlusBounds.fBounds) {
   1941         bounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
   1942         latticePlusBounds.fBounds = &bounds;
   1943     }
   1944 
   1945     if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) {
   1946         LatticePaint latticePaint(paint);
   1947         this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, latticePaint.get());
   1948     } else {
   1949         this->drawBitmapRect(bitmap, dst, paint);
   1950     }
   1951 }
   1952 
   1953 void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
   1954                          const SkColor colors[], int count, SkBlendMode mode,
   1955                          const SkRect* cull, const SkPaint* paint) {
   1956     TRACE_EVENT0("skia", TRACE_FUNC);
   1957     RETURN_ON_NULL(atlas);
   1958     if (count <= 0) {
   1959         return;
   1960     }
   1961     SkASSERT(atlas);
   1962     SkASSERT(tex);
   1963     this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
   1964 }
   1965 
   1966 void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
   1967     TRACE_EVENT0("skia", TRACE_FUNC);
   1968     if (key) {
   1969         this->onDrawAnnotation(rect, key, value);
   1970     }
   1971 }
   1972 
   1973 void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
   1974                                     const SkPaint* paint, SrcRectConstraint constraint) {
   1975     if (src) {
   1976         this->drawImageRect(image, *src, dst, paint, constraint);
   1977     } else {
   1978         this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
   1979                             dst, paint, constraint);
   1980     }
   1981 }
   1982 void SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
   1983                                      const SkPaint* paint, SrcRectConstraint constraint) {
   1984     if (src) {
   1985         this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
   1986     } else {
   1987         this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
   1988                              dst, paint, constraint);
   1989     }
   1990 }
   1991 
   1992 void SkCanvas::private_draw_shadow_rec(const SkPath& path, const SkDrawShadowRec& rec) {
   1993     TRACE_EVENT0("skia", TRACE_FUNC);
   1994     this->onDrawShadowRec(path, rec);
   1995 }
   1996 
   1997 void SkCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
   1998     SkPaint paint;
   1999     const SkRect& pathBounds = path.getBounds();
   2000 
   2001     LOOPER_BEGIN(paint, &pathBounds)
   2002     while (iter.next()) {
   2003         iter.fDevice->drawShadow(path, rec);
   2004     }
   2005     LOOPER_END
   2006 }
   2007 
   2008 //////////////////////////////////////////////////////////////////////////////
   2009 //  These are the virtual drawing methods
   2010 //////////////////////////////////////////////////////////////////////////////
   2011 
   2012 void SkCanvas::onDiscard() {
   2013     if (fSurfaceBase) {
   2014         fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
   2015     }
   2016 }
   2017 
   2018 void SkCanvas::onDrawPaint(const SkPaint& paint) {
   2019     this->internalDrawPaint(paint);
   2020 }
   2021 
   2022 void SkCanvas::internalDrawPaint(const SkPaint& paint) {
   2023     LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, nullptr, false)
   2024 
   2025     while (iter.next()) {
   2026         iter.fDevice->drawPaint(looper.paint());
   2027     }
   2028 
   2029     LOOPER_END
   2030 }
   2031 
   2032 void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
   2033                             const SkPaint& paint) {
   2034     if ((long)count <= 0) {
   2035         return;
   2036     }
   2037 
   2038     SkRect r;
   2039     const SkRect* bounds = nullptr;
   2040     if (paint.canComputeFastBounds()) {
   2041         // special-case 2 points (common for drawing a single line)
   2042         if (2 == count) {
   2043             r.set(pts[0], pts[1]);
   2044         } else {
   2045             r.set(pts, SkToInt(count));
   2046         }
   2047         if (!r.isFinite()) {
   2048             return;
   2049         }
   2050         SkRect storage;
   2051         if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
   2052             return;
   2053         }
   2054         bounds = &r;
   2055     }
   2056 
   2057     SkASSERT(pts != nullptr);
   2058 
   2059     LOOPER_BEGIN(paint, bounds)
   2060 
   2061     while (iter.next()) {
   2062         iter.fDevice->drawPoints(mode, count, pts, looper.paint());
   2063     }
   2064 
   2065     LOOPER_END
   2066 }
   2067 
   2068 static bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) {
   2069     return ((intptr_t)paint.getImageFilter()    |
   2070             (intptr_t)paint.getLooper()         ) != 0;
   2071 }
   2072 
   2073 void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
   2074     SkASSERT(r.isSorted());
   2075     if (paint.canComputeFastBounds()) {
   2076         SkRect storage;
   2077         if (this->quickReject(paint.computeFastBounds(r, &storage))) {
   2078             return;
   2079         }
   2080     }
   2081 
   2082     if (needs_autodrawlooper(this, paint)) {
   2083         LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, &r, false)
   2084 
   2085         while (iter.next()) {
   2086             iter.fDevice->drawRect(r, looper.paint());
   2087         }
   2088 
   2089         LOOPER_END
   2090     } else if (!paint.nothingToDraw()) {
   2091         this->predrawNotify(&r, &paint, false);
   2092         SkDrawIter iter(this);
   2093         while (iter.next()) {
   2094             iter.fDevice->drawRect(r, paint);
   2095         }
   2096     }
   2097 }
   2098 
   2099 void SkCanvas::onDrawEdgeAARect(const SkRect& r, QuadAAFlags edgeAA, SkColor color,
   2100                                 SkBlendMode mode) {
   2101     SkASSERT(r.isSorted());
   2102 
   2103     SkPaint paint;
   2104     LOOPER_BEGIN(paint, nullptr)
   2105 
   2106     while (iter.next()) {
   2107         iter.fDevice->drawEdgeAARect(r, edgeAA, color, mode);
   2108     }
   2109 
   2110     LOOPER_END
   2111 }
   2112 
   2113 void SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
   2114     SkRect regionRect = SkRect::Make(region.getBounds());
   2115     if (paint.canComputeFastBounds()) {
   2116         SkRect storage;
   2117         if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) {
   2118             return;
   2119         }
   2120     }
   2121 
   2122     LOOPER_BEGIN(paint, &regionRect)
   2123 
   2124     while (iter.next()) {
   2125         iter.fDevice->drawRegion(region, looper.paint());
   2126     }
   2127 
   2128     LOOPER_END
   2129 }
   2130 
   2131 void SkCanvas::onDrawBehind(const SkPaint& paint) {
   2132     SkIRect bounds;
   2133     SkDeque::Iter iter(fMCStack, SkDeque::Iter::kBack_IterStart);
   2134     for (;;) {
   2135         const MCRec* rec = (const MCRec*)iter.prev();
   2136         if (!rec) {
   2137             return; // no backimages, so nothing to draw
   2138         }
   2139         if (rec->fBackImage) {
   2140             bounds = SkIRect::MakeXYWH(rec->fBackImage->fLoc.fX, rec->fBackImage->fLoc.fY,
   2141                                        rec->fBackImage->fImage->width(),
   2142                                        rec->fBackImage->fImage->height());
   2143             break;
   2144         }
   2145     }
   2146 
   2147     LOOPER_BEGIN(paint, nullptr)
   2148 
   2149     while (iter.next()) {
   2150         SkBaseDevice* dev = iter.fDevice;
   2151 
   2152         dev->save();
   2153         // We use clipRegion because it is already defined to operate in dev-space
   2154         // (i.e. ignores the ctm). However, it is going to first translate by -origin,
   2155         // but we don't want that, so we undo that before calling in.
   2156         SkRegion rgn(bounds.makeOffset(dev->fOrigin.fX, dev->fOrigin.fY));
   2157         dev->clipRegion(rgn, SkClipOp::kIntersect);
   2158         dev->drawPaint(looper.paint());
   2159         dev->restore(fMCRec->fMatrix);
   2160     }
   2161 
   2162     LOOPER_END
   2163 }
   2164 
   2165 void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
   2166     SkASSERT(oval.isSorted());
   2167     if (paint.canComputeFastBounds()) {
   2168         SkRect storage;
   2169         if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
   2170             return;
   2171         }
   2172     }
   2173 
   2174     LOOPER_BEGIN(paint, &oval)
   2175 
   2176     while (iter.next()) {
   2177         iter.fDevice->drawOval(oval, looper.paint());
   2178     }
   2179 
   2180     LOOPER_END
   2181 }
   2182 
   2183 void SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle,
   2184                          SkScalar sweepAngle, bool useCenter,
   2185                          const SkPaint& paint) {
   2186     SkASSERT(oval.isSorted());
   2187     if (paint.canComputeFastBounds()) {
   2188         SkRect storage;
   2189         // Note we're using the entire oval as the bounds.
   2190         if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
   2191             return;
   2192         }
   2193     }
   2194 
   2195     LOOPER_BEGIN(paint, &oval)
   2196 
   2197     while (iter.next()) {
   2198         iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint());
   2199     }
   2200 
   2201     LOOPER_END
   2202 }
   2203 
   2204 void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
   2205     if (paint.canComputeFastBounds()) {
   2206         SkRect storage;
   2207         if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
   2208             return;
   2209         }
   2210     }
   2211 
   2212     if (rrect.isRect()) {
   2213         // call the non-virtual version
   2214         this->SkCanvas::drawRect(rrect.getBounds(), paint);
   2215         return;
   2216     } else if (rrect.isOval()) {
   2217         // call the non-virtual version
   2218         this->SkCanvas::drawOval(rrect.getBounds(), paint);
   2219         return;
   2220     }
   2221 
   2222     LOOPER_BEGIN(paint, &rrect.getBounds())
   2223 
   2224     while (iter.next()) {
   2225         iter.fDevice->drawRRect(rrect, looper.paint());
   2226     }
   2227 
   2228     LOOPER_END
   2229 }
   2230 
   2231 void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
   2232     if (paint.canComputeFastBounds()) {
   2233         SkRect storage;
   2234         if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
   2235             return;
   2236         }
   2237     }
   2238 
   2239     LOOPER_BEGIN(paint, &outer.getBounds())
   2240 
   2241     while (iter.next()) {
   2242         iter.fDevice->drawDRRect(outer, inner, looper.paint());
   2243     }
   2244 
   2245     LOOPER_END
   2246 }
   2247 
   2248 void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
   2249     if (!path.isFinite()) {
   2250         return;
   2251     }
   2252 
   2253     const SkRect& pathBounds = path.getBounds();
   2254     if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
   2255         SkRect storage;
   2256         if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
   2257             return;
   2258         }
   2259     }
   2260 
   2261     if (pathBounds.width() <= 0 && pathBounds.height() <= 0) {
   2262         if (path.isInverseFillType()) {
   2263             this->internalDrawPaint(paint);
   2264             return;
   2265         }
   2266     }
   2267 
   2268     LOOPER_BEGIN(paint, &pathBounds)
   2269 
   2270     while (iter.next()) {
   2271         iter.fDevice->drawPath(path, looper.paint());
   2272     }
   2273 
   2274     LOOPER_END
   2275 }
   2276 
   2277 bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
   2278     if (!paint.getImageFilter()) {
   2279         return false;
   2280     }
   2281 
   2282     const SkMatrix& ctm = this->getTotalMatrix();
   2283     if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
   2284         return false;
   2285     }
   2286 
   2287     // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
   2288     // Once we can filter and the filter will return a result larger than itself, we should be
   2289     // able to remove this constraint.
   2290     // skbug.com/4526
   2291     //
   2292     SkPoint pt;
   2293     ctm.mapXY(x, y, &pt);
   2294     SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
   2295     return ir.contains(fMCRec->fRasterClip.getBounds());
   2296 }
   2297 
   2298 // Given storage for a real paint, and an optional paint parameter, clean-up the param (if non-null)
   2299 // given the drawing semantics for drawImage/bitmap (skbug.com/7804) and return it, or the original
   2300 // null.
   2301 static const SkPaint* init_image_paint(SkPaint* real, const SkPaint* paintParam) {
   2302     if (paintParam) {
   2303         *real = *paintParam;
   2304         real->setStyle(SkPaint::kFill_Style);
   2305         real->setPathEffect(nullptr);
   2306         paintParam = real;
   2307     }
   2308     return paintParam;
   2309 }
   2310 
   2311 void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
   2312     SkPaint realPaint;
   2313     paint = init_image_paint(&realPaint, paint);
   2314 
   2315     SkRect bounds = SkRect::MakeXYWH(x, y,
   2316                                      SkIntToScalar(image->width()), SkIntToScalar(image->height()));
   2317     if (nullptr == paint || paint->canComputeFastBounds()) {
   2318         SkRect tmp = bounds;
   2319         if (paint) {
   2320             paint->computeFastBounds(tmp, &tmp);
   2321         }
   2322         if (this->quickReject(tmp)) {
   2323             return;
   2324         }
   2325     }
   2326     // At this point we need a real paint object. If the caller passed null, then we should
   2327     // use realPaint (in its default state). If the caller did pass a paint, then we have copied
   2328     // (and modified) it in realPaint. Thus either way, "realPaint" is what we want to use.
   2329     paint = &realPaint;
   2330 
   2331     sk_sp<SkSpecialImage> special;
   2332     bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
   2333                                                     *paint);
   2334     if (drawAsSprite && paint->getImageFilter()) {
   2335         special = this->getDevice()->makeSpecial(image);
   2336         if (!special) {
   2337             drawAsSprite = false;
   2338         }
   2339     }
   2340 
   2341     LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
   2342 
   2343     while (iter.next()) {
   2344         const SkPaint& pnt = looper.paint();
   2345         if (special) {
   2346             SkPoint pt;
   2347             iter.fDevice->ctm().mapXY(x, y, &pt);
   2348             iter.fDevice->drawSpecial(special.get(),
   2349                                       SkScalarRoundToInt(pt.fX),
   2350                                       SkScalarRoundToInt(pt.fY), pnt,
   2351                                       nullptr, SkMatrix::I());
   2352         } else {
   2353             iter.fDevice->drawImageRect(
   2354                     image, nullptr, SkRect::MakeXYWH(x, y, image->width(), image->height()), pnt,
   2355                     kStrict_SrcRectConstraint);
   2356         }
   2357     }
   2358 
   2359     LOOPER_END
   2360 }
   2361 
   2362 void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
   2363                                const SkPaint* paint, SrcRectConstraint constraint) {
   2364     SkPaint realPaint;
   2365     paint = init_image_paint(&realPaint, paint);
   2366 
   2367     if (nullptr == paint || paint->canComputeFastBounds()) {
   2368         SkRect storage = dst;
   2369         if (paint) {
   2370             paint->computeFastBounds(dst, &storage);
   2371         }
   2372         if (this->quickReject(storage)) {
   2373             return;
   2374         }
   2375     }
   2376     paint = &realPaint;
   2377 
   2378     LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, &dst, image->isOpaque())
   2379 
   2380     while (iter.next()) {
   2381         iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint);
   2382     }
   2383 
   2384     LOOPER_END
   2385 }
   2386 
   2387 void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
   2388     SkDEBUGCODE(bitmap.validate();)
   2389 
   2390     if (bitmap.drawsNothing()) {
   2391         return;
   2392     }
   2393 
   2394     SkPaint realPaint;
   2395     init_image_paint(&realPaint, paint);
   2396     paint = &realPaint;
   2397 
   2398     SkRect bounds;
   2399     bitmap.getBounds(&bounds);
   2400     bounds.offset(x, y);
   2401     bool canFastBounds = paint->canComputeFastBounds();
   2402     if (canFastBounds) {
   2403         SkRect storage;
   2404         if (this->quickReject(paint->computeFastBounds(bounds, &storage))) {
   2405             return;
   2406         }
   2407     }
   2408 
   2409     sk_sp<SkSpecialImage> special;
   2410     bool drawAsSprite = canFastBounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(),
   2411                                                                      bitmap.height(), *paint);
   2412     if (drawAsSprite && paint->getImageFilter()) {
   2413         special = this->getDevice()->makeSpecial(bitmap);
   2414         if (!special) {
   2415             drawAsSprite = false;
   2416         }
   2417     }
   2418 
   2419     LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
   2420 
   2421     while (iter.next()) {
   2422         const SkPaint& pnt = looper.paint();
   2423         if (special) {
   2424             SkPoint pt;
   2425             iter.fDevice->ctm().mapXY(x, y, &pt);
   2426             iter.fDevice->drawSpecial(special.get(),
   2427                                       SkScalarRoundToInt(pt.fX),
   2428                                       SkScalarRoundToInt(pt.fY), pnt,
   2429                                       nullptr, SkMatrix::I());
   2430         } else {
   2431             SkRect fullImage = SkRect::MakeWH(bitmap.width(), bitmap.height());
   2432             iter.fDevice->drawBitmapRect(bitmap, &fullImage, fullImage.makeOffset(x, y), pnt,
   2433                                          kStrict_SrcRectConstraint);
   2434         }
   2435     }
   2436 
   2437     LOOPER_END
   2438 }
   2439 
   2440 // this one is non-virtual, so it can be called safely by other canvas apis
   2441 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
   2442                                       const SkRect& dst, const SkPaint* paint,
   2443                                       SrcRectConstraint constraint) {
   2444     if (bitmap.drawsNothing() || dst.isEmpty()) {
   2445         return;
   2446     }
   2447 
   2448     if (nullptr == paint || paint->canComputeFastBounds()) {
   2449         SkRect storage;
   2450         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
   2451             return;
   2452         }
   2453     }
   2454 
   2455     SkLazyPaint lazy;
   2456     if (nullptr == paint) {
   2457         paint = lazy.init();
   2458     }
   2459 
   2460     LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, &dst, bitmap.isOpaque())
   2461 
   2462     while (iter.next()) {
   2463         iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint);
   2464     }
   2465 
   2466     LOOPER_END
   2467 }
   2468 
   2469 void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
   2470                                 const SkPaint* paint, SrcRectConstraint constraint) {
   2471     SkDEBUGCODE(bitmap.validate();)
   2472     this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
   2473 }
   2474 
   2475 void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
   2476                                const SkPaint* paint) {
   2477     SkPaint realPaint;
   2478     paint = init_image_paint(&realPaint, paint);
   2479 
   2480     if (nullptr == paint || paint->canComputeFastBounds()) {
   2481         SkRect storage;
   2482         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
   2483             return;
   2484         }
   2485     }
   2486     paint = &realPaint;
   2487 
   2488     LOOPER_BEGIN(*paint, &dst)
   2489 
   2490     while (iter.next()) {
   2491         iter.fDevice->drawImageNine(image, center, dst, looper.paint());
   2492     }
   2493 
   2494     LOOPER_END
   2495 }
   2496 
   2497 void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
   2498                                 const SkPaint* paint) {
   2499     SkDEBUGCODE(bitmap.validate();)
   2500     SkPaint realPaint;
   2501     paint = init_image_paint(&realPaint, paint);
   2502 
   2503     if (nullptr == paint || paint->canComputeFastBounds()) {
   2504         SkRect storage;
   2505         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
   2506             return;
   2507         }
   2508     }
   2509     paint = &realPaint;
   2510 
   2511     LOOPER_BEGIN(*paint, &dst)
   2512 
   2513     while (iter.next()) {
   2514         iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint());
   2515     }
   2516 
   2517     LOOPER_END
   2518 }
   2519 
   2520 void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
   2521                                   const SkPaint* paint) {
   2522     SkPaint realPaint;
   2523     paint = init_image_paint(&realPaint, paint);
   2524 
   2525     if (nullptr == paint || paint->canComputeFastBounds()) {
   2526         SkRect storage;
   2527         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
   2528             return;
   2529         }
   2530     }
   2531     paint = &realPaint;
   2532 
   2533     LOOPER_BEGIN(*paint, &dst)
   2534 
   2535     while (iter.next()) {
   2536         iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint());
   2537     }
   2538 
   2539     LOOPER_END
   2540 }
   2541 
   2542 void SkCanvas::onDrawImageSet(const ImageSetEntry imageSet[], int count,
   2543                               SkFilterQuality filterQuality, SkBlendMode mode) {
   2544     SkPaint paint;
   2545     LOOPER_BEGIN(paint, nullptr)
   2546     while (iter.next()) {
   2547         iter.fDevice->drawImageSet(imageSet, count, filterQuality, mode);
   2548     }
   2549     LOOPER_END
   2550 }
   2551 
   2552 void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
   2553                                    const SkRect& dst, const SkPaint* paint) {
   2554     SkPaint realPaint;
   2555     paint = init_image_paint(&realPaint, paint);
   2556 
   2557     if (nullptr == paint || paint->canComputeFastBounds()) {
   2558         SkRect storage;
   2559         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
   2560             return;
   2561         }
   2562     }
   2563     paint = &realPaint;
   2564 
   2565     LOOPER_BEGIN(*paint, &dst)
   2566 
   2567     while (iter.next()) {
   2568         iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint());
   2569     }
   2570 
   2571     LOOPER_END
   2572 }
   2573 
   2574 void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
   2575                               const SkPaint& paint) {
   2576     SkRect storage;
   2577     const SkRect* bounds = nullptr;
   2578     if (paint.canComputeFastBounds()) {
   2579         storage = blob->bounds().makeOffset(x, y);
   2580         SkRect tmp;
   2581         if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
   2582             return;
   2583         }
   2584         bounds = &storage;
   2585     }
   2586 
   2587     // We cannot filter in the looper as we normally do, because the paint is
   2588     // incomplete at this point (text-related attributes are embedded within blob run paints).
   2589     LOOPER_BEGIN(paint, bounds)
   2590 
   2591     while (iter.next()) {
   2592         fScratchGlyphRunBuilder->drawTextBlob(looper.paint(), *blob, {x, y}, iter.fDevice);
   2593     }
   2594 
   2595     LOOPER_END
   2596 }
   2597 
   2598 // These call the (virtual) onDraw... method
   2599 void SkCanvas::drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding,
   2600                               SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint) {
   2601     TRACE_EVENT0("skia", TRACE_FUNC);
   2602     if (byteLength) {
   2603         sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
   2604         this->drawTextBlob(SkTextBlob::MakeFromText(text, byteLength, font, encoding), x, y, paint);
   2605     }
   2606 }
   2607 
   2608 void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
   2609                             const SkPaint& paint) {
   2610     TRACE_EVENT0("skia", TRACE_FUNC);
   2611     RETURN_ON_NULL(blob);
   2612     RETURN_ON_FALSE(blob->bounds().makeOffset(x, y).isFinite());
   2613     this->onDrawTextBlob(blob, x, y, paint);
   2614 }
   2615 
   2616 void SkCanvas::onDrawVerticesObject(const SkVertices* vertices, const SkVertices::Bone bones[],
   2617                                     int boneCount, SkBlendMode bmode, const SkPaint& paint) {
   2618     LOOPER_BEGIN(paint, nullptr)
   2619 
   2620     while (iter.next()) {
   2621         // In the common case of one iteration we could std::move vertices here.
   2622         iter.fDevice->drawVertices(vertices, bones, boneCount, bmode, looper.paint());
   2623     }
   2624 
   2625     LOOPER_END
   2626 }
   2627 
   2628 void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
   2629                          const SkPoint texCoords[4], SkBlendMode bmode,
   2630                          const SkPaint& paint) {
   2631     TRACE_EVENT0("skia", TRACE_FUNC);
   2632     if (nullptr == cubics) {
   2633         return;
   2634     }
   2635 
   2636     this->onDrawPatch(cubics, colors, texCoords, bmode, paint);
   2637 }
   2638 
   2639 void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
   2640                            const SkPoint texCoords[4], SkBlendMode bmode,
   2641                            const SkPaint& paint) {
   2642     // Since a patch is always within the convex hull of the control points, we discard it when its
   2643     // bounding rectangle is completely outside the current clip.
   2644     SkRect bounds;
   2645     bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
   2646     if (this->quickReject(bounds)) {
   2647         return;
   2648     }
   2649 
   2650     LOOPER_BEGIN(paint, nullptr)
   2651 
   2652     while (iter.next()) {
   2653         iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, paint);
   2654     }
   2655 
   2656     LOOPER_END
   2657 }
   2658 
   2659 void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
   2660 #ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
   2661     TRACE_EVENT0("skia", TRACE_FUNC);
   2662 #endif
   2663     RETURN_ON_NULL(dr);
   2664     if (x || y) {
   2665         SkMatrix matrix = SkMatrix::MakeTrans(x, y);
   2666         this->onDrawDrawable(dr, &matrix);
   2667     } else {
   2668         this->onDrawDrawable(dr, nullptr);
   2669     }
   2670 }
   2671 
   2672 void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
   2673 #ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
   2674     TRACE_EVENT0("skia", TRACE_FUNC);
   2675 #endif
   2676     RETURN_ON_NULL(dr);
   2677     if (matrix && matrix->isIdentity()) {
   2678         matrix = nullptr;
   2679     }
   2680     this->onDrawDrawable(dr, matrix);
   2681 }
   2682 
   2683 void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
   2684     // drawable bounds are no longer reliable (e.g. android displaylist)
   2685     // so don't use them for quick-reject
   2686     this->getDevice()->drawDrawable(dr, matrix, this);
   2687 }
   2688 
   2689 void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
   2690                            const SkColor colors[], int count, SkBlendMode bmode,
   2691                            const SkRect* cull, const SkPaint* paint) {
   2692     if (cull && this->quickReject(*cull)) {
   2693         return;
   2694     }
   2695 
   2696     SkPaint pnt;
   2697     if (paint) {
   2698         pnt = *paint;
   2699     }
   2700 
   2701     LOOPER_BEGIN(pnt, nullptr)
   2702     while (iter.next()) {
   2703         iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt);
   2704     }
   2705     LOOPER_END
   2706 }
   2707 
   2708 void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
   2709     SkASSERT(key);
   2710 
   2711     SkPaint paint;
   2712     LOOPER_BEGIN(paint, nullptr)
   2713     while (iter.next()) {
   2714         iter.fDevice->drawAnnotation(rect, key, value);
   2715     }
   2716     LOOPER_END
   2717 }
   2718 
   2719 //////////////////////////////////////////////////////////////////////////////
   2720 // These methods are NOT virtual, and therefore must call back into virtual
   2721 // methods, rather than actually drawing themselves.
   2722 //////////////////////////////////////////////////////////////////////////////
   2723 
   2724 void SkCanvas::drawColor(SkColor c, SkBlendMode mode) {
   2725     SkPaint paint;
   2726     paint.setColor(c);
   2727     paint.setBlendMode(mode);
   2728     this->drawPaint(paint);
   2729 }
   2730 
   2731 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
   2732     const SkPoint pt = { x, y };
   2733     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
   2734 }
   2735 
   2736 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) {
   2737     SkPoint pts[2];
   2738     pts[0].set(x0, y0);
   2739     pts[1].set(x1, y1);
   2740     this->drawPoints(kLines_PointMode, 2, pts, paint);
   2741 }
   2742 
   2743 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) {
   2744     if (radius < 0) {
   2745         radius = 0;
   2746     }
   2747 
   2748     SkRect  r;
   2749     r.set(cx - radius, cy - radius, cx + radius, cy + radius);
   2750     this->drawOval(r, paint);
   2751 }
   2752 
   2753 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
   2754                              const SkPaint& paint) {
   2755     if (rx > 0 && ry > 0) {
   2756         SkRRect rrect;
   2757         rrect.setRectXY(r, rx, ry);
   2758         this->drawRRect(rrect, paint);
   2759     } else {
   2760         this->drawRect(r, paint);
   2761     }
   2762 }
   2763 
   2764 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
   2765                        SkScalar sweepAngle, bool useCenter,
   2766                        const SkPaint& paint) {
   2767     TRACE_EVENT0("skia", TRACE_FUNC);
   2768     if (oval.isEmpty() || !sweepAngle) {
   2769         return;
   2770     }
   2771     this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint);
   2772 }
   2773 
   2774 ///////////////////////////////////////////////////////////////////////////////
   2775 #ifdef SK_DISABLE_SKPICTURE
   2776 void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {}
   2777 
   2778 
   2779 void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
   2780                              const SkPaint* paint) {}
   2781 #else
   2782 /**
   2783  *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
   2784  *  against the playback cost of recursing into the subpicture to get at its actual ops.
   2785  *
   2786  *  For now we pick a conservatively small value, though measurement (and other heuristics like
   2787  *  the type of ops contained) may justify changing this value.
   2788  */
   2789 #define kMaxPictureOpsToUnrollInsteadOfRef  1
   2790 
   2791 void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
   2792     TRACE_EVENT0("skia", TRACE_FUNC);
   2793     RETURN_ON_NULL(picture);
   2794 
   2795     if (matrix && matrix->isIdentity()) {
   2796         matrix = nullptr;
   2797     }
   2798     if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
   2799         SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
   2800         picture->playback(this);
   2801     } else {
   2802         this->onDrawPicture(picture, matrix, paint);
   2803     }
   2804 }
   2805 
   2806 void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
   2807                              const SkPaint* paint) {
   2808     if (!paint || paint->canComputeFastBounds()) {
   2809         SkRect bounds = picture->cullRect();
   2810         if (paint) {
   2811             paint->computeFastBounds(bounds, &bounds);
   2812         }
   2813         if (matrix) {
   2814             matrix->mapRect(&bounds);
   2815         }
   2816         if (this->quickReject(bounds)) {
   2817             return;
   2818         }
   2819     }
   2820 
   2821     SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
   2822     picture->playback(this);
   2823 }
   2824 #endif
   2825 
   2826 ///////////////////////////////////////////////////////////////////////////////
   2827 ///////////////////////////////////////////////////////////////////////////////
   2828 
   2829 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas) {
   2830     static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
   2831 
   2832     SkASSERT(canvas);
   2833 
   2834     fImpl = new (fStorage) SkDrawIter(canvas);
   2835     fDone = !fImpl->next();
   2836 }
   2837 
   2838 SkCanvas::LayerIter::~LayerIter() {
   2839     fImpl->~SkDrawIter();
   2840 }
   2841 
   2842 void SkCanvas::LayerIter::next() {
   2843     fDone = !fImpl->next();
   2844 }
   2845 
   2846 SkBaseDevice* SkCanvas::LayerIter::device() const {
   2847     return fImpl->fDevice;
   2848 }
   2849 
   2850 const SkMatrix& SkCanvas::LayerIter::matrix() const {
   2851     return fImpl->fDevice->ctm();
   2852 }
   2853 
   2854 const SkPaint& SkCanvas::LayerIter::paint() const {
   2855     const SkPaint* paint = fImpl->getPaint();
   2856     if (nullptr == paint) {
   2857         paint = &fDefaultPaint;
   2858     }
   2859     return *paint;
   2860 }
   2861 
   2862 SkIRect SkCanvas::LayerIter::clipBounds() const {
   2863     return fImpl->fDevice->getGlobalBounds();
   2864 }
   2865 
   2866 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
   2867 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
   2868 
   2869 ///////////////////////////////////////////////////////////////////////////////
   2870 
   2871 std::unique_ptr<SkCanvas> SkCanvas::MakeRasterDirect(const SkImageInfo& info, void* pixels,
   2872                                                      size_t rowBytes, const SkSurfaceProps* props) {
   2873     if (!SkSurfaceValidateRasterInfo(info, rowBytes)) {
   2874         return nullptr;
   2875     }
   2876 
   2877     SkBitmap bitmap;
   2878     if (!bitmap.installPixels(info, pixels, rowBytes)) {
   2879         return nullptr;
   2880     }
   2881 
   2882     return props ?
   2883         skstd::make_unique<SkCanvas>(bitmap, *props) :
   2884         skstd::make_unique<SkCanvas>(bitmap);
   2885 }
   2886 
   2887 ///////////////////////////////////////////////////////////////////////////////
   2888 
   2889 SkNoDrawCanvas::SkNoDrawCanvas(int width, int height)
   2890     : INHERITED(SkIRect::MakeWH(width, height)) {}
   2891 
   2892 SkNoDrawCanvas::SkNoDrawCanvas(const SkIRect& bounds)
   2893     : INHERITED(bounds) {}
   2894 
   2895 SkNoDrawCanvas::SkNoDrawCanvas(sk_sp<SkBaseDevice> device)
   2896     : INHERITED(device) {}
   2897 
   2898 SkCanvas::SaveLayerStrategy SkNoDrawCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
   2899     (void)this->INHERITED::getSaveLayerStrategy(rec);
   2900     return kNoLayer_SaveLayerStrategy;
   2901 }
   2902 
   2903 bool SkNoDrawCanvas::onDoSaveBehind(const SkRect*) {
   2904     return false;
   2905 }
   2906 
   2907 ///////////////////////////////////////////////////////////////////////////////
   2908 
   2909 static_assert((int)SkRegion::kDifference_Op         == (int)kDifference_SkClipOp, "");
   2910 static_assert((int)SkRegion::kIntersect_Op          == (int)kIntersect_SkClipOp, "");
   2911 static_assert((int)SkRegion::kUnion_Op              == (int)kUnion_SkClipOp, "");
   2912 static_assert((int)SkRegion::kXOR_Op                == (int)kXOR_SkClipOp, "");
   2913 static_assert((int)SkRegion::kReverseDifference_Op  == (int)kReverseDifference_SkClipOp, "");
   2914 static_assert((int)SkRegion::kReplace_Op            == (int)kReplace_SkClipOp, "");
   2915 
   2916 ///////////////////////////////////////////////////////////////////////////////////////////////////
   2917 
   2918 SkRasterHandleAllocator::Handle SkCanvas::accessTopRasterHandle() const {
   2919     if (fAllocator && fMCRec->fTopLayer->fDevice) {
   2920         const auto& dev = fMCRec->fTopLayer->fDevice;
   2921         SkRasterHandleAllocator::Handle handle = dev->getRasterHandle();
   2922         SkIPoint origin = dev->getOrigin();
   2923         SkMatrix ctm = this->getTotalMatrix();
   2924         ctm.preTranslate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y()));
   2925 
   2926         SkIRect clip = fMCRec->fRasterClip.getBounds();
   2927         clip.offset(-origin.x(), -origin.y());
   2928         if (!clip.intersect(0, 0, dev->width(), dev->height())) {
   2929             clip.setEmpty();
   2930         }
   2931 
   2932         fAllocator->updateHandle(handle, ctm, clip);
   2933         return handle;
   2934     }
   2935     return nullptr;
   2936 }
   2937 
   2938 static bool install(SkBitmap* bm, const SkImageInfo& info,
   2939                     const SkRasterHandleAllocator::Rec& rec) {
   2940     return bm->installPixels(info, rec.fPixels, rec.fRowBytes, rec.fReleaseProc, rec.fReleaseCtx);
   2941 }
   2942 
   2943 SkRasterHandleAllocator::Handle SkRasterHandleAllocator::allocBitmap(const SkImageInfo& info,
   2944                                                                      SkBitmap* bm) {
   2945     SkRasterHandleAllocator::Rec rec;
   2946     if (!this->allocHandle(info, &rec) || !install(bm, info, rec)) {
   2947         return nullptr;
   2948     }
   2949     return rec.fHandle;
   2950 }
   2951 
   2952 std::unique_ptr<SkCanvas>
   2953 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,
   2954                                     const SkImageInfo& info, const Rec* rec) {
   2955     if (!alloc || !SkSurfaceValidateRasterInfo(info, rec ? rec->fRowBytes : kIgnoreRowBytesValue)) {
   2956         return nullptr;
   2957     }
   2958 
   2959     SkBitmap bm;
   2960     Handle hndl;
   2961 
   2962     if (rec) {
   2963         hndl = install(&bm, info, *rec) ? rec->fHandle : nullptr;
   2964     } else {
   2965         hndl = alloc->allocBitmap(info, &bm);
   2966     }
   2967     return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr;
   2968 }
   2969 
   2970 ///////////////////////////////////////////////////////////////////////////////////////////////////
   2971 
   2972 
   2973