SkCanvas.cpp revision 4edb5d219eb99aa1e8fbe5e37260d3b34314e54b
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
834#ifdef SK_SUPPORT_LEGACY_CANVAS_READPIXELS
835bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
836    bool weAllocated = false;
837    if (nullptr == bitmap->pixelRef()) {
838        if (!bitmap->tryAllocPixels()) {
839            return false;
840        }
841        weAllocated = true;
842    }
843
844    SkPixmap pm;
845    if (bitmap->peekPixels(&pm)) {
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#endif
876
877bool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
878    SkBaseDevice* device = this->getDevice();
879    if (!device) {
880        return false;
881    }
882
883    return device->readPixels(dstInfo, dstP, rowBytes, x, y);
884}
885
886bool SkCanvas::readPixels(const SkPixmap& pm, int x, int y) {
887    return pm.addr() && this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y);
888}
889
890bool SkCanvas::readPixels(const SkBitmap& bm, int x, int y) {
891    SkPixmap pm;
892    return bm.peekPixels(&pm) && this->readPixels(pm, x, y);
893}
894
895bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
896    SkPixmap pm;
897    if (bitmap.peekPixels(&pm)) {
898        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
899    }
900    return false;
901}
902
903bool SkCanvas::writePixels(const SkImageInfo& srcInfo, const void* pixels, size_t rowBytes,
904                           int x, int y) {
905    SkBaseDevice* device = this->getDevice();
906    if (!device) {
907        return false;
908    }
909
910    // This check gives us an early out and prevents generation ID churn on the surface.
911    // This is purely optional: it is a subset of the checks performed by SkWritePixelsRec.
912    SkIRect srcRect = SkIRect::MakeXYWH(x, y, srcInfo.width(), srcInfo.height());
913    if (!srcRect.intersect(0, 0, device->width(), device->height())) {
914        return false;
915    }
916
917    // Tell our owning surface to bump its generation ID.
918    const bool completeOverwrite =
919            srcRect.size() == SkISize::Make(device->width(), device->height());
920    this->predrawNotify(completeOverwrite);
921
922    // This can still fail, most notably in the case of a invalid color type or alpha type
923    // conversion.  We could pull those checks into this function and avoid the unnecessary
924    // generation ID bump.  But then we would be performing those checks twice, since they
925    // are also necessary at the bitmap/pixmap entry points.
926    return device->writePixels(srcInfo, pixels, rowBytes, x, y);
927}
928
929//////////////////////////////////////////////////////////////////////////////
930
931void SkCanvas::checkForDeferredSave() {
932    if (fMCRec->fDeferredSaveCount > 0) {
933        this->doSave();
934    }
935}
936
937int SkCanvas::getSaveCount() const {
938#ifdef SK_DEBUG
939    int count = 0;
940    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
941    for (;;) {
942        const MCRec* rec = (const MCRec*)iter.next();
943        if (!rec) {
944            break;
945        }
946        count += 1 + rec->fDeferredSaveCount;
947    }
948    SkASSERT(count == fSaveCount);
949#endif
950    return fSaveCount;
951}
952
953int SkCanvas::save() {
954    fSaveCount += 1;
955    fMCRec->fDeferredSaveCount += 1;
956    return this->getSaveCount() - 1;  // return our prev value
957}
958
959void SkCanvas::doSave() {
960    this->willSave();
961
962    SkASSERT(fMCRec->fDeferredSaveCount > 0);
963    fMCRec->fDeferredSaveCount -= 1;
964    this->internalSave();
965}
966
967void SkCanvas::restore() {
968    if (fMCRec->fDeferredSaveCount > 0) {
969        SkASSERT(fSaveCount > 1);
970        fSaveCount -= 1;
971        fMCRec->fDeferredSaveCount -= 1;
972    } else {
973        // check for underflow
974        if (fMCStack.count() > 1) {
975            this->willRestore();
976            SkASSERT(fSaveCount > 1);
977            fSaveCount -= 1;
978            this->internalRestore();
979            this->didRestore();
980        }
981    }
982}
983
984void SkCanvas::restoreToCount(int count) {
985    // sanity check
986    if (count < 1) {
987        count = 1;
988    }
989
990    int n = this->getSaveCount() - count;
991    for (int i = 0; i < n; ++i) {
992        this->restore();
993    }
994}
995
996void SkCanvas::internalSave() {
997    MCRec* newTop = (MCRec*)fMCStack.push_back();
998    new (newTop) MCRec(*fMCRec);    // balanced in restore()
999    fMCRec = newTop;
1000
1001    FOR_EACH_TOP_DEVICE(device->save());
1002}
1003
1004bool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) {
1005    return !(saveLayerFlags & SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag);
1006}
1007
1008bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlags,
1009                              SkIRect* intersection, const SkImageFilter* imageFilter) {
1010    SkIRect clipBounds = this->getDeviceClipBounds();
1011    if (clipBounds.isEmpty()) {
1012        return false;
1013    }
1014
1015    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
1016
1017    if (imageFilter) {
1018        clipBounds = imageFilter->filterBounds(clipBounds, ctm);
1019        if (bounds && !imageFilter->canComputeFastBounds()) {
1020            bounds = nullptr;
1021        }
1022    }
1023    SkIRect ir;
1024    if (bounds) {
1025        SkRect r;
1026
1027        ctm.mapRect(&r, *bounds);
1028        r.roundOut(&ir);
1029        // early exit if the layer's bounds are clipped out
1030        if (!ir.intersect(clipBounds)) {
1031            if (BoundsAffectsClip(saveLayerFlags)) {
1032                fMCRec->fTopLayer->fDevice->clipRegion(SkRegion(), SkClipOp::kIntersect); // empty
1033                fMCRec->fRasterClip.setEmpty();
1034                fDeviceClipBounds.setEmpty();
1035            }
1036            return false;
1037        }
1038    } else {    // no user bounds, so just use the clip
1039        ir = clipBounds;
1040    }
1041    SkASSERT(!ir.isEmpty());
1042
1043    if (BoundsAffectsClip(saveLayerFlags)) {
1044        // Simplify the current clips since they will be applied properly during restore()
1045        fMCRec->fRasterClip.setRect(ir);
1046        fDeviceClipBounds = qr_clip_bounds(ir);
1047    }
1048
1049    if (intersection) {
1050        *intersection = ir;
1051    }
1052    return true;
1053}
1054
1055
1056int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
1057    return this->saveLayer(SaveLayerRec(bounds, paint, 0));
1058}
1059
1060int SkCanvas::saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint) {
1061    return this->saveLayer(SaveLayerRec(bounds, paint, kPreserveLCDText_SaveLayerFlag));
1062}
1063
1064int SkCanvas::saveLayer(const SaveLayerRec& origRec) {
1065    SaveLayerRec rec(origRec);
1066    if (gIgnoreSaveLayerBounds) {
1067        rec.fBounds = nullptr;
1068    }
1069    SaveLayerStrategy strategy = this->getSaveLayerStrategy(rec);
1070    fSaveCount += 1;
1071    this->internalSaveLayer(rec, strategy);
1072    return this->getSaveCount() - 1;
1073}
1074
1075void SkCanvas::DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
1076                                    SkBaseDevice* dst, const SkIPoint& dstOrigin,
1077                                    const SkMatrix& ctm) {
1078    SkDraw draw;
1079    SkRasterClip rc;
1080    rc.setRect(SkIRect::MakeWH(dst->width(), dst->height()));
1081    if (!dst->accessPixels(&draw.fDst)) {
1082        draw.fDst.reset(dst->imageInfo(), nullptr, 0);
1083    }
1084    draw.fMatrix = &SkMatrix::I();
1085    draw.fRC = &rc;
1086
1087    SkPaint p;
1088    if (filter) {
1089        p.setImageFilter(filter->makeWithLocalMatrix(ctm));
1090    }
1091
1092    int x = src->getOrigin().x() - dstOrigin.x();
1093    int y = src->getOrigin().y() - dstOrigin.y();
1094    auto special = src->snapSpecial();
1095    if (special) {
1096        dst->drawSpecial(special.get(), x, y, p);
1097    }
1098}
1099
1100static SkImageInfo make_layer_info(const SkImageInfo& prev, int w, int h, bool isOpaque,
1101                                   const SkPaint* paint) {
1102    // need to force L32 for now if we have an image filter. Once filters support other colortypes
1103    // e.g. sRGB or F16, we can remove this check
1104    // SRGBTODO: Can we remove this check now?
1105    const bool hasImageFilter = paint && paint->getImageFilter();
1106
1107    SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
1108    if ((prev.bytesPerPixel() < 4) || hasImageFilter) {
1109        // force to L32
1110        return SkImageInfo::MakeN32(w, h, alphaType);
1111    } else {
1112        // keep the same characteristics as the prev
1113        return SkImageInfo::Make(w, h, prev.colorType(), alphaType, prev.refColorSpace());
1114    }
1115}
1116
1117void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
1118    const SkRect* bounds = rec.fBounds;
1119    const SkPaint* paint = rec.fPaint;
1120    SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
1121
1122    SkLazyPaint lazyP;
1123    SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL;
1124    SkMatrix stashedMatrix = fMCRec->fMatrix;
1125    SkMatrix remainder;
1126    SkSize scale;
1127    /*
1128     *  ImageFilters (so far) do not correctly handle matrices (CTM) that contain rotation/skew/etc.
1129     *  but they do handle scaling. To accommodate this, we do the following:
1130     *
1131     *  1. Stash off the current CTM
1132     *  2. Decompose the CTM into SCALE and REMAINDER
1133     *  3. Wack the CTM to be just SCALE, and wrap the imagefilter with a MatrixImageFilter that
1134     *     contains the REMAINDER
1135     *  4. Proceed as usual, allowing the client to draw into the layer (now with a scale-only CTM)
1136     *  5. During restore, we process the MatrixImageFilter, which applies REMAINDER to the output
1137     *     of the original imagefilter, and draw that (via drawSprite)
1138     *  6. Unwack the CTM to its original state (i.e. stashedMatrix)
1139     *
1140     *  Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
1141     *  a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter.
1142     */
1143    if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() &&
1144        stashedMatrix.decomposeScale(&scale, &remainder))
1145    {
1146        // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
1147        this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height()));
1148        SkPaint* p = lazyP.set(*paint);
1149        p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder,
1150                                                          SkFilterQuality::kLow_SkFilterQuality,
1151                                                          sk_ref_sp(imageFilter)));
1152        imageFilter = p->getImageFilter();
1153        paint = p;
1154    }
1155
1156    // do this before we create the layer. We don't call the public save() since
1157    // that would invoke a possibly overridden virtual
1158    this->internalSave();
1159
1160    SkIRect ir;
1161    if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
1162        return;
1163    }
1164
1165    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1166    // the clipRectBounds() call above?
1167    if (kNoLayer_SaveLayerStrategy == strategy) {
1168        return;
1169    }
1170
1171    bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag);
1172    SkPixelGeometry geo = fProps.pixelGeometry();
1173    if (paint) {
1174        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1175        if (paint->getImageFilter() || paint->getColorFilter()) {
1176            isOpaque = false;
1177            geo = kUnknown_SkPixelGeometry;
1178        }
1179    }
1180
1181    SkBaseDevice* priorDevice = this->getTopDevice();
1182    if (nullptr == priorDevice) {   // Do we still need this check???
1183        SkDebugf("Unable to find device for layer.");
1184        return;
1185    }
1186
1187    SkImageInfo info = make_layer_info(priorDevice->imageInfo(), ir.width(), ir.height(), isOpaque,
1188                                       paint);
1189
1190    sk_sp<SkBaseDevice> newDevice;
1191    {
1192        const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
1193                                     (saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
1194        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
1195        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
1196                                                                             preserveLCDText,
1197                                                                             fAllocator.get());
1198        newDevice.reset(priorDevice->onCreateDevice(createInfo, paint));
1199        if (!newDevice) {
1200            return;
1201        }
1202    }
1203    DeviceCM* layer =
1204            new DeviceCM(newDevice.get(), paint, this, stashedMatrix);
1205
1206    // only have a "next" if this new layer doesn't affect the clip (rare)
1207    layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
1208    fMCRec->fLayer = layer;
1209    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
1210
1211    if ((rec.fSaveLayerFlags & kInitWithPrevious_SaveLayerFlag) || rec.fBackdrop) {
1212        DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop },
1213                             fMCRec->fMatrix);
1214    }
1215
1216    newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
1217
1218    newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
1219    if (layer->fNext) {
1220        // need to punch a hole in the previous device, so we don't draw there, given that
1221        // the new top-layer will allow drawing to happen "below" it.
1222        SkRegion hole(ir);
1223        do {
1224            layer = layer->fNext;
1225            layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
1226        } while (layer->fNext);
1227    }
1228}
1229
1230int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1231    if (0xFF == alpha) {
1232        return this->saveLayer(bounds, nullptr);
1233    } else {
1234        SkPaint tmpPaint;
1235        tmpPaint.setAlpha(alpha);
1236        return this->saveLayer(bounds, &tmpPaint);
1237    }
1238}
1239
1240void SkCanvas::internalRestore() {
1241    SkASSERT(fMCStack.count() != 0);
1242
1243    // reserve our layer (if any)
1244    DeviceCM* layer = fMCRec->fLayer;   // may be null
1245    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
1246    fMCRec->fLayer = nullptr;
1247
1248    // now do the normal restore()
1249    fMCRec->~MCRec();       // balanced in save()
1250    fMCStack.pop_back();
1251    fMCRec = (MCRec*)fMCStack.back();
1252
1253    if (fMCRec) {
1254        FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
1255    }
1256
1257    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
1258        since if we're being recorded, we don't want to record this (the
1259        recorder will have already recorded the restore).
1260    */
1261    if (layer) {
1262        if (fMCRec) {
1263            const SkIPoint& origin = layer->fDevice->getOrigin();
1264            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(), layer->fPaint);
1265            // restore what we smashed in internalSaveLayer
1266            fMCRec->fMatrix = layer->fStashedMatrix;
1267            // reset this, since internalDrawDevice will have set it to true
1268            delete layer;
1269        } else {
1270            // we're at the root
1271            SkASSERT(layer == (void*)fDeviceCMStorage);
1272            layer->~DeviceCM();
1273            // no need to update fMCRec, 'cause we're killing the canvas
1274        }
1275    }
1276
1277    if (fMCRec) {
1278        fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
1279        fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1280    }
1281}
1282
1283sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
1284    if (nullptr == props) {
1285        props = &fProps;
1286    }
1287    return this->onNewSurface(info, *props);
1288}
1289
1290sk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
1291    SkBaseDevice* dev = this->getDevice();
1292    return dev ? dev->makeSurface(info, props) : nullptr;
1293}
1294
1295SkImageInfo SkCanvas::imageInfo() const {
1296    return this->onImageInfo();
1297}
1298
1299SkImageInfo SkCanvas::onImageInfo() const {
1300    SkBaseDevice* dev = this->getDevice();
1301    if (dev) {
1302        return dev->imageInfo();
1303    } else {
1304        return SkImageInfo::MakeUnknown(0, 0);
1305    }
1306}
1307
1308bool SkCanvas::getProps(SkSurfaceProps* props) const {
1309    return this->onGetProps(props);
1310}
1311
1312bool SkCanvas::onGetProps(SkSurfaceProps* props) const {
1313    SkBaseDevice* dev = this->getDevice();
1314    if (dev) {
1315        if (props) {
1316            *props = fProps;
1317        }
1318        return true;
1319    } else {
1320        return false;
1321    }
1322}
1323
1324bool SkCanvas::peekPixels(SkPixmap* pmap) {
1325    return this->onPeekPixels(pmap);
1326}
1327
1328bool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1329    SkBaseDevice* dev = this->getDevice();
1330    return dev && dev->peekPixels(pmap);
1331}
1332
1333void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1334    SkPixmap pmap;
1335    if (!this->onAccessTopLayerPixels(&pmap)) {
1336        return nullptr;
1337    }
1338    if (info) {
1339        *info = pmap.info();
1340    }
1341    if (rowBytes) {
1342        *rowBytes = pmap.rowBytes();
1343    }
1344    if (origin) {
1345        *origin = this->getTopDevice()->getOrigin();
1346    }
1347    return pmap.writable_addr();
1348}
1349
1350bool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
1351    SkBaseDevice* dev = this->getTopDevice();
1352    return dev && dev->accessPixels(pmap);
1353}
1354
1355/////////////////////////////////////////////////////////////////////////////
1356
1357void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint) {
1358    SkPaint tmp;
1359    if (nullptr == paint) {
1360        paint = &tmp;
1361    }
1362
1363    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1364
1365    while (iter.next()) {
1366        SkBaseDevice* dstDev = iter.fDevice;
1367        paint = &looper.paint();
1368        SkImageFilter* filter = paint->getImageFilter();
1369        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1370        if (filter) {
1371            sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
1372            if (specialImage) {
1373                dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint);
1374            }
1375        } else {
1376            dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint);
1377        }
1378    }
1379
1380    LOOPER_END
1381}
1382
1383/////////////////////////////////////////////////////////////////////////////
1384
1385void SkCanvas::translate(SkScalar dx, SkScalar dy) {
1386    if (dx || dy) {
1387        this->checkForDeferredSave();
1388        fMCRec->fMatrix.preTranslate(dx,dy);
1389
1390        // Translate shouldn't affect the is-scale-translateness of the matrix.
1391        SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1392
1393        FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1394
1395        this->didTranslate(dx,dy);
1396    }
1397}
1398
1399void SkCanvas::scale(SkScalar sx, SkScalar sy) {
1400    SkMatrix m;
1401    m.setScale(sx, sy);
1402    this->concat(m);
1403}
1404
1405void SkCanvas::rotate(SkScalar degrees) {
1406    SkMatrix m;
1407    m.setRotate(degrees);
1408    this->concat(m);
1409}
1410
1411void SkCanvas::rotate(SkScalar degrees, SkScalar px, SkScalar py) {
1412    SkMatrix m;
1413    m.setRotate(degrees, px, py);
1414    this->concat(m);
1415}
1416
1417void SkCanvas::skew(SkScalar sx, SkScalar sy) {
1418    SkMatrix m;
1419    m.setSkew(sx, sy);
1420    this->concat(m);
1421}
1422
1423void SkCanvas::concat(const SkMatrix& matrix) {
1424    if (matrix.isIdentity()) {
1425        return;
1426    }
1427
1428    this->checkForDeferredSave();
1429    fMCRec->fMatrix.preConcat(matrix);
1430    fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
1431
1432    FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1433
1434    this->didConcat(matrix);
1435}
1436
1437void SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
1438    fMCRec->fMatrix = matrix;
1439    fIsScaleTranslate = matrix.isScaleTranslate();
1440
1441    FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1442}
1443
1444void SkCanvas::setMatrix(const SkMatrix& matrix) {
1445    this->checkForDeferredSave();
1446    this->internalSetMatrix(matrix);
1447    this->didSetMatrix(matrix);
1448}
1449
1450void SkCanvas::resetMatrix() {
1451    this->setMatrix(SkMatrix::I());
1452}
1453
1454#ifdef SK_EXPERIMENTAL_SHADOWING
1455void SkCanvas::translateZ(SkScalar z) {
1456    this->checkForDeferredSave();
1457    this->fMCRec->fCurDrawDepth += z;
1458    this->didTranslateZ(z);
1459}
1460
1461SkScalar SkCanvas::getZ() const {
1462    return this->fMCRec->fCurDrawDepth;
1463}
1464
1465void SkCanvas::setLights(sk_sp<SkLights> lights) {
1466    this->fLights = lights;
1467}
1468
1469sk_sp<SkLights> SkCanvas::getLights() const {
1470    return this->fLights;
1471}
1472#endif
1473
1474//////////////////////////////////////////////////////////////////////////////
1475
1476void SkCanvas::clipRect(const SkRect& rect, SkClipOp op, bool doAA) {
1477    this->checkForDeferredSave();
1478    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1479    this->onClipRect(rect, op, edgeStyle);
1480}
1481
1482void SkCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1483    const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1484
1485    FOR_EACH_TOP_DEVICE(device->clipRect(rect, op, isAA));
1486
1487    AutoValidateClip avc(this);
1488    fMCRec->fRasterClip.op(rect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1489                           isAA);
1490    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1491}
1492
1493void SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
1494    fClipRestrictionRect = rect;
1495    if (fClipRestrictionRect.isEmpty()) {
1496        // we notify the device, but we *dont* resolve deferred saves (since we're just
1497        // removing the restriction if the rect is empty. how I hate this api.
1498        FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
1499    } else {
1500        this->checkForDeferredSave();
1501        FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
1502        AutoValidateClip avc(this);
1503        fMCRec->fRasterClip.op(fClipRestrictionRect, SkRegion::kIntersect_Op);
1504        fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1505    }
1506}
1507
1508void SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
1509    this->checkForDeferredSave();
1510    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1511    if (rrect.isRect()) {
1512        this->onClipRect(rrect.getBounds(), op, edgeStyle);
1513    } else {
1514        this->onClipRRect(rrect, op, edgeStyle);
1515    }
1516}
1517
1518void SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1519    AutoValidateClip avc(this);
1520
1521    bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1522
1523    FOR_EACH_TOP_DEVICE(device->clipRRect(rrect, op, isAA));
1524
1525    fMCRec->fRasterClip.op(rrect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1526                           isAA);
1527    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1528}
1529
1530void SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
1531    this->checkForDeferredSave();
1532    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1533
1534    if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) {
1535        SkRect r;
1536        if (path.isRect(&r)) {
1537            this->onClipRect(r, op, edgeStyle);
1538            return;
1539        }
1540        SkRRect rrect;
1541        if (path.isOval(&r)) {
1542            rrect.setOval(r);
1543            this->onClipRRect(rrect, op, edgeStyle);
1544            return;
1545        }
1546        if (path.isRRect(&rrect)) {
1547            this->onClipRRect(rrect, op, edgeStyle);
1548            return;
1549        }
1550    }
1551
1552    this->onClipPath(path, op, edgeStyle);
1553}
1554
1555void SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
1556    AutoValidateClip avc(this);
1557
1558    bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1559
1560    FOR_EACH_TOP_DEVICE(device->clipPath(path, op, isAA));
1561
1562    const SkPath* rasterClipPath = &path;
1563    const SkMatrix* matrix = &fMCRec->fMatrix;
1564    fMCRec->fRasterClip.op(*rasterClipPath, *matrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1565                           isAA);
1566    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1567}
1568
1569void SkCanvas::clipRegion(const SkRegion& rgn, SkClipOp op) {
1570    this->checkForDeferredSave();
1571    this->onClipRegion(rgn, op);
1572}
1573
1574void SkCanvas::onClipRegion(const SkRegion& rgn, SkClipOp op) {
1575    FOR_EACH_TOP_DEVICE(device->clipRegion(rgn, op));
1576
1577    AutoValidateClip avc(this);
1578
1579    fMCRec->fRasterClip.op(rgn, (SkRegion::Op)op);
1580    fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1581}
1582
1583#ifdef SK_DEBUG
1584void SkCanvas::validateClip() const {
1585    // construct clipRgn from the clipstack
1586    const SkBaseDevice* device = this->getDevice();
1587    if (!device) {
1588        SkASSERT(this->isClipEmpty());
1589        return;
1590    }
1591}
1592#endif
1593
1594bool SkCanvas::androidFramework_isClipAA() const {
1595    bool containsAA = false;
1596
1597    FOR_EACH_TOP_DEVICE(containsAA |= device->onClipIsAA());
1598
1599    return containsAA;
1600}
1601
1602class RgnAccumulator {
1603    SkRegion* fRgn;
1604public:
1605    RgnAccumulator(SkRegion* total) : fRgn(total) {}
1606    void accumulate(SkBaseDevice* device, SkRegion* rgn) {
1607        SkIPoint origin = device->getOrigin();
1608        if (origin.x() | origin.y()) {
1609            rgn->translate(origin.x(), origin.y());
1610        }
1611        fRgn->op(*rgn, SkRegion::kUnion_Op);
1612    }
1613};
1614
1615void SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
1616    RgnAccumulator accum(rgn);
1617    SkRegion tmp;
1618
1619    rgn->setEmpty();
1620    FOR_EACH_TOP_DEVICE(device->onAsRgnClip(&tmp); accum.accumulate(device, &tmp));
1621}
1622
1623///////////////////////////////////////////////////////////////////////////////
1624
1625bool SkCanvas::isClipEmpty() const {
1626    return fMCRec->fRasterClip.isEmpty();
1627
1628    // TODO: should we only use the conservative answer in a recording canvas?
1629#if 0
1630    SkBaseDevice* dev = this->getTopDevice();
1631    // if no device we return true
1632    return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
1633#endif
1634}
1635
1636bool SkCanvas::isClipRect() const {
1637    SkBaseDevice* dev = this->getTopDevice();
1638    // if no device we return false
1639    return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType;
1640}
1641
1642static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
1643#if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
1644    __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec);
1645    __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec);
1646    __m128 mask = _mm_cmplt_ps(lLtT, RrBb);
1647    return 0xF != _mm_movemask_ps(mask);
1648#elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
1649    float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0];
1650    float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1];
1651    uint32x4_t mask = vcltq_f32(lLtT, RrBb);
1652    return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask);
1653#else
1654    SkRect devRectAsRect;
1655    SkRect devClipAsRect;
1656    devRect.store(&devRectAsRect.fLeft);
1657    devClip.store(&devClipAsRect.fLeft);
1658    return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect);
1659#endif
1660}
1661
1662// It's important for this function to not be inlined.  Otherwise the compiler will share code
1663// between the fast path and the slow path, resulting in two slow paths.
1664static SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip,
1665                                                   const SkMatrix& matrix) {
1666    SkRect deviceRect;
1667    matrix.mapRect(&deviceRect, src);
1668    return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip);
1669}
1670
1671bool SkCanvas::quickReject(const SkRect& src) const {
1672#ifdef SK_DEBUG
1673    // Verify that fDeviceClipBounds are set properly.
1674    SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1675    if (fMCRec->fRasterClip.isEmpty()) {
1676        SkASSERT(fDeviceClipBounds.isEmpty());
1677    } else {
1678        SkASSERT(tmp == fDeviceClipBounds);
1679    }
1680
1681    // Verify that fIsScaleTranslate is set properly.
1682    SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1683#endif
1684
1685    if (!fIsScaleTranslate) {
1686        return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix);
1687    }
1688
1689    // We inline the implementation of mapScaleTranslate() for the fast path.
1690    float sx = fMCRec->fMatrix.getScaleX();
1691    float sy = fMCRec->fMatrix.getScaleY();
1692    float tx = fMCRec->fMatrix.getTranslateX();
1693    float ty = fMCRec->fMatrix.getTranslateY();
1694    Sk4f scale(sx, sy, sx, sy);
1695    Sk4f trans(tx, ty, tx, ty);
1696
1697    // Apply matrix.
1698    Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
1699
1700    // Make sure left < right, top < bottom.
1701    Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
1702    Sk4f min = Sk4f::Min(ltrb, rblt);
1703    Sk4f max = Sk4f::Max(ltrb, rblt);
1704    // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
1705    // ARM this sequence generates the fastest (a single instruction).
1706    Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]);
1707
1708    // Check if the device rect is NaN or outside the clip.
1709    return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft));
1710}
1711
1712bool SkCanvas::quickReject(const SkPath& path) const {
1713    return path.isEmpty() || this->quickReject(path.getBounds());
1714}
1715
1716SkRect SkCanvas::onGetLocalClipBounds() const {
1717    SkIRect ibounds = this->onGetDeviceClipBounds();
1718    if (ibounds.isEmpty()) {
1719        return SkRect::MakeEmpty();
1720    }
1721
1722    SkMatrix inverse;
1723    // if we can't invert the CTM, we can't return local clip bounds
1724    if (!fMCRec->fMatrix.invert(&inverse)) {
1725        return SkRect::MakeEmpty();
1726    }
1727
1728    SkRect bounds;
1729    SkRect r;
1730    // adjust it outwards in case we are antialiasing
1731    const int inset = 1;
1732
1733    r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1734           ibounds.fRight + inset, ibounds.fBottom + inset);
1735    inverse.mapRect(&bounds, r);
1736    return bounds;
1737}
1738
1739SkIRect SkCanvas::onGetDeviceClipBounds() const {
1740    return fMCRec->fRasterClip.getBounds();
1741}
1742
1743const SkMatrix& SkCanvas::getTotalMatrix() const {
1744    return fMCRec->fMatrix;
1745}
1746
1747GrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() {
1748    SkBaseDevice* dev = this->getTopDevice();
1749    return dev ? dev->accessRenderTargetContext() : nullptr;
1750}
1751
1752GrContext* SkCanvas::getGrContext() {
1753    SkBaseDevice* device = this->getTopDevice();
1754    return device ? device->context() : nullptr;
1755}
1756
1757void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1758                          const SkPaint& paint) {
1759    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1760    if (outer.isEmpty()) {
1761        return;
1762    }
1763    if (inner.isEmpty()) {
1764        this->drawRRect(outer, paint);
1765        return;
1766    }
1767
1768    // We don't have this method (yet), but technically this is what we should
1769    // be able to return ...
1770    // if (!outer.contains(inner))) {
1771    //
1772    // For now at least check for containment of bounds
1773    if (!outer.getBounds().contains(inner.getBounds())) {
1774        return;
1775    }
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(const sk_sp<SkVertices>& vertices, SkBlendMode mode,
1815                            const SkPaint& paint) {
1816    RETURN_ON_NULL(vertices);
1817    this->onDrawVerticesObject(vertices.get(), mode, paint);
1818}
1819
1820void SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
1821    RETURN_ON_NULL(vertices);
1822    this->onDrawVerticesObject(vertices, mode, paint);
1823}
1824
1825void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1826    this->onDrawPath(path, paint);
1827}
1828
1829void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1830    RETURN_ON_NULL(image);
1831    this->onDrawImage(image, x, y, paint);
1832}
1833
1834void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1835                             const SkPaint* paint, SrcRectConstraint constraint) {
1836    RETURN_ON_NULL(image);
1837    if (dst.isEmpty() || src.isEmpty()) {
1838        return;
1839    }
1840    this->onDrawImageRect(image, &src, dst, paint, constraint);
1841}
1842
1843void SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
1844                             const SkPaint* paint, SrcRectConstraint constraint) {
1845    RETURN_ON_NULL(image);
1846    this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
1847}
1848
1849void SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1850                             SrcRectConstraint constraint) {
1851    RETURN_ON_NULL(image);
1852    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1853                        constraint);
1854}
1855
1856void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
1857                             const SkPaint* paint) {
1858    RETURN_ON_NULL(image);
1859    if (dst.isEmpty()) {
1860        return;
1861    }
1862    if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
1863        this->onDrawImageNine(image, center, dst, paint);
1864    } else {
1865        this->drawImageRect(image, dst, paint);
1866    }
1867}
1868
1869void SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
1870                                const SkPaint* paint) {
1871    RETURN_ON_NULL(image);
1872    if (dst.isEmpty()) {
1873        return;
1874    }
1875
1876    SkIRect bounds;
1877    Lattice latticePlusBounds = lattice;
1878    if (!latticePlusBounds.fBounds) {
1879        bounds = SkIRect::MakeWH(image->width(), image->height());
1880        latticePlusBounds.fBounds = &bounds;
1881    }
1882
1883    if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
1884        this->onDrawImageLattice(image, latticePlusBounds, dst, paint);
1885    } else {
1886        this->drawImageRect(image, dst, paint);
1887    }
1888}
1889
1890void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
1891    if (bitmap.drawsNothing()) {
1892        return;
1893    }
1894    this->onDrawBitmap(bitmap, dx, dy, paint);
1895}
1896
1897void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1898                              const SkPaint* paint, SrcRectConstraint constraint) {
1899    if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1900        return;
1901    }
1902    this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
1903}
1904
1905void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
1906                              const SkPaint* paint, SrcRectConstraint constraint) {
1907    this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1908}
1909
1910void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1911                              SrcRectConstraint constraint) {
1912    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1913                         constraint);
1914}
1915
1916void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
1917                              const SkPaint* paint) {
1918    if (bitmap.drawsNothing() || dst.isEmpty()) {
1919        return;
1920    }
1921    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
1922        this->onDrawBitmapNine(bitmap, center, dst, paint);
1923    } else {
1924        this->drawBitmapRect(bitmap, dst, paint);
1925    }
1926}
1927
1928void SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
1929                                 const SkPaint* paint) {
1930    if (bitmap.drawsNothing() || dst.isEmpty()) {
1931        return;
1932    }
1933
1934    SkIRect bounds;
1935    Lattice latticePlusBounds = lattice;
1936    if (!latticePlusBounds.fBounds) {
1937        bounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
1938        latticePlusBounds.fBounds = &bounds;
1939    }
1940
1941    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) {
1942        this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, paint);
1943    } else {
1944        this->drawBitmapRect(bitmap, dst, paint);
1945    }
1946}
1947
1948void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
1949                         const SkColor colors[], int count, SkBlendMode mode,
1950                         const SkRect* cull, const SkPaint* paint) {
1951    RETURN_ON_NULL(atlas);
1952    if (count <= 0) {
1953        return;
1954    }
1955    SkASSERT(atlas);
1956    SkASSERT(tex);
1957    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
1958}
1959
1960void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
1961    if (key) {
1962        this->onDrawAnnotation(rect, key, value);
1963    }
1964}
1965
1966void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1967                                    const SkPaint* paint, SrcRectConstraint constraint) {
1968    if (src) {
1969        this->drawImageRect(image, *src, dst, paint, constraint);
1970    } else {
1971        this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
1972                            dst, paint, constraint);
1973    }
1974}
1975void SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1976                                     const SkPaint* paint, SrcRectConstraint constraint) {
1977    if (src) {
1978        this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
1979    } else {
1980        this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
1981                             dst, paint, constraint);
1982    }
1983}
1984
1985void SkCanvas::temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds) {
1986    SkIRect layer_bounds = this->getTopLayerBounds();
1987    if (matrix) {
1988        *matrix = this->getTotalMatrix();
1989        matrix->preTranslate(-layer_bounds.left(), -layer_bounds.top());
1990    }
1991    if (clip_bounds) {
1992        *clip_bounds = this->getDeviceClipBounds();
1993        clip_bounds->offset(-layer_bounds.left(), -layer_bounds.top());
1994    }
1995}
1996
1997//////////////////////////////////////////////////////////////////////////////
1998//  These are the virtual drawing methods
1999//////////////////////////////////////////////////////////////////////////////
2000
2001void SkCanvas::onDiscard() {
2002    if (fSurfaceBase) {
2003        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
2004    }
2005}
2006
2007void SkCanvas::onDrawPaint(const SkPaint& paint) {
2008    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
2009    this->internalDrawPaint(paint);
2010}
2011
2012void SkCanvas::internalDrawPaint(const SkPaint& paint) {
2013    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
2014
2015    while (iter.next()) {
2016        iter.fDevice->drawPaint(looper.paint());
2017    }
2018
2019    LOOPER_END
2020}
2021
2022void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
2023                            const SkPaint& paint) {
2024    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
2025    if ((long)count <= 0) {
2026        return;
2027    }
2028
2029    SkRect r;
2030    const SkRect* bounds = nullptr;
2031    if (paint.canComputeFastBounds()) {
2032        // special-case 2 points (common for drawing a single line)
2033        if (2 == count) {
2034            r.set(pts[0], pts[1]);
2035        } else {
2036            r.set(pts, SkToInt(count));
2037        }
2038        SkRect storage;
2039        if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
2040            return;
2041        }
2042        bounds = &r;
2043    }
2044
2045    SkASSERT(pts != nullptr);
2046
2047    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
2048
2049    while (iter.next()) {
2050        iter.fDevice->drawPoints(mode, count, pts, looper.paint());
2051    }
2052
2053    LOOPER_END
2054}
2055
2056static bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) {
2057    return ((intptr_t)paint.getImageFilter()    |
2058#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
2059            (intptr_t)canvas->getDrawFilter()   |
2060#endif
2061            (intptr_t)paint.getLooper()         ) != 0;
2062}
2063
2064void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
2065    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
2066    if (paint.canComputeFastBounds()) {
2067        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
2068        // To prevent accidental rejecting at this stage, we have to sort it before we check.
2069        SkRect tmp(r);
2070        tmp.sort();
2071
2072        SkRect storage;
2073        if (this->quickReject(paint.computeFastBounds(tmp, &storage))) {
2074            return;
2075        }
2076    }
2077
2078    if (needs_autodrawlooper(this, paint)) {
2079        LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false)
2080
2081        while (iter.next()) {
2082            iter.fDevice->drawRect(r, looper.paint());
2083        }
2084
2085        LOOPER_END
2086    } else {
2087        this->predrawNotify(&r, &paint, false);
2088        SkDrawIter iter(this);
2089        while (iter.next()) {
2090            iter.fDevice->drawRect(r, paint);
2091        }
2092    }
2093}
2094
2095void SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
2096    SkRect regionRect = SkRect::Make(region.getBounds());
2097    if (paint.canComputeFastBounds()) {
2098        SkRect storage;
2099        if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) {
2100            return;
2101        }
2102    }
2103
2104    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, &regionRect)
2105
2106    while (iter.next()) {
2107        iter.fDevice->drawRegion(region, looper.paint());
2108    }
2109
2110    LOOPER_END
2111}
2112
2113void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
2114    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
2115    if (paint.canComputeFastBounds()) {
2116        SkRect storage;
2117        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2118            return;
2119        }
2120    }
2121
2122    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2123
2124    while (iter.next()) {
2125        iter.fDevice->drawOval(oval, looper.paint());
2126    }
2127
2128    LOOPER_END
2129}
2130
2131void SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle,
2132                         SkScalar sweepAngle, bool useCenter,
2133                         const SkPaint& paint) {
2134    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2135    if (paint.canComputeFastBounds()) {
2136        SkRect storage;
2137        // Note we're using the entire oval as the bounds.
2138        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2139            return;
2140        }
2141    }
2142
2143    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2144
2145    while (iter.next()) {
2146        iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint());
2147    }
2148
2149    LOOPER_END
2150}
2151
2152void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
2153    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
2154    if (paint.canComputeFastBounds()) {
2155        SkRect storage;
2156        if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
2157            return;
2158        }
2159    }
2160
2161    if (rrect.isRect()) {
2162        // call the non-virtual version
2163        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2164        return;
2165    } else if (rrect.isOval()) {
2166        // call the non-virtual version
2167        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2168        return;
2169    }
2170
2171    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds())
2172
2173    while (iter.next()) {
2174        iter.fDevice->drawRRect(rrect, looper.paint());
2175    }
2176
2177    LOOPER_END
2178}
2179
2180void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
2181    if (paint.canComputeFastBounds()) {
2182        SkRect storage;
2183        if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
2184            return;
2185        }
2186    }
2187
2188    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds())
2189
2190    while (iter.next()) {
2191        iter.fDevice->drawDRRect(outer, inner, looper.paint());
2192    }
2193
2194    LOOPER_END
2195}
2196
2197void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
2198    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
2199    if (!path.isFinite()) {
2200        return;
2201    }
2202
2203    const SkRect& pathBounds = path.getBounds();
2204    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
2205        SkRect storage;
2206        if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
2207            return;
2208        }
2209    }
2210
2211    if (pathBounds.width() <= 0 && pathBounds.height() <= 0) {
2212        if (path.isInverseFillType()) {
2213            this->internalDrawPaint(paint);
2214            return;
2215        }
2216    }
2217
2218    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
2219
2220    while (iter.next()) {
2221        iter.fDevice->drawPath(path, looper.paint());
2222    }
2223
2224    LOOPER_END
2225}
2226
2227bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2228    if (!paint.getImageFilter()) {
2229        return false;
2230    }
2231
2232    const SkMatrix& ctm = this->getTotalMatrix();
2233    if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2234        return false;
2235    }
2236
2237    // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2238    // Once we can filter and the filter will return a result larger than itself, we should be
2239    // able to remove this constraint.
2240    // skbug.com/4526
2241    //
2242    SkPoint pt;
2243    ctm.mapXY(x, y, &pt);
2244    SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2245    return ir.contains(fMCRec->fRasterClip.getBounds());
2246}
2247
2248void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
2249    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2250    SkRect bounds = SkRect::MakeXYWH(x, y,
2251                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
2252    if (nullptr == paint || paint->canComputeFastBounds()) {
2253        SkRect tmp = bounds;
2254        if (paint) {
2255            paint->computeFastBounds(tmp, &tmp);
2256        }
2257        if (this->quickReject(tmp)) {
2258            return;
2259        }
2260    }
2261
2262    SkLazyPaint lazy;
2263    if (nullptr == paint) {
2264        paint = lazy.init();
2265    }
2266
2267    sk_sp<SkSpecialImage> special;
2268    bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2269                                                    *paint);
2270    if (drawAsSprite && paint->getImageFilter()) {
2271        special = this->getDevice()->makeSpecial(image);
2272        if (!special) {
2273            drawAsSprite = false;
2274        }
2275    }
2276
2277    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2278
2279    while (iter.next()) {
2280        const SkPaint& pnt = looper.paint();
2281        if (special) {
2282            SkPoint pt;
2283            iter.fDevice->ctm().mapXY(x, y, &pt);
2284            iter.fDevice->drawSpecial(special.get(),
2285                                      SkScalarRoundToInt(pt.fX),
2286                                      SkScalarRoundToInt(pt.fY), pnt);
2287        } else {
2288            iter.fDevice->drawImage(image, x, y, pnt);
2289        }
2290    }
2291
2292    LOOPER_END
2293}
2294
2295void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2296                               const SkPaint* paint, SrcRectConstraint constraint) {
2297    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
2298    if (nullptr == paint || paint->canComputeFastBounds()) {
2299        SkRect storage = dst;
2300        if (paint) {
2301            paint->computeFastBounds(dst, &storage);
2302        }
2303        if (this->quickReject(storage)) {
2304            return;
2305        }
2306    }
2307    SkLazyPaint lazy;
2308    if (nullptr == paint) {
2309        paint = lazy.init();
2310    }
2311
2312    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2313                                          image->isOpaque())
2314
2315    while (iter.next()) {
2316        iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint);
2317    }
2318
2319    LOOPER_END
2320}
2321
2322void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
2323    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
2324    SkDEBUGCODE(bitmap.validate();)
2325
2326    if (bitmap.drawsNothing()) {
2327        return;
2328    }
2329
2330    SkLazyPaint lazy;
2331    if (nullptr == paint) {
2332        paint = lazy.init();
2333    }
2334
2335    SkRect bounds;
2336    bitmap.getBounds(&bounds);
2337    bounds.offset(x, y);
2338    bool canFastBounds = paint->canComputeFastBounds();
2339    if (canFastBounds) {
2340        SkRect storage;
2341        if (this->quickReject(paint->computeFastBounds(bounds, &storage))) {
2342            return;
2343        }
2344    }
2345
2346    sk_sp<SkSpecialImage> special;
2347    bool drawAsSprite = canFastBounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(),
2348                                                                     bitmap.height(), *paint);
2349    if (drawAsSprite && paint->getImageFilter()) {
2350        special = this->getDevice()->makeSpecial(bitmap);
2351        if (!special) {
2352            drawAsSprite = false;
2353        }
2354    }
2355
2356    const SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2357
2358    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2359
2360    while (iter.next()) {
2361        const SkPaint& pnt = looper.paint();
2362        if (special) {
2363            SkPoint pt;
2364            iter.fDevice->ctm().mapXY(x, y, &pt);
2365            iter.fDevice->drawSpecial(special.get(),
2366                                      SkScalarRoundToInt(pt.fX),
2367                                      SkScalarRoundToInt(pt.fY), pnt);
2368        } else {
2369            iter.fDevice->drawBitmap(bitmap, matrix, looper.paint());
2370        }
2371    }
2372
2373    LOOPER_END
2374}
2375
2376// this one is non-virtual, so it can be called safely by other canvas apis
2377void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2378                                      const SkRect& dst, const SkPaint* paint,
2379                                      SrcRectConstraint constraint) {
2380    if (bitmap.drawsNothing() || dst.isEmpty()) {
2381        return;
2382    }
2383
2384    if (nullptr == paint || paint->canComputeFastBounds()) {
2385        SkRect storage;
2386        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2387            return;
2388        }
2389    }
2390
2391    SkLazyPaint lazy;
2392    if (nullptr == paint) {
2393        paint = lazy.init();
2394    }
2395
2396    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2397                                          bitmap.isOpaque())
2398
2399    while (iter.next()) {
2400        iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint);
2401    }
2402
2403    LOOPER_END
2404}
2405
2406void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2407                                const SkPaint* paint, SrcRectConstraint constraint) {
2408    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
2409    SkDEBUGCODE(bitmap.validate();)
2410    this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
2411}
2412
2413void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
2414                               const SkPaint* paint) {
2415    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
2416
2417    if (nullptr == paint || paint->canComputeFastBounds()) {
2418        SkRect storage;
2419        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2420            return;
2421        }
2422    }
2423
2424    SkLazyPaint lazy;
2425    if (nullptr == paint) {
2426        paint = lazy.init();
2427    }
2428
2429    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2430
2431    while (iter.next()) {
2432        iter.fDevice->drawImageNine(image, center, dst, looper.paint());
2433    }
2434
2435    LOOPER_END
2436}
2437
2438void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
2439                                const SkPaint* paint) {
2440    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
2441    SkDEBUGCODE(bitmap.validate();)
2442
2443    if (nullptr == paint || paint->canComputeFastBounds()) {
2444        SkRect storage;
2445        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2446            return;
2447        }
2448    }
2449
2450    SkLazyPaint lazy;
2451    if (nullptr == paint) {
2452        paint = lazy.init();
2453    }
2454
2455    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2456
2457    while (iter.next()) {
2458        iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint());
2459    }
2460
2461    LOOPER_END
2462}
2463
2464void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
2465                                  const SkPaint* paint) {
2466    if (nullptr == paint || paint->canComputeFastBounds()) {
2467        SkRect storage;
2468        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2469            return;
2470        }
2471    }
2472
2473    SkLazyPaint lazy;
2474    if (nullptr == paint) {
2475        paint = lazy.init();
2476    }
2477
2478    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2479
2480    while (iter.next()) {
2481        iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint());
2482    }
2483
2484    LOOPER_END
2485}
2486
2487void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
2488                                   const SkRect& dst, const SkPaint* paint) {
2489    if (nullptr == paint || paint->canComputeFastBounds()) {
2490        SkRect storage;
2491        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2492            return;
2493        }
2494    }
2495
2496    SkLazyPaint lazy;
2497    if (nullptr == paint) {
2498        paint = lazy.init();
2499    }
2500
2501    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2502
2503    while (iter.next()) {
2504        iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint());
2505    }
2506
2507    LOOPER_END
2508}
2509
2510class SkDeviceFilteredPaint {
2511public:
2512    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2513        uint32_t filteredFlags = device->filterTextFlags(paint);
2514        if (filteredFlags != paint.getFlags()) {
2515            SkPaint* newPaint = fLazy.set(paint);
2516            newPaint->setFlags(filteredFlags);
2517            fPaint = newPaint;
2518        } else {
2519            fPaint = &paint;
2520        }
2521    }
2522
2523    const SkPaint& paint() const { return *fPaint; }
2524
2525private:
2526    const SkPaint*  fPaint;
2527    SkLazyPaint     fLazy;
2528};
2529
2530void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2531                          const SkPaint& paint) {
2532    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2533
2534    while (iter.next()) {
2535        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2536        iter.fDevice->drawText(text, byteLength, x, y, dfp.paint());
2537    }
2538
2539    LOOPER_END
2540}
2541
2542void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2543                             const SkPaint& paint) {
2544    SkPoint textOffset = SkPoint::Make(0, 0);
2545
2546    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2547
2548    while (iter.next()) {
2549        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2550        iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset,
2551                                  dfp.paint());
2552    }
2553
2554    LOOPER_END
2555}
2556
2557void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2558                              SkScalar constY, const SkPaint& paint) {
2559
2560    SkPoint textOffset = SkPoint::Make(0, constY);
2561
2562    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2563
2564    while (iter.next()) {
2565        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2566        iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset,
2567                                  dfp.paint());
2568    }
2569
2570    LOOPER_END
2571}
2572
2573void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2574                                const SkMatrix* matrix, const SkPaint& paint) {
2575    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2576
2577    while (iter.next()) {
2578        iter.fDevice->drawTextOnPath(text, byteLength, path,
2579                                     matrix, looper.paint());
2580    }
2581
2582    LOOPER_END
2583}
2584
2585void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
2586                                 const SkRect* cullRect, const SkPaint& paint) {
2587    if (cullRect && this->quickReject(*cullRect)) {
2588        return;
2589    }
2590
2591    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2592
2593    while (iter.next()) {
2594        iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint());
2595    }
2596
2597    LOOPER_END
2598}
2599
2600void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2601                              const SkPaint& paint) {
2602
2603    SkRect storage;
2604    const SkRect* bounds = nullptr;
2605    if (paint.canComputeFastBounds()) {
2606        storage = blob->bounds().makeOffset(x, y);
2607        SkRect tmp;
2608        if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
2609            return;
2610        }
2611        bounds = &storage;
2612    }
2613
2614    // We cannot filter in the looper as we normally do, because the paint is
2615    // incomplete at this point (text-related attributes are embedded within blob run paints).
2616    SkDrawFilter* drawFilter = fMCRec->fFilter;
2617    fMCRec->fFilter = nullptr;
2618
2619    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
2620
2621    while (iter.next()) {
2622        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2623        iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter);
2624    }
2625
2626    LOOPER_END
2627
2628    fMCRec->fFilter = drawFilter;
2629}
2630
2631// These will become non-virtual, so they always call the (virtual) onDraw... method
2632void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2633                        const SkPaint& paint) {
2634    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2635    if (byteLength) {
2636        this->onDrawText(text, byteLength, x, y, paint);
2637    }
2638}
2639void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2640                           const SkPaint& paint) {
2641    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2642    if (byteLength) {
2643        this->onDrawPosText(text, byteLength, pos, paint);
2644    }
2645}
2646void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2647                            SkScalar constY, const SkPaint& paint) {
2648    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2649    if (byteLength) {
2650        this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2651    }
2652}
2653void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2654                              const SkMatrix* matrix, const SkPaint& paint) {
2655    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2656    if (byteLength) {
2657        this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2658    }
2659}
2660void SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
2661                               const SkRect* cullRect, const SkPaint& paint) {
2662    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextRSXform()");
2663    if (byteLength) {
2664        this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint);
2665    }
2666}
2667void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2668                            const SkPaint& paint) {
2669    RETURN_ON_NULL(blob);
2670    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2671    this->onDrawTextBlob(blob, x, y, paint);
2672}
2673
2674void SkCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
2675                                    const SkPaint& paint) {
2676    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
2677    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2678
2679    while (iter.next()) {
2680        // In the common case of one iteration we could std::move vertices here.
2681        iter.fDevice->drawVertices(vertices, bmode, looper.paint());
2682    }
2683
2684    LOOPER_END
2685}
2686
2687void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2688                         const SkPoint texCoords[4], SkBlendMode bmode,
2689                         const SkPaint& paint) {
2690    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
2691    if (nullptr == cubics) {
2692        return;
2693    }
2694
2695    this->onDrawPatch(cubics, colors, texCoords, bmode, paint);
2696}
2697
2698void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2699                           const SkPoint texCoords[4], SkBlendMode bmode,
2700                           const SkPaint& paint) {
2701    // Since a patch is always within the convex hull of the control points, we discard it when its
2702    // bounding rectangle is completely outside the current clip.
2703    SkRect bounds;
2704    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2705    if (this->quickReject(bounds)) {
2706        return;
2707    }
2708
2709    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2710
2711    while (iter.next()) {
2712        iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, paint);
2713    }
2714
2715    LOOPER_END
2716}
2717
2718void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2719    RETURN_ON_NULL(dr);
2720    if (x || y) {
2721        SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2722        this->onDrawDrawable(dr, &matrix);
2723    } else {
2724        this->onDrawDrawable(dr, nullptr);
2725    }
2726}
2727
2728void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2729    RETURN_ON_NULL(dr);
2730    if (matrix && matrix->isIdentity()) {
2731        matrix = nullptr;
2732    }
2733    this->onDrawDrawable(dr, matrix);
2734}
2735
2736void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2737    // drawable bounds are no longer reliable (e.g. android displaylist)
2738    // so don't use them for quick-reject
2739    dr->draw(this, matrix);
2740}
2741
2742void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2743                           const SkColor colors[], int count, SkBlendMode bmode,
2744                           const SkRect* cull, const SkPaint* paint) {
2745    if (cull && this->quickReject(*cull)) {
2746        return;
2747    }
2748
2749    SkPaint pnt;
2750    if (paint) {
2751        pnt = *paint;
2752    }
2753
2754    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
2755    while (iter.next()) {
2756        iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt);
2757    }
2758    LOOPER_END
2759}
2760
2761void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2762    SkASSERT(key);
2763
2764    SkPaint paint;
2765    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
2766    while (iter.next()) {
2767        iter.fDevice->drawAnnotation(rect, key, value);
2768    }
2769    LOOPER_END
2770}
2771
2772//////////////////////////////////////////////////////////////////////////////
2773// These methods are NOT virtual, and therefore must call back into virtual
2774// methods, rather than actually drawing themselves.
2775//////////////////////////////////////////////////////////////////////////////
2776
2777void SkCanvas::drawColor(SkColor c, SkBlendMode mode) {
2778    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
2779    SkPaint paint;
2780
2781    paint.setColor(c);
2782    paint.setBlendMode(mode);
2783    this->drawPaint(paint);
2784}
2785
2786void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2787    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
2788    const SkPoint pt = { x, y };
2789    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2790}
2791
2792void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) {
2793    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
2794    SkPoint pts[2];
2795
2796    pts[0].set(x0, y0);
2797    pts[1].set(x1, y1);
2798    this->drawPoints(kLines_PointMode, 2, pts, paint);
2799}
2800
2801void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) {
2802    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
2803    if (radius < 0) {
2804        radius = 0;
2805    }
2806
2807    SkRect  r;
2808    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2809    this->drawOval(r, paint);
2810}
2811
2812void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2813                             const SkPaint& paint) {
2814    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
2815    if (rx > 0 && ry > 0) {
2816        SkRRect rrect;
2817        rrect.setRectXY(r, rx, ry);
2818        this->drawRRect(rrect, paint);
2819    } else {
2820        this->drawRect(r, paint);
2821    }
2822}
2823
2824void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2825                       SkScalar sweepAngle, bool useCenter,
2826                       const SkPaint& paint) {
2827    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2828    if (oval.isEmpty() || !sweepAngle) {
2829        return;
2830    }
2831    this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint);
2832}
2833
2834void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2835                                const SkPath& path, SkScalar hOffset,
2836                                SkScalar vOffset, const SkPaint& paint) {
2837    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
2838    SkMatrix    matrix;
2839
2840    matrix.setTranslate(hOffset, vOffset);
2841    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2842}
2843
2844///////////////////////////////////////////////////////////////////////////////
2845
2846/**
2847 *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
2848 *  against the playback cost of recursing into the subpicture to get at its actual ops.
2849 *
2850 *  For now we pick a conservatively small value, though measurement (and other heuristics like
2851 *  the type of ops contained) may justify changing this value.
2852 */
2853#define kMaxPictureOpsToUnrollInsteadOfRef  1
2854
2855void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2856    RETURN_ON_NULL(picture);
2857
2858    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
2859    if (matrix && matrix->isIdentity()) {
2860        matrix = nullptr;
2861    }
2862    if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
2863        SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2864        picture->playback(this);
2865    } else {
2866        this->onDrawPicture(picture, matrix, paint);
2867    }
2868}
2869
2870void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2871                             const SkPaint* paint) {
2872    if (!paint || paint->canComputeFastBounds()) {
2873        SkRect bounds = picture->cullRect();
2874        if (paint) {
2875            paint->computeFastBounds(bounds, &bounds);
2876        }
2877        if (matrix) {
2878            matrix->mapRect(&bounds);
2879        }
2880        if (this->quickReject(bounds)) {
2881            return;
2882        }
2883    }
2884
2885    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2886    picture->playback(this);
2887}
2888
2889#ifdef SK_EXPERIMENTAL_SHADOWING
2890void SkCanvas::drawShadowedPicture(const SkPicture* picture,
2891                                   const SkMatrix* matrix,
2892                                   const SkPaint* paint,
2893                                   const SkShadowParams& params) {
2894    RETURN_ON_NULL(picture);
2895
2896    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawShadowedPicture()");
2897
2898    this->onDrawShadowedPicture(picture, matrix, paint, params);
2899}
2900
2901void SkCanvas::onDrawShadowedPicture(const SkPicture* picture,
2902                                     const SkMatrix* matrix,
2903                                     const SkPaint* paint,
2904                                     const SkShadowParams& params) {
2905    if (!paint || paint->canComputeFastBounds()) {
2906        SkRect bounds = picture->cullRect();
2907        if (paint) {
2908            paint->computeFastBounds(bounds, &bounds);
2909        }
2910        if (matrix) {
2911            matrix->mapRect(&bounds);
2912        }
2913        if (this->quickReject(bounds)) {
2914            return;
2915        }
2916    }
2917
2918    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2919
2920    sk_sp<SkImage> povDepthMap;
2921    sk_sp<SkImage> diffuseMap;
2922
2923    // povDepthMap
2924    {
2925        SkLights::Builder builder;
2926        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
2927                                                     SkVector3::Make(0.0f, 0.0f, 1.0f)));
2928        sk_sp<SkLights> povLight = builder.finish();
2929
2930        SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(),
2931                                             picture->cullRect().height(),
2932                                             kBGRA_8888_SkColorType,
2933                                             kOpaque_SkAlphaType);
2934
2935        // Create a new surface (that matches the backend of canvas)
2936        // to create the povDepthMap
2937        sk_sp<SkSurface> surf(this->makeSurface(info));
2938
2939        // Wrap another SPFCanvas around the surface
2940        sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
2941                sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
2942
2943        // set the depth map canvas to have the light as the user's POV
2944        depthMapCanvas->setLights(std::move(povLight));
2945
2946        depthMapCanvas->drawPicture(picture);
2947        povDepthMap = surf->makeImageSnapshot();
2948    }
2949
2950    // diffuseMap
2951    {
2952        SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(),
2953                                             picture->cullRect().height(),
2954                                             kBGRA_8888_SkColorType,
2955                                             kOpaque_SkAlphaType);
2956
2957        sk_sp<SkSurface> surf(this->makeSurface(info));
2958        surf->getCanvas()->drawPicture(picture);
2959
2960        diffuseMap = surf->makeImageSnapshot();
2961    }
2962
2963    sk_sp<SkShader> povDepthShader = povDepthMap->makeShader(SkShader::kClamp_TileMode,
2964                                                             SkShader::kClamp_TileMode);
2965    sk_sp<SkShader> diffuseShader = diffuseMap->makeShader(SkShader::kClamp_TileMode,
2966                                                           SkShader::kClamp_TileMode);
2967
2968    // TODO: pass the depth to the shader in vertices, or uniforms
2969    //       so we don't have to render depth and color separately
2970    for (int i = 0; i < fLights->numLights(); ++i) {
2971        // skip over ambient lights; they don't cast shadows
2972        // lights that have shadow maps do not need updating (because lights are immutable)
2973        sk_sp<SkImage> depthMap;
2974        SkISize shMapSize;
2975
2976        if (fLights->light(i).getShadowMap() != nullptr) {
2977            continue;
2978        }
2979
2980        if (fLights->light(i).isRadial()) {
2981            shMapSize.fHeight = 1;
2982            shMapSize.fWidth = (int) picture->cullRect().width();
2983
2984            SkImageInfo info = SkImageInfo::Make(diffuseMap->width(), 1,
2985                                                 kBGRA_8888_SkColorType,
2986                                                 kOpaque_SkAlphaType);
2987
2988            // Create new surface (that matches the backend of canvas)
2989            // for each shadow map
2990            sk_sp<SkSurface> surf(this->makeSurface(info));
2991
2992            // Wrap another SPFCanvas around the surface
2993            SkCanvas* depthMapCanvas = surf->getCanvas();
2994
2995            SkLights::Builder builder;
2996            builder.add(fLights->light(i));
2997            sk_sp<SkLights> curLight = builder.finish();
2998
2999            sk_sp<SkShader> shadowMapShader;
3000            shadowMapShader = SkRadialShadowMapShader::Make(
3001                    povDepthShader, curLight,
3002                    (int) picture->cullRect().width(),
3003                    (int) picture->cullRect().height());
3004
3005            SkPaint shadowMapPaint;
3006            shadowMapPaint.setShader(std::move(shadowMapShader));
3007
3008            depthMapCanvas->setLights(curLight);
3009
3010            depthMapCanvas->drawRect(SkRect::MakeIWH(diffuseMap->width(),
3011                                                     diffuseMap->height()),
3012                                     shadowMapPaint);
3013
3014            depthMap = surf->makeImageSnapshot();
3015
3016        } else {
3017            // TODO: compute the correct size of the depth map from the light properties
3018            // TODO: maybe add a kDepth_8_SkColorType
3019            // TODO: find actual max depth of picture
3020            shMapSize = SkShadowPaintFilterCanvas::ComputeDepthMapSize(
3021                    fLights->light(i), 255,
3022                    (int) picture->cullRect().width(),
3023                    (int) picture->cullRect().height());
3024
3025            SkImageInfo info = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight,
3026                                                 kBGRA_8888_SkColorType,
3027                                                 kOpaque_SkAlphaType);
3028
3029            // Create a new surface (that matches the backend of canvas)
3030            // for each shadow map
3031            sk_sp<SkSurface> surf(this->makeSurface(info));
3032
3033            // Wrap another SPFCanvas around the surface
3034            sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
3035                    sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
3036            depthMapCanvas->setShadowParams(params);
3037
3038            // set the depth map canvas to have the light we're drawing.
3039            SkLights::Builder builder;
3040            builder.add(fLights->light(i));
3041            sk_sp<SkLights> curLight = builder.finish();
3042            depthMapCanvas->setLights(std::move(curLight));
3043
3044            depthMapCanvas->drawPicture(picture);
3045            depthMap = surf->makeImageSnapshot();
3046        }
3047
3048        if (params.fType == SkShadowParams::kNoBlur_ShadowType) {
3049            fLights->light(i).setShadowMap(std::move(depthMap));
3050        } else if (params.fType == SkShadowParams::kVariance_ShadowType) {
3051            // we blur the variance map
3052            SkPaint blurPaint;
3053            blurPaint.setImageFilter(SkImageFilter::MakeBlur(params.fShadowRadius,
3054                                                             params.fShadowRadius, nullptr));
3055
3056            SkImageInfo blurInfo = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight,
3057                                                     kBGRA_8888_SkColorType,
3058                                                     kOpaque_SkAlphaType);
3059
3060            sk_sp<SkSurface> blurSurf(this->makeSurface(blurInfo));
3061
3062            blurSurf->getCanvas()->drawImage(std::move(depthMap), 0, 0, &blurPaint);
3063
3064            fLights->light(i).setShadowMap(blurSurf->makeImageSnapshot());
3065        }
3066    }
3067
3068    SkPaint shadowPaint;
3069    sk_sp<SkShader> shadowShader = SkShadowShader::Make(std::move(povDepthShader),
3070                                                        std::move(diffuseShader),
3071                                                        fLights,
3072                                                        diffuseMap->width(),
3073                                                        diffuseMap->height(),
3074                                                        params);
3075
3076    shadowPaint.setShader(shadowShader);
3077
3078    this->drawRect(SkRect::MakeIWH(diffuseMap->width(), diffuseMap->height()), shadowPaint);
3079}
3080#endif
3081
3082///////////////////////////////////////////////////////////////////////////////
3083///////////////////////////////////////////////////////////////////////////////
3084
3085SkCanvas::LayerIter::LayerIter(SkCanvas* canvas) {
3086    static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
3087
3088    SkASSERT(canvas);
3089
3090    fImpl = new (fStorage) SkDrawIter(canvas);
3091    fDone = !fImpl->next();
3092}
3093
3094SkCanvas::LayerIter::~LayerIter() {
3095    fImpl->~SkDrawIter();
3096}
3097
3098void SkCanvas::LayerIter::next() {
3099    fDone = !fImpl->next();
3100}
3101
3102SkBaseDevice* SkCanvas::LayerIter::device() const {
3103    return fImpl->fDevice;
3104}
3105
3106const SkMatrix& SkCanvas::LayerIter::matrix() const {
3107    return fImpl->fDevice->ctm();
3108}
3109
3110const SkPaint& SkCanvas::LayerIter::paint() const {
3111    const SkPaint* paint = fImpl->getPaint();
3112    if (nullptr == paint) {
3113        paint = &fDefaultPaint;
3114    }
3115    return *paint;
3116}
3117
3118void SkCanvas::LayerIter::clip(SkRegion* rgn) const {
3119    return fImpl->fDevice->onAsRgnClip(rgn);
3120}
3121
3122int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
3123int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
3124
3125///////////////////////////////////////////////////////////////////////////////
3126
3127static bool supported_for_raster_canvas(const SkImageInfo& info) {
3128    switch (info.alphaType()) {
3129        case kPremul_SkAlphaType:
3130        case kOpaque_SkAlphaType:
3131            break;
3132        default:
3133            return false;
3134    }
3135
3136    switch (info.colorType()) {
3137        case kAlpha_8_SkColorType:
3138        case kRGB_565_SkColorType:
3139        case kN32_SkColorType:
3140        case kRGBA_F16_SkColorType:
3141            break;
3142        default:
3143            return false;
3144    }
3145
3146    return true;
3147}
3148
3149std::unique_ptr<SkCanvas> SkCanvas::MakeRasterDirect(const SkImageInfo& info, void* pixels,
3150                                                     size_t rowBytes) {
3151    if (!supported_for_raster_canvas(info)) {
3152        return nullptr;
3153    }
3154
3155    SkBitmap bitmap;
3156    if (!bitmap.installPixels(info, pixels, rowBytes)) {
3157        return nullptr;
3158    }
3159    return skstd::make_unique<SkCanvas>(bitmap);
3160}
3161
3162///////////////////////////////////////////////////////////////////////////////
3163
3164SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
3165                                                 const SkPaint* paint, const SkRect& bounds)
3166    : fCanvas(canvas)
3167    , fSaveCount(canvas->getSaveCount())
3168{
3169    if (paint) {
3170        SkRect newBounds = bounds;
3171        if (matrix) {
3172            matrix->mapRect(&newBounds);
3173        }
3174        canvas->saveLayer(&newBounds, paint);
3175    } else if (matrix) {
3176        canvas->save();
3177    }
3178
3179    if (matrix) {
3180        canvas->concat(*matrix);
3181    }
3182}
3183
3184SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
3185    fCanvas->restoreToCount(fSaveCount);
3186}
3187
3188///////////////////////////////////////////////////////////////////////////////
3189
3190SkNoDrawCanvas::SkNoDrawCanvas(int width, int height)
3191    : INHERITED(SkIRect::MakeWH(width, height), kConservativeRasterClip_InitFlag) {}
3192
3193SkNoDrawCanvas::SkNoDrawCanvas(const SkIRect& bounds)
3194    : INHERITED(bounds, kConservativeRasterClip_InitFlag) {}
3195
3196SkCanvas::SaveLayerStrategy SkNoDrawCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
3197    (void)this->INHERITED::getSaveLayerStrategy(rec);
3198    return kNoLayer_SaveLayerStrategy;
3199}
3200
3201///////////////////////////////////////////////////////////////////////////////
3202
3203static_assert((int)SkRegion::kDifference_Op         == (int)kDifference_SkClipOp, "");
3204static_assert((int)SkRegion::kIntersect_Op          == (int)kIntersect_SkClipOp, "");
3205static_assert((int)SkRegion::kUnion_Op              == (int)kUnion_SkClipOp, "");
3206static_assert((int)SkRegion::kXOR_Op                == (int)kXOR_SkClipOp, "");
3207static_assert((int)SkRegion::kReverseDifference_Op  == (int)kReverseDifference_SkClipOp, "");
3208static_assert((int)SkRegion::kReplace_Op            == (int)kReplace_SkClipOp, "");
3209
3210///////////////////////////////////////////////////////////////////////////////////////////////////
3211
3212SkRasterHandleAllocator::Handle SkCanvas::accessTopRasterHandle() const {
3213    if (fAllocator && fMCRec->fTopLayer->fDevice) {
3214        const SkBaseDevice* dev = fMCRec->fTopLayer->fDevice;
3215        SkRasterHandleAllocator::Handle handle = dev->getRasterHandle();
3216        SkIPoint origin = dev->getOrigin();
3217        SkMatrix ctm = this->getTotalMatrix();
3218        ctm.preTranslate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y()));
3219
3220        SkIRect clip = fMCRec->fRasterClip.getBounds();
3221        clip.offset(-origin.x(), -origin.y());
3222        if (!clip.intersect(0, 0, dev->width(), dev->height())) {
3223            clip.setEmpty();
3224        }
3225
3226        fAllocator->updateHandle(handle, ctm, clip);
3227        return handle;
3228    }
3229    return nullptr;
3230}
3231
3232static bool install(SkBitmap* bm, const SkImageInfo& info,
3233                    const SkRasterHandleAllocator::Rec& rec) {
3234    return bm->installPixels(info, rec.fPixels, rec.fRowBytes, nullptr,
3235                             rec.fReleaseProc, rec.fReleaseCtx);
3236}
3237
3238SkRasterHandleAllocator::Handle SkRasterHandleAllocator::allocBitmap(const SkImageInfo& info,
3239                                                                     SkBitmap* bm) {
3240    SkRasterHandleAllocator::Rec rec;
3241    if (!this->allocHandle(info, &rec) || !install(bm, info, rec)) {
3242        return nullptr;
3243    }
3244    return rec.fHandle;
3245}
3246
3247std::unique_ptr<SkCanvas>
3248SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,
3249                                    const SkImageInfo& info, const Rec* rec) {
3250    if (!alloc || !supported_for_raster_canvas(info)) {
3251        return nullptr;
3252    }
3253
3254    SkBitmap bm;
3255    Handle hndl;
3256
3257    if (rec) {
3258        hndl = install(&bm, info, *rec) ? rec->fHandle : nullptr;
3259    } else {
3260        hndl = alloc->allocBitmap(info, &bm);
3261    }
3262    return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr;
3263}
3264