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