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