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