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