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