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