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