SkCanvas.cpp revision 54d60293cecb384de5683d9bea925c97f6ed485b
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::getTopLayerSize() const {
816    SkBaseDevice* d = this->getTopDevice();
817    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
818}
819
820SkIPoint SkCanvas::getTopLayerOrigin() const {
821    SkBaseDevice* d = this->getTopDevice();
822    return d ? d->getOrigin() : SkIPoint::Make(0, 0);
823}
824
825SkISize SkCanvas::getBaseLayerSize() const {
826    SkBaseDevice* d = this->getDevice();
827    return d ? SkISize::Make(d->width(), d->height()) : SkISize::Make(0, 0);
828}
829
830SkBaseDevice* SkCanvas::getDevice() const {
831    // return root device
832    MCRec* rec = (MCRec*) fMCStack.front();
833    SkASSERT(rec && rec->fLayer);
834    return rec->fLayer->fDevice;
835}
836
837SkBaseDevice* SkCanvas::getTopDevice(bool updateMatrixClip) const {
838    if (updateMatrixClip) {
839        const_cast<SkCanvas*>(this)->updateDeviceCMCache();
840    }
841    return fMCRec->fTopLayer->fDevice;
842}
843
844bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
845    if (kUnknown_SkColorType == bitmap->colorType() || bitmap->getTexture()) {
846        return false;
847    }
848
849    bool weAllocated = false;
850    if (nullptr == bitmap->pixelRef()) {
851        if (!bitmap->tryAllocPixels()) {
852            return false;
853        }
854        weAllocated = true;
855    }
856
857    SkAutoPixmapUnlock unlocker;
858    if (bitmap->requestLock(&unlocker)) {
859        const SkPixmap& pm = unlocker.pixmap();
860        if (this->readPixels(pm.info(), pm.writable_addr(), pm.rowBytes(), x, y)) {
861            return true;
862        }
863    }
864
865    if (weAllocated) {
866        bitmap->setPixelRef(nullptr);
867    }
868    return false;
869}
870
871bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
872    SkIRect r = srcRect;
873    const SkISize size = this->getBaseLayerSize();
874    if (!r.intersect(0, 0, size.width(), size.height())) {
875        bitmap->reset();
876        return false;
877    }
878
879    if (!bitmap->tryAllocN32Pixels(r.width(), r.height())) {
880        // bitmap will already be reset.
881        return false;
882    }
883    if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), r.x(), r.y())) {
884        bitmap->reset();
885        return false;
886    }
887    return true;
888}
889
890bool SkCanvas::readPixels(const SkImageInfo& dstInfo, void* dstP, size_t rowBytes, int x, int y) {
891    SkBaseDevice* device = this->getDevice();
892    if (!device) {
893        return false;
894    }
895    const SkISize size = this->getBaseLayerSize();
896
897    SkReadPixelsRec rec(dstInfo, dstP, rowBytes, x, y);
898    if (!rec.trim(size.width(), size.height())) {
899        return false;
900    }
901
902    // The device can assert that the requested area is always contained in its bounds
903    return device->readPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, rec.fX, rec.fY);
904}
905
906bool SkCanvas::writePixels(const SkBitmap& bitmap, int x, int y) {
907    if (bitmap.getTexture()) {
908        return false;
909    }
910
911    SkAutoPixmapUnlock unlocker;
912    if (bitmap.requestLock(&unlocker)) {
913        const SkPixmap& pm = unlocker.pixmap();
914        return this->writePixels(pm.info(), pm.addr(), pm.rowBytes(), x, y);
915    }
916    return false;
917}
918
919bool SkCanvas::writePixels(const SkImageInfo& origInfo, const void* pixels, size_t rowBytes,
920                           int x, int y) {
921    switch (origInfo.colorType()) {
922        case kUnknown_SkColorType:
923        case kIndex_8_SkColorType:
924            return false;
925        default:
926            break;
927    }
928    if (nullptr == pixels || rowBytes < origInfo.minRowBytes()) {
929        return false;
930    }
931
932    const SkISize size = this->getBaseLayerSize();
933    SkIRect target = SkIRect::MakeXYWH(x, y, origInfo.width(), origInfo.height());
934    if (!target.intersect(0, 0, size.width(), size.height())) {
935        return false;
936    }
937
938    SkBaseDevice* device = this->getDevice();
939    if (!device) {
940        return false;
941    }
942
943    // the intersect may have shrunk info's logical size
944    const SkImageInfo info = origInfo.makeWH(target.width(), target.height());
945
946    // if x or y are negative, then we have to adjust pixels
947    if (x > 0) {
948        x = 0;
949    }
950    if (y > 0) {
951        y = 0;
952    }
953    // here x,y are either 0 or negative
954    pixels = ((const char*)pixels - y * rowBytes - x * info.bytesPerPixel());
955
956    // Tell our owning surface to bump its generation ID
957    const bool completeOverwrite = info.dimensions() == size;
958    this->predrawNotify(completeOverwrite);
959
960    // The device can assert that the requested area is always contained in its bounds
961    return device->writePixels(info, pixels, rowBytes, target.x(), target.y());
962}
963
964SkCanvas* SkCanvas::canvasForDrawIter() {
965    return this;
966}
967
968//////////////////////////////////////////////////////////////////////////////
969
970void SkCanvas::updateDeviceCMCache() {
971    if (fDeviceCMDirty) {
972        const SkMatrix& totalMatrix = this->getTotalMatrix();
973        const SkRasterClip& totalClip = fMCRec->fRasterClip;
974        DeviceCM*       layer = fMCRec->fTopLayer;
975
976        if (nullptr == layer->fNext) {   // only one layer
977            layer->updateMC(totalMatrix, totalClip, *fClipStack, nullptr);
978        } else {
979            SkRasterClip clip(totalClip);
980            do {
981                layer->updateMC(totalMatrix, clip, *fClipStack, &clip);
982            } while ((layer = layer->fNext) != nullptr);
983        }
984        fDeviceCMDirty = false;
985    }
986}
987
988///////////////////////////////////////////////////////////////////////////////
989
990void SkCanvas::checkForDeferredSave() {
991    if (fMCRec->fDeferredSaveCount > 0) {
992        this->doSave();
993    }
994}
995
996int SkCanvas::getSaveCount() const {
997#ifdef SK_DEBUG
998    int count = 0;
999    SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
1000    for (;;) {
1001        const MCRec* rec = (const MCRec*)iter.next();
1002        if (!rec) {
1003            break;
1004        }
1005        count += 1 + rec->fDeferredSaveCount;
1006    }
1007    SkASSERT(count == fSaveCount);
1008#endif
1009    return fSaveCount;
1010}
1011
1012int SkCanvas::save() {
1013    fSaveCount += 1;
1014    fMCRec->fDeferredSaveCount += 1;
1015    return this->getSaveCount() - 1;  // return our prev value
1016}
1017
1018void SkCanvas::doSave() {
1019    this->willSave();
1020
1021    SkASSERT(fMCRec->fDeferredSaveCount > 0);
1022    fMCRec->fDeferredSaveCount -= 1;
1023    this->internalSave();
1024}
1025
1026void SkCanvas::restore() {
1027    if (fMCRec->fDeferredSaveCount > 0) {
1028        SkASSERT(fSaveCount > 1);
1029        fSaveCount -= 1;
1030        fMCRec->fDeferredSaveCount -= 1;
1031    } else {
1032        // check for underflow
1033        if (fMCStack.count() > 1) {
1034            this->willRestore();
1035            SkASSERT(fSaveCount > 1);
1036            fSaveCount -= 1;
1037            this->internalRestore();
1038            this->didRestore();
1039        }
1040    }
1041}
1042
1043void SkCanvas::restoreToCount(int count) {
1044    // sanity check
1045    if (count < 1) {
1046        count = 1;
1047    }
1048
1049    int n = this->getSaveCount() - count;
1050    for (int i = 0; i < n; ++i) {
1051        this->restore();
1052    }
1053}
1054
1055void SkCanvas::internalSave() {
1056    MCRec* newTop = (MCRec*)fMCStack.push_back();
1057    new (newTop) MCRec(*fMCRec);    // balanced in restore()
1058    fMCRec = newTop;
1059
1060    fClipStack->save();
1061}
1062
1063bool SkCanvas::BoundsAffectsClip(SaveLayerFlags saveLayerFlags) {
1064#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
1065    return !(saveLayerFlags & SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag);
1066#else
1067    return true;
1068#endif
1069}
1070
1071bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlags,
1072                              SkIRect* intersection, const SkImageFilter* imageFilter) {
1073    SkIRect clipBounds;
1074    if (!this->getClipDeviceBounds(&clipBounds)) {
1075        return false;
1076    }
1077
1078    const SkMatrix& ctm = fMCRec->fMatrix;  // this->getTotalMatrix()
1079
1080    if (imageFilter) {
1081        imageFilter->filterBounds(clipBounds, ctm, &clipBounds);
1082        if (bounds && !imageFilter->canComputeFastBounds()) {
1083            bounds = nullptr;
1084        }
1085    }
1086    SkIRect ir;
1087    if (bounds) {
1088        SkRect r;
1089
1090        ctm.mapRect(&r, *bounds);
1091        r.roundOut(&ir);
1092        // early exit if the layer's bounds are clipped out
1093        if (!ir.intersect(clipBounds)) {
1094            if (BoundsAffectsClip(saveLayerFlags)) {
1095                fCachedLocalClipBoundsDirty = true;
1096                fMCRec->fRasterClip.setEmpty();
1097            }
1098            return false;
1099        }
1100    } else {    // no user bounds, so just use the clip
1101        ir = clipBounds;
1102    }
1103    SkASSERT(!ir.isEmpty());
1104
1105    if (BoundsAffectsClip(saveLayerFlags)) {
1106        // Simplify the current clips since they will be applied properly during restore()
1107        fCachedLocalClipBoundsDirty = true;
1108        fClipStack->clipDevRect(ir, SkRegion::kReplace_Op);
1109        fMCRec->fRasterClip.setRect(ir);
1110    }
1111
1112    if (intersection) {
1113        *intersection = ir;
1114    }
1115    return true;
1116}
1117
1118
1119int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
1120    return this->saveLayer(SaveLayerRec(bounds, paint, 0));
1121}
1122
1123int SkCanvas::saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint) {
1124    return this->saveLayer(SaveLayerRec(bounds, paint, kPreserveLCDText_SaveLayerFlag));
1125}
1126
1127int SkCanvas::saveLayer(const SaveLayerRec& origRec) {
1128    SaveLayerRec rec(origRec);
1129    if (gIgnoreSaveLayerBounds) {
1130        rec.fBounds = nullptr;
1131    }
1132    SaveLayerStrategy strategy = this->getSaveLayerStrategy(rec);
1133    fSaveCount += 1;
1134    this->internalSaveLayer(rec, strategy);
1135    return this->getSaveCount() - 1;
1136}
1137
1138static void draw_filter_into_device(SkBaseDevice* src, const SkImageFilter* filter,
1139                                    SkBaseDevice* dst, const SkMatrix& ctm) {
1140
1141    SkBitmap srcBM;
1142
1143#if SK_SUPPORT_GPU
1144    GrRenderTarget* srcRT = src->accessRenderTarget();
1145    if (srcRT && !srcRT->asTexture() && dst->accessRenderTarget()) {
1146        // When both the src & the dst are on the gpu but the src doesn't have a texture,
1147        // we create a temporary texture for the draw.
1148        // TODO: we should actually only copy the portion of the source needed to apply the image
1149        // filter
1150        GrContext* context = srcRT->getContext();
1151        SkAutoTUnref<GrTexture> tex(context->textureProvider()->createTexture(srcRT->desc(), true));
1152
1153        context->copySurface(tex, srcRT);
1154
1155        GrWrapTextureInBitmap(tex, src->width(), src->height(), src->isOpaque(), &srcBM);
1156    } else
1157#endif
1158    {
1159        srcBM = src->accessBitmap(false);
1160    }
1161
1162    SkCanvas c(dst);
1163
1164    SkAutoTUnref<SkImageFilter> localF(filter->newWithLocalMatrix(ctm));
1165    SkPaint p;
1166    p.setImageFilter(localF);
1167    const SkScalar x = SkIntToScalar(src->getOrigin().x());
1168    const SkScalar y = SkIntToScalar(src->getOrigin().y());
1169    c.drawBitmap(srcBM, x, y, &p);
1170}
1171
1172void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
1173    const SkRect* bounds = rec.fBounds;
1174    const SkPaint* paint = rec.fPaint;
1175    SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
1176
1177#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
1178    saveLayerFlags &= ~kDontClipToLayer_PrivateSaveLayerFlag;
1179#endif
1180
1181    // do this before we create the layer. We don't call the public save() since
1182    // that would invoke a possibly overridden virtual
1183    this->internalSave();
1184
1185    fDeviceCMDirty = true;
1186
1187    SkIRect ir;
1188    if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, paint ? paint->getImageFilter() : nullptr)) {
1189        return;
1190    }
1191
1192    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1193    // the clipRectBounds() call above?
1194    if (kNoLayer_SaveLayerStrategy == strategy) {
1195        return;
1196    }
1197
1198    bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag);
1199    SkPixelGeometry geo = fProps.pixelGeometry();
1200    if (paint) {
1201        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1202        if (paint->getImageFilter() || paint->getColorFilter()) {
1203            isOpaque = false;
1204            geo = kUnknown_SkPixelGeometry;
1205        }
1206    }
1207    SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(),
1208                        isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
1209
1210    SkBaseDevice* device = this->getTopDevice();
1211    if (nullptr == device) {
1212        SkDebugf("Unable to find device for layer.");
1213        return;
1214    }
1215
1216    bool forceSpriteOnRestore = false;
1217    {
1218        const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
1219                                     (saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
1220        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
1221        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
1222                                                                            preserveLCDText, false);
1223        SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint);
1224        if (nullptr == newDev) {
1225            // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint)
1226            const SkSurfaceProps surfaceProps(fProps.flags(), createInfo.fPixelGeometry);
1227            newDev = SkBitmapDevice::Create(createInfo.fInfo, surfaceProps);
1228            if (nullptr == newDev) {
1229                SkErrorInternals::SetError(kInternalError_SkError,
1230                                           "Unable to create device for layer.");
1231                return;
1232            }
1233            forceSpriteOnRestore = true;
1234        }
1235        device = newDev;
1236    }
1237    device->setOrigin(ir.fLeft, ir.fTop);
1238
1239    if (rec.fBackdrop) {
1240        draw_filter_into_device(fMCRec->fTopLayer->fDevice, rec.fBackdrop, device, fMCRec->fMatrix);
1241    }
1242
1243    DeviceCM* layer =
1244            new DeviceCM(device, paint, this, fConservativeRasterClip, forceSpriteOnRestore);
1245    device->unref();
1246
1247    layer->fNext = fMCRec->fTopLayer;
1248    fMCRec->fLayer = layer;
1249    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
1250}
1251
1252int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1253    if (0xFF == alpha) {
1254        return this->saveLayer(bounds, nullptr);
1255    } else {
1256        SkPaint tmpPaint;
1257        tmpPaint.setAlpha(alpha);
1258        return this->saveLayer(bounds, &tmpPaint);
1259    }
1260}
1261
1262void SkCanvas::internalRestore() {
1263    SkASSERT(fMCStack.count() != 0);
1264
1265    fDeviceCMDirty = true;
1266    fCachedLocalClipBoundsDirty = true;
1267
1268    fClipStack->restore();
1269
1270    // reserve our layer (if any)
1271    DeviceCM* layer = fMCRec->fLayer;   // may be null
1272    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
1273    fMCRec->fLayer = nullptr;
1274
1275    // now do the normal restore()
1276    fMCRec->~MCRec();       // balanced in save()
1277    fMCStack.pop_back();
1278    fMCRec = (MCRec*)fMCStack.back();
1279
1280    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
1281        since if we're being recorded, we don't want to record this (the
1282        recorder will have already recorded the restore).
1283    */
1284    if (layer) {
1285        if (layer->fNext) {
1286            const SkIPoint& origin = layer->fDevice->getOrigin();
1287            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
1288                                     layer->fPaint, layer->fDeviceIsBitmapDevice);
1289            // reset this, since internalDrawDevice will have set it to true
1290            fDeviceCMDirty = true;
1291            delete layer;
1292        } else {
1293            // we're at the root
1294            SkASSERT(layer == (void*)fDeviceCMStorage);
1295            layer->~DeviceCM();
1296        }
1297    }
1298}
1299
1300SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
1301    if (nullptr == props) {
1302        props = &fProps;
1303    }
1304    return this->onNewSurface(info, *props);
1305}
1306
1307SkSurface* SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
1308    SkBaseDevice* dev = this->getDevice();
1309    return dev ? dev->newSurface(info, props) : nullptr;
1310}
1311
1312SkImageInfo SkCanvas::imageInfo() const {
1313    SkBaseDevice* dev = this->getDevice();
1314    if (dev) {
1315        return dev->imageInfo();
1316    } else {
1317        return SkImageInfo::MakeUnknown(0, 0);
1318    }
1319}
1320
1321const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1322    SkPixmap pmap;
1323    if (!this->onPeekPixels(&pmap)) {
1324        return nullptr;
1325    }
1326    if (info) {
1327        *info = pmap.info();
1328    }
1329    if (rowBytes) {
1330        *rowBytes = pmap.rowBytes();
1331    }
1332    return pmap.addr();
1333}
1334
1335bool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1336    SkBaseDevice* dev = this->getDevice();
1337    return dev && dev->peekPixels(pmap);
1338}
1339
1340void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1341    SkPixmap pmap;
1342    if (!this->onAccessTopLayerPixels(&pmap)) {
1343        return nullptr;
1344    }
1345    if (info) {
1346        *info = pmap.info();
1347    }
1348    if (rowBytes) {
1349        *rowBytes = pmap.rowBytes();
1350    }
1351    if (origin) {
1352        *origin = this->getTopDevice(false)->getOrigin();
1353    }
1354    return pmap.writable_addr();
1355}
1356
1357bool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
1358    SkBaseDevice* dev = this->getTopDevice();
1359    return dev && dev->accessPixels(pmap);
1360}
1361
1362/////////////////////////////////////////////////////////////////////////////
1363
1364void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
1365                                  const SkPaint* paint, bool deviceIsBitmapDevice) {
1366    SkPaint tmp;
1367    if (nullptr == paint) {
1368        paint = &tmp;
1369    }
1370
1371    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1372    while (iter.next()) {
1373        SkBaseDevice* dstDev = iter.fDevice;
1374        paint = &looper.paint();
1375        SkImageFilter* filter = paint->getImageFilter();
1376        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1377        if (filter && !dstDev->canHandleImageFilter(filter)) {
1378            SkImageFilter::DeviceProxy proxy(dstDev);
1379            SkBitmap dst;
1380            SkIPoint offset = SkIPoint::Make(0, 0);
1381            const SkBitmap& src = srcDev->accessBitmap(false);
1382            SkMatrix matrix = *iter.fMatrix;
1383            matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y()));
1384            SkIRect clipBounds = iter.fClip->getBounds().makeOffset(-pos.x(), -pos.y());
1385            SkAutoTUnref<SkImageFilter::Cache> cache(dstDev->getImageFilterCache());
1386            SkImageFilter::Context ctx(matrix, clipBounds, cache.get());
1387            if (filter->filterImage(&proxy, src, ctx, &dst, &offset)) {
1388                SkPaint tmpUnfiltered(*paint);
1389                tmpUnfiltered.setImageFilter(nullptr);
1390                dstDev->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(),
1391                                   tmpUnfiltered);
1392            }
1393        } else if (deviceIsBitmapDevice) {
1394            const SkBitmap& src = static_cast<SkBitmapDevice*>(srcDev)->fBitmap;
1395            dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint);
1396        } else {
1397            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
1398        }
1399    }
1400    LOOPER_END
1401}
1402
1403/////////////////////////////////////////////////////////////////////////////
1404
1405void SkCanvas::translate(SkScalar dx, SkScalar dy) {
1406    SkMatrix m;
1407    m.setTranslate(dx, dy);
1408    this->concat(m);
1409}
1410
1411void SkCanvas::scale(SkScalar sx, SkScalar sy) {
1412    SkMatrix m;
1413    m.setScale(sx, sy);
1414    this->concat(m);
1415}
1416
1417void SkCanvas::rotate(SkScalar degrees) {
1418    SkMatrix m;
1419    m.setRotate(degrees);
1420    this->concat(m);
1421}
1422
1423void SkCanvas::skew(SkScalar sx, SkScalar sy) {
1424    SkMatrix m;
1425    m.setSkew(sx, sy);
1426    this->concat(m);
1427}
1428
1429void SkCanvas::concat(const SkMatrix& matrix) {
1430    if (matrix.isIdentity()) {
1431        return;
1432    }
1433
1434    this->checkForDeferredSave();
1435    fDeviceCMDirty = true;
1436    fCachedLocalClipBoundsDirty = true;
1437    fMCRec->fMatrix.preConcat(matrix);
1438
1439    this->didConcat(matrix);
1440}
1441
1442void SkCanvas::setMatrix(const SkMatrix& matrix) {
1443    this->checkForDeferredSave();
1444    fDeviceCMDirty = true;
1445    fCachedLocalClipBoundsDirty = true;
1446    fMCRec->fMatrix = matrix;
1447    this->didSetMatrix(matrix);
1448}
1449
1450void SkCanvas::resetMatrix() {
1451    SkMatrix matrix;
1452
1453    matrix.reset();
1454    this->setMatrix(matrix);
1455}
1456
1457//////////////////////////////////////////////////////////////////////////////
1458
1459void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1460    this->checkForDeferredSave();
1461    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1462    this->onClipRect(rect, op, edgeStyle);
1463}
1464
1465void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1466#ifdef SK_ENABLE_CLIP_QUICKREJECT
1467    if (SkRegion::kIntersect_Op == op) {
1468        if (fMCRec->fRasterClip.isEmpty()) {
1469            return false;
1470        }
1471
1472        if (this->quickReject(rect)) {
1473            fDeviceCMDirty = true;
1474            fCachedLocalClipBoundsDirty = true;
1475
1476            fClipStack->clipEmpty();
1477            return fMCRec->fRasterClip.setEmpty();
1478        }
1479    }
1480#endif
1481
1482    if (!fAllowSoftClip) {
1483        edgeStyle = kHard_ClipEdgeStyle;
1484    }
1485
1486    const bool rectStaysRect = fMCRec->fMatrix.rectStaysRect();
1487    SkRect devR;
1488    if (rectStaysRect) {
1489        fMCRec->fMatrix.mapRect(&devR, rect);
1490    }
1491
1492    // Check if we can quick-accept the clip call (and do nothing)
1493    //
1494    // TODO: investigate if a (conservative) version of this could be done in ::clipRect,
1495    //       so that subclasses (like PictureRecording) didn't see unnecessary clips, which in turn
1496    //       might allow lazy save/restores to eliminate entire save/restore blocks.
1497    //
1498    if (SkRegion::kIntersect_Op == op &&
1499        kHard_ClipEdgeStyle == edgeStyle
1500        && rectStaysRect)
1501    {
1502        if (devR.round().contains(fMCRec->fRasterClip.getBounds())) {
1503#if 0
1504            SkDebugf("------- ignored clipRect [%g %g %g %g]\n",
1505                     rect.left(), rect.top(), rect.right(), rect.bottom());
1506#endif
1507            return;
1508        }
1509    }
1510
1511    AutoValidateClip avc(this);
1512
1513    fDeviceCMDirty = true;
1514    fCachedLocalClipBoundsDirty = true;
1515
1516    if (rectStaysRect) {
1517        const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1518        fClipStack->clipDevRect(devR, op, isAA);
1519        fMCRec->fRasterClip.op(devR, this->getBaseLayerSize(), op, isAA);
1520    } else {
1521        // since we're rotated or some such thing, we convert the rect to a path
1522        // and clip against that, since it can handle any matrix. However, to
1523        // avoid recursion in the case where we are subclassed (e.g. Pictures)
1524        // we explicitly call "our" version of clipPath.
1525        SkPath  path;
1526
1527        path.addRect(rect);
1528        this->SkCanvas::onClipPath(path, op, edgeStyle);
1529    }
1530}
1531
1532static void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPath& devPath,
1533                            SkRegion::Op op, bool doAA) {
1534    rc->op(devPath, canvas->getBaseLayerSize(), op, doAA);
1535}
1536
1537void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1538    this->checkForDeferredSave();
1539    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1540    if (rrect.isRect()) {
1541        this->onClipRect(rrect.getBounds(), op, edgeStyle);
1542    } else {
1543        this->onClipRRect(rrect, op, edgeStyle);
1544    }
1545}
1546
1547void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1548    SkRRect transformedRRect;
1549    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
1550        AutoValidateClip avc(this);
1551
1552        fDeviceCMDirty = true;
1553        fCachedLocalClipBoundsDirty = true;
1554        if (!fAllowSoftClip) {
1555            edgeStyle = kHard_ClipEdgeStyle;
1556        }
1557
1558        fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
1559
1560        fMCRec->fRasterClip.op(transformedRRect, this->getBaseLayerSize(), op,
1561                               kSoft_ClipEdgeStyle == edgeStyle);
1562        return;
1563    }
1564
1565    SkPath path;
1566    path.addRRect(rrect);
1567    // call the non-virtual version
1568    this->SkCanvas::onClipPath(path, op, edgeStyle);
1569}
1570
1571void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1572    this->checkForDeferredSave();
1573    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1574
1575    if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) {
1576        SkRect r;
1577        if (path.isRect(&r)) {
1578            this->onClipRect(r, op, edgeStyle);
1579            return;
1580        }
1581        SkRRect rrect;
1582        if (path.isOval(&r)) {
1583            rrect.setOval(r);
1584            this->onClipRRect(rrect, op, edgeStyle);
1585            return;
1586        }
1587        if (path.isRRect(&rrect)) {
1588            this->onClipRRect(rrect, op, edgeStyle);
1589            return;
1590        }
1591    }
1592
1593    this->onClipPath(path, op, edgeStyle);
1594}
1595
1596void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1597#ifdef SK_ENABLE_CLIP_QUICKREJECT
1598    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1599        if (fMCRec->fRasterClip.isEmpty()) {
1600            return false;
1601        }
1602
1603        if (this->quickReject(path.getBounds())) {
1604            fDeviceCMDirty = true;
1605            fCachedLocalClipBoundsDirty = true;
1606
1607            fClipStack->clipEmpty();
1608            return fMCRec->fRasterClip.setEmpty();
1609        }
1610    }
1611#endif
1612
1613    AutoValidateClip avc(this);
1614
1615    fDeviceCMDirty = true;
1616    fCachedLocalClipBoundsDirty = true;
1617    if (!fAllowSoftClip) {
1618        edgeStyle = kHard_ClipEdgeStyle;
1619    }
1620
1621    SkPath devPath;
1622    path.transform(fMCRec->fMatrix, &devPath);
1623
1624    // Check if the transfomation, or the original path itself
1625    // made us empty. Note this can also happen if we contained NaN
1626    // values. computing the bounds detects this, and will set our
1627    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1628    if (devPath.getBounds().isEmpty()) {
1629        // resetting the path will remove any NaN or other wanky values
1630        // that might upset our scan converter.
1631        devPath.reset();
1632    }
1633
1634    // if we called path.swap() we could avoid a deep copy of this path
1635    fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1636
1637    if (fAllowSimplifyClip) {
1638        bool clipIsAA = getClipStack()->asPath(&devPath);
1639        if (clipIsAA) {
1640            edgeStyle = kSoft_ClipEdgeStyle;
1641        }
1642
1643        op = SkRegion::kReplace_Op;
1644    }
1645
1646    rasterclip_path(&fMCRec->fRasterClip, this, devPath, op, edgeStyle);
1647}
1648
1649void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1650    this->checkForDeferredSave();
1651    this->onClipRegion(rgn, op);
1652}
1653
1654void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
1655    AutoValidateClip avc(this);
1656
1657    fDeviceCMDirty = true;
1658    fCachedLocalClipBoundsDirty = true;
1659
1660    // todo: signal fClipStack that we have a region, and therefore (I guess)
1661    // we have to ignore it, and use the region directly?
1662    fClipStack->clipDevRect(rgn.getBounds(), op);
1663
1664    fMCRec->fRasterClip.op(rgn, op);
1665}
1666
1667#ifdef SK_DEBUG
1668void SkCanvas::validateClip() const {
1669    // construct clipRgn from the clipstack
1670    const SkBaseDevice* device = this->getDevice();
1671    if (!device) {
1672        SkASSERT(this->isClipEmpty());
1673        return;
1674    }
1675
1676    SkIRect ir;
1677    ir.set(0, 0, device->width(), device->height());
1678    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1679
1680    SkClipStack::B2TIter                iter(*fClipStack);
1681    const SkClipStack::Element* element;
1682    while ((element = iter.next()) != nullptr) {
1683        switch (element->getType()) {
1684            case SkClipStack::Element::kRect_Type:
1685                element->getRect().round(&ir);
1686                tmpClip.op(ir, element->getOp());
1687                break;
1688            case SkClipStack::Element::kEmpty_Type:
1689                tmpClip.setEmpty();
1690                break;
1691            default: {
1692                SkPath path;
1693                element->asPath(&path);
1694                rasterclip_path(&tmpClip, this, path, element->getOp(), element->isAA());
1695                break;
1696            }
1697        }
1698    }
1699}
1700#endif
1701
1702void SkCanvas::replayClips(ClipVisitor* visitor) const {
1703    SkClipStack::B2TIter                iter(*fClipStack);
1704    const SkClipStack::Element*         element;
1705
1706    while ((element = iter.next()) != nullptr) {
1707        element->replay(visitor);
1708    }
1709}
1710
1711///////////////////////////////////////////////////////////////////////////////
1712
1713bool SkCanvas::isClipEmpty() const {
1714    return fMCRec->fRasterClip.isEmpty();
1715}
1716
1717bool SkCanvas::isClipRect() const {
1718    return fMCRec->fRasterClip.isRect();
1719}
1720
1721bool SkCanvas::quickReject(const SkRect& rect) const {
1722    if (!rect.isFinite())
1723        return true;
1724
1725    if (fMCRec->fRasterClip.isEmpty()) {
1726        return true;
1727    }
1728
1729    if (fMCRec->fMatrix.hasPerspective()) {
1730        SkRect dst;
1731        fMCRec->fMatrix.mapRect(&dst, rect);
1732        return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds());
1733    } else {
1734        const SkRect& clipR = this->getLocalClipBounds();
1735
1736        // for speed, do the most likely reject compares first
1737        // TODO: should we use | instead, or compare all 4 at once?
1738        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1739            return true;
1740        }
1741        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1742            return true;
1743        }
1744        return false;
1745    }
1746}
1747
1748bool SkCanvas::quickReject(const SkPath& path) const {
1749    return path.isEmpty() || this->quickReject(path.getBounds());
1750}
1751
1752bool SkCanvas::getClipBounds(SkRect* bounds) const {
1753    SkIRect ibounds;
1754    if (!this->getClipDeviceBounds(&ibounds)) {
1755        return false;
1756    }
1757
1758    SkMatrix inverse;
1759    // if we can't invert the CTM, we can't return local clip bounds
1760    if (!fMCRec->fMatrix.invert(&inverse)) {
1761        if (bounds) {
1762            bounds->setEmpty();
1763        }
1764        return false;
1765    }
1766
1767    if (bounds) {
1768        SkRect r;
1769        // adjust it outwards in case we are antialiasing
1770        const int inset = 1;
1771
1772        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1773               ibounds.fRight + inset, ibounds.fBottom + inset);
1774        inverse.mapRect(bounds, r);
1775    }
1776    return true;
1777}
1778
1779bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1780    const SkRasterClip& clip = fMCRec->fRasterClip;
1781    if (clip.isEmpty()) {
1782        if (bounds) {
1783            bounds->setEmpty();
1784        }
1785        return false;
1786    }
1787
1788    if (bounds) {
1789        *bounds = clip.getBounds();
1790    }
1791    return true;
1792}
1793
1794const SkMatrix& SkCanvas::getTotalMatrix() const {
1795    return fMCRec->fMatrix;
1796}
1797
1798const SkRegion& SkCanvas::internal_private_getTotalClip() const {
1799    return fMCRec->fRasterClip.forceGetBW();
1800}
1801
1802GrRenderTarget* SkCanvas::internal_private_accessTopLayerRenderTarget() {
1803    SkBaseDevice* dev = this->getTopDevice();
1804    return dev ? dev->accessRenderTarget() : nullptr;
1805}
1806
1807GrContext* SkCanvas::getGrContext() {
1808#if SK_SUPPORT_GPU
1809    SkBaseDevice* device = this->getTopDevice();
1810    if (device) {
1811        GrRenderTarget* renderTarget = device->accessRenderTarget();
1812        if (renderTarget) {
1813            return renderTarget->getContext();
1814        }
1815    }
1816#endif
1817
1818    return nullptr;
1819
1820}
1821
1822void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1823                          const SkPaint& paint) {
1824    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1825    if (outer.isEmpty()) {
1826        return;
1827    }
1828    if (inner.isEmpty()) {
1829        this->drawRRect(outer, paint);
1830        return;
1831    }
1832
1833    // We don't have this method (yet), but technically this is what we should
1834    // be able to assert...
1835    // SkASSERT(outer.contains(inner));
1836    //
1837    // For now at least check for containment of bounds
1838    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1839
1840    this->onDrawDRRect(outer, inner, paint);
1841}
1842
1843// These need to stop being virtual -- clients need to override the onDraw... versions
1844
1845void SkCanvas::drawPaint(const SkPaint& paint) {
1846    this->onDrawPaint(paint);
1847}
1848
1849void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1850    this->onDrawRect(r, paint);
1851}
1852
1853void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
1854    this->onDrawOval(r, paint);
1855}
1856
1857void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1858    this->onDrawRRect(rrect, paint);
1859}
1860
1861void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
1862    this->onDrawPoints(mode, count, pts, paint);
1863}
1864
1865void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
1866                            const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
1867                            const uint16_t indices[], int indexCount, const SkPaint& paint) {
1868    this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
1869                         indices, indexCount, paint);
1870}
1871
1872void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1873    this->onDrawPath(path, paint);
1874}
1875
1876void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1877    RETURN_ON_NULL(image);
1878    this->onDrawImage(image, x, y, paint);
1879}
1880
1881void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1882                             const SkPaint* paint, SrcRectConstraint constraint) {
1883    RETURN_ON_NULL(image);
1884    if (dst.isEmpty() || src.isEmpty()) {
1885        return;
1886    }
1887    this->onDrawImageRect(image, &src, dst, paint, constraint);
1888}
1889
1890void SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
1891                             const SkPaint* paint, SrcRectConstraint constraint) {
1892    RETURN_ON_NULL(image);
1893    this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
1894}
1895
1896void SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1897                             SrcRectConstraint constraint) {
1898    RETURN_ON_NULL(image);
1899    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1900                        constraint);
1901}
1902
1903void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
1904                             const SkPaint* paint) {
1905    RETURN_ON_NULL(image);
1906    if (dst.isEmpty()) {
1907        return;
1908    }
1909    if (!SkNinePatchIter::Valid(image->width(), image->height(), center)) {
1910        this->drawImageRect(image, dst, paint);
1911    }
1912    this->onDrawImageNine(image, center, dst, paint);
1913}
1914
1915void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
1916    if (bitmap.drawsNothing()) {
1917        return;
1918    }
1919    this->onDrawBitmap(bitmap, dx, dy, paint);
1920}
1921
1922void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1923                              const SkPaint* paint, SrcRectConstraint constraint) {
1924    if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1925        return;
1926    }
1927    this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
1928}
1929
1930void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
1931                              const SkPaint* paint, SrcRectConstraint constraint) {
1932    this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1933}
1934
1935void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1936                              SrcRectConstraint constraint) {
1937    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1938                         constraint);
1939}
1940
1941void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
1942                              const SkPaint* paint) {
1943    if (bitmap.drawsNothing() || dst.isEmpty()) {
1944        return;
1945    }
1946    if (!SkNinePatchIter::Valid(bitmap.width(), bitmap.height(), center)) {
1947        this->drawBitmapRect(bitmap, dst, paint);
1948    }
1949    this->onDrawBitmapNine(bitmap, center, dst, paint);
1950}
1951
1952void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
1953                         const SkColor colors[], int count, SkXfermode::Mode mode,
1954                         const SkRect* cull, const SkPaint* paint) {
1955    RETURN_ON_NULL(atlas);
1956    if (count <= 0) {
1957        return;
1958    }
1959    SkASSERT(atlas);
1960    SkASSERT(xform);
1961    SkASSERT(tex);
1962    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
1963}
1964
1965void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1966                                    const SkPaint* paint, SrcRectConstraint constraint) {
1967    if (src) {
1968        this->drawImageRect(image, *src, dst, paint, constraint);
1969    } else {
1970        this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
1971                            dst, paint, constraint);
1972    }
1973}
1974void SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1975                                     const SkPaint* paint, SrcRectConstraint constraint) {
1976    if (src) {
1977        this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
1978    } else {
1979        this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
1980                             dst, paint, constraint);
1981    }
1982}
1983
1984//////////////////////////////////////////////////////////////////////////////
1985//  These are the virtual drawing methods
1986//////////////////////////////////////////////////////////////////////////////
1987
1988void SkCanvas::onDiscard() {
1989    if (fSurfaceBase) {
1990        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
1991    }
1992}
1993
1994void SkCanvas::onDrawPaint(const SkPaint& paint) {
1995    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
1996    this->internalDrawPaint(paint);
1997}
1998
1999void SkCanvas::internalDrawPaint(const SkPaint& paint) {
2000    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
2001
2002    while (iter.next()) {
2003        iter.fDevice->drawPaint(iter, looper.paint());
2004    }
2005
2006    LOOPER_END
2007}
2008
2009void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
2010                            const SkPaint& paint) {
2011    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
2012    if ((long)count <= 0) {
2013        return;
2014    }
2015
2016    SkRect r, storage;
2017    const SkRect* bounds = nullptr;
2018    if (paint.canComputeFastBounds()) {
2019        // special-case 2 points (common for drawing a single line)
2020        if (2 == count) {
2021            r.set(pts[0], pts[1]);
2022        } else {
2023            r.set(pts, SkToInt(count));
2024        }
2025        if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
2026            return;
2027        }
2028        bounds = &r;
2029    }
2030
2031    SkASSERT(pts != nullptr);
2032
2033    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
2034
2035    while (iter.next()) {
2036        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
2037    }
2038
2039    LOOPER_END
2040}
2041
2042void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
2043    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
2044    SkRect storage;
2045    const SkRect* bounds = nullptr;
2046    if (paint.canComputeFastBounds()) {
2047        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
2048        // To prevent accidental rejecting at this stage, we have to sort it before we check.
2049        SkRect tmp(r);
2050        tmp.sort();
2051
2052        if (this->quickReject(paint.computeFastBounds(tmp, &storage))) {
2053            return;
2054        }
2055        bounds = &r;
2056    }
2057
2058    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, bounds, false)
2059
2060    while (iter.next()) {
2061        iter.fDevice->drawRect(iter, r, looper.paint());
2062    }
2063
2064    LOOPER_END
2065}
2066
2067void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
2068    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
2069    SkRect storage;
2070    const SkRect* bounds = nullptr;
2071    if (paint.canComputeFastBounds()) {
2072        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2073            return;
2074        }
2075        bounds = &oval;
2076    }
2077
2078    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
2079
2080    while (iter.next()) {
2081        iter.fDevice->drawOval(iter, oval, looper.paint());
2082    }
2083
2084    LOOPER_END
2085}
2086
2087void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
2088    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
2089    SkRect storage;
2090    const SkRect* bounds = nullptr;
2091    if (paint.canComputeFastBounds()) {
2092        if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
2093            return;
2094        }
2095        bounds = &rrect.getBounds();
2096    }
2097
2098    if (rrect.isRect()) {
2099        // call the non-virtual version
2100        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2101        return;
2102    } else if (rrect.isOval()) {
2103        // call the non-virtual version
2104        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2105        return;
2106    }
2107
2108    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2109
2110    while (iter.next()) {
2111        iter.fDevice->drawRRect(iter, rrect, looper.paint());
2112    }
2113
2114    LOOPER_END
2115}
2116
2117void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2118                            const SkPaint& paint) {
2119    SkRect storage;
2120    const SkRect* bounds = nullptr;
2121    if (paint.canComputeFastBounds()) {
2122        if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
2123            return;
2124        }
2125        bounds = &outer.getBounds();
2126    }
2127
2128    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2129
2130    while (iter.next()) {
2131        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
2132    }
2133
2134    LOOPER_END
2135}
2136
2137void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
2138    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
2139    if (!path.isFinite()) {
2140        return;
2141    }
2142
2143    SkRect storage;
2144    const SkRect* bounds = nullptr;
2145    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
2146        const SkRect& pathBounds = path.getBounds();
2147        if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
2148            return;
2149        }
2150        bounds = &pathBounds;
2151    }
2152
2153    const SkRect& r = path.getBounds();
2154    if (r.width() <= 0 && r.height() <= 0) {
2155        if (path.isInverseFillType()) {
2156            this->internalDrawPaint(paint);
2157            return;
2158        }
2159    }
2160
2161    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
2162
2163    while (iter.next()) {
2164        iter.fDevice->drawPath(iter, path, looper.paint());
2165    }
2166
2167    LOOPER_END
2168}
2169
2170bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2171    if (!paint.getImageFilter()) {
2172        return false;
2173    }
2174
2175    const SkMatrix& ctm = this->getTotalMatrix();
2176    if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2177        return false;
2178    }
2179
2180    // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2181    // Once we can filter and the filter will return a result larger than itself, we should be
2182    // able to remove this constraint.
2183    // skbug.com/4526
2184    //
2185    SkPoint pt;
2186    ctm.mapXY(x, y, &pt);
2187    SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2188    return ir.contains(fMCRec->fRasterClip.getBounds());
2189}
2190
2191void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
2192    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2193    SkRect bounds = SkRect::MakeXYWH(x, y,
2194                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
2195    if (nullptr == paint || paint->canComputeFastBounds()) {
2196        SkRect tmp = bounds;
2197        if (paint) {
2198            paint->computeFastBounds(tmp, &tmp);
2199        }
2200        if (this->quickReject(tmp)) {
2201            return;
2202        }
2203    }
2204
2205    SkLazyPaint lazy;
2206    if (nullptr == paint) {
2207        paint = lazy.init();
2208    }
2209
2210    const bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2211                                                          *paint);
2212    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2213
2214    while (iter.next()) {
2215        const SkPaint& pnt = looper.paint();
2216        if (drawAsSprite && pnt.getImageFilter()) {
2217            SkBitmap bitmap;
2218            if (as_IB(image)->asBitmapForImageFilters(&bitmap)) {
2219                SkPoint pt;
2220                iter.fMatrix->mapXY(x, y, &pt);
2221                iter.fDevice->drawBitmapAsSprite(iter, bitmap,
2222                                                 SkScalarRoundToInt(pt.fX),
2223                                                 SkScalarRoundToInt(pt.fY), pnt);
2224            }
2225        } else {
2226            iter.fDevice->drawImage(iter, image, x, y, pnt);
2227        }
2228    }
2229
2230    LOOPER_END
2231}
2232
2233void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2234                               const SkPaint* paint, SrcRectConstraint constraint) {
2235    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
2236    if (nullptr == paint || paint->canComputeFastBounds()) {
2237        SkRect storage = dst;
2238        if (paint) {
2239            paint->computeFastBounds(dst, &storage);
2240        }
2241        if (this->quickReject(storage)) {
2242            return;
2243        }
2244    }
2245    SkLazyPaint lazy;
2246    if (nullptr == paint) {
2247        paint = lazy.init();
2248    }
2249
2250    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2251                                          image->isOpaque())
2252
2253    while (iter.next()) {
2254        iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint);
2255    }
2256
2257    LOOPER_END
2258}
2259
2260void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
2261    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
2262    SkDEBUGCODE(bitmap.validate();)
2263
2264    if (bitmap.drawsNothing()) {
2265        return;
2266    }
2267
2268    SkLazyPaint lazy;
2269    if (nullptr == paint) {
2270        paint = lazy.init();
2271    }
2272
2273    const SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2274
2275    SkRect storage;
2276    const SkRect* bounds = nullptr;
2277    if (paint->canComputeFastBounds()) {
2278        bitmap.getBounds(&storage);
2279        matrix.mapRect(&storage);
2280        SkRect tmp = storage;
2281        if (this->quickReject(paint->computeFastBounds(tmp, &tmp))) {
2282            return;
2283        }
2284        bounds = &storage;
2285    }
2286
2287    const bool drawAsSprite = bounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(),
2288                                                                    bitmap.height(), *paint);
2289    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, bounds)
2290
2291    while (iter.next()) {
2292        const SkPaint& pnt = looper.paint();
2293        if (drawAsSprite && pnt.getImageFilter()) {
2294            SkPoint pt;
2295            iter.fMatrix->mapXY(x, y, &pt);
2296            iter.fDevice->drawBitmapAsSprite(iter, bitmap,
2297                                             SkScalarRoundToInt(pt.fX),
2298                                             SkScalarRoundToInt(pt.fY), pnt);
2299        } else {
2300            iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
2301        }
2302    }
2303
2304    LOOPER_END
2305}
2306
2307// this one is non-virtual, so it can be called safely by other canvas apis
2308void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2309                                      const SkRect& dst, const SkPaint* paint,
2310                                      SrcRectConstraint constraint) {
2311    if (bitmap.drawsNothing() || dst.isEmpty()) {
2312        return;
2313    }
2314
2315    if (nullptr == paint || paint->canComputeFastBounds()) {
2316        SkRect storage;
2317        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2318            return;
2319        }
2320    }
2321
2322    SkLazyPaint lazy;
2323    if (nullptr == paint) {
2324        paint = lazy.init();
2325    }
2326
2327    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2328                                          bitmap.isOpaque())
2329
2330    while (iter.next()) {
2331        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint);
2332    }
2333
2334    LOOPER_END
2335}
2336
2337void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2338                                const SkPaint* paint, SrcRectConstraint constraint) {
2339    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
2340    SkDEBUGCODE(bitmap.validate();)
2341    this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
2342}
2343
2344void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
2345                               const SkPaint* paint) {
2346    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
2347
2348    if (nullptr == paint || paint->canComputeFastBounds()) {
2349        SkRect storage;
2350        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2351            return;
2352        }
2353    }
2354
2355    SkLazyPaint lazy;
2356    if (nullptr == paint) {
2357        paint = lazy.init();
2358    }
2359
2360    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2361
2362    while (iter.next()) {
2363        iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint());
2364    }
2365
2366    LOOPER_END
2367}
2368
2369void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
2370                                const SkPaint* paint) {
2371    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
2372    SkDEBUGCODE(bitmap.validate();)
2373
2374    if (nullptr == paint || paint->canComputeFastBounds()) {
2375        SkRect storage;
2376        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2377            return;
2378        }
2379    }
2380
2381    SkLazyPaint lazy;
2382    if (nullptr == paint) {
2383        paint = lazy.init();
2384    }
2385
2386    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2387
2388    while (iter.next()) {
2389        iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint());
2390    }
2391
2392    LOOPER_END
2393}
2394
2395class SkDeviceFilteredPaint {
2396public:
2397    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2398        uint32_t filteredFlags = device->filterTextFlags(paint);
2399        if (filteredFlags != paint.getFlags()) {
2400            SkPaint* newPaint = fLazy.set(paint);
2401            newPaint->setFlags(filteredFlags);
2402            fPaint = newPaint;
2403        } else {
2404            fPaint = &paint;
2405        }
2406    }
2407
2408    const SkPaint& paint() const { return *fPaint; }
2409
2410private:
2411    const SkPaint*  fPaint;
2412    SkLazyPaint     fLazy;
2413};
2414
2415void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
2416                        const SkRect& r, SkScalar textSize) {
2417    if (paint.getStyle() == SkPaint::kFill_Style) {
2418        draw.fDevice->drawRect(draw, r, paint);
2419    } else {
2420        SkPaint p(paint);
2421        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
2422        draw.fDevice->drawRect(draw, r, p);
2423    }
2424}
2425
2426void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
2427                                   const char text[], size_t byteLength,
2428                                   SkScalar x, SkScalar y) {
2429    SkASSERT(byteLength == 0 || text != nullptr);
2430
2431    // nothing to draw
2432    if (text == nullptr || byteLength == 0 ||
2433        draw.fClip->isEmpty() ||
2434        (paint.getAlpha() == 0 && paint.getXfermode() == nullptr)) {
2435        return;
2436    }
2437
2438    SkScalar    width = 0;
2439    SkPoint     start;
2440
2441    start.set(0, 0);    // to avoid warning
2442    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
2443                            SkPaint::kStrikeThruText_Flag)) {
2444        width = paint.measureText(text, byteLength);
2445
2446        SkScalar offsetX = 0;
2447        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2448            offsetX = SkScalarHalf(width);
2449        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
2450            offsetX = width;
2451        }
2452        start.set(x - offsetX, y);
2453    }
2454
2455    if (0 == width) {
2456        return;
2457    }
2458
2459    uint32_t flags = paint.getFlags();
2460
2461    if (flags & (SkPaint::kUnderlineText_Flag |
2462                 SkPaint::kStrikeThruText_Flag)) {
2463        SkScalar textSize = paint.getTextSize();
2464        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
2465        SkRect   r;
2466
2467        r.fLeft = start.fX;
2468        r.fRight = start.fX + width;
2469
2470        if (flags & SkPaint::kUnderlineText_Flag) {
2471            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
2472                                             start.fY);
2473            r.fTop = offset;
2474            r.fBottom = offset + height;
2475            DrawRect(draw, paint, r, 1);
2476        }
2477        if (flags & SkPaint::kStrikeThruText_Flag) {
2478            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
2479                                             start.fY);
2480            r.fTop = offset;
2481            r.fBottom = offset + height;
2482            DrawRect(draw, paint, r, 1);
2483        }
2484    }
2485}
2486
2487void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2488                          const SkPaint& paint) {
2489    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2490
2491    while (iter.next()) {
2492        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2493        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
2494        DrawTextDecorations(iter, dfp.paint(),
2495                            static_cast<const char*>(text), byteLength, x, y);
2496    }
2497
2498    LOOPER_END
2499}
2500
2501void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2502                             const SkPaint& paint) {
2503    SkPoint textOffset = SkPoint::Make(0, 0);
2504
2505    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2506
2507    while (iter.next()) {
2508        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2509        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2510                                  dfp.paint());
2511    }
2512
2513    LOOPER_END
2514}
2515
2516void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2517                              SkScalar constY, const SkPaint& paint) {
2518
2519    SkPoint textOffset = SkPoint::Make(0, constY);
2520
2521    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2522
2523    while (iter.next()) {
2524        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2525        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2526                                  dfp.paint());
2527    }
2528
2529    LOOPER_END
2530}
2531
2532void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2533                                const SkMatrix* matrix, const SkPaint& paint) {
2534    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2535
2536    while (iter.next()) {
2537        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
2538                                     matrix, looper.paint());
2539    }
2540
2541    LOOPER_END
2542}
2543
2544void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2545                              const SkPaint& paint) {
2546
2547    SkRect storage;
2548    const SkRect* bounds = nullptr;
2549    if (paint.canComputeFastBounds()) {
2550        storage = blob->bounds().makeOffset(x, y);
2551        SkRect tmp;
2552        if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
2553            return;
2554        }
2555        bounds = &storage;
2556    }
2557
2558    // We cannot filter in the looper as we normally do, because the paint is
2559    // incomplete at this point (text-related attributes are embedded within blob run paints).
2560    SkDrawFilter* drawFilter = fMCRec->fFilter;
2561    fMCRec->fFilter = nullptr;
2562
2563    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
2564
2565    while (iter.next()) {
2566        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2567        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
2568    }
2569
2570    LOOPER_END
2571
2572    fMCRec->fFilter = drawFilter;
2573}
2574
2575// These will become non-virtual, so they always call the (virtual) onDraw... method
2576void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2577                        const SkPaint& paint) {
2578    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2579    this->onDrawText(text, byteLength, x, y, paint);
2580}
2581void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2582                           const SkPaint& paint) {
2583    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2584    this->onDrawPosText(text, byteLength, pos, paint);
2585}
2586void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2587                            SkScalar constY, const SkPaint& paint) {
2588    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2589    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2590}
2591void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2592                              const SkMatrix* matrix, const SkPaint& paint) {
2593    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2594    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2595}
2596void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2597                            const SkPaint& paint) {
2598    RETURN_ON_NULL(blob);
2599    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2600    this->onDrawTextBlob(blob, x, y, paint);
2601}
2602
2603void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
2604                              const SkPoint verts[], const SkPoint texs[],
2605                              const SkColor colors[], SkXfermode* xmode,
2606                              const uint16_t indices[], int indexCount,
2607                              const SkPaint& paint) {
2608    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
2609    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2610
2611    while (iter.next()) {
2612        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
2613                                   colors, xmode, indices, indexCount,
2614                                   looper.paint());
2615    }
2616
2617    LOOPER_END
2618}
2619
2620void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2621                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2622    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
2623    if (nullptr == cubics) {
2624        return;
2625    }
2626
2627    // Since a patch is always within the convex hull of the control points, we discard it when its
2628    // bounding rectangle is completely outside the current clip.
2629    SkRect bounds;
2630    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2631    if (this->quickReject(bounds)) {
2632        return;
2633    }
2634
2635    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2636}
2637
2638void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2639                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2640
2641    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2642
2643    while (iter.next()) {
2644        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2645    }
2646
2647    LOOPER_END
2648}
2649
2650void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2651    RETURN_ON_NULL(dr);
2652    if (x || y) {
2653        SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2654        this->onDrawDrawable(dr, &matrix);
2655    } else {
2656        this->onDrawDrawable(dr, nullptr);
2657    }
2658}
2659
2660void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2661    RETURN_ON_NULL(dr);
2662    if (matrix && matrix->isIdentity()) {
2663        matrix = nullptr;
2664    }
2665    this->onDrawDrawable(dr, matrix);
2666}
2667
2668void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2669    SkRect bounds = dr->getBounds();
2670    if (matrix) {
2671        matrix->mapRect(&bounds);
2672    }
2673    if (this->quickReject(bounds)) {
2674        return;
2675    }
2676    dr->draw(this, matrix);
2677}
2678
2679void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2680                           const SkColor colors[], int count, SkXfermode::Mode mode,
2681                           const SkRect* cull, const SkPaint* paint) {
2682    if (cull && this->quickReject(*cull)) {
2683        return;
2684    }
2685
2686    SkPaint pnt;
2687    if (paint) {
2688        pnt = *paint;
2689    }
2690
2691    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
2692    while (iter.next()) {
2693        iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, mode, pnt);
2694    }
2695    LOOPER_END
2696}
2697
2698//////////////////////////////////////////////////////////////////////////////
2699// These methods are NOT virtual, and therefore must call back into virtual
2700// methods, rather than actually drawing themselves.
2701//////////////////////////////////////////////////////////////////////////////
2702
2703void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2704                        SkXfermode::Mode mode) {
2705    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
2706    SkPaint paint;
2707
2708    paint.setARGB(a, r, g, b);
2709    if (SkXfermode::kSrcOver_Mode != mode) {
2710        paint.setXfermodeMode(mode);
2711    }
2712    this->drawPaint(paint);
2713}
2714
2715void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
2716    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
2717    SkPaint paint;
2718
2719    paint.setColor(c);
2720    if (SkXfermode::kSrcOver_Mode != mode) {
2721        paint.setXfermodeMode(mode);
2722    }
2723    this->drawPaint(paint);
2724}
2725
2726void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2727    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
2728    SkPoint pt;
2729
2730    pt.set(x, y);
2731    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2732}
2733
2734void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
2735    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
2736    SkPoint pt;
2737    SkPaint paint;
2738
2739    pt.set(x, y);
2740    paint.setColor(color);
2741    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2742}
2743
2744void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
2745                        const SkPaint& paint) {
2746    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
2747    SkPoint pts[2];
2748
2749    pts[0].set(x0, y0);
2750    pts[1].set(x1, y1);
2751    this->drawPoints(kLines_PointMode, 2, pts, paint);
2752}
2753
2754void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
2755                              SkScalar right, SkScalar bottom,
2756                              const SkPaint& paint) {
2757    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
2758    SkRect  r;
2759
2760    r.set(left, top, right, bottom);
2761    this->drawRect(r, paint);
2762}
2763
2764void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
2765                          const SkPaint& paint) {
2766    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
2767    if (radius < 0) {
2768        radius = 0;
2769    }
2770
2771    SkRect  r;
2772    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2773    this->drawOval(r, paint);
2774}
2775
2776void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2777                             const SkPaint& paint) {
2778    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
2779    if (rx > 0 && ry > 0) {
2780        if (paint.canComputeFastBounds()) {
2781            SkRect storage;
2782            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2783                return;
2784            }
2785        }
2786        SkRRect rrect;
2787        rrect.setRectXY(r, rx, ry);
2788        this->drawRRect(rrect, paint);
2789    } else {
2790        this->drawRect(r, paint);
2791    }
2792}
2793
2794void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2795                       SkScalar sweepAngle, bool useCenter,
2796                       const SkPaint& paint) {
2797    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2798    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
2799        this->drawOval(oval, paint);
2800    } else {
2801        SkPath  path;
2802        if (useCenter) {
2803            path.moveTo(oval.centerX(), oval.centerY());
2804        }
2805        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
2806        if (useCenter) {
2807            path.close();
2808        }
2809        this->drawPath(path, paint);
2810    }
2811}
2812
2813void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2814                                const SkPath& path, SkScalar hOffset,
2815                                SkScalar vOffset, const SkPaint& paint) {
2816    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
2817    SkMatrix    matrix;
2818
2819    matrix.setTranslate(hOffset, vOffset);
2820    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2821}
2822
2823///////////////////////////////////////////////////////////////////////////////
2824
2825/**
2826 *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
2827 *  against the playback cost of recursing into the subpicture to get at its actual ops.
2828 *
2829 *  For now we pick a conservatively small value, though measurement (and other heuristics like
2830 *  the type of ops contained) may justify changing this value.
2831 */
2832#define kMaxPictureOpsToUnrollInsteadOfRef  1
2833
2834void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2835    RETURN_ON_NULL(picture);
2836
2837    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
2838    if (matrix && matrix->isIdentity()) {
2839        matrix = nullptr;
2840    }
2841    if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
2842        SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2843        picture->playback(this);
2844    } else {
2845        this->onDrawPicture(picture, matrix, paint);
2846    }
2847}
2848
2849void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2850                             const SkPaint* paint) {
2851    if (!paint || paint->canComputeFastBounds()) {
2852        SkRect bounds = picture->cullRect();
2853        if (paint) {
2854            paint->computeFastBounds(bounds, &bounds);
2855        }
2856        if (matrix) {
2857            matrix->mapRect(&bounds);
2858        }
2859        if (this->quickReject(bounds)) {
2860            return;
2861        }
2862    }
2863
2864    SkBaseDevice* device = this->getTopDevice();
2865    if (device) {
2866        // Canvas has to first give the device the opportunity to render
2867        // the picture itself.
2868        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2869            return; // the device has rendered the entire picture
2870        }
2871    }
2872
2873    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2874    picture->playback(this);
2875}
2876
2877///////////////////////////////////////////////////////////////////////////////
2878///////////////////////////////////////////////////////////////////////////////
2879
2880SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2881    static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
2882
2883    SkASSERT(canvas);
2884
2885    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
2886    fDone = !fImpl->next();
2887}
2888
2889SkCanvas::LayerIter::~LayerIter() {
2890    fImpl->~SkDrawIter();
2891}
2892
2893void SkCanvas::LayerIter::next() {
2894    fDone = !fImpl->next();
2895}
2896
2897SkBaseDevice* SkCanvas::LayerIter::device() const {
2898    return fImpl->getDevice();
2899}
2900
2901const SkMatrix& SkCanvas::LayerIter::matrix() const {
2902    return fImpl->getMatrix();
2903}
2904
2905const SkPaint& SkCanvas::LayerIter::paint() const {
2906    const SkPaint* paint = fImpl->getPaint();
2907    if (nullptr == paint) {
2908        paint = &fDefaultPaint;
2909    }
2910    return *paint;
2911}
2912
2913const SkRegion& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
2914int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
2915int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2916
2917///////////////////////////////////////////////////////////////////////////////
2918
2919SkCanvasClipVisitor::~SkCanvasClipVisitor() { }
2920
2921///////////////////////////////////////////////////////////////////////////////
2922
2923static bool supported_for_raster_canvas(const SkImageInfo& info) {
2924    switch (info.alphaType()) {
2925        case kPremul_SkAlphaType:
2926        case kOpaque_SkAlphaType:
2927            break;
2928        default:
2929            return false;
2930    }
2931
2932    switch (info.colorType()) {
2933        case kAlpha_8_SkColorType:
2934        case kRGB_565_SkColorType:
2935        case kN32_SkColorType:
2936            break;
2937        default:
2938            return false;
2939    }
2940
2941    return true;
2942}
2943
2944SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
2945    if (!supported_for_raster_canvas(info)) {
2946        return nullptr;
2947    }
2948
2949    SkBitmap bitmap;
2950    if (!bitmap.installPixels(info, pixels, rowBytes)) {
2951        return nullptr;
2952    }
2953    return new SkCanvas(bitmap);
2954}
2955
2956///////////////////////////////////////////////////////////////////////////////
2957
2958SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
2959                                                 const SkPaint* paint, const SkRect& bounds)
2960    : fCanvas(canvas)
2961    , fSaveCount(canvas->getSaveCount())
2962{
2963    if (paint) {
2964        SkRect newBounds = bounds;
2965        if (matrix) {
2966            matrix->mapRect(&newBounds);
2967        }
2968        canvas->saveLayer(&newBounds, paint);
2969    } else if (matrix) {
2970        canvas->save();
2971    }
2972
2973    if (matrix) {
2974        canvas->concat(*matrix);
2975    }
2976}
2977
2978SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
2979    fCanvas->restoreToCount(fSaveCount);
2980}
2981