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