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