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