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