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