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