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