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