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