SkCanvas.cpp revision 93b1b4feda10c50ce10763ddf7e807f9b85c7953
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
1576#ifdef SK_SUPPORT_OBSOLETE_REPLAYCLIP
1577void SkCanvas::replayClips(ClipVisitor* visitor) const {
1578#if 0
1579    SkClipStack::B2TIter                iter(*fClipStack);
1580    const SkClipStack::Element*         element;
1581
1582    while ((element = iter.next()) != nullptr) {
1583        element->replay(visitor);
1584    }
1585#endif
1586}
1587#endif
1588
1589bool SkCanvas::androidFramework_isClipAA() const {
1590    bool containsAA = false;
1591
1592    FOR_EACH_TOP_DEVICE(containsAA |= device->onClipIsAA());
1593
1594    return containsAA;
1595}
1596
1597class RgnAccumulator {
1598    SkRegion* fRgn;
1599public:
1600    RgnAccumulator(SkRegion* total) : fRgn(total) {}
1601    void accumulate(SkBaseDevice* device, SkRegion* rgn) {
1602        SkIPoint origin = device->getOrigin();
1603        if (origin.x() | origin.y()) {
1604            rgn->translate(origin.x(), origin.y());
1605        }
1606        fRgn->op(*rgn, SkRegion::kUnion_Op);
1607    }
1608};
1609
1610void SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
1611    RgnAccumulator accum(rgn);
1612    SkRegion tmp;
1613
1614    rgn->setEmpty();
1615    FOR_EACH_TOP_DEVICE(device->onAsRgnClip(&tmp); accum.accumulate(device, &tmp));
1616}
1617
1618///////////////////////////////////////////////////////////////////////////////
1619
1620bool SkCanvas::isClipEmpty() const {
1621    return fMCRec->fRasterClip.isEmpty();
1622
1623    // TODO: should we only use the conservative answer in a recording canvas?
1624#if 0
1625    SkBaseDevice* dev = this->getTopDevice();
1626    // if no device we return true
1627    return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
1628#endif
1629}
1630
1631bool SkCanvas::isClipRect() const {
1632    SkBaseDevice* dev = this->getTopDevice();
1633    // if no device we return false
1634    return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType;
1635}
1636
1637static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
1638#if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
1639    __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec);
1640    __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec);
1641    __m128 mask = _mm_cmplt_ps(lLtT, RrBb);
1642    return 0xF != _mm_movemask_ps(mask);
1643#elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
1644    float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0];
1645    float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1];
1646    uint32x4_t mask = vcltq_f32(lLtT, RrBb);
1647    return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask);
1648#else
1649    SkRect devRectAsRect;
1650    SkRect devClipAsRect;
1651    devRect.store(&devRectAsRect.fLeft);
1652    devClip.store(&devClipAsRect.fLeft);
1653    return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect);
1654#endif
1655}
1656
1657// It's important for this function to not be inlined.  Otherwise the compiler will share code
1658// between the fast path and the slow path, resulting in two slow paths.
1659static SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip,
1660                                                   const SkMatrix& matrix) {
1661    SkRect deviceRect;
1662    matrix.mapRect(&deviceRect, src);
1663    return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip);
1664}
1665
1666bool SkCanvas::quickReject(const SkRect& src) const {
1667#ifdef SK_DEBUG
1668    // Verify that fDeviceClipBounds are set properly.
1669    SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1670    if (fMCRec->fRasterClip.isEmpty()) {
1671        SkASSERT(fDeviceClipBounds.isEmpty());
1672    } else {
1673        SkASSERT(tmp == fDeviceClipBounds);
1674    }
1675
1676    // Verify that fIsScaleTranslate is set properly.
1677    SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1678#endif
1679
1680    if (!fIsScaleTranslate) {
1681        return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix);
1682    }
1683
1684    // We inline the implementation of mapScaleTranslate() for the fast path.
1685    float sx = fMCRec->fMatrix.getScaleX();
1686    float sy = fMCRec->fMatrix.getScaleY();
1687    float tx = fMCRec->fMatrix.getTranslateX();
1688    float ty = fMCRec->fMatrix.getTranslateY();
1689    Sk4f scale(sx, sy, sx, sy);
1690    Sk4f trans(tx, ty, tx, ty);
1691
1692    // Apply matrix.
1693    Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
1694
1695    // Make sure left < right, top < bottom.
1696    Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
1697    Sk4f min = Sk4f::Min(ltrb, rblt);
1698    Sk4f max = Sk4f::Max(ltrb, rblt);
1699    // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
1700    // ARM this sequence generates the fastest (a single instruction).
1701    Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]);
1702
1703    // Check if the device rect is NaN or outside the clip.
1704    return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft));
1705}
1706
1707bool SkCanvas::quickReject(const SkPath& path) const {
1708    return path.isEmpty() || this->quickReject(path.getBounds());
1709}
1710
1711SkRect SkCanvas::onGetLocalClipBounds() const {
1712    SkIRect ibounds = this->onGetDeviceClipBounds();
1713    if (ibounds.isEmpty()) {
1714        return SkRect::MakeEmpty();
1715    }
1716
1717    SkMatrix inverse;
1718    // if we can't invert the CTM, we can't return local clip bounds
1719    if (!fMCRec->fMatrix.invert(&inverse)) {
1720        return SkRect::MakeEmpty();
1721    }
1722
1723    SkRect bounds;
1724    SkRect r;
1725    // adjust it outwards in case we are antialiasing
1726    const int inset = 1;
1727
1728    r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1729           ibounds.fRight + inset, ibounds.fBottom + inset);
1730    inverse.mapRect(&bounds, r);
1731    return bounds;
1732}
1733
1734SkIRect SkCanvas::onGetDeviceClipBounds() const {
1735    return fMCRec->fRasterClip.getBounds();
1736}
1737
1738const SkMatrix& SkCanvas::getTotalMatrix() const {
1739    return fMCRec->fMatrix;
1740}
1741
1742GrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() {
1743    SkBaseDevice* dev = this->getTopDevice();
1744    return dev ? dev->accessRenderTargetContext() : nullptr;
1745}
1746
1747GrContext* SkCanvas::getGrContext() {
1748    SkBaseDevice* device = this->getTopDevice();
1749    return device ? device->context() : nullptr;
1750}
1751
1752void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1753                          const SkPaint& paint) {
1754    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1755    if (outer.isEmpty()) {
1756        return;
1757    }
1758    if (inner.isEmpty()) {
1759        this->drawRRect(outer, paint);
1760        return;
1761    }
1762
1763    // We don't have this method (yet), but technically this is what we should
1764    // be able to assert...
1765    // SkASSERT(outer.contains(inner));
1766    //
1767    // For now at least check for containment of bounds
1768    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1769
1770    this->onDrawDRRect(outer, inner, paint);
1771}
1772
1773// These need to stop being virtual -- clients need to override the onDraw... versions
1774
1775void SkCanvas::drawPaint(const SkPaint& paint) {
1776    this->onDrawPaint(paint);
1777}
1778
1779void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1780    this->onDrawRect(r, paint);
1781}
1782
1783void SkCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
1784    if (region.isEmpty()) {
1785        return;
1786    }
1787
1788    if (region.isRect()) {
1789        return this->drawIRect(region.getBounds(), paint);
1790    }
1791
1792    this->onDrawRegion(region, paint);
1793}
1794
1795void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
1796    this->onDrawOval(r, paint);
1797}
1798
1799void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1800    this->onDrawRRect(rrect, paint);
1801}
1802
1803void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
1804    this->onDrawPoints(mode, count, pts, paint);
1805}
1806
1807#ifdef SK_SUPPORT_LEGACY_CANVAS_VERTICES
1808void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint positions[],
1809                            const SkPoint texs[], const SkColor colors[], SkBlendMode bmode,
1810                            const uint16_t indices[], int indexCount, const SkPaint& paint) {
1811    auto vertices = SkVertices::MakeCopy(vmode, vertexCount, positions, texs, colors,
1812                                         indexCount, indices);
1813    if (vertices) {
1814        this->onDrawVerticesObject(vertices.get(), bmode, paint);
1815    }
1816}
1817#endif
1818
1819void SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode,
1820                            const SkPaint& paint) {
1821    RETURN_ON_NULL(vertices);
1822    this->onDrawVerticesObject(vertices.get(), mode, paint);
1823}
1824
1825void SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
1826    RETURN_ON_NULL(vertices);
1827    this->onDrawVerticesObject(vertices, mode, paint);
1828}
1829
1830void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1831    this->onDrawPath(path, paint);
1832}
1833
1834void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1835    RETURN_ON_NULL(image);
1836    this->onDrawImage(image, x, y, paint);
1837}
1838
1839void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1840                             const SkPaint* paint, SrcRectConstraint constraint) {
1841    RETURN_ON_NULL(image);
1842    if (dst.isEmpty() || src.isEmpty()) {
1843        return;
1844    }
1845    this->onDrawImageRect(image, &src, dst, paint, constraint);
1846}
1847
1848void SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
1849                             const SkPaint* paint, SrcRectConstraint constraint) {
1850    RETURN_ON_NULL(image);
1851    this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
1852}
1853
1854void SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1855                             SrcRectConstraint constraint) {
1856    RETURN_ON_NULL(image);
1857    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1858                        constraint);
1859}
1860
1861void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
1862                             const SkPaint* paint) {
1863    RETURN_ON_NULL(image);
1864    if (dst.isEmpty()) {
1865        return;
1866    }
1867    if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
1868        this->onDrawImageNine(image, center, dst, paint);
1869    } else {
1870        this->drawImageRect(image, dst, paint);
1871    }
1872}
1873
1874void SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
1875                                const SkPaint* paint) {
1876    RETURN_ON_NULL(image);
1877    if (dst.isEmpty()) {
1878        return;
1879    }
1880
1881    SkIRect bounds;
1882    Lattice latticePlusBounds = lattice;
1883    if (!latticePlusBounds.fBounds) {
1884        bounds = SkIRect::MakeWH(image->width(), image->height());
1885        latticePlusBounds.fBounds = &bounds;
1886    }
1887
1888    if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
1889        this->onDrawImageLattice(image, latticePlusBounds, dst, paint);
1890    } else {
1891        this->drawImageRect(image, dst, paint);
1892    }
1893}
1894
1895void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
1896    if (bitmap.drawsNothing()) {
1897        return;
1898    }
1899    this->onDrawBitmap(bitmap, dx, dy, paint);
1900}
1901
1902void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1903                              const SkPaint* paint, SrcRectConstraint constraint) {
1904    if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1905        return;
1906    }
1907    this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
1908}
1909
1910void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
1911                              const SkPaint* paint, SrcRectConstraint constraint) {
1912    this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1913}
1914
1915void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1916                              SrcRectConstraint constraint) {
1917    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1918                         constraint);
1919}
1920
1921void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
1922                              const SkPaint* paint) {
1923    if (bitmap.drawsNothing() || dst.isEmpty()) {
1924        return;
1925    }
1926    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
1927        this->onDrawBitmapNine(bitmap, center, dst, paint);
1928    } else {
1929        this->drawBitmapRect(bitmap, dst, paint);
1930    }
1931}
1932
1933void SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
1934                                 const SkPaint* paint) {
1935    if (bitmap.drawsNothing() || dst.isEmpty()) {
1936        return;
1937    }
1938
1939    SkIRect bounds;
1940    Lattice latticePlusBounds = lattice;
1941    if (!latticePlusBounds.fBounds) {
1942        bounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
1943        latticePlusBounds.fBounds = &bounds;
1944    }
1945
1946    if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) {
1947        this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, paint);
1948    } else {
1949        this->drawBitmapRect(bitmap, dst, paint);
1950    }
1951}
1952
1953void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
1954                         const SkColor colors[], int count, SkBlendMode mode,
1955                         const SkRect* cull, const SkPaint* paint) {
1956    RETURN_ON_NULL(atlas);
1957    if (count <= 0) {
1958        return;
1959    }
1960    SkASSERT(atlas);
1961    SkASSERT(tex);
1962    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
1963}
1964
1965void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
1966    if (key) {
1967        this->onDrawAnnotation(rect, key, value);
1968    }
1969}
1970
1971void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1972                                    const SkPaint* paint, SrcRectConstraint constraint) {
1973    if (src) {
1974        this->drawImageRect(image, *src, dst, paint, constraint);
1975    } else {
1976        this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
1977                            dst, paint, constraint);
1978    }
1979}
1980void SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1981                                     const SkPaint* paint, SrcRectConstraint constraint) {
1982    if (src) {
1983        this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
1984    } else {
1985        this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
1986                             dst, paint, constraint);
1987    }
1988}
1989
1990void SkCanvas::temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds) {
1991    SkIRect layer_bounds = this->getTopLayerBounds();
1992    if (matrix) {
1993        *matrix = this->getTotalMatrix();
1994        matrix->preTranslate(-layer_bounds.left(), -layer_bounds.top());
1995    }
1996    if (clip_bounds) {
1997        *clip_bounds = this->getDeviceClipBounds();
1998        clip_bounds->offset(-layer_bounds.left(), -layer_bounds.top());
1999    }
2000}
2001
2002//////////////////////////////////////////////////////////////////////////////
2003//  These are the virtual drawing methods
2004//////////////////////////////////////////////////////////////////////////////
2005
2006void SkCanvas::onDiscard() {
2007    if (fSurfaceBase) {
2008        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
2009    }
2010}
2011
2012void SkCanvas::onDrawPaint(const SkPaint& paint) {
2013    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
2014    this->internalDrawPaint(paint);
2015}
2016
2017void SkCanvas::internalDrawPaint(const SkPaint& paint) {
2018    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
2019
2020    while (iter.next()) {
2021        iter.fDevice->drawPaint(looper.paint());
2022    }
2023
2024    LOOPER_END
2025}
2026
2027void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
2028                            const SkPaint& paint) {
2029    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
2030    if ((long)count <= 0) {
2031        return;
2032    }
2033
2034    SkRect r;
2035    const SkRect* bounds = nullptr;
2036    if (paint.canComputeFastBounds()) {
2037        // special-case 2 points (common for drawing a single line)
2038        if (2 == count) {
2039            r.set(pts[0], pts[1]);
2040        } else {
2041            r.set(pts, SkToInt(count));
2042        }
2043        SkRect storage;
2044        if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
2045            return;
2046        }
2047        bounds = &r;
2048    }
2049
2050    SkASSERT(pts != nullptr);
2051
2052    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
2053
2054    while (iter.next()) {
2055        iter.fDevice->drawPoints(mode, count, pts, looper.paint());
2056    }
2057
2058    LOOPER_END
2059}
2060
2061static bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) {
2062    return ((intptr_t)paint.getImageFilter()    |
2063#ifdef SK_SUPPORT_LEGACY_DRAWFILTER
2064            (intptr_t)canvas->getDrawFilter()   |
2065#endif
2066            (intptr_t)paint.getLooper()         ) != 0;
2067}
2068
2069void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
2070    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
2071    if (paint.canComputeFastBounds()) {
2072        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
2073        // To prevent accidental rejecting at this stage, we have to sort it before we check.
2074        SkRect tmp(r);
2075        tmp.sort();
2076
2077        SkRect storage;
2078        if (this->quickReject(paint.computeFastBounds(tmp, &storage))) {
2079            return;
2080        }
2081    }
2082
2083    if (needs_autodrawlooper(this, paint)) {
2084        LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false)
2085
2086        while (iter.next()) {
2087            iter.fDevice->drawRect(r, looper.paint());
2088        }
2089
2090        LOOPER_END
2091    } else {
2092        this->predrawNotify(&r, &paint, false);
2093        SkDrawIter iter(this);
2094        while (iter.next()) {
2095            iter.fDevice->drawRect(r, paint);
2096        }
2097    }
2098}
2099
2100void SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
2101    SkRect regionRect = SkRect::Make(region.getBounds());
2102    if (paint.canComputeFastBounds()) {
2103        SkRect storage;
2104        if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) {
2105            return;
2106        }
2107    }
2108
2109    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, &regionRect)
2110
2111    while (iter.next()) {
2112        iter.fDevice->drawRegion(region, looper.paint());
2113    }
2114
2115    LOOPER_END
2116}
2117
2118void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
2119    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
2120    if (paint.canComputeFastBounds()) {
2121        SkRect storage;
2122        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2123            return;
2124        }
2125    }
2126
2127    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2128
2129    while (iter.next()) {
2130        iter.fDevice->drawOval(oval, looper.paint());
2131    }
2132
2133    LOOPER_END
2134}
2135
2136void SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle,
2137                         SkScalar sweepAngle, bool useCenter,
2138                         const SkPaint& paint) {
2139    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2140    if (paint.canComputeFastBounds()) {
2141        SkRect storage;
2142        // Note we're using the entire oval as the bounds.
2143        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2144            return;
2145        }
2146    }
2147
2148    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2149
2150    while (iter.next()) {
2151        iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint());
2152    }
2153
2154    LOOPER_END
2155}
2156
2157void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
2158    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
2159    if (paint.canComputeFastBounds()) {
2160        SkRect storage;
2161        if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
2162            return;
2163        }
2164    }
2165
2166    if (rrect.isRect()) {
2167        // call the non-virtual version
2168        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2169        return;
2170    } else if (rrect.isOval()) {
2171        // call the non-virtual version
2172        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2173        return;
2174    }
2175
2176    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds())
2177
2178    while (iter.next()) {
2179        iter.fDevice->drawRRect(rrect, looper.paint());
2180    }
2181
2182    LOOPER_END
2183}
2184
2185void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
2186    if (paint.canComputeFastBounds()) {
2187        SkRect storage;
2188        if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
2189            return;
2190        }
2191    }
2192
2193    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds())
2194
2195    while (iter.next()) {
2196        iter.fDevice->drawDRRect(outer, inner, looper.paint());
2197    }
2198
2199    LOOPER_END
2200}
2201
2202void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
2203    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
2204    if (!path.isFinite()) {
2205        return;
2206    }
2207
2208    const SkRect& pathBounds = path.getBounds();
2209    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
2210        SkRect storage;
2211        if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
2212            return;
2213        }
2214    }
2215
2216    if (pathBounds.width() <= 0 && pathBounds.height() <= 0) {
2217        if (path.isInverseFillType()) {
2218            this->internalDrawPaint(paint);
2219            return;
2220        }
2221    }
2222
2223    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
2224
2225    while (iter.next()) {
2226        iter.fDevice->drawPath(path, looper.paint());
2227    }
2228
2229    LOOPER_END
2230}
2231
2232bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2233    if (!paint.getImageFilter()) {
2234        return false;
2235    }
2236
2237    const SkMatrix& ctm = this->getTotalMatrix();
2238    if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2239        return false;
2240    }
2241
2242    // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2243    // Once we can filter and the filter will return a result larger than itself, we should be
2244    // able to remove this constraint.
2245    // skbug.com/4526
2246    //
2247    SkPoint pt;
2248    ctm.mapXY(x, y, &pt);
2249    SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2250    return ir.contains(fMCRec->fRasterClip.getBounds());
2251}
2252
2253void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
2254    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2255    SkRect bounds = SkRect::MakeXYWH(x, y,
2256                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
2257    if (nullptr == paint || paint->canComputeFastBounds()) {
2258        SkRect tmp = bounds;
2259        if (paint) {
2260            paint->computeFastBounds(tmp, &tmp);
2261        }
2262        if (this->quickReject(tmp)) {
2263            return;
2264        }
2265    }
2266
2267    SkLazyPaint lazy;
2268    if (nullptr == paint) {
2269        paint = lazy.init();
2270    }
2271
2272    sk_sp<SkSpecialImage> special;
2273    bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2274                                                    *paint);
2275    if (drawAsSprite && paint->getImageFilter()) {
2276        special = this->getDevice()->makeSpecial(image);
2277        if (!special) {
2278            drawAsSprite = false;
2279        }
2280    }
2281
2282    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2283
2284    while (iter.next()) {
2285        const SkPaint& pnt = looper.paint();
2286        if (special) {
2287            SkPoint pt;
2288            iter.fDevice->ctm().mapXY(x, y, &pt);
2289            iter.fDevice->drawSpecial(special.get(),
2290                                      SkScalarRoundToInt(pt.fX),
2291                                      SkScalarRoundToInt(pt.fY), pnt);
2292        } else {
2293            iter.fDevice->drawImage(image, x, y, pnt);
2294        }
2295    }
2296
2297    LOOPER_END
2298}
2299
2300void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2301                               const SkPaint* paint, SrcRectConstraint constraint) {
2302    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
2303    if (nullptr == paint || paint->canComputeFastBounds()) {
2304        SkRect storage = dst;
2305        if (paint) {
2306            paint->computeFastBounds(dst, &storage);
2307        }
2308        if (this->quickReject(storage)) {
2309            return;
2310        }
2311    }
2312    SkLazyPaint lazy;
2313    if (nullptr == paint) {
2314        paint = lazy.init();
2315    }
2316
2317    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2318                                          image->isOpaque())
2319
2320    while (iter.next()) {
2321        iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint);
2322    }
2323
2324    LOOPER_END
2325}
2326
2327void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
2328    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
2329    SkDEBUGCODE(bitmap.validate();)
2330
2331    if (bitmap.drawsNothing()) {
2332        return;
2333    }
2334
2335    SkLazyPaint lazy;
2336    if (nullptr == paint) {
2337        paint = lazy.init();
2338    }
2339
2340    SkRect bounds;
2341    bitmap.getBounds(&bounds);
2342    bounds.offset(x, y);
2343    bool canFastBounds = paint->canComputeFastBounds();
2344    if (canFastBounds) {
2345        SkRect storage;
2346        if (this->quickReject(paint->computeFastBounds(bounds, &storage))) {
2347            return;
2348        }
2349    }
2350
2351    sk_sp<SkSpecialImage> special;
2352    bool drawAsSprite = canFastBounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(),
2353                                                                     bitmap.height(), *paint);
2354    if (drawAsSprite && paint->getImageFilter()) {
2355        special = this->getDevice()->makeSpecial(bitmap);
2356        if (!special) {
2357            drawAsSprite = false;
2358        }
2359    }
2360
2361    const SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2362
2363    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2364
2365    while (iter.next()) {
2366        const SkPaint& pnt = looper.paint();
2367        if (special) {
2368            SkPoint pt;
2369            iter.fDevice->ctm().mapXY(x, y, &pt);
2370            iter.fDevice->drawSpecial(special.get(),
2371                                      SkScalarRoundToInt(pt.fX),
2372                                      SkScalarRoundToInt(pt.fY), pnt);
2373        } else {
2374            iter.fDevice->drawBitmap(bitmap, matrix, looper.paint());
2375        }
2376    }
2377
2378    LOOPER_END
2379}
2380
2381// this one is non-virtual, so it can be called safely by other canvas apis
2382void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2383                                      const SkRect& dst, const SkPaint* paint,
2384                                      SrcRectConstraint constraint) {
2385    if (bitmap.drawsNothing() || dst.isEmpty()) {
2386        return;
2387    }
2388
2389    if (nullptr == paint || paint->canComputeFastBounds()) {
2390        SkRect storage;
2391        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2392            return;
2393        }
2394    }
2395
2396    SkLazyPaint lazy;
2397    if (nullptr == paint) {
2398        paint = lazy.init();
2399    }
2400
2401    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2402                                          bitmap.isOpaque())
2403
2404    while (iter.next()) {
2405        iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint);
2406    }
2407
2408    LOOPER_END
2409}
2410
2411void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2412                                const SkPaint* paint, SrcRectConstraint constraint) {
2413    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
2414    SkDEBUGCODE(bitmap.validate();)
2415    this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
2416}
2417
2418void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
2419                               const SkPaint* paint) {
2420    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
2421
2422    if (nullptr == paint || paint->canComputeFastBounds()) {
2423        SkRect storage;
2424        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2425            return;
2426        }
2427    }
2428
2429    SkLazyPaint lazy;
2430    if (nullptr == paint) {
2431        paint = lazy.init();
2432    }
2433
2434    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2435
2436    while (iter.next()) {
2437        iter.fDevice->drawImageNine(image, center, dst, looper.paint());
2438    }
2439
2440    LOOPER_END
2441}
2442
2443void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
2444                                const SkPaint* paint) {
2445    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
2446    SkDEBUGCODE(bitmap.validate();)
2447
2448    if (nullptr == paint || paint->canComputeFastBounds()) {
2449        SkRect storage;
2450        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2451            return;
2452        }
2453    }
2454
2455    SkLazyPaint lazy;
2456    if (nullptr == paint) {
2457        paint = lazy.init();
2458    }
2459
2460    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2461
2462    while (iter.next()) {
2463        iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint());
2464    }
2465
2466    LOOPER_END
2467}
2468
2469void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
2470                                  const SkPaint* paint) {
2471    if (nullptr == paint || paint->canComputeFastBounds()) {
2472        SkRect storage;
2473        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2474            return;
2475        }
2476    }
2477
2478    SkLazyPaint lazy;
2479    if (nullptr == paint) {
2480        paint = lazy.init();
2481    }
2482
2483    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2484
2485    while (iter.next()) {
2486        iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint());
2487    }
2488
2489    LOOPER_END
2490}
2491
2492void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
2493                                   const SkRect& dst, const SkPaint* paint) {
2494    if (nullptr == paint || paint->canComputeFastBounds()) {
2495        SkRect storage;
2496        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2497            return;
2498        }
2499    }
2500
2501    SkLazyPaint lazy;
2502    if (nullptr == paint) {
2503        paint = lazy.init();
2504    }
2505
2506    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2507
2508    while (iter.next()) {
2509        iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint());
2510    }
2511
2512    LOOPER_END
2513}
2514
2515class SkDeviceFilteredPaint {
2516public:
2517    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2518        uint32_t filteredFlags = device->filterTextFlags(paint);
2519        if (filteredFlags != paint.getFlags()) {
2520            SkPaint* newPaint = fLazy.set(paint);
2521            newPaint->setFlags(filteredFlags);
2522            fPaint = newPaint;
2523        } else {
2524            fPaint = &paint;
2525        }
2526    }
2527
2528    const SkPaint& paint() const { return *fPaint; }
2529
2530private:
2531    const SkPaint*  fPaint;
2532    SkLazyPaint     fLazy;
2533};
2534
2535void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2536                          const SkPaint& paint) {
2537    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2538
2539    while (iter.next()) {
2540        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2541        iter.fDevice->drawText(text, byteLength, x, y, dfp.paint());
2542    }
2543
2544    LOOPER_END
2545}
2546
2547void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2548                             const SkPaint& paint) {
2549    SkPoint textOffset = SkPoint::Make(0, 0);
2550
2551    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2552
2553    while (iter.next()) {
2554        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2555        iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset,
2556                                  dfp.paint());
2557    }
2558
2559    LOOPER_END
2560}
2561
2562void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2563                              SkScalar constY, const SkPaint& paint) {
2564
2565    SkPoint textOffset = SkPoint::Make(0, constY);
2566
2567    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2568
2569    while (iter.next()) {
2570        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2571        iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset,
2572                                  dfp.paint());
2573    }
2574
2575    LOOPER_END
2576}
2577
2578void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2579                                const SkMatrix* matrix, const SkPaint& paint) {
2580    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2581
2582    while (iter.next()) {
2583        iter.fDevice->drawTextOnPath(text, byteLength, path,
2584                                     matrix, looper.paint());
2585    }
2586
2587    LOOPER_END
2588}
2589
2590void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
2591                                 const SkRect* cullRect, const SkPaint& paint) {
2592    if (cullRect && this->quickReject(*cullRect)) {
2593        return;
2594    }
2595
2596    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2597
2598    while (iter.next()) {
2599        iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint());
2600    }
2601
2602    LOOPER_END
2603}
2604
2605void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2606                              const SkPaint& paint) {
2607
2608    SkRect storage;
2609    const SkRect* bounds = nullptr;
2610    if (paint.canComputeFastBounds()) {
2611        storage = blob->bounds().makeOffset(x, y);
2612        SkRect tmp;
2613        if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
2614            return;
2615        }
2616        bounds = &storage;
2617    }
2618
2619    // We cannot filter in the looper as we normally do, because the paint is
2620    // incomplete at this point (text-related attributes are embedded within blob run paints).
2621    SkDrawFilter* drawFilter = fMCRec->fFilter;
2622    fMCRec->fFilter = nullptr;
2623
2624    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
2625
2626    while (iter.next()) {
2627        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2628        iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter);
2629    }
2630
2631    LOOPER_END
2632
2633    fMCRec->fFilter = drawFilter;
2634}
2635
2636// These will become non-virtual, so they always call the (virtual) onDraw... method
2637void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2638                        const SkPaint& paint) {
2639    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2640    if (byteLength) {
2641        this->onDrawText(text, byteLength, x, y, paint);
2642    }
2643}
2644void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2645                           const SkPaint& paint) {
2646    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2647    if (byteLength) {
2648        this->onDrawPosText(text, byteLength, pos, paint);
2649    }
2650}
2651void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2652                            SkScalar constY, const SkPaint& paint) {
2653    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2654    if (byteLength) {
2655        this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2656    }
2657}
2658void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2659                              const SkMatrix* matrix, const SkPaint& paint) {
2660    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2661    if (byteLength) {
2662        this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2663    }
2664}
2665void SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
2666                               const SkRect* cullRect, const SkPaint& paint) {
2667    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextRSXform()");
2668    if (byteLength) {
2669        this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint);
2670    }
2671}
2672void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2673                            const SkPaint& paint) {
2674    RETURN_ON_NULL(blob);
2675    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2676    this->onDrawTextBlob(blob, x, y, paint);
2677}
2678
2679void SkCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
2680                                    const SkPaint& paint) {
2681    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
2682    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2683
2684    while (iter.next()) {
2685        // In the common case of one iteration we could std::move vertices here.
2686        iter.fDevice->drawVertices(vertices, bmode, looper.paint());
2687    }
2688
2689    LOOPER_END
2690}
2691
2692void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2693                         const SkPoint texCoords[4], SkBlendMode bmode,
2694                         const SkPaint& paint) {
2695    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
2696    if (nullptr == cubics) {
2697        return;
2698    }
2699
2700    this->onDrawPatch(cubics, colors, texCoords, bmode, paint);
2701}
2702
2703void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2704                           const SkPoint texCoords[4], SkBlendMode bmode,
2705                           const SkPaint& paint) {
2706    // Since a patch is always within the convex hull of the control points, we discard it when its
2707    // bounding rectangle is completely outside the current clip.
2708    SkRect bounds;
2709    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2710    if (this->quickReject(bounds)) {
2711        return;
2712    }
2713
2714    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2715
2716    while (iter.next()) {
2717        iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, paint);
2718    }
2719
2720    LOOPER_END
2721}
2722
2723void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2724    RETURN_ON_NULL(dr);
2725    if (x || y) {
2726        SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2727        this->onDrawDrawable(dr, &matrix);
2728    } else {
2729        this->onDrawDrawable(dr, nullptr);
2730    }
2731}
2732
2733void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2734    RETURN_ON_NULL(dr);
2735    if (matrix && matrix->isIdentity()) {
2736        matrix = nullptr;
2737    }
2738    this->onDrawDrawable(dr, matrix);
2739}
2740
2741void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2742    // drawable bounds are no longer reliable (e.g. android displaylist)
2743    // so don't use them for quick-reject
2744    dr->draw(this, matrix);
2745}
2746
2747void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2748                           const SkColor colors[], int count, SkBlendMode bmode,
2749                           const SkRect* cull, const SkPaint* paint) {
2750    if (cull && this->quickReject(*cull)) {
2751        return;
2752    }
2753
2754    SkPaint pnt;
2755    if (paint) {
2756        pnt = *paint;
2757    }
2758
2759    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
2760    while (iter.next()) {
2761        iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt);
2762    }
2763    LOOPER_END
2764}
2765
2766void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2767    SkASSERT(key);
2768
2769    SkPaint paint;
2770    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
2771    while (iter.next()) {
2772        iter.fDevice->drawAnnotation(rect, key, value);
2773    }
2774    LOOPER_END
2775}
2776
2777//////////////////////////////////////////////////////////////////////////////
2778// These methods are NOT virtual, and therefore must call back into virtual
2779// methods, rather than actually drawing themselves.
2780//////////////////////////////////////////////////////////////////////////////
2781
2782void SkCanvas::drawColor(SkColor c, SkBlendMode mode) {
2783    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
2784    SkPaint paint;
2785
2786    paint.setColor(c);
2787    paint.setBlendMode(mode);
2788    this->drawPaint(paint);
2789}
2790
2791void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2792    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
2793    const SkPoint pt = { x, y };
2794    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2795}
2796
2797void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) {
2798    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
2799    SkPoint pts[2];
2800
2801    pts[0].set(x0, y0);
2802    pts[1].set(x1, y1);
2803    this->drawPoints(kLines_PointMode, 2, pts, paint);
2804}
2805
2806void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) {
2807    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
2808    if (radius < 0) {
2809        radius = 0;
2810    }
2811
2812    SkRect  r;
2813    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2814    this->drawOval(r, paint);
2815}
2816
2817void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2818                             const SkPaint& paint) {
2819    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
2820    if (rx > 0 && ry > 0) {
2821        SkRRect rrect;
2822        rrect.setRectXY(r, rx, ry);
2823        this->drawRRect(rrect, paint);
2824    } else {
2825        this->drawRect(r, paint);
2826    }
2827}
2828
2829void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2830                       SkScalar sweepAngle, bool useCenter,
2831                       const SkPaint& paint) {
2832    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2833    if (oval.isEmpty() || !sweepAngle) {
2834        return;
2835    }
2836    this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint);
2837}
2838
2839void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2840                                const SkPath& path, SkScalar hOffset,
2841                                SkScalar vOffset, const SkPaint& paint) {
2842    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
2843    SkMatrix    matrix;
2844
2845    matrix.setTranslate(hOffset, vOffset);
2846    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2847}
2848
2849///////////////////////////////////////////////////////////////////////////////
2850
2851/**
2852 *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
2853 *  against the playback cost of recursing into the subpicture to get at its actual ops.
2854 *
2855 *  For now we pick a conservatively small value, though measurement (and other heuristics like
2856 *  the type of ops contained) may justify changing this value.
2857 */
2858#define kMaxPictureOpsToUnrollInsteadOfRef  1
2859
2860void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2861    RETURN_ON_NULL(picture);
2862
2863    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
2864    if (matrix && matrix->isIdentity()) {
2865        matrix = nullptr;
2866    }
2867    if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
2868        SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2869        picture->playback(this);
2870    } else {
2871        this->onDrawPicture(picture, matrix, paint);
2872    }
2873}
2874
2875void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2876                             const SkPaint* paint) {
2877    if (!paint || paint->canComputeFastBounds()) {
2878        SkRect bounds = picture->cullRect();
2879        if (paint) {
2880            paint->computeFastBounds(bounds, &bounds);
2881        }
2882        if (matrix) {
2883            matrix->mapRect(&bounds);
2884        }
2885        if (this->quickReject(bounds)) {
2886            return;
2887        }
2888    }
2889
2890    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2891    picture->playback(this);
2892}
2893
2894#ifdef SK_EXPERIMENTAL_SHADOWING
2895void SkCanvas::drawShadowedPicture(const SkPicture* picture,
2896                                   const SkMatrix* matrix,
2897                                   const SkPaint* paint,
2898                                   const SkShadowParams& params) {
2899    RETURN_ON_NULL(picture);
2900
2901    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawShadowedPicture()");
2902
2903    this->onDrawShadowedPicture(picture, matrix, paint, params);
2904}
2905
2906void SkCanvas::onDrawShadowedPicture(const SkPicture* picture,
2907                                     const SkMatrix* matrix,
2908                                     const SkPaint* paint,
2909                                     const SkShadowParams& params) {
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
2925    sk_sp<SkImage> povDepthMap;
2926    sk_sp<SkImage> diffuseMap;
2927
2928    // povDepthMap
2929    {
2930        SkLights::Builder builder;
2931        builder.add(SkLights::Light::MakeDirectional(SkColor3f::Make(1.0f, 1.0f, 1.0f),
2932                                                     SkVector3::Make(0.0f, 0.0f, 1.0f)));
2933        sk_sp<SkLights> povLight = builder.finish();
2934
2935        SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(),
2936                                             picture->cullRect().height(),
2937                                             kBGRA_8888_SkColorType,
2938                                             kOpaque_SkAlphaType);
2939
2940        // Create a new surface (that matches the backend of canvas)
2941        // to create the povDepthMap
2942        sk_sp<SkSurface> surf(this->makeSurface(info));
2943
2944        // Wrap another SPFCanvas around the surface
2945        sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
2946                sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
2947
2948        // set the depth map canvas to have the light as the user's POV
2949        depthMapCanvas->setLights(std::move(povLight));
2950
2951        depthMapCanvas->drawPicture(picture);
2952        povDepthMap = surf->makeImageSnapshot();
2953    }
2954
2955    // diffuseMap
2956    {
2957        SkImageInfo info = SkImageInfo::Make(picture->cullRect().width(),
2958                                             picture->cullRect().height(),
2959                                             kBGRA_8888_SkColorType,
2960                                             kOpaque_SkAlphaType);
2961
2962        sk_sp<SkSurface> surf(this->makeSurface(info));
2963        surf->getCanvas()->drawPicture(picture);
2964
2965        diffuseMap = surf->makeImageSnapshot();
2966    }
2967
2968    sk_sp<SkShader> povDepthShader = povDepthMap->makeShader(SkShader::kClamp_TileMode,
2969                                                             SkShader::kClamp_TileMode);
2970    sk_sp<SkShader> diffuseShader = diffuseMap->makeShader(SkShader::kClamp_TileMode,
2971                                                           SkShader::kClamp_TileMode);
2972
2973    // TODO: pass the depth to the shader in vertices, or uniforms
2974    //       so we don't have to render depth and color separately
2975    for (int i = 0; i < fLights->numLights(); ++i) {
2976        // skip over ambient lights; they don't cast shadows
2977        // lights that have shadow maps do not need updating (because lights are immutable)
2978        sk_sp<SkImage> depthMap;
2979        SkISize shMapSize;
2980
2981        if (fLights->light(i).getShadowMap() != nullptr) {
2982            continue;
2983        }
2984
2985        if (fLights->light(i).isRadial()) {
2986            shMapSize.fHeight = 1;
2987            shMapSize.fWidth = (int) picture->cullRect().width();
2988
2989            SkImageInfo info = SkImageInfo::Make(diffuseMap->width(), 1,
2990                                                 kBGRA_8888_SkColorType,
2991                                                 kOpaque_SkAlphaType);
2992
2993            // Create new surface (that matches the backend of canvas)
2994            // for each shadow map
2995            sk_sp<SkSurface> surf(this->makeSurface(info));
2996
2997            // Wrap another SPFCanvas around the surface
2998            SkCanvas* depthMapCanvas = surf->getCanvas();
2999
3000            SkLights::Builder builder;
3001            builder.add(fLights->light(i));
3002            sk_sp<SkLights> curLight = builder.finish();
3003
3004            sk_sp<SkShader> shadowMapShader;
3005            shadowMapShader = SkRadialShadowMapShader::Make(
3006                    povDepthShader, curLight,
3007                    (int) picture->cullRect().width(),
3008                    (int) picture->cullRect().height());
3009
3010            SkPaint shadowMapPaint;
3011            shadowMapPaint.setShader(std::move(shadowMapShader));
3012
3013            depthMapCanvas->setLights(curLight);
3014
3015            depthMapCanvas->drawRect(SkRect::MakeIWH(diffuseMap->width(),
3016                                                     diffuseMap->height()),
3017                                     shadowMapPaint);
3018
3019            depthMap = surf->makeImageSnapshot();
3020
3021        } else {
3022            // TODO: compute the correct size of the depth map from the light properties
3023            // TODO: maybe add a kDepth_8_SkColorType
3024            // TODO: find actual max depth of picture
3025            shMapSize = SkShadowPaintFilterCanvas::ComputeDepthMapSize(
3026                    fLights->light(i), 255,
3027                    (int) picture->cullRect().width(),
3028                    (int) picture->cullRect().height());
3029
3030            SkImageInfo info = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight,
3031                                                 kBGRA_8888_SkColorType,
3032                                                 kOpaque_SkAlphaType);
3033
3034            // Create a new surface (that matches the backend of canvas)
3035            // for each shadow map
3036            sk_sp<SkSurface> surf(this->makeSurface(info));
3037
3038            // Wrap another SPFCanvas around the surface
3039            sk_sp<SkShadowPaintFilterCanvas> depthMapCanvas =
3040                    sk_make_sp<SkShadowPaintFilterCanvas>(surf->getCanvas());
3041            depthMapCanvas->setShadowParams(params);
3042
3043            // set the depth map canvas to have the light we're drawing.
3044            SkLights::Builder builder;
3045            builder.add(fLights->light(i));
3046            sk_sp<SkLights> curLight = builder.finish();
3047            depthMapCanvas->setLights(std::move(curLight));
3048
3049            depthMapCanvas->drawPicture(picture);
3050            depthMap = surf->makeImageSnapshot();
3051        }
3052
3053        if (params.fType == SkShadowParams::kNoBlur_ShadowType) {
3054            fLights->light(i).setShadowMap(std::move(depthMap));
3055        } else if (params.fType == SkShadowParams::kVariance_ShadowType) {
3056            // we blur the variance map
3057            SkPaint blurPaint;
3058            blurPaint.setImageFilter(SkImageFilter::MakeBlur(params.fShadowRadius,
3059                                                             params.fShadowRadius, nullptr));
3060
3061            SkImageInfo blurInfo = SkImageInfo::Make(shMapSize.fWidth, shMapSize.fHeight,
3062                                                     kBGRA_8888_SkColorType,
3063                                                     kOpaque_SkAlphaType);
3064
3065            sk_sp<SkSurface> blurSurf(this->makeSurface(blurInfo));
3066
3067            blurSurf->getCanvas()->drawImage(std::move(depthMap), 0, 0, &blurPaint);
3068
3069            fLights->light(i).setShadowMap(blurSurf->makeImageSnapshot());
3070        }
3071    }
3072
3073    SkPaint shadowPaint;
3074    sk_sp<SkShader> shadowShader = SkShadowShader::Make(std::move(povDepthShader),
3075                                                        std::move(diffuseShader),
3076                                                        fLights,
3077                                                        diffuseMap->width(),
3078                                                        diffuseMap->height(),
3079                                                        params);
3080
3081    shadowPaint.setShader(shadowShader);
3082
3083    this->drawRect(SkRect::MakeIWH(diffuseMap->width(), diffuseMap->height()), shadowPaint);
3084}
3085#endif
3086
3087///////////////////////////////////////////////////////////////////////////////
3088///////////////////////////////////////////////////////////////////////////////
3089
3090SkCanvas::LayerIter::LayerIter(SkCanvas* canvas) {
3091    static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
3092
3093    SkASSERT(canvas);
3094
3095    fImpl = new (fStorage) SkDrawIter(canvas);
3096    fDone = !fImpl->next();
3097}
3098
3099SkCanvas::LayerIter::~LayerIter() {
3100    fImpl->~SkDrawIter();
3101}
3102
3103void SkCanvas::LayerIter::next() {
3104    fDone = !fImpl->next();
3105}
3106
3107SkBaseDevice* SkCanvas::LayerIter::device() const {
3108    return fImpl->fDevice;
3109}
3110
3111const SkMatrix& SkCanvas::LayerIter::matrix() const {
3112    return fImpl->fDevice->ctm();
3113}
3114
3115const SkPaint& SkCanvas::LayerIter::paint() const {
3116    const SkPaint* paint = fImpl->getPaint();
3117    if (nullptr == paint) {
3118        paint = &fDefaultPaint;
3119    }
3120    return *paint;
3121}
3122
3123void SkCanvas::LayerIter::clip(SkRegion* rgn) const {
3124    return fImpl->fDevice->onAsRgnClip(rgn);
3125}
3126
3127int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
3128int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
3129
3130///////////////////////////////////////////////////////////////////////////////
3131
3132#ifdef SK_SUPPORT_OBSOLETE_REPLAYCLIP
3133SkCanvasClipVisitor::~SkCanvasClipVisitor() { }
3134#endif
3135
3136///////////////////////////////////////////////////////////////////////////////
3137
3138static bool supported_for_raster_canvas(const SkImageInfo& info) {
3139    switch (info.alphaType()) {
3140        case kPremul_SkAlphaType:
3141        case kOpaque_SkAlphaType:
3142            break;
3143        default:
3144            return false;
3145    }
3146
3147    switch (info.colorType()) {
3148        case kAlpha_8_SkColorType:
3149        case kRGB_565_SkColorType:
3150        case kN32_SkColorType:
3151        case kRGBA_F16_SkColorType:
3152            break;
3153        default:
3154            return false;
3155    }
3156
3157    return true;
3158}
3159
3160std::unique_ptr<SkCanvas> SkCanvas::MakeRasterDirect(const SkImageInfo& info, void* pixels,
3161                                                     size_t rowBytes) {
3162    if (!supported_for_raster_canvas(info)) {
3163        return nullptr;
3164    }
3165
3166    SkBitmap bitmap;
3167    if (!bitmap.installPixels(info, pixels, rowBytes)) {
3168        return nullptr;
3169    }
3170    return skstd::make_unique<SkCanvas>(bitmap);
3171}
3172
3173///////////////////////////////////////////////////////////////////////////////
3174
3175SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
3176                                                 const SkPaint* paint, const SkRect& bounds)
3177    : fCanvas(canvas)
3178    , fSaveCount(canvas->getSaveCount())
3179{
3180    if (paint) {
3181        SkRect newBounds = bounds;
3182        if (matrix) {
3183            matrix->mapRect(&newBounds);
3184        }
3185        canvas->saveLayer(&newBounds, paint);
3186    } else if (matrix) {
3187        canvas->save();
3188    }
3189
3190    if (matrix) {
3191        canvas->concat(*matrix);
3192    }
3193}
3194
3195SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
3196    fCanvas->restoreToCount(fSaveCount);
3197}
3198
3199///////////////////////////////////////////////////////////////////////////////
3200
3201SkNoDrawCanvas::SkNoDrawCanvas(int width, int height)
3202    : INHERITED(SkIRect::MakeWH(width, height), kConservativeRasterClip_InitFlag) {}
3203
3204SkNoDrawCanvas::SkNoDrawCanvas(const SkIRect& bounds)
3205    : INHERITED(bounds, kConservativeRasterClip_InitFlag) {}
3206
3207SkCanvas::SaveLayerStrategy SkNoDrawCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
3208    (void)this->INHERITED::getSaveLayerStrategy(rec);
3209    return kNoLayer_SaveLayerStrategy;
3210}
3211
3212///////////////////////////////////////////////////////////////////////////////
3213
3214static_assert((int)SkRegion::kDifference_Op         == (int)kDifference_SkClipOp, "");
3215static_assert((int)SkRegion::kIntersect_Op          == (int)kIntersect_SkClipOp, "");
3216static_assert((int)SkRegion::kUnion_Op              == (int)kUnion_SkClipOp, "");
3217static_assert((int)SkRegion::kXOR_Op                == (int)kXOR_SkClipOp, "");
3218static_assert((int)SkRegion::kReverseDifference_Op  == (int)kReverseDifference_SkClipOp, "");
3219static_assert((int)SkRegion::kReplace_Op            == (int)kReplace_SkClipOp, "");
3220
3221///////////////////////////////////////////////////////////////////////////////////////////////////
3222
3223SkRasterHandleAllocator::Handle SkCanvas::accessTopRasterHandle() const {
3224    if (fAllocator && fMCRec->fTopLayer->fDevice) {
3225        const SkBaseDevice* dev = fMCRec->fTopLayer->fDevice;
3226        SkRasterHandleAllocator::Handle handle = dev->getRasterHandle();
3227        SkIPoint origin = dev->getOrigin();
3228        SkMatrix ctm = this->getTotalMatrix();
3229        ctm.preTranslate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y()));
3230
3231        SkIRect clip = fMCRec->fRasterClip.getBounds();
3232        clip.offset(-origin.x(), -origin.y());
3233        if (!clip.intersect(0, 0, dev->width(), dev->height())) {
3234            clip.setEmpty();
3235        }
3236
3237        fAllocator->updateHandle(handle, ctm, clip);
3238        return handle;
3239    }
3240    return nullptr;
3241}
3242
3243static bool install(SkBitmap* bm, const SkImageInfo& info,
3244                    const SkRasterHandleAllocator::Rec& rec) {
3245    return bm->installPixels(info, rec.fPixels, rec.fRowBytes, nullptr,
3246                             rec.fReleaseProc, rec.fReleaseCtx);
3247}
3248
3249SkRasterHandleAllocator::Handle SkRasterHandleAllocator::allocBitmap(const SkImageInfo& info,
3250                                                                     SkBitmap* bm) {
3251    SkRasterHandleAllocator::Rec rec;
3252    if (!this->allocHandle(info, &rec) || !install(bm, info, rec)) {
3253        return nullptr;
3254    }
3255    return rec.fHandle;
3256}
3257
3258std::unique_ptr<SkCanvas>
3259SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,
3260                                    const SkImageInfo& info, const Rec* rec) {
3261    if (!alloc || !supported_for_raster_canvas(info)) {
3262        return nullptr;
3263    }
3264
3265    SkBitmap bm;
3266    Handle hndl;
3267
3268    if (rec) {
3269        hndl = install(&bm, info, *rec) ? rec->fHandle : nullptr;
3270    } else {
3271        hndl = alloc->allocBitmap(info, &bm);
3272    }
3273    return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr;
3274}
3275