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