SkCanvas.cpp revision 944876f2745a62a839e49275daf93a0329372e67
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    // SRGBTODO: Can we remove this check now?
1181    const bool hasImageFilter = paint && paint->getImageFilter();
1182
1183    SkAlphaType alphaType = isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
1184    if ((prev.bytesPerPixel() < 4) || hasImageFilter) {
1185        // force to L32
1186        return SkImageInfo::MakeN32(w, h, alphaType);
1187    } else {
1188        // keep the same characteristics as the prev
1189        return SkImageInfo::Make(w, h, prev.colorType(), alphaType, sk_ref_sp(prev.colorSpace()));
1190    }
1191}
1192
1193void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
1194    const SkRect* bounds = rec.fBounds;
1195    const SkPaint* paint = rec.fPaint;
1196    SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
1197
1198#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
1199    saveLayerFlags &= ~kDontClipToLayer_PrivateSaveLayerFlag;
1200#endif
1201
1202    SkLazyPaint lazyP;
1203    SkImageFilter* imageFilter = paint ? paint->getImageFilter() : NULL;
1204    SkMatrix stashedMatrix = fMCRec->fMatrix;
1205    SkMatrix remainder;
1206    SkSize scale;
1207    /*
1208     *  ImageFilters (so far) do not correctly handle matrices (CTM) that contain rotation/skew/etc.
1209     *  but they do handle scaling. To accommodate this, we do the following:
1210     *
1211     *  1. Stash off the current CTM
1212     *  2. Decompose the CTM into SCALE and REMAINDER
1213     *  3. Wack the CTM to be just SCALE, and wrap the imagefilter with a MatrixImageFilter that
1214     *     contains the REMAINDER
1215     *  4. Proceed as usual, allowing the client to draw into the layer (now with a scale-only CTM)
1216     *  5. During restore, we process the MatrixImageFilter, which applies REMAINDER to the output
1217     *     of the original imagefilter, and draw that (via drawSprite)
1218     *  6. Unwack the CTM to its original state (i.e. stashedMatrix)
1219     *
1220     *  Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
1221     *  a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter.
1222     */
1223    if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() &&
1224        stashedMatrix.decomposeScale(&scale, &remainder))
1225    {
1226        // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
1227        this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height()));
1228        SkPaint* p = lazyP.set(*paint);
1229        p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder,
1230                                                          SkFilterQuality::kLow_SkFilterQuality,
1231                                                          sk_ref_sp(imageFilter)));
1232        imageFilter = p->getImageFilter();
1233        paint = p;
1234    }
1235
1236    // do this before we create the layer. We don't call the public save() since
1237    // that would invoke a possibly overridden virtual
1238    this->internalSave();
1239
1240    fDeviceCMDirty = true;
1241
1242    SkIRect ir;
1243    if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
1244        return;
1245    }
1246
1247    // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1248    // the clipRectBounds() call above?
1249    if (kNoLayer_SaveLayerStrategy == strategy) {
1250        return;
1251    }
1252
1253    bool isOpaque = SkToBool(saveLayerFlags & kIsOpaque_SaveLayerFlag);
1254    SkPixelGeometry geo = fProps.pixelGeometry();
1255    if (paint) {
1256        // TODO: perhaps add a query to filters so we might preserve opaqueness...
1257        if (paint->getImageFilter() || paint->getColorFilter()) {
1258            isOpaque = false;
1259            geo = kUnknown_SkPixelGeometry;
1260        }
1261    }
1262
1263    SkBaseDevice* device = this->getTopDevice();
1264    if (nullptr == device) {
1265        SkDebugf("Unable to find device for layer.");
1266        return;
1267    }
1268
1269    SkImageInfo info = make_layer_info(device->imageInfo(), ir.width(), ir.height(), isOpaque,
1270                                       paint);
1271
1272    bool forceSpriteOnRestore = false;
1273    {
1274        const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
1275                                     (saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
1276        const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
1277        const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
1278                                                                            preserveLCDText, false);
1279        SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint);
1280        if (nullptr == newDev) {
1281            // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint)
1282            const SkSurfaceProps surfaceProps(fProps.flags(), createInfo.fPixelGeometry);
1283            newDev = SkBitmapDevice::Create(createInfo.fInfo, surfaceProps);
1284            if (nullptr == newDev) {
1285                SkErrorInternals::SetError(kInternalError_SkError,
1286                                           "Unable to create device for layer.");
1287                return;
1288            }
1289            forceSpriteOnRestore = true;
1290        }
1291        device = newDev;
1292    }
1293    device->setOrigin(ir.fLeft, ir.fTop);
1294
1295    if (rec.fBackdrop) {
1296        draw_filter_into_device(fMCRec->fTopLayer->fDevice, rec.fBackdrop, device, fMCRec->fMatrix);
1297    }
1298
1299    DeviceCM* layer = new DeviceCM(device, paint, this, fConservativeRasterClip,
1300                                   forceSpriteOnRestore, stashedMatrix);
1301    device->unref();
1302
1303    layer->fNext = fMCRec->fTopLayer;
1304    fMCRec->fLayer = layer;
1305    fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
1306}
1307
1308int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1309    if (0xFF == alpha) {
1310        return this->saveLayer(bounds, nullptr);
1311    } else {
1312        SkPaint tmpPaint;
1313        tmpPaint.setAlpha(alpha);
1314        return this->saveLayer(bounds, &tmpPaint);
1315    }
1316}
1317
1318void SkCanvas::internalRestore() {
1319    SkASSERT(fMCStack.count() != 0);
1320
1321    fDeviceCMDirty = true;
1322    fCachedLocalClipBoundsDirty = true;
1323
1324    fClipStack->restore();
1325
1326    // reserve our layer (if any)
1327    DeviceCM* layer = fMCRec->fLayer;   // may be null
1328    // now detach it from fMCRec so we can pop(). Gets freed after its drawn
1329    fMCRec->fLayer = nullptr;
1330
1331    // now do the normal restore()
1332    fMCRec->~MCRec();       // balanced in save()
1333    fMCStack.pop_back();
1334    fMCRec = (MCRec*)fMCStack.back();
1335
1336    /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
1337        since if we're being recorded, we don't want to record this (the
1338        recorder will have already recorded the restore).
1339    */
1340    if (layer) {
1341        if (layer->fNext) {
1342            const SkIPoint& origin = layer->fDevice->getOrigin();
1343            this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
1344                                     layer->fPaint, layer->fDeviceIsBitmapDevice);
1345            // restore what we smashed in internalSaveLayer
1346            fMCRec->fMatrix = layer->fStashedMatrix;
1347            // reset this, since internalDrawDevice will have set it to true
1348            fDeviceCMDirty = true;
1349            delete layer;
1350        } else {
1351            // we're at the root
1352            SkASSERT(layer == (void*)fDeviceCMStorage);
1353            layer->~DeviceCM();
1354            // no need to update fMCRec, 'cause we're killing the canvas
1355        }
1356    }
1357}
1358
1359sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
1360    if (nullptr == props) {
1361        props = &fProps;
1362    }
1363    return this->onNewSurface(info, *props);
1364}
1365
1366sk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
1367    SkBaseDevice* dev = this->getDevice();
1368    return dev ? dev->makeSurface(info, props) : nullptr;
1369}
1370
1371SkImageInfo SkCanvas::imageInfo() const {
1372    SkBaseDevice* dev = this->getDevice();
1373    if (dev) {
1374        return dev->imageInfo();
1375    } else {
1376        return SkImageInfo::MakeUnknown(0, 0);
1377    }
1378}
1379
1380bool SkCanvas::getProps(SkSurfaceProps* props) const {
1381    SkBaseDevice* dev = this->getDevice();
1382    if (dev) {
1383        if (props) {
1384            *props = fProps;
1385        }
1386        return true;
1387    } else {
1388        return false;
1389    }
1390}
1391
1392#ifdef SK_SUPPORT_LEGACY_PEEKPIXELS_PARMS
1393const void* SkCanvas::peekPixels(SkImageInfo* info, size_t* rowBytes) {
1394    SkPixmap pmap;
1395    if (this->peekPixels(&pmap)) {
1396        if (info) {
1397            *info = pmap.info();
1398        }
1399        if (rowBytes) {
1400            *rowBytes = pmap.rowBytes();
1401        }
1402        return pmap.addr();
1403    }
1404    return nullptr;
1405}
1406#endif
1407
1408bool SkCanvas::peekPixels(SkPixmap* pmap) {
1409    return this->onPeekPixels(pmap);
1410}
1411
1412bool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1413    SkBaseDevice* dev = this->getDevice();
1414    return dev && dev->peekPixels(pmap);
1415}
1416
1417void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1418    SkPixmap pmap;
1419    if (!this->onAccessTopLayerPixels(&pmap)) {
1420        return nullptr;
1421    }
1422    if (info) {
1423        *info = pmap.info();
1424    }
1425    if (rowBytes) {
1426        *rowBytes = pmap.rowBytes();
1427    }
1428    if (origin) {
1429        *origin = this->getTopDevice(false)->getOrigin();
1430    }
1431    return pmap.writable_addr();
1432}
1433
1434bool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
1435    SkBaseDevice* dev = this->getTopDevice();
1436    return dev && dev->accessPixels(pmap);
1437}
1438
1439/////////////////////////////////////////////////////////////////////////////
1440
1441void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y,
1442                                  const SkPaint* paint, bool deviceIsBitmapDevice) {
1443    SkPaint tmp;
1444    if (nullptr == paint) {
1445        paint = &tmp;
1446    }
1447
1448    LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1449    while (iter.next()) {
1450        SkBaseDevice* dstDev = iter.fDevice;
1451        paint = &looper.paint();
1452        SkImageFilter* filter = paint->getImageFilter();
1453        SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1454        if (filter) {
1455            const SkBitmap& srcBM = srcDev->accessBitmap(false);
1456            dstDev->drawSpriteWithFilter(iter, srcBM, pos.x(), pos.y(), *paint);
1457        } else if (deviceIsBitmapDevice) {
1458            const SkBitmap& src = static_cast<SkBitmapDevice*>(srcDev)->fBitmap;
1459            dstDev->drawSprite(iter, src, pos.x(), pos.y(), *paint);
1460        } else {
1461            dstDev->drawDevice(iter, srcDev, pos.x(), pos.y(), *paint);
1462        }
1463    }
1464    LOOPER_END
1465}
1466
1467/////////////////////////////////////////////////////////////////////////////
1468
1469void SkCanvas::translate(SkScalar dx, SkScalar dy) {
1470    SkMatrix m;
1471    m.setTranslate(dx, dy);
1472    this->concat(m);
1473}
1474
1475void SkCanvas::scale(SkScalar sx, SkScalar sy) {
1476    SkMatrix m;
1477    m.setScale(sx, sy);
1478    this->concat(m);
1479}
1480
1481void SkCanvas::rotate(SkScalar degrees) {
1482    SkMatrix m;
1483    m.setRotate(degrees);
1484    this->concat(m);
1485}
1486
1487void SkCanvas::skew(SkScalar sx, SkScalar sy) {
1488    SkMatrix m;
1489    m.setSkew(sx, sy);
1490    this->concat(m);
1491}
1492
1493void SkCanvas::concat(const SkMatrix& matrix) {
1494    if (matrix.isIdentity()) {
1495        return;
1496    }
1497
1498    this->checkForDeferredSave();
1499    fDeviceCMDirty = true;
1500    fCachedLocalClipBoundsDirty = true;
1501    fMCRec->fMatrix.preConcat(matrix);
1502
1503    this->didConcat(matrix);
1504}
1505
1506void SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
1507    fDeviceCMDirty = true;
1508    fCachedLocalClipBoundsDirty = true;
1509    fMCRec->fMatrix = matrix;
1510}
1511
1512void SkCanvas::setMatrix(const SkMatrix& matrix) {
1513    this->checkForDeferredSave();
1514    this->internalSetMatrix(matrix);
1515    this->didSetMatrix(matrix);
1516}
1517
1518void SkCanvas::resetMatrix() {
1519    this->setMatrix(SkMatrix::I());
1520}
1521
1522//////////////////////////////////////////////////////////////////////////////
1523
1524void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
1525    this->checkForDeferredSave();
1526    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1527    this->onClipRect(rect, op, edgeStyle);
1528}
1529
1530void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1531#ifdef SK_ENABLE_CLIP_QUICKREJECT
1532    if (SkRegion::kIntersect_Op == op) {
1533        if (fMCRec->fRasterClip.isEmpty()) {
1534            return false;
1535        }
1536
1537        if (this->quickReject(rect)) {
1538            fDeviceCMDirty = true;
1539            fCachedLocalClipBoundsDirty = true;
1540
1541            fClipStack->clipEmpty();
1542            return fMCRec->fRasterClip.setEmpty();
1543        }
1544    }
1545#endif
1546
1547    if (!fAllowSoftClip) {
1548        edgeStyle = kHard_ClipEdgeStyle;
1549    }
1550
1551    const bool rectStaysRect = fMCRec->fMatrix.rectStaysRect();
1552    SkRect devR;
1553    if (rectStaysRect) {
1554        fMCRec->fMatrix.mapRect(&devR, rect);
1555    }
1556
1557    // Check if we can quick-accept the clip call (and do nothing)
1558    //
1559    // TODO: investigate if a (conservative) version of this could be done in ::clipRect,
1560    //       so that subclasses (like PictureRecording) didn't see unnecessary clips, which in turn
1561    //       might allow lazy save/restores to eliminate entire save/restore blocks.
1562    //
1563    if (SkRegion::kIntersect_Op == op &&
1564        kHard_ClipEdgeStyle == edgeStyle
1565        && rectStaysRect)
1566    {
1567        if (devR.round().contains(fMCRec->fRasterClip.getBounds())) {
1568#if 0
1569            SkDebugf("------- ignored clipRect [%g %g %g %g]\n",
1570                     rect.left(), rect.top(), rect.right(), rect.bottom());
1571#endif
1572            return;
1573        }
1574    }
1575
1576    AutoValidateClip avc(this);
1577
1578    fDeviceCMDirty = true;
1579    fCachedLocalClipBoundsDirty = true;
1580
1581    if (rectStaysRect) {
1582        const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1583        fClipStack->clipDevRect(devR, op, isAA);
1584        fMCRec->fRasterClip.op(devR, this->getTopLayerBounds(), op, isAA);
1585    } else {
1586        // since we're rotated or some such thing, we convert the rect to a path
1587        // and clip against that, since it can handle any matrix. However, to
1588        // avoid recursion in the case where we are subclassed (e.g. Pictures)
1589        // we explicitly call "our" version of clipPath.
1590        SkPath  path;
1591
1592        path.addRect(rect);
1593        this->SkCanvas::onClipPath(path, op, edgeStyle);
1594    }
1595}
1596
1597void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
1598    this->checkForDeferredSave();
1599    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1600    if (rrect.isRect()) {
1601        this->onClipRect(rrect.getBounds(), op, edgeStyle);
1602    } else {
1603        this->onClipRRect(rrect, op, edgeStyle);
1604    }
1605}
1606
1607void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1608    SkRRect transformedRRect;
1609    if (rrect.transform(fMCRec->fMatrix, &transformedRRect)) {
1610        AutoValidateClip avc(this);
1611
1612        fDeviceCMDirty = true;
1613        fCachedLocalClipBoundsDirty = true;
1614        if (!fAllowSoftClip) {
1615            edgeStyle = kHard_ClipEdgeStyle;
1616        }
1617
1618        fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle);
1619
1620        fMCRec->fRasterClip.op(transformedRRect, this->getTopLayerBounds(), op,
1621                               kSoft_ClipEdgeStyle == edgeStyle);
1622        return;
1623    }
1624
1625    SkPath path;
1626    path.addRRect(rrect);
1627    // call the non-virtual version
1628    this->SkCanvas::onClipPath(path, op, edgeStyle);
1629}
1630
1631void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
1632    this->checkForDeferredSave();
1633    ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1634
1635    if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) {
1636        SkRect r;
1637        if (path.isRect(&r)) {
1638            this->onClipRect(r, op, edgeStyle);
1639            return;
1640        }
1641        SkRRect rrect;
1642        if (path.isOval(&r)) {
1643            rrect.setOval(r);
1644            this->onClipRRect(rrect, op, edgeStyle);
1645            return;
1646        }
1647        if (path.isRRect(&rrect)) {
1648            this->onClipRRect(rrect, op, edgeStyle);
1649            return;
1650        }
1651    }
1652
1653    this->onClipPath(path, op, edgeStyle);
1654}
1655
1656void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
1657#ifdef SK_ENABLE_CLIP_QUICKREJECT
1658    if (SkRegion::kIntersect_Op == op && !path.isInverseFillType()) {
1659        if (fMCRec->fRasterClip.isEmpty()) {
1660            return false;
1661        }
1662
1663        if (this->quickReject(path.getBounds())) {
1664            fDeviceCMDirty = true;
1665            fCachedLocalClipBoundsDirty = true;
1666
1667            fClipStack->clipEmpty();
1668            return fMCRec->fRasterClip.setEmpty();
1669        }
1670    }
1671#endif
1672
1673    AutoValidateClip avc(this);
1674
1675    fDeviceCMDirty = true;
1676    fCachedLocalClipBoundsDirty = true;
1677    if (!fAllowSoftClip) {
1678        edgeStyle = kHard_ClipEdgeStyle;
1679    }
1680
1681    SkPath devPath;
1682    path.transform(fMCRec->fMatrix, &devPath);
1683
1684    // Check if the transfomation, or the original path itself
1685    // made us empty. Note this can also happen if we contained NaN
1686    // values. computing the bounds detects this, and will set our
1687    // bounds to empty if that is the case. (see SkRect::set(pts, count))
1688    if (devPath.getBounds().isEmpty()) {
1689        // resetting the path will remove any NaN or other wanky values
1690        // that might upset our scan converter.
1691        devPath.reset();
1692    }
1693
1694    // if we called path.swap() we could avoid a deep copy of this path
1695    fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle);
1696
1697    if (fAllowSimplifyClip) {
1698        bool clipIsAA = getClipStack()->asPath(&devPath);
1699        if (clipIsAA) {
1700            edgeStyle = kSoft_ClipEdgeStyle;
1701        }
1702
1703        op = SkRegion::kReplace_Op;
1704    }
1705
1706    fMCRec->fRasterClip.op(devPath, this->getTopLayerBounds(), op, edgeStyle);
1707}
1708
1709void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
1710    this->checkForDeferredSave();
1711    this->onClipRegion(rgn, op);
1712}
1713
1714void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) {
1715    AutoValidateClip avc(this);
1716
1717    fDeviceCMDirty = true;
1718    fCachedLocalClipBoundsDirty = true;
1719
1720    // todo: signal fClipStack that we have a region, and therefore (I guess)
1721    // we have to ignore it, and use the region directly?
1722    fClipStack->clipDevRect(rgn.getBounds(), op);
1723
1724    fMCRec->fRasterClip.op(rgn, op);
1725}
1726
1727#ifdef SK_DEBUG
1728void SkCanvas::validateClip() const {
1729    // construct clipRgn from the clipstack
1730    const SkBaseDevice* device = this->getDevice();
1731    if (!device) {
1732        SkASSERT(this->isClipEmpty());
1733        return;
1734    }
1735
1736    SkIRect ir;
1737    ir.set(0, 0, device->width(), device->height());
1738    SkRasterClip tmpClip(ir, fConservativeRasterClip);
1739
1740    SkClipStack::B2TIter                iter(*fClipStack);
1741    const SkClipStack::Element* element;
1742    while ((element = iter.next()) != nullptr) {
1743        switch (element->getType()) {
1744            case SkClipStack::Element::kRect_Type:
1745                element->getRect().round(&ir);
1746                tmpClip.op(ir, element->getOp());
1747                break;
1748            case SkClipStack::Element::kEmpty_Type:
1749                tmpClip.setEmpty();
1750                break;
1751            default: {
1752                SkPath path;
1753                element->asPath(&path);
1754                tmpClip.op(path, this->getTopLayerBounds(), element->getOp(), element->isAA());
1755                break;
1756            }
1757        }
1758    }
1759}
1760#endif
1761
1762void SkCanvas::replayClips(ClipVisitor* visitor) const {
1763    SkClipStack::B2TIter                iter(*fClipStack);
1764    const SkClipStack::Element*         element;
1765
1766    while ((element = iter.next()) != nullptr) {
1767        element->replay(visitor);
1768    }
1769}
1770
1771///////////////////////////////////////////////////////////////////////////////
1772
1773bool SkCanvas::isClipEmpty() const {
1774    return fMCRec->fRasterClip.isEmpty();
1775}
1776
1777bool SkCanvas::isClipRect() const {
1778    return fMCRec->fRasterClip.isRect();
1779}
1780
1781bool SkCanvas::quickReject(const SkRect& rect) const {
1782    if (!rect.isFinite())
1783        return true;
1784
1785    if (fMCRec->fRasterClip.isEmpty()) {
1786        return true;
1787    }
1788
1789    if (fMCRec->fMatrix.hasPerspective()) {
1790        SkRect dst;
1791        fMCRec->fMatrix.mapRect(&dst, rect);
1792        return !SkIRect::Intersects(dst.roundOut(), fMCRec->fRasterClip.getBounds());
1793    } else {
1794        const SkRect& clipR = this->getLocalClipBounds();
1795
1796        // for speed, do the most likely reject compares first
1797        // TODO: should we use | instead, or compare all 4 at once?
1798        if (rect.fTop >= clipR.fBottom || rect.fBottom <= clipR.fTop) {
1799            return true;
1800        }
1801        if (rect.fLeft >= clipR.fRight || rect.fRight <= clipR.fLeft) {
1802            return true;
1803        }
1804        return false;
1805    }
1806}
1807
1808bool SkCanvas::quickReject(const SkPath& path) const {
1809    return path.isEmpty() || this->quickReject(path.getBounds());
1810}
1811
1812bool SkCanvas::getClipBounds(SkRect* bounds) const {
1813    SkIRect ibounds;
1814    if (!this->getClipDeviceBounds(&ibounds)) {
1815        return false;
1816    }
1817
1818    SkMatrix inverse;
1819    // if we can't invert the CTM, we can't return local clip bounds
1820    if (!fMCRec->fMatrix.invert(&inverse)) {
1821        if (bounds) {
1822            bounds->setEmpty();
1823        }
1824        return false;
1825    }
1826
1827    if (bounds) {
1828        SkRect r;
1829        // adjust it outwards in case we are antialiasing
1830        const int inset = 1;
1831
1832        r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1833               ibounds.fRight + inset, ibounds.fBottom + inset);
1834        inverse.mapRect(bounds, r);
1835    }
1836    return true;
1837}
1838
1839bool SkCanvas::getClipDeviceBounds(SkIRect* bounds) const {
1840    const SkRasterClip& clip = fMCRec->fRasterClip;
1841    if (clip.isEmpty()) {
1842        if (bounds) {
1843            bounds->setEmpty();
1844        }
1845        return false;
1846    }
1847
1848    if (bounds) {
1849        *bounds = clip.getBounds();
1850    }
1851    return true;
1852}
1853
1854const SkMatrix& SkCanvas::getTotalMatrix() const {
1855    return fMCRec->fMatrix;
1856}
1857
1858const SkRegion& SkCanvas::internal_private_getTotalClip() const {
1859    return fMCRec->fRasterClip.forceGetBW();
1860}
1861
1862GrDrawContext* SkCanvas::internal_private_accessTopLayerDrawContext() {
1863    SkBaseDevice* dev = this->getTopDevice();
1864    return dev ? dev->accessDrawContext() : nullptr;
1865}
1866
1867GrContext* SkCanvas::getGrContext() {
1868    SkBaseDevice* device = this->getTopDevice();
1869    return device ? device->context() : nullptr;
1870}
1871
1872void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1873                          const SkPaint& paint) {
1874    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawDRRect()");
1875    if (outer.isEmpty()) {
1876        return;
1877    }
1878    if (inner.isEmpty()) {
1879        this->drawRRect(outer, paint);
1880        return;
1881    }
1882
1883    // We don't have this method (yet), but technically this is what we should
1884    // be able to assert...
1885    // SkASSERT(outer.contains(inner));
1886    //
1887    // For now at least check for containment of bounds
1888    SkASSERT(outer.getBounds().contains(inner.getBounds()));
1889
1890    this->onDrawDRRect(outer, inner, paint);
1891}
1892
1893// These need to stop being virtual -- clients need to override the onDraw... versions
1894
1895void SkCanvas::drawPaint(const SkPaint& paint) {
1896    this->onDrawPaint(paint);
1897}
1898
1899void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1900    this->onDrawRect(r, paint);
1901}
1902
1903void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
1904    this->onDrawOval(r, paint);
1905}
1906
1907void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1908    this->onDrawRRect(rrect, paint);
1909}
1910
1911void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
1912    this->onDrawPoints(mode, count, pts, paint);
1913}
1914
1915void SkCanvas::drawVertices(VertexMode vmode, int vertexCount, const SkPoint vertices[],
1916                            const SkPoint texs[], const SkColor colors[], SkXfermode* xmode,
1917                            const uint16_t indices[], int indexCount, const SkPaint& paint) {
1918    this->onDrawVertices(vmode, vertexCount, vertices, texs, colors, xmode,
1919                         indices, indexCount, paint);
1920}
1921
1922void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1923    this->onDrawPath(path, paint);
1924}
1925
1926void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1927    RETURN_ON_NULL(image);
1928    this->onDrawImage(image, x, y, paint);
1929}
1930
1931void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1932                             const SkPaint* paint, SrcRectConstraint constraint) {
1933    RETURN_ON_NULL(image);
1934    if (dst.isEmpty() || src.isEmpty()) {
1935        return;
1936    }
1937    this->onDrawImageRect(image, &src, dst, paint, constraint);
1938}
1939
1940void SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
1941                             const SkPaint* paint, SrcRectConstraint constraint) {
1942    RETURN_ON_NULL(image);
1943    this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
1944}
1945
1946void SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1947                             SrcRectConstraint constraint) {
1948    RETURN_ON_NULL(image);
1949    this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1950                        constraint);
1951}
1952
1953void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
1954                             const SkPaint* paint) {
1955    RETURN_ON_NULL(image);
1956    if (dst.isEmpty()) {
1957        return;
1958    }
1959    if (!SkNinePatchIter::Valid(image->width(), image->height(), center)) {
1960        this->drawImageRect(image, dst, paint);
1961    }
1962    this->onDrawImageNine(image, center, dst, paint);
1963}
1964
1965void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
1966    if (bitmap.drawsNothing()) {
1967        return;
1968    }
1969    this->onDrawBitmap(bitmap, dx, dy, paint);
1970}
1971
1972void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1973                              const SkPaint* paint, SrcRectConstraint constraint) {
1974    if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1975        return;
1976    }
1977    this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
1978}
1979
1980void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
1981                              const SkPaint* paint, SrcRectConstraint constraint) {
1982    this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1983}
1984
1985void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1986                              SrcRectConstraint constraint) {
1987    this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1988                         constraint);
1989}
1990
1991void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
1992                              const SkPaint* paint) {
1993    if (bitmap.drawsNothing() || dst.isEmpty()) {
1994        return;
1995    }
1996    if (!SkNinePatchIter::Valid(bitmap.width(), bitmap.height(), center)) {
1997        this->drawBitmapRect(bitmap, dst, paint);
1998    }
1999    this->onDrawBitmapNine(bitmap, center, dst, paint);
2000}
2001
2002void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2003                         const SkColor colors[], int count, SkXfermode::Mode mode,
2004                         const SkRect* cull, const SkPaint* paint) {
2005    RETURN_ON_NULL(atlas);
2006    if (count <= 0) {
2007        return;
2008    }
2009    SkASSERT(atlas);
2010    SkASSERT(xform);
2011    SkASSERT(tex);
2012    this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
2013}
2014
2015void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2016    if (key) {
2017        this->onDrawAnnotation(rect, key, value);
2018    }
2019}
2020
2021void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2022                                    const SkPaint* paint, SrcRectConstraint constraint) {
2023    if (src) {
2024        this->drawImageRect(image, *src, dst, paint, constraint);
2025    } else {
2026        this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
2027                            dst, paint, constraint);
2028    }
2029}
2030void SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2031                                     const SkPaint* paint, SrcRectConstraint constraint) {
2032    if (src) {
2033        this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
2034    } else {
2035        this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
2036                             dst, paint, constraint);
2037    }
2038}
2039
2040void SkCanvas::temporary_internal_describeTopLayer(SkMatrix* matrix, SkIRect* clip_bounds) {
2041    SkIRect layer_bounds = this->getTopLayerBounds();
2042    if (matrix) {
2043        *matrix = this->getTotalMatrix();
2044        matrix->preTranslate(-layer_bounds.left(), -layer_bounds.top());
2045    }
2046    if (clip_bounds) {
2047        this->getClipDeviceBounds(clip_bounds);
2048        clip_bounds->offset(-layer_bounds.left(), -layer_bounds.top());
2049    }
2050}
2051
2052//////////////////////////////////////////////////////////////////////////////
2053//  These are the virtual drawing methods
2054//////////////////////////////////////////////////////////////////////////////
2055
2056void SkCanvas::onDiscard() {
2057    if (fSurfaceBase) {
2058        fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
2059    }
2060}
2061
2062void SkCanvas::onDrawPaint(const SkPaint& paint) {
2063    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPaint()");
2064    this->internalDrawPaint(paint);
2065}
2066
2067void SkCanvas::internalDrawPaint(const SkPaint& paint) {
2068    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
2069
2070    while (iter.next()) {
2071        iter.fDevice->drawPaint(iter, looper.paint());
2072    }
2073
2074    LOOPER_END
2075}
2076
2077void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
2078                            const SkPaint& paint) {
2079    TRACE_EVENT1("disabled-by-default-skia", "SkCanvas::drawPoints()", "count", static_cast<uint64_t>(count));
2080    if ((long)count <= 0) {
2081        return;
2082    }
2083
2084    SkRect r, storage;
2085    const SkRect* bounds = nullptr;
2086    if (paint.canComputeFastBounds()) {
2087        // special-case 2 points (common for drawing a single line)
2088        if (2 == count) {
2089            r.set(pts[0], pts[1]);
2090        } else {
2091            r.set(pts, SkToInt(count));
2092        }
2093        if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
2094            return;
2095        }
2096        bounds = &r;
2097    }
2098
2099    SkASSERT(pts != nullptr);
2100
2101    LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
2102
2103    while (iter.next()) {
2104        iter.fDevice->drawPoints(iter, mode, count, pts, looper.paint());
2105    }
2106
2107    LOOPER_END
2108}
2109
2110void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
2111    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRect()");
2112    SkRect storage;
2113    const SkRect* bounds = nullptr;
2114    if (paint.canComputeFastBounds()) {
2115        // Skia will draw an inverted rect, because it explicitly "sorts" it downstream.
2116        // To prevent accidental rejecting at this stage, we have to sort it before we check.
2117        SkRect tmp(r);
2118        tmp.sort();
2119
2120        if (this->quickReject(paint.computeFastBounds(tmp, &storage))) {
2121            return;
2122        }
2123        bounds = &r;
2124    }
2125
2126    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, bounds, false)
2127
2128    while (iter.next()) {
2129        iter.fDevice->drawRect(iter, r, looper.paint());
2130    }
2131
2132    LOOPER_END
2133}
2134
2135void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
2136    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawOval()");
2137    SkRect storage;
2138    const SkRect* bounds = nullptr;
2139    if (paint.canComputeFastBounds()) {
2140        if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2141            return;
2142        }
2143        bounds = &oval;
2144    }
2145
2146    LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, bounds)
2147
2148    while (iter.next()) {
2149        iter.fDevice->drawOval(iter, oval, looper.paint());
2150    }
2151
2152    LOOPER_END
2153}
2154
2155void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
2156    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRRect()");
2157    SkRect storage;
2158    const SkRect* bounds = nullptr;
2159    if (paint.canComputeFastBounds()) {
2160        if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
2161            return;
2162        }
2163        bounds = &rrect.getBounds();
2164    }
2165
2166    if (rrect.isRect()) {
2167        // call the non-virtual version
2168        this->SkCanvas::drawRect(rrect.getBounds(), paint);
2169        return;
2170    } else if (rrect.isOval()) {
2171        // call the non-virtual version
2172        this->SkCanvas::drawOval(rrect.getBounds(), paint);
2173        return;
2174    }
2175
2176    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2177
2178    while (iter.next()) {
2179        iter.fDevice->drawRRect(iter, rrect, looper.paint());
2180    }
2181
2182    LOOPER_END
2183}
2184
2185void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
2186                            const SkPaint& paint) {
2187    SkRect storage;
2188    const SkRect* bounds = nullptr;
2189    if (paint.canComputeFastBounds()) {
2190        if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
2191            return;
2192        }
2193        bounds = &outer.getBounds();
2194    }
2195
2196    LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, bounds)
2197
2198    while (iter.next()) {
2199        iter.fDevice->drawDRRect(iter, outer, inner, looper.paint());
2200    }
2201
2202    LOOPER_END
2203}
2204
2205void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
2206    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPath()");
2207    if (!path.isFinite()) {
2208        return;
2209    }
2210
2211    SkRect storage;
2212    const SkRect* bounds = nullptr;
2213    if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
2214        const SkRect& pathBounds = path.getBounds();
2215        if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
2216            return;
2217        }
2218        bounds = &pathBounds;
2219    }
2220
2221    const SkRect& r = path.getBounds();
2222    if (r.width() <= 0 && r.height() <= 0) {
2223        if (path.isInverseFillType()) {
2224            this->internalDrawPaint(paint);
2225            return;
2226        }
2227    }
2228
2229    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, bounds)
2230
2231    while (iter.next()) {
2232        iter.fDevice->drawPath(iter, path, looper.paint());
2233    }
2234
2235    LOOPER_END
2236}
2237
2238bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2239    if (!paint.getImageFilter()) {
2240        return false;
2241    }
2242
2243    const SkMatrix& ctm = this->getTotalMatrix();
2244    if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2245        return false;
2246    }
2247
2248    // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2249    // Once we can filter and the filter will return a result larger than itself, we should be
2250    // able to remove this constraint.
2251    // skbug.com/4526
2252    //
2253    SkPoint pt;
2254    ctm.mapXY(x, y, &pt);
2255    SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2256    return ir.contains(fMCRec->fRasterClip.getBounds());
2257}
2258
2259void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
2260    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()");
2261    SkRect bounds = SkRect::MakeXYWH(x, y,
2262                                     SkIntToScalar(image->width()), SkIntToScalar(image->height()));
2263    if (nullptr == paint || paint->canComputeFastBounds()) {
2264        SkRect tmp = bounds;
2265        if (paint) {
2266            paint->computeFastBounds(tmp, &tmp);
2267        }
2268        if (this->quickReject(tmp)) {
2269            return;
2270        }
2271    }
2272
2273    SkLazyPaint lazy;
2274    if (nullptr == paint) {
2275        paint = lazy.init();
2276    }
2277
2278    bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2279                                                    *paint);
2280    if (drawAsSprite && paint->getImageFilter()) {
2281        SkBitmap bitmap;
2282        if (!as_IB(image)->asBitmapForImageFilters(&bitmap)) {
2283            drawAsSprite = false;
2284        } else{
2285            // Until imagefilters are updated, they cannot handle any src type but N32...
2286            if (bitmap.info().colorType() != kN32_SkColorType || bitmap.info().isSRGB()) {
2287                drawAsSprite = false;
2288            }
2289        }
2290    }
2291
2292    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2293
2294    while (iter.next()) {
2295        const SkPaint& pnt = looper.paint();
2296        if (drawAsSprite && pnt.getImageFilter()) {
2297            SkBitmap bitmap;
2298            if (as_IB(image)->asBitmapForImageFilters(&bitmap)) {
2299                SkPoint pt;
2300                iter.fMatrix->mapXY(x, y, &pt);
2301                iter.fDevice->drawSpriteWithFilter(iter, bitmap,
2302                                                   SkScalarRoundToInt(pt.fX),
2303                                                   SkScalarRoundToInt(pt.fY), pnt);
2304            }
2305        } else {
2306            iter.fDevice->drawImage(iter, image, x, y, pnt);
2307        }
2308    }
2309
2310    LOOPER_END
2311}
2312
2313void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2314                               const SkPaint* paint, SrcRectConstraint constraint) {
2315    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageRect()");
2316    if (nullptr == paint || paint->canComputeFastBounds()) {
2317        SkRect storage = dst;
2318        if (paint) {
2319            paint->computeFastBounds(dst, &storage);
2320        }
2321        if (this->quickReject(storage)) {
2322            return;
2323        }
2324    }
2325    SkLazyPaint lazy;
2326    if (nullptr == paint) {
2327        paint = lazy.init();
2328    }
2329
2330    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2331                                          image->isOpaque())
2332
2333    while (iter.next()) {
2334        iter.fDevice->drawImageRect(iter, image, src, dst, looper.paint(), constraint);
2335    }
2336
2337    LOOPER_END
2338}
2339
2340void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
2341    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmap()");
2342    SkDEBUGCODE(bitmap.validate();)
2343
2344    if (bitmap.drawsNothing()) {
2345        return;
2346    }
2347
2348    SkLazyPaint lazy;
2349    if (nullptr == paint) {
2350        paint = lazy.init();
2351    }
2352
2353    const SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2354
2355    SkRect storage;
2356    const SkRect* bounds = nullptr;
2357    if (paint->canComputeFastBounds()) {
2358        bitmap.getBounds(&storage);
2359        matrix.mapRect(&storage);
2360        SkRect tmp = storage;
2361        if (this->quickReject(paint->computeFastBounds(tmp, &tmp))) {
2362            return;
2363        }
2364        bounds = &storage;
2365    }
2366
2367    bool drawAsSprite = bounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(), bitmap.height(),
2368                                                              *paint);
2369    if (drawAsSprite && paint->getImageFilter()) {
2370        // Until imagefilters are updated, they cannot handle any src type but N32...
2371        if (bitmap.info().colorType() != kN32_SkColorType || bitmap.info().isSRGB()) {
2372            drawAsSprite = false;
2373        }
2374    }
2375
2376    LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, bounds)
2377
2378    while (iter.next()) {
2379        const SkPaint& pnt = looper.paint();
2380        if (drawAsSprite && pnt.getImageFilter()) {
2381            SkPoint pt;
2382            iter.fMatrix->mapXY(x, y, &pt);
2383            iter.fDevice->drawSpriteWithFilter(iter, bitmap,
2384                                               SkScalarRoundToInt(pt.fX),
2385                                               SkScalarRoundToInt(pt.fY), pnt);
2386        } else {
2387            iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint());
2388        }
2389    }
2390
2391    LOOPER_END
2392}
2393
2394// this one is non-virtual, so it can be called safely by other canvas apis
2395void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2396                                      const SkRect& dst, const SkPaint* paint,
2397                                      SrcRectConstraint constraint) {
2398    if (bitmap.drawsNothing() || dst.isEmpty()) {
2399        return;
2400    }
2401
2402    if (nullptr == paint || paint->canComputeFastBounds()) {
2403        SkRect storage;
2404        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2405            return;
2406        }
2407    }
2408
2409    SkLazyPaint lazy;
2410    if (nullptr == paint) {
2411        paint = lazy.init();
2412    }
2413
2414    LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2415                                          bitmap.isOpaque())
2416
2417    while (iter.next()) {
2418        iter.fDevice->drawBitmapRect(iter, bitmap, src, dst, looper.paint(), constraint);
2419    }
2420
2421    LOOPER_END
2422}
2423
2424void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2425                                const SkPaint* paint, SrcRectConstraint constraint) {
2426    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapRectToRect()");
2427    SkDEBUGCODE(bitmap.validate();)
2428    this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
2429}
2430
2431void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
2432                               const SkPaint* paint) {
2433    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImageNine()");
2434
2435    if (nullptr == paint || paint->canComputeFastBounds()) {
2436        SkRect storage;
2437        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2438            return;
2439        }
2440    }
2441
2442    SkLazyPaint lazy;
2443    if (nullptr == paint) {
2444        paint = lazy.init();
2445    }
2446
2447    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2448
2449    while (iter.next()) {
2450        iter.fDevice->drawImageNine(iter, image, center, dst, looper.paint());
2451    }
2452
2453    LOOPER_END
2454}
2455
2456void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
2457                                const SkPaint* paint) {
2458    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawBitmapNine()");
2459    SkDEBUGCODE(bitmap.validate();)
2460
2461    if (nullptr == paint || paint->canComputeFastBounds()) {
2462        SkRect storage;
2463        if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2464            return;
2465        }
2466    }
2467
2468    SkLazyPaint lazy;
2469    if (nullptr == paint) {
2470        paint = lazy.init();
2471    }
2472
2473    LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2474
2475    while (iter.next()) {
2476        iter.fDevice->drawBitmapNine(iter, bitmap, center, dst, looper.paint());
2477    }
2478
2479    LOOPER_END
2480}
2481
2482class SkDeviceFilteredPaint {
2483public:
2484    SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2485        uint32_t filteredFlags = device->filterTextFlags(paint);
2486        if (filteredFlags != paint.getFlags()) {
2487            SkPaint* newPaint = fLazy.set(paint);
2488            newPaint->setFlags(filteredFlags);
2489            fPaint = newPaint;
2490        } else {
2491            fPaint = &paint;
2492        }
2493    }
2494
2495    const SkPaint& paint() const { return *fPaint; }
2496
2497private:
2498    const SkPaint*  fPaint;
2499    SkLazyPaint     fLazy;
2500};
2501
2502void SkCanvas::DrawRect(const SkDraw& draw, const SkPaint& paint,
2503                        const SkRect& r, SkScalar textSize) {
2504    if (paint.getStyle() == SkPaint::kFill_Style) {
2505        draw.fDevice->drawRect(draw, r, paint);
2506    } else {
2507        SkPaint p(paint);
2508        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
2509        draw.fDevice->drawRect(draw, r, p);
2510    }
2511}
2512
2513void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
2514                                   const char text[], size_t byteLength,
2515                                   SkScalar x, SkScalar y) {
2516    SkASSERT(byteLength == 0 || text != nullptr);
2517
2518    // nothing to draw
2519    if (text == nullptr || byteLength == 0 ||
2520        draw.fRC->isEmpty() ||
2521        (paint.getAlpha() == 0 && paint.getXfermode() == nullptr)) {
2522        return;
2523    }
2524
2525    SkScalar    width = 0;
2526    SkPoint     start;
2527
2528    start.set(0, 0);    // to avoid warning
2529    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
2530                            SkPaint::kStrikeThruText_Flag)) {
2531        width = paint.measureText(text, byteLength);
2532
2533        SkScalar offsetX = 0;
2534        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2535            offsetX = SkScalarHalf(width);
2536        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
2537            offsetX = width;
2538        }
2539        start.set(x - offsetX, y);
2540    }
2541
2542    if (0 == width) {
2543        return;
2544    }
2545
2546    uint32_t flags = paint.getFlags();
2547
2548    if (flags & (SkPaint::kUnderlineText_Flag |
2549                 SkPaint::kStrikeThruText_Flag)) {
2550        SkScalar textSize = paint.getTextSize();
2551        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
2552        SkRect   r;
2553
2554        r.fLeft = start.fX;
2555        r.fRight = start.fX + width;
2556
2557        if (flags & SkPaint::kUnderlineText_Flag) {
2558            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
2559                                             start.fY);
2560            r.fTop = offset;
2561            r.fBottom = offset + height;
2562            DrawRect(draw, paint, r, 1);
2563        }
2564        if (flags & SkPaint::kStrikeThruText_Flag) {
2565            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
2566                                             start.fY);
2567            r.fTop = offset;
2568            r.fBottom = offset + height;
2569            DrawRect(draw, paint, r, 1);
2570        }
2571    }
2572}
2573
2574void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2575                          const SkPaint& paint) {
2576    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2577
2578    while (iter.next()) {
2579        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2580        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
2581        DrawTextDecorations(iter, dfp.paint(),
2582                            static_cast<const char*>(text), byteLength, x, y);
2583    }
2584
2585    LOOPER_END
2586}
2587
2588void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2589                             const SkPaint& paint) {
2590    SkPoint textOffset = SkPoint::Make(0, 0);
2591
2592    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2593
2594    while (iter.next()) {
2595        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2596        iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 2, textOffset,
2597                                  dfp.paint());
2598    }
2599
2600    LOOPER_END
2601}
2602
2603void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2604                              SkScalar constY, const SkPaint& paint) {
2605
2606    SkPoint textOffset = SkPoint::Make(0, constY);
2607
2608    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2609
2610    while (iter.next()) {
2611        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2612        iter.fDevice->drawPosText(iter, text, byteLength, xpos, 1, textOffset,
2613                                  dfp.paint());
2614    }
2615
2616    LOOPER_END
2617}
2618
2619void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2620                                const SkMatrix* matrix, const SkPaint& paint) {
2621    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2622
2623    while (iter.next()) {
2624        iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
2625                                     matrix, looper.paint());
2626    }
2627
2628    LOOPER_END
2629}
2630
2631void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2632                              const SkPaint& paint) {
2633
2634    SkRect storage;
2635    const SkRect* bounds = nullptr;
2636    if (paint.canComputeFastBounds()) {
2637        storage = blob->bounds().makeOffset(x, y);
2638        SkRect tmp;
2639        if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
2640            return;
2641        }
2642        bounds = &storage;
2643    }
2644
2645    // We cannot filter in the looper as we normally do, because the paint is
2646    // incomplete at this point (text-related attributes are embedded within blob run paints).
2647    SkDrawFilter* drawFilter = fMCRec->fFilter;
2648    fMCRec->fFilter = nullptr;
2649
2650    LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
2651
2652    while (iter.next()) {
2653        SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2654        iter.fDevice->drawTextBlob(iter, blob, x, y, dfp.paint(), drawFilter);
2655    }
2656
2657    LOOPER_END
2658
2659    fMCRec->fFilter = drawFilter;
2660}
2661
2662// These will become non-virtual, so they always call the (virtual) onDraw... method
2663void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2664                        const SkPaint& paint) {
2665    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawText()");
2666    this->onDrawText(text, byteLength, x, y, paint);
2667}
2668void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2669                           const SkPaint& paint) {
2670    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosText()");
2671    this->onDrawPosText(text, byteLength, pos, paint);
2672}
2673void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2674                            SkScalar constY, const SkPaint& paint) {
2675    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPosTextH()");
2676    this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2677}
2678void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2679                              const SkMatrix* matrix, const SkPaint& paint) {
2680    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPath()");
2681    this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2682}
2683void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2684                            const SkPaint& paint) {
2685    RETURN_ON_NULL(blob);
2686    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextBlob()");
2687    this->onDrawTextBlob(blob, x, y, paint);
2688}
2689
2690void SkCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
2691                              const SkPoint verts[], const SkPoint texs[],
2692                              const SkColor colors[], SkXfermode* xmode,
2693                              const uint16_t indices[], int indexCount,
2694                              const SkPaint& paint) {
2695    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawVertices()");
2696    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2697
2698    while (iter.next()) {
2699        iter.fDevice->drawVertices(iter, vmode, vertexCount, verts, texs,
2700                                   colors, xmode, indices, indexCount,
2701                                   looper.paint());
2702    }
2703
2704    LOOPER_END
2705}
2706
2707void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2708                         const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2709    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPatch()");
2710    if (nullptr == cubics) {
2711        return;
2712    }
2713
2714    // Since a patch is always within the convex hull of the control points, we discard it when its
2715    // bounding rectangle is completely outside the current clip.
2716    SkRect bounds;
2717    bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2718    if (this->quickReject(bounds)) {
2719        return;
2720    }
2721
2722    this->onDrawPatch(cubics, colors, texCoords, xmode, paint);
2723}
2724
2725void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2726                           const SkPoint texCoords[4], SkXfermode* xmode, const SkPaint& paint) {
2727
2728    LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2729
2730    while (iter.next()) {
2731        iter.fDevice->drawPatch(iter, cubics, colors, texCoords, xmode, paint);
2732    }
2733
2734    LOOPER_END
2735}
2736
2737void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2738    RETURN_ON_NULL(dr);
2739    if (x || y) {
2740        SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2741        this->onDrawDrawable(dr, &matrix);
2742    } else {
2743        this->onDrawDrawable(dr, nullptr);
2744    }
2745}
2746
2747void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2748    RETURN_ON_NULL(dr);
2749    if (matrix && matrix->isIdentity()) {
2750        matrix = nullptr;
2751    }
2752    this->onDrawDrawable(dr, matrix);
2753}
2754
2755void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2756    SkRect bounds = dr->getBounds();
2757    if (matrix) {
2758        matrix->mapRect(&bounds);
2759    }
2760    if (this->quickReject(bounds)) {
2761        return;
2762    }
2763    dr->draw(this, matrix);
2764}
2765
2766void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2767                           const SkColor colors[], int count, SkXfermode::Mode mode,
2768                           const SkRect* cull, const SkPaint* paint) {
2769    if (cull && this->quickReject(*cull)) {
2770        return;
2771    }
2772
2773    SkPaint pnt;
2774    if (paint) {
2775        pnt = *paint;
2776    }
2777
2778    LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
2779    while (iter.next()) {
2780        iter.fDevice->drawAtlas(iter, atlas, xform, tex, colors, count, mode, pnt);
2781    }
2782    LOOPER_END
2783}
2784
2785void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2786    SkASSERT(key);
2787
2788    SkPaint paint;
2789    LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
2790    while (iter.next()) {
2791        iter.fDevice->drawAnnotation(iter, rect, key, value);
2792    }
2793    LOOPER_END
2794}
2795
2796//////////////////////////////////////////////////////////////////////////////
2797// These methods are NOT virtual, and therefore must call back into virtual
2798// methods, rather than actually drawing themselves.
2799//////////////////////////////////////////////////////////////////////////////
2800
2801void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b,
2802                        SkXfermode::Mode mode) {
2803    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()");
2804    SkPaint paint;
2805
2806    paint.setARGB(a, r, g, b);
2807    if (SkXfermode::kSrcOver_Mode != mode) {
2808        paint.setXfermodeMode(mode);
2809    }
2810    this->drawPaint(paint);
2811}
2812
2813void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) {
2814    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()");
2815    SkPaint paint;
2816
2817    paint.setColor(c);
2818    if (SkXfermode::kSrcOver_Mode != mode) {
2819        paint.setXfermodeMode(mode);
2820    }
2821    this->drawPaint(paint);
2822}
2823
2824void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2825    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkPaint)");
2826    SkPoint pt;
2827
2828    pt.set(x, y);
2829    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2830}
2831
2832void SkCanvas::drawPoint(SkScalar x, SkScalar y, SkColor color) {
2833    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPoint(SkColor)");
2834    SkPoint pt;
2835    SkPaint paint;
2836
2837    pt.set(x, y);
2838    paint.setColor(color);
2839    this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2840}
2841
2842void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1,
2843                        const SkPaint& paint) {
2844    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawLine()");
2845    SkPoint pts[2];
2846
2847    pts[0].set(x0, y0);
2848    pts[1].set(x1, y1);
2849    this->drawPoints(kLines_PointMode, 2, pts, paint);
2850}
2851
2852void SkCanvas::drawRectCoords(SkScalar left, SkScalar top,
2853                              SkScalar right, SkScalar bottom,
2854                              const SkPaint& paint) {
2855    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRectCoords()");
2856    SkRect  r;
2857
2858    r.set(left, top, right, bottom);
2859    this->drawRect(r, paint);
2860}
2861
2862void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius,
2863                          const SkPaint& paint) {
2864    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawCircle()");
2865    if (radius < 0) {
2866        radius = 0;
2867    }
2868
2869    SkRect  r;
2870    r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2871    this->drawOval(r, paint);
2872}
2873
2874void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2875                             const SkPaint& paint) {
2876    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawRoundRect()");
2877    if (rx > 0 && ry > 0) {
2878        if (paint.canComputeFastBounds()) {
2879            SkRect storage;
2880            if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2881                return;
2882            }
2883        }
2884        SkRRect rrect;
2885        rrect.setRectXY(r, rx, ry);
2886        this->drawRRect(rrect, paint);
2887    } else {
2888        this->drawRect(r, paint);
2889    }
2890}
2891
2892void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2893                       SkScalar sweepAngle, bool useCenter,
2894                       const SkPaint& paint) {
2895    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawArc()");
2896    if (SkScalarAbs(sweepAngle) >= SkIntToScalar(360)) {
2897        this->drawOval(oval, paint);
2898    } else {
2899        SkPath  path;
2900        if (useCenter) {
2901            path.moveTo(oval.centerX(), oval.centerY());
2902        }
2903        path.arcTo(oval, startAngle, sweepAngle, !useCenter);
2904        if (useCenter) {
2905            path.close();
2906        }
2907        this->drawPath(path, paint);
2908    }
2909}
2910
2911void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2912                                const SkPath& path, SkScalar hOffset,
2913                                SkScalar vOffset, const SkPaint& paint) {
2914    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawTextOnPathHV()");
2915    SkMatrix    matrix;
2916
2917    matrix.setTranslate(hOffset, vOffset);
2918    this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2919}
2920
2921///////////////////////////////////////////////////////////////////////////////
2922
2923/**
2924 *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
2925 *  against the playback cost of recursing into the subpicture to get at its actual ops.
2926 *
2927 *  For now we pick a conservatively small value, though measurement (and other heuristics like
2928 *  the type of ops contained) may justify changing this value.
2929 */
2930#define kMaxPictureOpsToUnrollInsteadOfRef  1
2931
2932void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2933    RETURN_ON_NULL(picture);
2934
2935    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawPicture()");
2936    if (matrix && matrix->isIdentity()) {
2937        matrix = nullptr;
2938    }
2939    if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
2940        SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2941        picture->playback(this);
2942    } else {
2943        this->onDrawPicture(picture, matrix, paint);
2944    }
2945}
2946
2947void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2948                             const SkPaint* paint) {
2949    if (!paint || paint->canComputeFastBounds()) {
2950        SkRect bounds = picture->cullRect();
2951        if (paint) {
2952            paint->computeFastBounds(bounds, &bounds);
2953        }
2954        if (matrix) {
2955            matrix->mapRect(&bounds);
2956        }
2957        if (this->quickReject(bounds)) {
2958            return;
2959        }
2960    }
2961
2962    SkBaseDevice* device = this->getTopDevice();
2963    if (device) {
2964        // Canvas has to first give the device the opportunity to render
2965        // the picture itself.
2966        if (device->EXPERIMENTAL_drawPicture(this, picture, matrix, paint)) {
2967            return; // the device has rendered the entire picture
2968        }
2969    }
2970
2971    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2972    picture->playback(this);
2973}
2974
2975///////////////////////////////////////////////////////////////////////////////
2976///////////////////////////////////////////////////////////////////////////////
2977
2978SkCanvas::LayerIter::LayerIter(SkCanvas* canvas, bool skipEmptyClips) {
2979    static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
2980
2981    SkASSERT(canvas);
2982
2983    fImpl = new (fStorage) SkDrawIter(canvas, skipEmptyClips);
2984    fDone = !fImpl->next();
2985}
2986
2987SkCanvas::LayerIter::~LayerIter() {
2988    fImpl->~SkDrawIter();
2989}
2990
2991void SkCanvas::LayerIter::next() {
2992    fDone = !fImpl->next();
2993}
2994
2995SkBaseDevice* SkCanvas::LayerIter::device() const {
2996    return fImpl->getDevice();
2997}
2998
2999const SkMatrix& SkCanvas::LayerIter::matrix() const {
3000    return fImpl->getMatrix();
3001}
3002
3003const SkPaint& SkCanvas::LayerIter::paint() const {
3004    const SkPaint* paint = fImpl->getPaint();
3005    if (nullptr == paint) {
3006        paint = &fDefaultPaint;
3007    }
3008    return *paint;
3009}
3010
3011const SkRasterClip& SkCanvas::LayerIter::clip() const { return fImpl->getClip(); }
3012int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
3013int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
3014
3015///////////////////////////////////////////////////////////////////////////////
3016
3017SkCanvasClipVisitor::~SkCanvasClipVisitor() { }
3018
3019///////////////////////////////////////////////////////////////////////////////
3020
3021static bool supported_for_raster_canvas(const SkImageInfo& info) {
3022    switch (info.alphaType()) {
3023        case kPremul_SkAlphaType:
3024        case kOpaque_SkAlphaType:
3025            break;
3026        default:
3027            return false;
3028    }
3029
3030    switch (info.colorType()) {
3031        case kAlpha_8_SkColorType:
3032        case kRGB_565_SkColorType:
3033        case kN32_SkColorType:
3034            break;
3035        default:
3036            return false;
3037    }
3038
3039    return true;
3040}
3041
3042SkCanvas* SkCanvas::NewRasterDirect(const SkImageInfo& info, void* pixels, size_t rowBytes) {
3043    if (!supported_for_raster_canvas(info)) {
3044        return nullptr;
3045    }
3046
3047    SkBitmap bitmap;
3048    if (!bitmap.installPixels(info, pixels, rowBytes)) {
3049        return nullptr;
3050    }
3051    return new SkCanvas(bitmap);
3052}
3053
3054///////////////////////////////////////////////////////////////////////////////
3055
3056SkAutoCanvasMatrixPaint::SkAutoCanvasMatrixPaint(SkCanvas* canvas, const SkMatrix* matrix,
3057                                                 const SkPaint* paint, const SkRect& bounds)
3058    : fCanvas(canvas)
3059    , fSaveCount(canvas->getSaveCount())
3060{
3061    if (paint) {
3062        SkRect newBounds = bounds;
3063        if (matrix) {
3064            matrix->mapRect(&newBounds);
3065        }
3066        canvas->saveLayer(&newBounds, paint);
3067    } else if (matrix) {
3068        canvas->save();
3069    }
3070
3071    if (matrix) {
3072        canvas->concat(*matrix);
3073    }
3074}
3075
3076SkAutoCanvasMatrixPaint::~SkAutoCanvasMatrixPaint() {
3077    fCanvas->restoreToCount(fSaveCount);
3078}
3079
3080#ifdef SK_SUPPORT_LEGACY_NEW_SURFACE_API
3081SkSurface* SkCanvas::newSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
3082    return this->makeSurface(info, props).release();
3083}
3084#endif
3085