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