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