LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkCanvas.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 537 1487 36.1 %
Date: 2017-07-14 16:53:18 Functions: 83 242 34.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13