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