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