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