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