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