• 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 imgCF->makeComposed(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,const SkPaint * paint)1039 static SkImageInfo make_layer_info(const SkImageInfo& prev, int w, int h, const SkPaint* paint) {
1040     // Need to force L32 for now if we have an image filter.
1041     // If filters ever support other colortypes, e.g. sRGB or F16, we can remove this check.
1042     if (paint && paint->getImageFilter()) {
1043         return SkImageInfo::MakeN32Premul(w, h);
1044     }
1045 
1046     SkColorType ct = prev.colorType();
1047     if (prev.bytesPerPixel() <= 4) {
1048         // "Upgrade" A8, G8, 565, 4444, 1010102, 101010x, and 888x to 8888,
1049         // ensuring plenty of alpha bits for the layer, perhaps losing some color bits in return.
1050         ct = kN32_SkColorType;
1051     }
1052     return SkImageInfo::Make(w, h, ct, kPremul_SkAlphaType, prev.refColorSpace());
1053 }
1054 
internalSaveLayer(const SaveLayerRec & rec,SaveLayerStrategy strategy)1055 void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy strategy) {
1056     const SkRect* bounds = rec.fBounds;
1057     const SkPaint* paint = rec.fPaint;
1058     SaveLayerFlags saveLayerFlags = rec.fSaveLayerFlags;
1059 
1060     SkLazyPaint lazyP;
1061     SkImageFilter* imageFilter = paint ? paint->getImageFilter() : nullptr;
1062     SkMatrix stashedMatrix = fMCRec->fMatrix;
1063     SkMatrix remainder;
1064     SkSize scale;
1065     /*
1066      *  ImageFilters (so far) do not correctly handle matrices (CTM) that contain rotation/skew/etc.
1067      *  but they do handle scaling. To accommodate this, we do the following:
1068      *
1069      *  1. Stash off the current CTM
1070      *  2. Decompose the CTM into SCALE and REMAINDER
1071      *  3. Wack the CTM to be just SCALE, and wrap the imagefilter with a MatrixImageFilter that
1072      *     contains the REMAINDER
1073      *  4. Proceed as usual, allowing the client to draw into the layer (now with a scale-only CTM)
1074      *  5. During restore, we process the MatrixImageFilter, which applies REMAINDER to the output
1075      *     of the original imagefilter, and draw that (via drawSprite)
1076      *  6. Unwack the CTM to its original state (i.e. stashedMatrix)
1077      *
1078      *  Perhaps in the future we could augment #5 to apply REMAINDER as part of the draw (no longer
1079      *  a sprite operation) to avoid the extra buffer/overhead of MatrixImageFilter.
1080      */
1081     if (imageFilter && !stashedMatrix.isScaleTranslate() && !imageFilter->canHandleComplexCTM() &&
1082         stashedMatrix.decomposeScale(&scale, &remainder))
1083     {
1084         // We will restore the matrix (which we are overwriting here) in restore via fStashedMatrix
1085         this->internalSetMatrix(SkMatrix::MakeScale(scale.width(), scale.height()));
1086         SkPaint* p = lazyP.set(*paint);
1087         p->setImageFilter(SkImageFilter::MakeMatrixFilter(remainder,
1088                                                           SkFilterQuality::kLow_SkFilterQuality,
1089                                                           sk_ref_sp(imageFilter)));
1090         imageFilter = p->getImageFilter();
1091         paint = p;
1092     }
1093 
1094     // do this before we create the layer. We don't call the public save() since
1095     // that would invoke a possibly overridden virtual
1096     this->internalSave();
1097 
1098     SkIRect ir;
1099     if (!this->clipRectBounds(bounds, saveLayerFlags, &ir, imageFilter)) {
1100         return;
1101     }
1102 
1103     // FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
1104     // the clipRectBounds() call above?
1105     if (kNoLayer_SaveLayerStrategy == strategy) {
1106         return;
1107     }
1108 
1109     SkPixelGeometry geo = fProps.pixelGeometry();
1110     if (paint) {
1111         // TODO: perhaps add a query to filters so we might preserve opaqueness...
1112         if (paint->getImageFilter() || paint->getColorFilter()) {
1113             geo = kUnknown_SkPixelGeometry;
1114         }
1115     }
1116 
1117     SkBaseDevice* priorDevice = this->getTopDevice();
1118     if (nullptr == priorDevice) {   // Do we still need this check???
1119         SkDebugf("Unable to find device for layer.");
1120         return;
1121     }
1122 
1123     SkImageInfo info = make_layer_info(priorDevice->imageInfo(), ir.width(), ir.height(), paint);
1124 
1125     sk_sp<SkBaseDevice> newDevice;
1126     {
1127         const bool preserveLCDText = kOpaque_SkAlphaType == info.alphaType() ||
1128                                      (saveLayerFlags & kPreserveLCDText_SaveLayerFlag);
1129         const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
1130         const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
1131                                                                              preserveLCDText,
1132                                                                              fAllocator.get());
1133         newDevice.reset(priorDevice->onCreateDevice(createInfo, paint));
1134         if (!newDevice) {
1135             return;
1136         }
1137     }
1138     DeviceCM* layer = new DeviceCM(newDevice, paint, stashedMatrix, rec.fClipMask, rec.fClipMatrix);
1139 
1140     // only have a "next" if this new layer doesn't affect the clip (rare)
1141     layer->fNext = BoundsAffectsClip(saveLayerFlags) ? nullptr : fMCRec->fTopLayer;
1142     fMCRec->fLayer = layer;
1143     fMCRec->fTopLayer = layer;    // this field is NOT an owner of layer
1144 
1145     if ((rec.fSaveLayerFlags & kInitWithPrevious_SaveLayerFlag) || rec.fBackdrop) {
1146         DrawDeviceWithFilter(priorDevice, rec.fBackdrop, newDevice.get(), { ir.fLeft, ir.fTop },
1147                              fMCRec->fMatrix);
1148     }
1149 
1150     newDevice->setOrigin(fMCRec->fMatrix, ir.fLeft, ir.fTop);
1151 
1152     newDevice->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect);
1153     if (layer->fNext) {
1154         // need to punch a hole in the previous device, so we don't draw there, given that
1155         // the new top-layer will allow drawing to happen "below" it.
1156         SkRegion hole(ir);
1157         do {
1158             layer = layer->fNext;
1159             layer->fDevice->clipRegion(hole, SkClipOp::kDifference);
1160         } while (layer->fNext);
1161     }
1162 }
1163 
saveLayerAlpha(const SkRect * bounds,U8CPU alpha)1164 int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
1165     if (0xFF == alpha) {
1166         return this->saveLayer(bounds, nullptr);
1167     } else {
1168         SkPaint tmpPaint;
1169         tmpPaint.setAlpha(alpha);
1170         return this->saveLayer(bounds, &tmpPaint);
1171     }
1172 }
1173 
internalRestore()1174 void SkCanvas::internalRestore() {
1175     SkASSERT(fMCStack.count() != 0);
1176 
1177     // reserve our layer (if any)
1178     DeviceCM* layer = fMCRec->fLayer;   // may be null
1179     // now detach it from fMCRec so we can pop(). Gets freed after its drawn
1180     fMCRec->fLayer = nullptr;
1181 
1182     // now do the normal restore()
1183     fMCRec->~MCRec();       // balanced in save()
1184     fMCStack.pop_back();
1185     fMCRec = (MCRec*)fMCStack.back();
1186 
1187     if (fMCRec) {
1188         FOR_EACH_TOP_DEVICE(device->restore(fMCRec->fMatrix));
1189     }
1190 
1191     /*  Time to draw the layer's offscreen. We can't call the public drawSprite,
1192         since if we're being recorded, we don't want to record this (the
1193         recorder will have already recorded the restore).
1194     */
1195     if (layer) {
1196         if (fMCRec) {
1197             const SkIPoint& origin = layer->fDevice->getOrigin();
1198             this->internalDrawDevice(layer->fDevice.get(), origin.x(), origin.y(),
1199                                      layer->fPaint.get(),
1200                                      layer->fClipImage.get(), layer->fClipMatrix);
1201             // restore what we smashed in internalSaveLayer
1202             fMCRec->fMatrix = layer->fStashedMatrix;
1203             // reset this, since internalDrawDevice will have set it to true
1204             delete layer;
1205         } else {
1206             // we're at the root
1207             SkASSERT(layer == (void*)fDeviceCMStorage);
1208             layer->~DeviceCM();
1209             // no need to update fMCRec, 'cause we're killing the canvas
1210         }
1211     }
1212 
1213     if (fMCRec) {
1214         fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
1215         fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1216     }
1217 }
1218 
makeSurface(const SkImageInfo & info,const SkSurfaceProps * props)1219 sk_sp<SkSurface> SkCanvas::makeSurface(const SkImageInfo& info, const SkSurfaceProps* props) {
1220     if (nullptr == props) {
1221         props = &fProps;
1222     }
1223     return this->onNewSurface(info, *props);
1224 }
1225 
onNewSurface(const SkImageInfo & info,const SkSurfaceProps & props)1226 sk_sp<SkSurface> SkCanvas::onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
1227     SkBaseDevice* dev = this->getDevice();
1228     return dev ? dev->makeSurface(info, props) : nullptr;
1229 }
1230 
imageInfo() const1231 SkImageInfo SkCanvas::imageInfo() const {
1232     return this->onImageInfo();
1233 }
1234 
onImageInfo() const1235 SkImageInfo SkCanvas::onImageInfo() const {
1236     SkBaseDevice* dev = this->getDevice();
1237     if (dev) {
1238         return dev->imageInfo();
1239     } else {
1240         return SkImageInfo::MakeUnknown(0, 0);
1241     }
1242 }
1243 
getProps(SkSurfaceProps * props) const1244 bool SkCanvas::getProps(SkSurfaceProps* props) const {
1245     return this->onGetProps(props);
1246 }
1247 
onGetProps(SkSurfaceProps * props) const1248 bool SkCanvas::onGetProps(SkSurfaceProps* props) const {
1249     SkBaseDevice* dev = this->getDevice();
1250     if (dev) {
1251         if (props) {
1252             *props = fProps;
1253         }
1254         return true;
1255     } else {
1256         return false;
1257     }
1258 }
1259 
peekPixels(SkPixmap * pmap)1260 bool SkCanvas::peekPixels(SkPixmap* pmap) {
1261     return this->onPeekPixels(pmap);
1262 }
1263 
onPeekPixels(SkPixmap * pmap)1264 bool SkCanvas::onPeekPixels(SkPixmap* pmap) {
1265     SkBaseDevice* dev = this->getDevice();
1266     return dev && dev->peekPixels(pmap);
1267 }
1268 
accessTopLayerPixels(SkImageInfo * info,size_t * rowBytes,SkIPoint * origin)1269 void* SkCanvas::accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin) {
1270     SkPixmap pmap;
1271     if (!this->onAccessTopLayerPixels(&pmap)) {
1272         return nullptr;
1273     }
1274     if (info) {
1275         *info = pmap.info();
1276     }
1277     if (rowBytes) {
1278         *rowBytes = pmap.rowBytes();
1279     }
1280     if (origin) {
1281         *origin = this->getTopDevice()->getOrigin();
1282     }
1283     return pmap.writable_addr();
1284 }
1285 
onAccessTopLayerPixels(SkPixmap * pmap)1286 bool SkCanvas::onAccessTopLayerPixels(SkPixmap* pmap) {
1287     SkBaseDevice* dev = this->getTopDevice();
1288     return dev && dev->accessPixels(pmap);
1289 }
1290 
1291 /////////////////////////////////////////////////////////////////////////////
1292 
internalDrawDevice(SkBaseDevice * srcDev,int x,int y,const SkPaint * paint,SkImage * clipImage,const SkMatrix & clipMatrix)1293 void SkCanvas::internalDrawDevice(SkBaseDevice* srcDev, int x, int y, const SkPaint* paint,
1294                                   SkImage* clipImage, const SkMatrix& clipMatrix) {
1295     SkPaint tmp;
1296     if (nullptr == paint) {
1297         paint = &tmp;
1298     }
1299 
1300     LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type)
1301 
1302     while (iter.next()) {
1303         SkBaseDevice* dstDev = iter.fDevice;
1304         paint = &looper.paint();
1305         SkImageFilter* filter = paint->getImageFilter();
1306         SkIPoint pos = { x - iter.getX(), y - iter.getY() };
1307         if (filter || clipImage) {
1308             sk_sp<SkSpecialImage> specialImage = srcDev->snapSpecial();
1309             if (specialImage) {
1310                 dstDev->drawSpecial(specialImage.get(), pos.x(), pos.y(), *paint,
1311                                     clipImage, clipMatrix);
1312             }
1313         } else {
1314             dstDev->drawDevice(srcDev, pos.x(), pos.y(), *paint);
1315         }
1316     }
1317 
1318     LOOPER_END
1319 }
1320 
1321 /////////////////////////////////////////////////////////////////////////////
1322 
translate(SkScalar dx,SkScalar dy)1323 void SkCanvas::translate(SkScalar dx, SkScalar dy) {
1324     if (dx || dy) {
1325         this->checkForDeferredSave();
1326         fMCRec->fMatrix.preTranslate(dx,dy);
1327 
1328         // Translate shouldn't affect the is-scale-translateness of the matrix.
1329         SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1330 
1331         FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1332 
1333         this->didTranslate(dx,dy);
1334     }
1335 }
1336 
scale(SkScalar sx,SkScalar sy)1337 void SkCanvas::scale(SkScalar sx, SkScalar sy) {
1338     SkMatrix m;
1339     m.setScale(sx, sy);
1340     this->concat(m);
1341 }
1342 
rotate(SkScalar degrees)1343 void SkCanvas::rotate(SkScalar degrees) {
1344     SkMatrix m;
1345     m.setRotate(degrees);
1346     this->concat(m);
1347 }
1348 
rotate(SkScalar degrees,SkScalar px,SkScalar py)1349 void SkCanvas::rotate(SkScalar degrees, SkScalar px, SkScalar py) {
1350     SkMatrix m;
1351     m.setRotate(degrees, px, py);
1352     this->concat(m);
1353 }
1354 
skew(SkScalar sx,SkScalar sy)1355 void SkCanvas::skew(SkScalar sx, SkScalar sy) {
1356     SkMatrix m;
1357     m.setSkew(sx, sy);
1358     this->concat(m);
1359 }
1360 
concat(const SkMatrix & matrix)1361 void SkCanvas::concat(const SkMatrix& matrix) {
1362     if (matrix.isIdentity()) {
1363         return;
1364     }
1365 
1366     this->checkForDeferredSave();
1367     fMCRec->fMatrix.preConcat(matrix);
1368     fIsScaleTranslate = fMCRec->fMatrix.isScaleTranslate();
1369 
1370     FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1371 
1372     this->didConcat(matrix);
1373 }
1374 
internalSetMatrix(const SkMatrix & matrix)1375 void SkCanvas::internalSetMatrix(const SkMatrix& matrix) {
1376     fMCRec->fMatrix = matrix;
1377     fIsScaleTranslate = matrix.isScaleTranslate();
1378 
1379     FOR_EACH_TOP_DEVICE(device->setGlobalCTM(fMCRec->fMatrix));
1380 }
1381 
setMatrix(const SkMatrix & matrix)1382 void SkCanvas::setMatrix(const SkMatrix& matrix) {
1383     this->checkForDeferredSave();
1384     this->internalSetMatrix(matrix);
1385     this->didSetMatrix(matrix);
1386 }
1387 
resetMatrix()1388 void SkCanvas::resetMatrix() {
1389     this->setMatrix(SkMatrix::I());
1390 }
1391 
1392 //////////////////////////////////////////////////////////////////////////////
1393 
clipRect(const SkRect & rect,SkClipOp op,bool doAA)1394 void SkCanvas::clipRect(const SkRect& rect, SkClipOp op, bool doAA) {
1395     if (!rect.isFinite()) {
1396         return;
1397     }
1398     this->checkForDeferredSave();
1399     ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1400     this->onClipRect(rect, op, edgeStyle);
1401 }
1402 
onClipRect(const SkRect & rect,SkClipOp op,ClipEdgeStyle edgeStyle)1403 void SkCanvas::onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1404     const bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1405 
1406     FOR_EACH_TOP_DEVICE(device->clipRect(rect, op, isAA));
1407 
1408     AutoValidateClip avc(this);
1409     fMCRec->fRasterClip.opRect(rect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1410                                isAA);
1411     fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1412 }
1413 
androidFramework_setDeviceClipRestriction(const SkIRect & rect)1414 void SkCanvas::androidFramework_setDeviceClipRestriction(const SkIRect& rect) {
1415     fClipRestrictionRect = rect;
1416     if (fClipRestrictionRect.isEmpty()) {
1417         // we notify the device, but we *dont* resolve deferred saves (since we're just
1418         // removing the restriction if the rect is empty. how I hate this api.
1419         FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
1420     } else {
1421         this->checkForDeferredSave();
1422         FOR_EACH_TOP_DEVICE(device->androidFramework_setDeviceClipRestriction(&fClipRestrictionRect));
1423         AutoValidateClip avc(this);
1424         fMCRec->fRasterClip.opIRect(fClipRestrictionRect, SkRegion::kIntersect_Op);
1425         fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1426     }
1427 }
1428 
clipRRect(const SkRRect & rrect,SkClipOp op,bool doAA)1429 void SkCanvas::clipRRect(const SkRRect& rrect, SkClipOp op, bool doAA) {
1430     this->checkForDeferredSave();
1431     ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1432     if (rrect.isRect()) {
1433         this->onClipRect(rrect.getBounds(), op, edgeStyle);
1434     } else {
1435         this->onClipRRect(rrect, op, edgeStyle);
1436     }
1437 }
1438 
onClipRRect(const SkRRect & rrect,SkClipOp op,ClipEdgeStyle edgeStyle)1439 void SkCanvas::onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle) {
1440     AutoValidateClip avc(this);
1441 
1442     bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1443 
1444     FOR_EACH_TOP_DEVICE(device->clipRRect(rrect, op, isAA));
1445 
1446     fMCRec->fRasterClip.opRRect(rrect, fMCRec->fMatrix, this->getTopLayerBounds(), (SkRegion::Op)op,
1447                                 isAA);
1448     fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1449 }
1450 
clipPath(const SkPath & path,SkClipOp op,bool doAA)1451 void SkCanvas::clipPath(const SkPath& path, SkClipOp op, bool doAA) {
1452     this->checkForDeferredSave();
1453     ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
1454 
1455     if (!path.isInverseFillType() && fMCRec->fMatrix.rectStaysRect()) {
1456         SkRect r;
1457         if (path.isRect(&r)) {
1458             this->onClipRect(r, op, edgeStyle);
1459             return;
1460         }
1461         SkRRect rrect;
1462         if (path.isOval(&r)) {
1463             rrect.setOval(r);
1464             this->onClipRRect(rrect, op, edgeStyle);
1465             return;
1466         }
1467         if (path.isRRect(&rrect)) {
1468             this->onClipRRect(rrect, op, edgeStyle);
1469             return;
1470         }
1471     }
1472 
1473     this->onClipPath(path, op, edgeStyle);
1474 }
1475 
onClipPath(const SkPath & path,SkClipOp op,ClipEdgeStyle edgeStyle)1476 void SkCanvas::onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle) {
1477     AutoValidateClip avc(this);
1478 
1479     bool isAA = kSoft_ClipEdgeStyle == edgeStyle;
1480 
1481     FOR_EACH_TOP_DEVICE(device->clipPath(path, op, isAA));
1482 
1483     const SkPath* rasterClipPath = &path;
1484     const SkMatrix* matrix = &fMCRec->fMatrix;
1485     fMCRec->fRasterClip.opPath(*rasterClipPath, *matrix, this->getTopLayerBounds(),
1486                                (SkRegion::Op)op, isAA);
1487     fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1488 }
1489 
clipRegion(const SkRegion & rgn,SkClipOp op)1490 void SkCanvas::clipRegion(const SkRegion& rgn, SkClipOp op) {
1491     this->checkForDeferredSave();
1492     this->onClipRegion(rgn, op);
1493 }
1494 
onClipRegion(const SkRegion & rgn,SkClipOp op)1495 void SkCanvas::onClipRegion(const SkRegion& rgn, SkClipOp op) {
1496     FOR_EACH_TOP_DEVICE(device->clipRegion(rgn, op));
1497 
1498     AutoValidateClip avc(this);
1499 
1500     fMCRec->fRasterClip.opRegion(rgn, (SkRegion::Op)op);
1501     fDeviceClipBounds = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1502 }
1503 
1504 #ifdef SK_DEBUG
validateClip() const1505 void SkCanvas::validateClip() const {
1506     // construct clipRgn from the clipstack
1507     const SkBaseDevice* device = this->getDevice();
1508     if (!device) {
1509         SkASSERT(this->isClipEmpty());
1510         return;
1511     }
1512 }
1513 #endif
1514 
androidFramework_isClipAA() const1515 bool SkCanvas::androidFramework_isClipAA() const {
1516     bool containsAA = false;
1517 
1518     FOR_EACH_TOP_DEVICE(containsAA |= device->onClipIsAA());
1519 
1520     return containsAA;
1521 }
1522 
1523 class RgnAccumulator {
1524     SkRegion* fRgn;
1525 public:
RgnAccumulator(SkRegion * total)1526     RgnAccumulator(SkRegion* total) : fRgn(total) {}
accumulate(SkBaseDevice * device,SkRegion * rgn)1527     void accumulate(SkBaseDevice* device, SkRegion* rgn) {
1528         SkIPoint origin = device->getOrigin();
1529         if (origin.x() | origin.y()) {
1530             rgn->translate(origin.x(), origin.y());
1531         }
1532         fRgn->op(*rgn, SkRegion::kUnion_Op);
1533     }
1534 };
1535 
temporary_internal_getRgnClip(SkRegion * rgn)1536 void SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
1537     RgnAccumulator accum(rgn);
1538     SkRegion tmp;
1539 
1540     rgn->setEmpty();
1541     FOR_EACH_TOP_DEVICE(device->onAsRgnClip(&tmp); accum.accumulate(device, &tmp));
1542 }
1543 
1544 ///////////////////////////////////////////////////////////////////////////////
1545 
isClipEmpty() const1546 bool SkCanvas::isClipEmpty() const {
1547     return fMCRec->fRasterClip.isEmpty();
1548 
1549     // TODO: should we only use the conservative answer in a recording canvas?
1550 #if 0
1551     SkBaseDevice* dev = this->getTopDevice();
1552     // if no device we return true
1553     return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
1554 #endif
1555 }
1556 
isClipRect() const1557 bool SkCanvas::isClipRect() const {
1558     SkBaseDevice* dev = this->getTopDevice();
1559     // if no device we return false
1560     return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType;
1561 }
1562 
is_nan_or_clipped(const Sk4f & devRect,const Sk4f & devClip)1563 static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
1564 #if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
1565     __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec);
1566     __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec);
1567     __m128 mask = _mm_cmplt_ps(lLtT, RrBb);
1568     return 0xF != _mm_movemask_ps(mask);
1569 #elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
1570     float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0];
1571     float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1];
1572     uint32x4_t mask = vcltq_f32(lLtT, RrBb);
1573     return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask);
1574 #else
1575     SkRect devRectAsRect;
1576     SkRect devClipAsRect;
1577     devRect.store(&devRectAsRect.fLeft);
1578     devClip.store(&devClipAsRect.fLeft);
1579     return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect);
1580 #endif
1581 }
1582 
1583 // It's important for this function to not be inlined.  Otherwise the compiler will share code
1584 // 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)1585 static SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip,
1586                                                    const SkMatrix& matrix) {
1587     SkRect deviceRect;
1588     matrix.mapRect(&deviceRect, src);
1589     return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip);
1590 }
1591 
quickReject(const SkRect & src) const1592 bool SkCanvas::quickReject(const SkRect& src) const {
1593 #ifdef SK_DEBUG
1594     // Verify that fDeviceClipBounds are set properly.
1595     SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1596     if (fMCRec->fRasterClip.isEmpty()) {
1597         SkASSERT(fDeviceClipBounds.isEmpty());
1598     } else {
1599         SkASSERT(tmp == fDeviceClipBounds);
1600     }
1601 
1602     // Verify that fIsScaleTranslate is set properly.
1603     SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1604 #endif
1605 
1606     if (!fIsScaleTranslate) {
1607         return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix);
1608     }
1609 
1610     // We inline the implementation of mapScaleTranslate() for the fast path.
1611     float sx = fMCRec->fMatrix.getScaleX();
1612     float sy = fMCRec->fMatrix.getScaleY();
1613     float tx = fMCRec->fMatrix.getTranslateX();
1614     float ty = fMCRec->fMatrix.getTranslateY();
1615     Sk4f scale(sx, sy, sx, sy);
1616     Sk4f trans(tx, ty, tx, ty);
1617 
1618     // Apply matrix.
1619     Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
1620 
1621     // Make sure left < right, top < bottom.
1622     Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
1623     Sk4f min = Sk4f::Min(ltrb, rblt);
1624     Sk4f max = Sk4f::Max(ltrb, rblt);
1625     // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
1626     // ARM this sequence generates the fastest (a single instruction).
1627     Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]);
1628 
1629     // Check if the device rect is NaN or outside the clip.
1630     return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft));
1631 }
1632 
quickReject(const SkPath & path) const1633 bool SkCanvas::quickReject(const SkPath& path) const {
1634     return path.isEmpty() || this->quickReject(path.getBounds());
1635 }
1636 
getLocalClipBounds() const1637 SkRect SkCanvas::getLocalClipBounds() const {
1638     SkIRect ibounds = this->getDeviceClipBounds();
1639     if (ibounds.isEmpty()) {
1640         return SkRect::MakeEmpty();
1641     }
1642 
1643     SkMatrix inverse;
1644     // if we can't invert the CTM, we can't return local clip bounds
1645     if (!fMCRec->fMatrix.invert(&inverse)) {
1646         return SkRect::MakeEmpty();
1647     }
1648 
1649     SkRect bounds;
1650     SkRect r;
1651     // adjust it outwards in case we are antialiasing
1652     const int inset = 1;
1653 
1654     r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1655            ibounds.fRight + inset, ibounds.fBottom + inset);
1656     inverse.mapRect(&bounds, r);
1657     return bounds;
1658 }
1659 
getDeviceClipBounds() const1660 SkIRect SkCanvas::getDeviceClipBounds() const {
1661     return fMCRec->fRasterClip.getBounds();
1662 }
1663 
getTotalMatrix() const1664 const SkMatrix& SkCanvas::getTotalMatrix() const {
1665     return fMCRec->fMatrix;
1666 }
1667 
internal_private_accessTopLayerRenderTargetContext()1668 GrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() {
1669     SkBaseDevice* dev = this->getTopDevice();
1670     return dev ? dev->accessRenderTargetContext() : nullptr;
1671 }
1672 
getGrContext()1673 GrContext* SkCanvas::getGrContext() {
1674     SkBaseDevice* device = this->getTopDevice();
1675     return device ? device->context() : nullptr;
1676 }
1677 
drawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)1678 void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1679                           const SkPaint& paint) {
1680     TRACE_EVENT0("skia", TRACE_FUNC);
1681     if (outer.isEmpty()) {
1682         return;
1683     }
1684     if (inner.isEmpty()) {
1685         this->drawRRect(outer, paint);
1686         return;
1687     }
1688 
1689     // We don't have this method (yet), but technically this is what we should
1690     // be able to return ...
1691     // if (!outer.contains(inner))) {
1692     //
1693     // For now at least check for containment of bounds
1694     if (!outer.getBounds().contains(inner.getBounds())) {
1695         return;
1696     }
1697 
1698     this->onDrawDRRect(outer, inner, paint);
1699 }
1700 
drawPaint(const SkPaint & paint)1701 void SkCanvas::drawPaint(const SkPaint& paint) {
1702     TRACE_EVENT0("skia", TRACE_FUNC);
1703     this->onDrawPaint(paint);
1704 }
1705 
drawRect(const SkRect & r,const SkPaint & paint)1706 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1707     TRACE_EVENT0("skia", TRACE_FUNC);
1708     // To avoid redundant logic in our culling code and various backends, we always sort rects
1709     // before passing them along.
1710     this->onDrawRect(r.makeSorted(), paint);
1711 }
1712 
drawRegion(const SkRegion & region,const SkPaint & paint)1713 void SkCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
1714     TRACE_EVENT0("skia", TRACE_FUNC);
1715     if (region.isEmpty()) {
1716         return;
1717     }
1718 
1719     if (region.isRect()) {
1720         return this->drawIRect(region.getBounds(), paint);
1721     }
1722 
1723     this->onDrawRegion(region, paint);
1724 }
1725 
drawOval(const SkRect & r,const SkPaint & paint)1726 void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
1727     TRACE_EVENT0("skia", TRACE_FUNC);
1728     // To avoid redundant logic in our culling code and various backends, we always sort rects
1729     // before passing them along.
1730     this->onDrawOval(r.makeSorted(), paint);
1731 }
1732 
drawRRect(const SkRRect & rrect,const SkPaint & paint)1733 void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1734     TRACE_EVENT0("skia", TRACE_FUNC);
1735     this->onDrawRRect(rrect, paint);
1736 }
1737 
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1738 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
1739     TRACE_EVENT0("skia", TRACE_FUNC);
1740     this->onDrawPoints(mode, count, pts, paint);
1741 }
1742 
drawVertices(const sk_sp<SkVertices> & vertices,SkBlendMode mode,const SkPaint & paint)1743 void SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode,
1744                             const SkPaint& paint) {
1745     TRACE_EVENT0("skia", TRACE_FUNC);
1746     RETURN_ON_NULL(vertices);
1747     this->onDrawVerticesObject(vertices.get(), mode, paint);
1748 }
1749 
drawVertices(const SkVertices * vertices,SkBlendMode mode,const SkPaint & paint)1750 void SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
1751     TRACE_EVENT0("skia", TRACE_FUNC);
1752     RETURN_ON_NULL(vertices);
1753     this->onDrawVerticesObject(vertices, mode, paint);
1754 }
1755 
drawPath(const SkPath & path,const SkPaint & paint)1756 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1757     TRACE_EVENT0("skia", TRACE_FUNC);
1758     this->onDrawPath(path, paint);
1759 }
1760 
drawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)1761 void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1762     TRACE_EVENT0("skia", TRACE_FUNC);
1763     RETURN_ON_NULL(image);
1764     this->onDrawImage(image, x, y, paint);
1765 }
1766 
1767 // Returns true if the rect can be "filled" : non-empty and finite
fillable(const SkRect & r)1768 static bool fillable(const SkRect& r) {
1769     SkScalar w = r.width();
1770     SkScalar h = r.height();
1771     return SkScalarIsFinite(w) && w > 0 && SkScalarIsFinite(h) && h > 0;
1772 }
1773 
drawImageRect(const SkImage * image,const SkRect & src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1774 void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1775                              const SkPaint* paint, SrcRectConstraint constraint) {
1776     TRACE_EVENT0("skia", TRACE_FUNC);
1777     RETURN_ON_NULL(image);
1778     if (!fillable(dst) || !fillable(src)) {
1779         return;
1780     }
1781     this->onDrawImageRect(image, &src, dst, paint, constraint);
1782 }
1783 
drawImageRect(const SkImage * image,const SkIRect & isrc,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1784 void SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
1785                              const SkPaint* paint, SrcRectConstraint constraint) {
1786     RETURN_ON_NULL(image);
1787     this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
1788 }
1789 
drawImageRect(const SkImage * image,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1790 void SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1791                              SrcRectConstraint constraint) {
1792     RETURN_ON_NULL(image);
1793     this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1794                         constraint);
1795 }
1796 
1797 namespace {
1798 class NoneOrLowQualityFilterPaint : SkNoncopyable {
1799 public:
NoneOrLowQualityFilterPaint(const SkPaint * origPaint)1800     NoneOrLowQualityFilterPaint(const SkPaint* origPaint) {
1801         if (origPaint && origPaint->getFilterQuality() > kLow_SkFilterQuality) {
1802             fLazyPaint.set(*origPaint);
1803             fLazyPaint.get()->setFilterQuality(kLow_SkFilterQuality);
1804             fPaint = fLazyPaint.get();
1805         } else {
1806             fPaint = origPaint;
1807         }
1808     }
1809 
get() const1810     const SkPaint* get() const {
1811         return fPaint;
1812     }
1813 
1814 private:
1815     const SkPaint* fPaint;
1816     SkLazyPaint fLazyPaint;
1817 };
1818 } // namespace
1819 
drawImageNine(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1820 void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
1821                              const SkPaint* paint) {
1822     TRACE_EVENT0("skia", TRACE_FUNC);
1823     RETURN_ON_NULL(image);
1824     if (dst.isEmpty()) {
1825         return;
1826     }
1827     if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
1828         NoneOrLowQualityFilterPaint lowPaint(paint);
1829         this->onDrawImageNine(image, center, dst, lowPaint.get());
1830     } else {
1831         this->drawImageRect(image, dst, paint);
1832     }
1833 }
1834 
drawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)1835 void SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
1836                                 const SkPaint* paint) {
1837     TRACE_EVENT0("skia", TRACE_FUNC);
1838     RETURN_ON_NULL(image);
1839     if (dst.isEmpty()) {
1840         return;
1841     }
1842 
1843     SkIRect bounds;
1844     Lattice latticePlusBounds = lattice;
1845     if (!latticePlusBounds.fBounds) {
1846         bounds = SkIRect::MakeWH(image->width(), image->height());
1847         latticePlusBounds.fBounds = &bounds;
1848     }
1849 
1850     if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
1851         NoneOrLowQualityFilterPaint lowPaint(paint);
1852         this->onDrawImageLattice(image, latticePlusBounds, dst, lowPaint.get());
1853     } else {
1854         this->drawImageRect(image, dst, paint);
1855     }
1856 }
1857 
drawBitmap(const SkBitmap & bitmap,SkScalar dx,SkScalar dy,const SkPaint * paint)1858 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
1859     TRACE_EVENT0("skia", TRACE_FUNC);
1860     if (bitmap.drawsNothing()) {
1861         return;
1862     }
1863     this->onDrawBitmap(bitmap, dx, dy, paint);
1864 }
1865 
drawBitmapRect(const SkBitmap & bitmap,const SkRect & src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1866 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1867                               const SkPaint* paint, SrcRectConstraint constraint) {
1868     TRACE_EVENT0("skia", TRACE_FUNC);
1869     if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1870         return;
1871     }
1872     this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
1873 }
1874 
drawBitmapRect(const SkBitmap & bitmap,const SkIRect & isrc,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1875 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
1876                               const SkPaint* paint, SrcRectConstraint constraint) {
1877     this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1878 }
1879 
drawBitmapRect(const SkBitmap & bitmap,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1880 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1881                               SrcRectConstraint constraint) {
1882     this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1883                          constraint);
1884 }
1885 
drawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1886 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
1887                               const SkPaint* paint) {
1888     TRACE_EVENT0("skia", TRACE_FUNC);
1889     if (bitmap.drawsNothing() || dst.isEmpty()) {
1890         return;
1891     }
1892     if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
1893         NoneOrLowQualityFilterPaint lowPaint(paint);
1894         this->onDrawBitmapNine(bitmap, center, dst, lowPaint.get());
1895     } else {
1896         this->drawBitmapRect(bitmap, dst, paint);
1897     }
1898 }
1899 
drawBitmapLattice(const SkBitmap & bitmap,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)1900 void SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
1901                                  const SkPaint* paint) {
1902     TRACE_EVENT0("skia", TRACE_FUNC);
1903     if (bitmap.drawsNothing() || dst.isEmpty()) {
1904         return;
1905     }
1906 
1907     SkIRect bounds;
1908     Lattice latticePlusBounds = lattice;
1909     if (!latticePlusBounds.fBounds) {
1910         bounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
1911         latticePlusBounds.fBounds = &bounds;
1912     }
1913 
1914     if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) {
1915         NoneOrLowQualityFilterPaint lowPaint(paint);
1916         this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, lowPaint.get());
1917     } else {
1918         this->drawBitmapRect(bitmap, dst, paint);
1919     }
1920 }
1921 
drawAtlas(const SkImage * atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode mode,const SkRect * cull,const SkPaint * paint)1922 void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
1923                          const SkColor colors[], int count, SkBlendMode mode,
1924                          const SkRect* cull, const SkPaint* paint) {
1925     TRACE_EVENT0("skia", TRACE_FUNC);
1926     RETURN_ON_NULL(atlas);
1927     if (count <= 0) {
1928         return;
1929     }
1930     SkASSERT(atlas);
1931     SkASSERT(tex);
1932     this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
1933 }
1934 
drawAnnotation(const SkRect & rect,const char key[],SkData * value)1935 void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
1936     TRACE_EVENT0("skia", TRACE_FUNC);
1937     if (key) {
1938         this->onDrawAnnotation(rect, key, value);
1939     }
1940 }
1941 
legacy_drawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1942 void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1943                                     const SkPaint* paint, SrcRectConstraint constraint) {
1944     if (src) {
1945         this->drawImageRect(image, *src, dst, paint, constraint);
1946     } else {
1947         this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
1948                             dst, paint, constraint);
1949     }
1950 }
legacy_drawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1951 void SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1952                                      const SkPaint* paint, SrcRectConstraint constraint) {
1953     if (src) {
1954         this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
1955     } else {
1956         this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
1957                              dst, paint, constraint);
1958     }
1959 }
1960 
private_draw_shadow_rec(const SkPath & path,const SkDrawShadowRec & rec)1961 void SkCanvas::private_draw_shadow_rec(const SkPath& path, const SkDrawShadowRec& rec) {
1962     TRACE_EVENT0("skia", TRACE_FUNC);
1963     this->onDrawShadowRec(path, rec);
1964 }
1965 
onDrawShadowRec(const SkPath & path,const SkDrawShadowRec & rec)1966 void SkCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
1967     SkPaint paint;
1968     const SkRect& pathBounds = path.getBounds();
1969 
1970     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
1971     while (iter.next()) {
1972         iter.fDevice->drawShadow(path, rec);
1973     }
1974     LOOPER_END
1975 }
1976 
1977 //////////////////////////////////////////////////////////////////////////////
1978 //  These are the virtual drawing methods
1979 //////////////////////////////////////////////////////////////////////////////
1980 
onDiscard()1981 void SkCanvas::onDiscard() {
1982     if (fSurfaceBase) {
1983         fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
1984     }
1985 }
1986 
onDrawPaint(const SkPaint & paint)1987 void SkCanvas::onDrawPaint(const SkPaint& paint) {
1988     this->internalDrawPaint(paint);
1989 }
1990 
internalDrawPaint(const SkPaint & paint)1991 void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1992     LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
1993 
1994     while (iter.next()) {
1995         iter.fDevice->drawPaint(looper.paint());
1996     }
1997 
1998     LOOPER_END
1999 }
2000 
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)2001 void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
2002                             const SkPaint& paint) {
2003     if ((long)count <= 0) {
2004         return;
2005     }
2006 
2007     SkRect r;
2008     const SkRect* bounds = nullptr;
2009     if (paint.canComputeFastBounds()) {
2010         // special-case 2 points (common for drawing a single line)
2011         if (2 == count) {
2012             r.set(pts[0], pts[1]);
2013         } else {
2014             r.set(pts, SkToInt(count));
2015         }
2016         if (!r.isFinite()) {
2017             return;
2018         }
2019         SkRect storage;
2020         if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
2021             return;
2022         }
2023         bounds = &r;
2024     }
2025 
2026     SkASSERT(pts != nullptr);
2027 
2028     LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
2029 
2030     while (iter.next()) {
2031         iter.fDevice->drawPoints(mode, count, pts, looper.paint());
2032     }
2033 
2034     LOOPER_END
2035 }
2036 
needs_autodrawlooper(SkCanvas * canvas,const SkPaint & paint)2037 static bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) {
2038     return ((intptr_t)paint.getImageFilter()    |
2039 #ifdef SK_SUPPORT_LEGACY_DRAWFILTER
2040             (intptr_t)canvas->getDrawFilter()   |
2041 #endif
2042             (intptr_t)paint.getLooper()         ) != 0;
2043 }
2044 
onDrawRect(const SkRect & r,const SkPaint & paint)2045 void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
2046     SkASSERT(r.isSorted());
2047     if (paint.canComputeFastBounds()) {
2048         SkRect storage;
2049         if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2050             return;
2051         }
2052     }
2053 
2054     if (needs_autodrawlooper(this, paint)) {
2055         LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false)
2056 
2057         while (iter.next()) {
2058             iter.fDevice->drawRect(r, looper.paint());
2059         }
2060 
2061         LOOPER_END
2062     } else {
2063         this->predrawNotify(&r, &paint, false);
2064         SkDrawIter iter(this);
2065         while (iter.next()) {
2066             iter.fDevice->drawRect(r, paint);
2067         }
2068     }
2069 }
2070 
onDrawRegion(const SkRegion & region,const SkPaint & paint)2071 void SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
2072     SkRect regionRect = SkRect::Make(region.getBounds());
2073     if (paint.canComputeFastBounds()) {
2074         SkRect storage;
2075         if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) {
2076             return;
2077         }
2078     }
2079 
2080     LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, &regionRect)
2081 
2082     while (iter.next()) {
2083         iter.fDevice->drawRegion(region, looper.paint());
2084     }
2085 
2086     LOOPER_END
2087 }
2088 
onDrawOval(const SkRect & oval,const SkPaint & paint)2089 void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
2090     SkASSERT(oval.isSorted());
2091     if (paint.canComputeFastBounds()) {
2092         SkRect storage;
2093         if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2094             return;
2095         }
2096     }
2097 
2098     LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2099 
2100     while (iter.next()) {
2101         iter.fDevice->drawOval(oval, looper.paint());
2102     }
2103 
2104     LOOPER_END
2105 }
2106 
onDrawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)2107 void SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle,
2108                          SkScalar sweepAngle, bool useCenter,
2109                          const SkPaint& paint) {
2110     SkASSERT(oval.isSorted());
2111     if (paint.canComputeFastBounds()) {
2112         SkRect storage;
2113         // Note we're using the entire oval as the bounds.
2114         if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2115             return;
2116         }
2117     }
2118 
2119     LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2120 
2121     while (iter.next()) {
2122         iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint());
2123     }
2124 
2125     LOOPER_END
2126 }
2127 
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)2128 void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
2129     if (paint.canComputeFastBounds()) {
2130         SkRect storage;
2131         if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
2132             return;
2133         }
2134     }
2135 
2136     if (rrect.isRect()) {
2137         // call the non-virtual version
2138         this->SkCanvas::drawRect(rrect.getBounds(), paint);
2139         return;
2140     } else if (rrect.isOval()) {
2141         // call the non-virtual version
2142         this->SkCanvas::drawOval(rrect.getBounds(), paint);
2143         return;
2144     }
2145 
2146     LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds())
2147 
2148     while (iter.next()) {
2149         iter.fDevice->drawRRect(rrect, looper.paint());
2150     }
2151 
2152     LOOPER_END
2153 }
2154 
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)2155 void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
2156     if (paint.canComputeFastBounds()) {
2157         SkRect storage;
2158         if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
2159             return;
2160         }
2161     }
2162 
2163     LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds())
2164 
2165     while (iter.next()) {
2166         iter.fDevice->drawDRRect(outer, inner, looper.paint());
2167     }
2168 
2169     LOOPER_END
2170 }
2171 
onDrawPath(const SkPath & path,const SkPaint & paint)2172 void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
2173     if (!path.isFinite()) {
2174         return;
2175     }
2176 
2177     const SkRect& pathBounds = path.getBounds();
2178     if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
2179         SkRect storage;
2180         if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
2181             return;
2182         }
2183     }
2184 
2185     if (pathBounds.width() <= 0 && pathBounds.height() <= 0) {
2186         if (path.isInverseFillType()) {
2187             this->internalDrawPaint(paint);
2188             return;
2189         }
2190     }
2191 
2192     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
2193 
2194     while (iter.next()) {
2195         iter.fDevice->drawPath(path, looper.paint());
2196     }
2197 
2198     LOOPER_END
2199 }
2200 
canDrawBitmapAsSprite(SkScalar x,SkScalar y,int w,int h,const SkPaint & paint)2201 bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2202     if (!paint.getImageFilter()) {
2203         return false;
2204     }
2205 
2206     const SkMatrix& ctm = this->getTotalMatrix();
2207     if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2208         return false;
2209     }
2210 
2211     // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2212     // Once we can filter and the filter will return a result larger than itself, we should be
2213     // able to remove this constraint.
2214     // skbug.com/4526
2215     //
2216     SkPoint pt;
2217     ctm.mapXY(x, y, &pt);
2218     SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2219     return ir.contains(fMCRec->fRasterClip.getBounds());
2220 }
2221 
onDrawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)2222 void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
2223     SkRect bounds = SkRect::MakeXYWH(x, y,
2224                                      SkIntToScalar(image->width()), SkIntToScalar(image->height()));
2225     if (nullptr == paint || paint->canComputeFastBounds()) {
2226         SkRect tmp = bounds;
2227         if (paint) {
2228             paint->computeFastBounds(tmp, &tmp);
2229         }
2230         if (this->quickReject(tmp)) {
2231             return;
2232         }
2233     }
2234 
2235     SkLazyPaint lazy;
2236     if (nullptr == paint) {
2237         paint = lazy.init();
2238     }
2239 
2240     sk_sp<SkSpecialImage> special;
2241     bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2242                                                     *paint);
2243     if (drawAsSprite && paint->getImageFilter()) {
2244         special = this->getDevice()->makeSpecial(image);
2245         if (!special) {
2246             drawAsSprite = false;
2247         }
2248     }
2249 
2250     LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2251 
2252     while (iter.next()) {
2253         const SkPaint& pnt = looper.paint();
2254         if (special) {
2255             SkPoint pt;
2256             iter.fDevice->ctm().mapXY(x, y, &pt);
2257             iter.fDevice->drawSpecial(special.get(),
2258                                       SkScalarRoundToInt(pt.fX),
2259                                       SkScalarRoundToInt(pt.fY), pnt,
2260                                       nullptr, SkMatrix::I());
2261         } else {
2262             iter.fDevice->drawImage(image, x, y, pnt);
2263         }
2264     }
2265 
2266     LOOPER_END
2267 }
2268 
onDrawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)2269 void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2270                                const SkPaint* paint, SrcRectConstraint constraint) {
2271     if (nullptr == paint || paint->canComputeFastBounds()) {
2272         SkRect storage = dst;
2273         if (paint) {
2274             paint->computeFastBounds(dst, &storage);
2275         }
2276         if (this->quickReject(storage)) {
2277             return;
2278         }
2279     }
2280     SkLazyPaint lazy;
2281     if (nullptr == paint) {
2282         paint = lazy.init();
2283     }
2284 
2285     LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2286                                           image->isOpaque())
2287 
2288     while (iter.next()) {
2289         iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint);
2290     }
2291 
2292     LOOPER_END
2293 }
2294 
onDrawBitmap(const SkBitmap & bitmap,SkScalar x,SkScalar y,const SkPaint * paint)2295 void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
2296     SkDEBUGCODE(bitmap.validate();)
2297 
2298     if (bitmap.drawsNothing()) {
2299         return;
2300     }
2301 
2302     SkLazyPaint lazy;
2303     if (nullptr == paint) {
2304         paint = lazy.init();
2305     }
2306 
2307     SkRect bounds;
2308     bitmap.getBounds(&bounds);
2309     bounds.offset(x, y);
2310     bool canFastBounds = paint->canComputeFastBounds();
2311     if (canFastBounds) {
2312         SkRect storage;
2313         if (this->quickReject(paint->computeFastBounds(bounds, &storage))) {
2314             return;
2315         }
2316     }
2317 
2318     sk_sp<SkSpecialImage> special;
2319     bool drawAsSprite = canFastBounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(),
2320                                                                      bitmap.height(), *paint);
2321     if (drawAsSprite && paint->getImageFilter()) {
2322         special = this->getDevice()->makeSpecial(bitmap);
2323         if (!special) {
2324             drawAsSprite = false;
2325         }
2326     }
2327 
2328     LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2329 
2330     while (iter.next()) {
2331         const SkPaint& pnt = looper.paint();
2332         if (special) {
2333             SkPoint pt;
2334             iter.fDevice->ctm().mapXY(x, y, &pt);
2335             iter.fDevice->drawSpecial(special.get(),
2336                                       SkScalarRoundToInt(pt.fX),
2337                                       SkScalarRoundToInt(pt.fY), pnt,
2338                                       nullptr, SkMatrix::I());
2339         } else {
2340             iter.fDevice->drawBitmap(bitmap, x, y, looper.paint());
2341         }
2342     }
2343 
2344     LOOPER_END
2345 }
2346 
2347 // 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)2348 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2349                                       const SkRect& dst, const SkPaint* paint,
2350                                       SrcRectConstraint constraint) {
2351     if (bitmap.drawsNothing() || dst.isEmpty()) {
2352         return;
2353     }
2354 
2355     if (nullptr == paint || paint->canComputeFastBounds()) {
2356         SkRect storage;
2357         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2358             return;
2359         }
2360     }
2361 
2362     SkLazyPaint lazy;
2363     if (nullptr == paint) {
2364         paint = lazy.init();
2365     }
2366 
2367     LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2368                                           bitmap.isOpaque())
2369 
2370     while (iter.next()) {
2371         iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint);
2372     }
2373 
2374     LOOPER_END
2375 }
2376 
onDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)2377 void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2378                                 const SkPaint* paint, SrcRectConstraint constraint) {
2379     SkDEBUGCODE(bitmap.validate();)
2380     this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
2381 }
2382 
onDrawImageNine(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)2383 void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
2384                                const SkPaint* paint) {
2385     if (nullptr == paint || paint->canComputeFastBounds()) {
2386         SkRect storage;
2387         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2388             return;
2389         }
2390     }
2391 
2392     SkLazyPaint lazy;
2393     if (nullptr == paint) {
2394         paint = lazy.init();
2395     }
2396 
2397     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2398 
2399     while (iter.next()) {
2400         iter.fDevice->drawImageNine(image, center, dst, looper.paint());
2401     }
2402 
2403     LOOPER_END
2404 }
2405 
onDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)2406 void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
2407                                 const SkPaint* paint) {
2408     SkDEBUGCODE(bitmap.validate();)
2409 
2410     if (nullptr == paint || paint->canComputeFastBounds()) {
2411         SkRect storage;
2412         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2413             return;
2414         }
2415     }
2416 
2417     SkLazyPaint lazy;
2418     if (nullptr == paint) {
2419         paint = lazy.init();
2420     }
2421 
2422     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2423 
2424     while (iter.next()) {
2425         iter.fDevice->drawBitmapNine(bitmap, center, dst, looper.paint());
2426     }
2427 
2428     LOOPER_END
2429 }
2430 
onDrawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)2431 void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
2432                                   const SkPaint* paint) {
2433     if (nullptr == paint || paint->canComputeFastBounds()) {
2434         SkRect storage;
2435         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2436             return;
2437         }
2438     }
2439 
2440     SkLazyPaint lazy;
2441     if (nullptr == paint) {
2442         paint = lazy.init();
2443     }
2444 
2445     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2446 
2447     while (iter.next()) {
2448         iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint());
2449     }
2450 
2451     LOOPER_END
2452 }
2453 
onDrawBitmapLattice(const SkBitmap & bitmap,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)2454 void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
2455                                    const SkRect& dst, const SkPaint* paint) {
2456     if (nullptr == paint || paint->canComputeFastBounds()) {
2457         SkRect storage;
2458         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2459             return;
2460         }
2461     }
2462 
2463     SkLazyPaint lazy;
2464     if (nullptr == paint) {
2465         paint = lazy.init();
2466     }
2467 
2468     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2469 
2470     while (iter.next()) {
2471         iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint());
2472     }
2473 
2474     LOOPER_END
2475 }
2476 
2477 class SkDeviceFilteredPaint {
2478 public:
SkDeviceFilteredPaint(SkBaseDevice * device,const SkPaint & paint)2479     SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2480         uint32_t filteredFlags = device->filterTextFlags(paint);
2481         if (filteredFlags != paint.getFlags()) {
2482             SkPaint* newPaint = fLazy.set(paint);
2483             newPaint->setFlags(filteredFlags);
2484             fPaint = newPaint;
2485         } else {
2486             fPaint = &paint;
2487         }
2488     }
2489 
paint() const2490     const SkPaint& paint() const { return *fPaint; }
2491 
2492 private:
2493     const SkPaint*  fPaint;
2494     SkLazyPaint     fLazy;
2495 };
2496 
onDrawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)2497 void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2498                           const SkPaint& paint) {
2499     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2500 
2501     while (iter.next()) {
2502         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2503         iter.fDevice->drawText(text, byteLength, x, y, dfp.paint());
2504     }
2505 
2506     LOOPER_END
2507 }
2508 
onDrawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)2509 void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2510                              const SkPaint& paint) {
2511     SkPoint textOffset = SkPoint::Make(0, 0);
2512 
2513     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2514 
2515     while (iter.next()) {
2516         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2517         iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset,
2518                                   dfp.paint());
2519     }
2520 
2521     LOOPER_END
2522 }
2523 
onDrawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)2524 void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2525                               SkScalar constY, const SkPaint& paint) {
2526 
2527     SkPoint textOffset = SkPoint::Make(0, constY);
2528 
2529     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2530 
2531     while (iter.next()) {
2532         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2533         iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset,
2534                                   dfp.paint());
2535     }
2536 
2537     LOOPER_END
2538 }
2539 
onDrawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)2540 void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2541                                 const SkMatrix* matrix, const SkPaint& paint) {
2542     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2543 
2544     while (iter.next()) {
2545         iter.fDevice->drawTextOnPath(text, byteLength, path,
2546                                      matrix, looper.paint());
2547     }
2548 
2549     LOOPER_END
2550 }
2551 
onDrawTextRSXform(const void * text,size_t byteLength,const SkRSXform xform[],const SkRect * cullRect,const SkPaint & paint)2552 void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
2553                                  const SkRect* cullRect, const SkPaint& paint) {
2554     if (cullRect && this->quickReject(*cullRect)) {
2555         return;
2556     }
2557 
2558     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2559 
2560     while (iter.next()) {
2561         iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint());
2562     }
2563 
2564     LOOPER_END
2565 }
2566 
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)2567 void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2568                               const SkPaint& paint) {
2569 
2570     SkRect storage;
2571     const SkRect* bounds = nullptr;
2572     if (paint.canComputeFastBounds()) {
2573         storage = blob->bounds().makeOffset(x, y);
2574         SkRect tmp;
2575         if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
2576             return;
2577         }
2578         bounds = &storage;
2579     }
2580 
2581     // We cannot filter in the looper as we normally do, because the paint is
2582     // incomplete at this point (text-related attributes are embedded within blob run paints).
2583     SkDrawFilter* drawFilter = fMCRec->fFilter;
2584     fMCRec->fFilter = nullptr;
2585 
2586     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
2587 
2588     while (iter.next()) {
2589         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2590         iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter);
2591     }
2592 
2593     LOOPER_END
2594 
2595     fMCRec->fFilter = drawFilter;
2596 }
2597 
drawString(const SkString & string,SkScalar x,SkScalar y,const SkPaint & paint)2598 void SkCanvas::drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint) {
2599     this->drawText(string.c_str(), string.size(), x, y, paint);
2600 }
2601 
2602 // 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)2603 void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2604                         const SkPaint& paint) {
2605     TRACE_EVENT0("skia", TRACE_FUNC);
2606     if (byteLength) {
2607         sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2608         this->onDrawText(text, byteLength, x, y, paint);
2609     }
2610 }
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)2611 void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2612                            const SkPaint& paint) {
2613     TRACE_EVENT0("skia", TRACE_FUNC);
2614     if (byteLength) {
2615         sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2616         this->onDrawPosText(text, byteLength, pos, paint);
2617     }
2618 }
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)2619 void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2620                             SkScalar constY, const SkPaint& paint) {
2621     TRACE_EVENT0("skia", TRACE_FUNC);
2622     if (byteLength) {
2623         sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2624         this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2625     }
2626 }
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)2627 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2628                               const SkMatrix* matrix, const SkPaint& paint) {
2629     TRACE_EVENT0("skia", TRACE_FUNC);
2630     if (byteLength) {
2631         sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2632         this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2633     }
2634 }
drawTextRSXform(const void * text,size_t byteLength,const SkRSXform xform[],const SkRect * cullRect,const SkPaint & paint)2635 void SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
2636                                const SkRect* cullRect, const SkPaint& paint) {
2637     TRACE_EVENT0("skia", TRACE_FUNC);
2638     if (byteLength) {
2639         sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2640         this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint);
2641     }
2642 }
drawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)2643 void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2644                             const SkPaint& paint) {
2645     TRACE_EVENT0("skia", TRACE_FUNC);
2646     RETURN_ON_NULL(blob);
2647     RETURN_ON_FALSE(blob->bounds().makeOffset(x, y).isFinite());
2648     this->onDrawTextBlob(blob, x, y, paint);
2649 }
2650 
onDrawVerticesObject(const SkVertices * vertices,SkBlendMode bmode,const SkPaint & paint)2651 void SkCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
2652                                     const SkPaint& paint) {
2653     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2654 
2655     while (iter.next()) {
2656         // In the common case of one iteration we could std::move vertices here.
2657         iter.fDevice->drawVertices(vertices, bmode, looper.paint());
2658     }
2659 
2660     LOOPER_END
2661 }
2662 
drawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)2663 void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2664                          const SkPoint texCoords[4], SkBlendMode bmode,
2665                          const SkPaint& paint) {
2666     TRACE_EVENT0("skia", TRACE_FUNC);
2667     if (nullptr == cubics) {
2668         return;
2669     }
2670 
2671     this->onDrawPatch(cubics, colors, texCoords, bmode, paint);
2672 }
2673 
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)2674 void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2675                            const SkPoint texCoords[4], SkBlendMode bmode,
2676                            const SkPaint& paint) {
2677     // Since a patch is always within the convex hull of the control points, we discard it when its
2678     // bounding rectangle is completely outside the current clip.
2679     SkRect bounds;
2680     bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2681     if (this->quickReject(bounds)) {
2682         return;
2683     }
2684 
2685     const bool interpColorsLinearly = (this->imageInfo().colorSpace() != nullptr);
2686 
2687     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2688 
2689     while (iter.next()) {
2690         iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, interpColorsLinearly, paint);
2691     }
2692 
2693     LOOPER_END
2694 }
2695 
drawDrawable(SkDrawable * dr,SkScalar x,SkScalar y)2696 void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2697 #ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
2698     TRACE_EVENT0("skia", TRACE_FUNC);
2699 #endif
2700     RETURN_ON_NULL(dr);
2701     if (x || y) {
2702         SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2703         this->onDrawDrawable(dr, &matrix);
2704     } else {
2705         this->onDrawDrawable(dr, nullptr);
2706     }
2707 }
2708 
drawDrawable(SkDrawable * dr,const SkMatrix * matrix)2709 void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2710 #ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
2711     TRACE_EVENT0("skia", TRACE_FUNC);
2712 #endif
2713     RETURN_ON_NULL(dr);
2714     if (matrix && matrix->isIdentity()) {
2715         matrix = nullptr;
2716     }
2717     this->onDrawDrawable(dr, matrix);
2718 }
2719 
onDrawDrawable(SkDrawable * dr,const SkMatrix * matrix)2720 void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2721     // drawable bounds are no longer reliable (e.g. android displaylist)
2722     // so don't use them for quick-reject
2723     dr->draw(this, matrix);
2724 }
2725 
onDrawAtlas(const SkImage * atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode bmode,const SkRect * cull,const SkPaint * paint)2726 void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2727                            const SkColor colors[], int count, SkBlendMode bmode,
2728                            const SkRect* cull, const SkPaint* paint) {
2729     if (cull && this->quickReject(*cull)) {
2730         return;
2731     }
2732 
2733     SkPaint pnt;
2734     if (paint) {
2735         pnt = *paint;
2736     }
2737 
2738     LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
2739     while (iter.next()) {
2740         iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt);
2741     }
2742     LOOPER_END
2743 }
2744 
onDrawAnnotation(const SkRect & rect,const char key[],SkData * value)2745 void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2746     SkASSERT(key);
2747 
2748     SkPaint paint;
2749     LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
2750     while (iter.next()) {
2751         iter.fDevice->drawAnnotation(rect, key, value);
2752     }
2753     LOOPER_END
2754 }
2755 
2756 //////////////////////////////////////////////////////////////////////////////
2757 // These methods are NOT virtual, and therefore must call back into virtual
2758 // methods, rather than actually drawing themselves.
2759 //////////////////////////////////////////////////////////////////////////////
2760 
drawColor(SkColor c,SkBlendMode mode)2761 void SkCanvas::drawColor(SkColor c, SkBlendMode mode) {
2762     SkPaint paint;
2763     paint.setColor(c);
2764     paint.setBlendMode(mode);
2765     this->drawPaint(paint);
2766 }
2767 
drawPoint(SkScalar x,SkScalar y,const SkPaint & paint)2768 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2769     const SkPoint pt = { x, y };
2770     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2771 }
2772 
drawLine(SkScalar x0,SkScalar y0,SkScalar x1,SkScalar y1,const SkPaint & paint)2773 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) {
2774     SkPoint pts[2];
2775     pts[0].set(x0, y0);
2776     pts[1].set(x1, y1);
2777     this->drawPoints(kLines_PointMode, 2, pts, paint);
2778 }
2779 
drawCircle(SkScalar cx,SkScalar cy,SkScalar radius,const SkPaint & paint)2780 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) {
2781     if (radius < 0) {
2782         radius = 0;
2783     }
2784 
2785     SkRect  r;
2786     r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2787     this->drawOval(r, paint);
2788 }
2789 
drawRoundRect(const SkRect & r,SkScalar rx,SkScalar ry,const SkPaint & paint)2790 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2791                              const SkPaint& paint) {
2792     if (rx > 0 && ry > 0) {
2793         SkRRect rrect;
2794         rrect.setRectXY(r, rx, ry);
2795         this->drawRRect(rrect, paint);
2796     } else {
2797         this->drawRect(r, paint);
2798     }
2799 }
2800 
drawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)2801 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2802                        SkScalar sweepAngle, bool useCenter,
2803                        const SkPaint& paint) {
2804     TRACE_EVENT0("skia", TRACE_FUNC);
2805     if (oval.isEmpty() || !sweepAngle) {
2806         return;
2807     }
2808     this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint);
2809 }
2810 
drawTextOnPathHV(const void * text,size_t byteLength,const SkPath & path,SkScalar hOffset,SkScalar vOffset,const SkPaint & paint)2811 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2812                                 const SkPath& path, SkScalar hOffset,
2813                                 SkScalar vOffset, const SkPaint& paint) {
2814     SkMatrix    matrix;
2815 
2816     matrix.setTranslate(hOffset, vOffset);
2817     this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2818 }
2819 
2820 ///////////////////////////////////////////////////////////////////////////////
2821 
2822 /**
2823  *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
2824  *  against the playback cost of recursing into the subpicture to get at its actual ops.
2825  *
2826  *  For now we pick a conservatively small value, though measurement (and other heuristics like
2827  *  the type of ops contained) may justify changing this value.
2828  */
2829 #define kMaxPictureOpsToUnrollInsteadOfRef  1
2830 
drawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)2831 void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2832     TRACE_EVENT0("skia", TRACE_FUNC);
2833     RETURN_ON_NULL(picture);
2834 
2835     if (matrix && matrix->isIdentity()) {
2836         matrix = nullptr;
2837     }
2838     if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
2839         SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2840         picture->playback(this);
2841     } else {
2842         this->onDrawPicture(picture, matrix, paint);
2843     }
2844 }
2845 
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)2846 void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2847                              const SkPaint* paint) {
2848     if (!paint || paint->canComputeFastBounds()) {
2849         SkRect bounds = picture->cullRect();
2850         if (paint) {
2851             paint->computeFastBounds(bounds, &bounds);
2852         }
2853         if (matrix) {
2854             matrix->mapRect(&bounds);
2855         }
2856         if (this->quickReject(bounds)) {
2857             return;
2858         }
2859     }
2860 
2861     SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2862     picture->playback(this);
2863 }
2864 
2865 ///////////////////////////////////////////////////////////////////////////////
2866 ///////////////////////////////////////////////////////////////////////////////
2867 
LayerIter(SkCanvas * canvas)2868 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas) {
2869     static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
2870 
2871     SkASSERT(canvas);
2872 
2873     fImpl = new (fStorage) SkDrawIter(canvas);
2874     fDone = !fImpl->next();
2875 }
2876 
~LayerIter()2877 SkCanvas::LayerIter::~LayerIter() {
2878     fImpl->~SkDrawIter();
2879 }
2880 
next()2881 void SkCanvas::LayerIter::next() {
2882     fDone = !fImpl->next();
2883 }
2884 
device() const2885 SkBaseDevice* SkCanvas::LayerIter::device() const {
2886     return fImpl->fDevice;
2887 }
2888 
matrix() const2889 const SkMatrix& SkCanvas::LayerIter::matrix() const {
2890     return fImpl->fDevice->ctm();
2891 }
2892 
paint() const2893 const SkPaint& SkCanvas::LayerIter::paint() const {
2894     const SkPaint* paint = fImpl->getPaint();
2895     if (nullptr == paint) {
2896         paint = &fDefaultPaint;
2897     }
2898     return *paint;
2899 }
2900 
clip(SkRegion * rgn) const2901 void SkCanvas::LayerIter::clip(SkRegion* rgn) const {
2902     return fImpl->fDevice->onAsRgnClip(rgn);
2903 }
2904 
x() const2905 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
y() const2906 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2907 
2908 ///////////////////////////////////////////////////////////////////////////////
2909 
2910 // TODO: This still disagrees with SkSurfaceValidateRasterInfo
supported_for_raster_canvas(const SkImageInfo & info)2911 static bool supported_for_raster_canvas(const SkImageInfo& info) {
2912     switch (info.alphaType()) {
2913         case kPremul_SkAlphaType:
2914         case kOpaque_SkAlphaType:
2915             break;
2916         default:
2917             return false;
2918     }
2919 
2920     switch (info.colorType()) {
2921         case kAlpha_8_SkColorType:
2922         case kRGB_565_SkColorType:
2923         case kN32_SkColorType:
2924         case kRGBA_F16_SkColorType:
2925         case kRGBA_1010102_SkColorType:
2926             break;
2927         default:
2928             return false;
2929     }
2930 
2931     return true;
2932 }
2933 
MakeRasterDirect(const SkImageInfo & info,void * pixels,size_t rowBytes,const SkSurfaceProps * props)2934 std::unique_ptr<SkCanvas> SkCanvas::MakeRasterDirect(const SkImageInfo& info, void* pixels,
2935                                                      size_t rowBytes, const SkSurfaceProps* props) {
2936     if (!supported_for_raster_canvas(info)) {
2937         return nullptr;
2938     }
2939 
2940     SkBitmap bitmap;
2941     if (!bitmap.installPixels(info, pixels, rowBytes)) {
2942         return nullptr;
2943     }
2944 
2945     return props ?
2946         skstd::make_unique<SkCanvas>(bitmap, *props) :
2947         skstd::make_unique<SkCanvas>(bitmap);
2948 }
2949 
2950 ///////////////////////////////////////////////////////////////////////////////
2951 
SkNoDrawCanvas(int width,int height)2952 SkNoDrawCanvas::SkNoDrawCanvas(int width, int height)
2953     : INHERITED(SkIRect::MakeWH(width, height), kConservativeRasterClip_InitFlag) {}
2954 
SkNoDrawCanvas(const SkIRect & bounds)2955 SkNoDrawCanvas::SkNoDrawCanvas(const SkIRect& bounds)
2956     : INHERITED(bounds, kConservativeRasterClip_InitFlag) {}
2957 
getSaveLayerStrategy(const SaveLayerRec & rec)2958 SkCanvas::SaveLayerStrategy SkNoDrawCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
2959     (void)this->INHERITED::getSaveLayerStrategy(rec);
2960     return kNoLayer_SaveLayerStrategy;
2961 }
2962 
2963 ///////////////////////////////////////////////////////////////////////////////
2964 
2965 static_assert((int)SkRegion::kDifference_Op         == (int)kDifference_SkClipOp, "");
2966 static_assert((int)SkRegion::kIntersect_Op          == (int)kIntersect_SkClipOp, "");
2967 static_assert((int)SkRegion::kUnion_Op              == (int)kUnion_SkClipOp, "");
2968 static_assert((int)SkRegion::kXOR_Op                == (int)kXOR_SkClipOp, "");
2969 static_assert((int)SkRegion::kReverseDifference_Op  == (int)kReverseDifference_SkClipOp, "");
2970 static_assert((int)SkRegion::kReplace_Op            == (int)kReplace_SkClipOp, "");
2971 
2972 ///////////////////////////////////////////////////////////////////////////////////////////////////
2973 
accessTopRasterHandle() const2974 SkRasterHandleAllocator::Handle SkCanvas::accessTopRasterHandle() const {
2975     if (fAllocator && fMCRec->fTopLayer->fDevice) {
2976         const auto& dev = fMCRec->fTopLayer->fDevice;
2977         SkRasterHandleAllocator::Handle handle = dev->getRasterHandle();
2978         SkIPoint origin = dev->getOrigin();
2979         SkMatrix ctm = this->getTotalMatrix();
2980         ctm.preTranslate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y()));
2981 
2982         SkIRect clip = fMCRec->fRasterClip.getBounds();
2983         clip.offset(-origin.x(), -origin.y());
2984         if (!clip.intersect(0, 0, dev->width(), dev->height())) {
2985             clip.setEmpty();
2986         }
2987 
2988         fAllocator->updateHandle(handle, ctm, clip);
2989         return handle;
2990     }
2991     return nullptr;
2992 }
2993 
install(SkBitmap * bm,const SkImageInfo & info,const SkRasterHandleAllocator::Rec & rec)2994 static bool install(SkBitmap* bm, const SkImageInfo& info,
2995                     const SkRasterHandleAllocator::Rec& rec) {
2996     return bm->installPixels(info, rec.fPixels, rec.fRowBytes, rec.fReleaseProc, rec.fReleaseCtx);
2997 }
2998 
allocBitmap(const SkImageInfo & info,SkBitmap * bm)2999 SkRasterHandleAllocator::Handle SkRasterHandleAllocator::allocBitmap(const SkImageInfo& info,
3000                                                                      SkBitmap* bm) {
3001     SkRasterHandleAllocator::Rec rec;
3002     if (!this->allocHandle(info, &rec) || !install(bm, info, rec)) {
3003         return nullptr;
3004     }
3005     return rec.fHandle;
3006 }
3007 
3008 std::unique_ptr<SkCanvas>
MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,const SkImageInfo & info,const Rec * rec)3009 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,
3010                                     const SkImageInfo& info, const Rec* rec) {
3011     if (!alloc || !supported_for_raster_canvas(info)) {
3012         return nullptr;
3013     }
3014 
3015     SkBitmap bm;
3016     Handle hndl;
3017 
3018     if (rec) {
3019         hndl = install(&bm, info, *rec) ? rec->fHandle : nullptr;
3020     } else {
3021         hndl = alloc->allocBitmap(info, &bm);
3022     }
3023     return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr;
3024 }
3025 
3026 ///////////////////////////////////////////////////////////////////////////////////////////////////
3027 
3028 
3029