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