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 #ifndef SK_DISABLE_SLOW_DEBUG_VALIDATION
1507     // construct clipRgn from the clipstack
1508     const SkBaseDevice* device = this->getDevice();
1509     if (!device) {
1510         SkASSERT(this->isClipEmpty());
1511         return;
1512     }
1513 #endif
1514 }
1515 #endif
1516 
androidFramework_isClipAA() const1517 bool SkCanvas::androidFramework_isClipAA() const {
1518     bool containsAA = false;
1519 
1520     FOR_EACH_TOP_DEVICE(containsAA |= device->onClipIsAA());
1521 
1522     return containsAA;
1523 }
1524 
1525 class RgnAccumulator {
1526     SkRegion* fRgn;
1527 public:
RgnAccumulator(SkRegion * total)1528     RgnAccumulator(SkRegion* total) : fRgn(total) {}
accumulate(SkBaseDevice * device,SkRegion * rgn)1529     void accumulate(SkBaseDevice* device, SkRegion* rgn) {
1530         SkIPoint origin = device->getOrigin();
1531         if (origin.x() | origin.y()) {
1532             rgn->translate(origin.x(), origin.y());
1533         }
1534         fRgn->op(*rgn, SkRegion::kUnion_Op);
1535     }
1536 };
1537 
temporary_internal_getRgnClip(SkRegion * rgn)1538 void SkCanvas::temporary_internal_getRgnClip(SkRegion* rgn) {
1539     RgnAccumulator accum(rgn);
1540     SkRegion tmp;
1541 
1542     rgn->setEmpty();
1543     FOR_EACH_TOP_DEVICE(device->onAsRgnClip(&tmp); accum.accumulate(device, &tmp));
1544 }
1545 
1546 ///////////////////////////////////////////////////////////////////////////////
1547 
isClipEmpty() const1548 bool SkCanvas::isClipEmpty() const {
1549     return fMCRec->fRasterClip.isEmpty();
1550 
1551     // TODO: should we only use the conservative answer in a recording canvas?
1552 #if 0
1553     SkBaseDevice* dev = this->getTopDevice();
1554     // if no device we return true
1555     return !dev || dev->onGetClipType() == SkBaseDevice::kEmpty_ClipType;
1556 #endif
1557 }
1558 
isClipRect() const1559 bool SkCanvas::isClipRect() const {
1560     SkBaseDevice* dev = this->getTopDevice();
1561     // if no device we return false
1562     return dev && dev->onGetClipType() == SkBaseDevice::kRect_ClipType;
1563 }
1564 
is_nan_or_clipped(const Sk4f & devRect,const Sk4f & devClip)1565 static inline bool is_nan_or_clipped(const Sk4f& devRect, const Sk4f& devClip) {
1566 #if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
1567     __m128 lLtT = _mm_unpacklo_ps(devRect.fVec, devClip.fVec);
1568     __m128 RrBb = _mm_unpackhi_ps(devClip.fVec, devRect.fVec);
1569     __m128 mask = _mm_cmplt_ps(lLtT, RrBb);
1570     return 0xF != _mm_movemask_ps(mask);
1571 #elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
1572     float32x4_t lLtT = vzipq_f32(devRect.fVec, devClip.fVec).val[0];
1573     float32x4_t RrBb = vzipq_f32(devClip.fVec, devRect.fVec).val[1];
1574     uint32x4_t mask = vcltq_f32(lLtT, RrBb);
1575     return 0xFFFFFFFFFFFFFFFF != (uint64_t) vmovn_u32(mask);
1576 #else
1577     SkRect devRectAsRect;
1578     SkRect devClipAsRect;
1579     devRect.store(&devRectAsRect.fLeft);
1580     devClip.store(&devClipAsRect.fLeft);
1581     return !devRectAsRect.isFinite() || !devRectAsRect.intersect(devClipAsRect);
1582 #endif
1583 }
1584 
1585 // It's important for this function to not be inlined.  Otherwise the compiler will share code
1586 // 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)1587 static SK_NEVER_INLINE bool quick_reject_slow_path(const SkRect& src, const SkRect& deviceClip,
1588                                                    const SkMatrix& matrix) {
1589     SkRect deviceRect;
1590     matrix.mapRect(&deviceRect, src);
1591     return !deviceRect.isFinite() || !deviceRect.intersect(deviceClip);
1592 }
1593 
quickReject(const SkRect & src) const1594 bool SkCanvas::quickReject(const SkRect& src) const {
1595 #ifdef SK_DEBUG
1596     // Verify that fDeviceClipBounds are set properly.
1597     SkRect tmp = qr_clip_bounds(fMCRec->fRasterClip.getBounds());
1598     if (fMCRec->fRasterClip.isEmpty()) {
1599         SkASSERT(fDeviceClipBounds.isEmpty());
1600     } else {
1601         SkASSERT(tmp == fDeviceClipBounds);
1602     }
1603 
1604     // Verify that fIsScaleTranslate is set properly.
1605     SkASSERT(fIsScaleTranslate == fMCRec->fMatrix.isScaleTranslate());
1606 #endif
1607 
1608     if (!fIsScaleTranslate) {
1609         return quick_reject_slow_path(src, fDeviceClipBounds, fMCRec->fMatrix);
1610     }
1611 
1612     // We inline the implementation of mapScaleTranslate() for the fast path.
1613     float sx = fMCRec->fMatrix.getScaleX();
1614     float sy = fMCRec->fMatrix.getScaleY();
1615     float tx = fMCRec->fMatrix.getTranslateX();
1616     float ty = fMCRec->fMatrix.getTranslateY();
1617     Sk4f scale(sx, sy, sx, sy);
1618     Sk4f trans(tx, ty, tx, ty);
1619 
1620     // Apply matrix.
1621     Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
1622 
1623     // Make sure left < right, top < bottom.
1624     Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
1625     Sk4f min = Sk4f::Min(ltrb, rblt);
1626     Sk4f max = Sk4f::Max(ltrb, rblt);
1627     // We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
1628     // ARM this sequence generates the fastest (a single instruction).
1629     Sk4f devRect = Sk4f(min[2], min[3], max[0], max[1]);
1630 
1631     // Check if the device rect is NaN or outside the clip.
1632     return is_nan_or_clipped(devRect, Sk4f::Load(&fDeviceClipBounds.fLeft));
1633 }
1634 
quickReject(const SkPath & path) const1635 bool SkCanvas::quickReject(const SkPath& path) const {
1636     return path.isEmpty() || this->quickReject(path.getBounds());
1637 }
1638 
getLocalClipBounds() const1639 SkRect SkCanvas::getLocalClipBounds() const {
1640     SkIRect ibounds = this->getDeviceClipBounds();
1641     if (ibounds.isEmpty()) {
1642         return SkRect::MakeEmpty();
1643     }
1644 
1645     SkMatrix inverse;
1646     // if we can't invert the CTM, we can't return local clip bounds
1647     if (!fMCRec->fMatrix.invert(&inverse)) {
1648         return SkRect::MakeEmpty();
1649     }
1650 
1651     SkRect bounds;
1652     SkRect r;
1653     // adjust it outwards in case we are antialiasing
1654     const int inset = 1;
1655 
1656     r.iset(ibounds.fLeft - inset, ibounds.fTop - inset,
1657            ibounds.fRight + inset, ibounds.fBottom + inset);
1658     inverse.mapRect(&bounds, r);
1659     return bounds;
1660 }
1661 
getDeviceClipBounds() const1662 SkIRect SkCanvas::getDeviceClipBounds() const {
1663     return fMCRec->fRasterClip.getBounds();
1664 }
1665 
getTotalMatrix() const1666 const SkMatrix& SkCanvas::getTotalMatrix() const {
1667     return fMCRec->fMatrix;
1668 }
1669 
internal_private_accessTopLayerRenderTargetContext()1670 GrRenderTargetContext* SkCanvas::internal_private_accessTopLayerRenderTargetContext() {
1671     SkBaseDevice* dev = this->getTopDevice();
1672     return dev ? dev->accessRenderTargetContext() : nullptr;
1673 }
1674 
getGrContext()1675 GrContext* SkCanvas::getGrContext() {
1676     SkBaseDevice* device = this->getTopDevice();
1677     return device ? device->context() : nullptr;
1678 }
1679 
drawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)1680 void SkCanvas::drawDRRect(const SkRRect& outer, const SkRRect& inner,
1681                           const SkPaint& paint) {
1682     TRACE_EVENT0("skia", TRACE_FUNC);
1683     if (outer.isEmpty()) {
1684         return;
1685     }
1686     if (inner.isEmpty()) {
1687         this->drawRRect(outer, paint);
1688         return;
1689     }
1690 
1691     // We don't have this method (yet), but technically this is what we should
1692     // be able to return ...
1693     // if (!outer.contains(inner))) {
1694     //
1695     // For now at least check for containment of bounds
1696     if (!outer.getBounds().contains(inner.getBounds())) {
1697         return;
1698     }
1699 
1700     this->onDrawDRRect(outer, inner, paint);
1701 }
1702 
drawPaint(const SkPaint & paint)1703 void SkCanvas::drawPaint(const SkPaint& paint) {
1704     TRACE_EVENT0("skia", TRACE_FUNC);
1705     this->onDrawPaint(paint);
1706 }
1707 
drawRect(const SkRect & r,const SkPaint & paint)1708 void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
1709     TRACE_EVENT0("skia", TRACE_FUNC);
1710     // To avoid redundant logic in our culling code and various backends, we always sort rects
1711     // before passing them along.
1712     this->onDrawRect(r.makeSorted(), paint);
1713 }
1714 
drawRegion(const SkRegion & region,const SkPaint & paint)1715 void SkCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
1716     TRACE_EVENT0("skia", TRACE_FUNC);
1717     if (region.isEmpty()) {
1718         return;
1719     }
1720 
1721     if (region.isRect()) {
1722         return this->drawIRect(region.getBounds(), paint);
1723     }
1724 
1725     this->onDrawRegion(region, paint);
1726 }
1727 
drawOval(const SkRect & r,const SkPaint & paint)1728 void SkCanvas::drawOval(const SkRect& r, const SkPaint& paint) {
1729     TRACE_EVENT0("skia", TRACE_FUNC);
1730     // To avoid redundant logic in our culling code and various backends, we always sort rects
1731     // before passing them along.
1732     this->onDrawOval(r.makeSorted(), paint);
1733 }
1734 
drawRRect(const SkRRect & rrect,const SkPaint & paint)1735 void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
1736     TRACE_EVENT0("skia", TRACE_FUNC);
1737     this->onDrawRRect(rrect, paint);
1738 }
1739 
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1740 void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint) {
1741     TRACE_EVENT0("skia", TRACE_FUNC);
1742     this->onDrawPoints(mode, count, pts, paint);
1743 }
1744 
drawVertices(const sk_sp<SkVertices> & vertices,SkBlendMode mode,const SkPaint & paint)1745 void SkCanvas::drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode,
1746                             const SkPaint& paint) {
1747     TRACE_EVENT0("skia", TRACE_FUNC);
1748     RETURN_ON_NULL(vertices);
1749     this->onDrawVerticesObject(vertices.get(), mode, paint);
1750 }
1751 
drawVertices(const SkVertices * vertices,SkBlendMode mode,const SkPaint & paint)1752 void SkCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
1753     TRACE_EVENT0("skia", TRACE_FUNC);
1754     RETURN_ON_NULL(vertices);
1755     this->onDrawVerticesObject(vertices, mode, paint);
1756 }
1757 
drawPath(const SkPath & path,const SkPaint & paint)1758 void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
1759     TRACE_EVENT0("skia", TRACE_FUNC);
1760     this->onDrawPath(path, paint);
1761 }
1762 
drawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)1763 void SkCanvas::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
1764     TRACE_EVENT0("skia", TRACE_FUNC);
1765     RETURN_ON_NULL(image);
1766     this->onDrawImage(image, x, y, paint);
1767 }
1768 
1769 // Returns true if the rect can be "filled" : non-empty and finite
fillable(const SkRect & r)1770 static bool fillable(const SkRect& r) {
1771     SkScalar w = r.width();
1772     SkScalar h = r.height();
1773     return SkScalarIsFinite(w) && w > 0 && SkScalarIsFinite(h) && h > 0;
1774 }
1775 
drawImageRect(const SkImage * image,const SkRect & src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1776 void SkCanvas::drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
1777                              const SkPaint* paint, SrcRectConstraint constraint) {
1778     TRACE_EVENT0("skia", TRACE_FUNC);
1779     RETURN_ON_NULL(image);
1780     if (!fillable(dst) || !fillable(src)) {
1781         return;
1782     }
1783     this->onDrawImageRect(image, &src, dst, paint, constraint);
1784 }
1785 
drawImageRect(const SkImage * image,const SkIRect & isrc,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1786 void SkCanvas::drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
1787                              const SkPaint* paint, SrcRectConstraint constraint) {
1788     RETURN_ON_NULL(image);
1789     this->drawImageRect(image, SkRect::Make(isrc), dst, paint, constraint);
1790 }
1791 
drawImageRect(const SkImage * image,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1792 void SkCanvas::drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
1793                              SrcRectConstraint constraint) {
1794     RETURN_ON_NULL(image);
1795     this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()), dst, paint,
1796                         constraint);
1797 }
1798 
drawImageNine(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1799 void SkCanvas::drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
1800                              const SkPaint* paint) {
1801     TRACE_EVENT0("skia", TRACE_FUNC);
1802     RETURN_ON_NULL(image);
1803     if (dst.isEmpty()) {
1804         return;
1805     }
1806     if (SkLatticeIter::Valid(image->width(), image->height(), center)) {
1807         this->onDrawImageNine(image, center, dst, paint);
1808     } else {
1809         this->drawImageRect(image, dst, paint);
1810     }
1811 }
1812 
drawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)1813 void SkCanvas::drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
1814                                 const SkPaint* paint) {
1815     TRACE_EVENT0("skia", TRACE_FUNC);
1816     RETURN_ON_NULL(image);
1817     if (dst.isEmpty()) {
1818         return;
1819     }
1820 
1821     SkIRect bounds;
1822     Lattice latticePlusBounds = lattice;
1823     if (!latticePlusBounds.fBounds) {
1824         bounds = SkIRect::MakeWH(image->width(), image->height());
1825         latticePlusBounds.fBounds = &bounds;
1826     }
1827 
1828     if (SkLatticeIter::Valid(image->width(), image->height(), latticePlusBounds)) {
1829         this->onDrawImageLattice(image, latticePlusBounds, dst, paint);
1830     } else {
1831         this->drawImageRect(image, dst, paint);
1832     }
1833 }
1834 
drawBitmap(const SkBitmap & bitmap,SkScalar dx,SkScalar dy,const SkPaint * paint)1835 void SkCanvas::drawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy, const SkPaint* paint) {
1836     TRACE_EVENT0("skia", TRACE_FUNC);
1837     if (bitmap.drawsNothing()) {
1838         return;
1839     }
1840     this->onDrawBitmap(bitmap, dx, dy, paint);
1841 }
1842 
drawBitmapRect(const SkBitmap & bitmap,const SkRect & src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1843 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
1844                               const SkPaint* paint, SrcRectConstraint constraint) {
1845     TRACE_EVENT0("skia", TRACE_FUNC);
1846     if (bitmap.drawsNothing() || dst.isEmpty() || src.isEmpty()) {
1847         return;
1848     }
1849     this->onDrawBitmapRect(bitmap, &src, dst, paint, constraint);
1850 }
1851 
drawBitmapRect(const SkBitmap & bitmap,const SkIRect & isrc,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1852 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
1853                               const SkPaint* paint, SrcRectConstraint constraint) {
1854     this->drawBitmapRect(bitmap, SkRect::Make(isrc), dst, paint, constraint);
1855 }
1856 
drawBitmapRect(const SkBitmap & bitmap,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1857 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
1858                               SrcRectConstraint constraint) {
1859     this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, paint,
1860                          constraint);
1861 }
1862 
drawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)1863 void SkCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
1864                               const SkPaint* paint) {
1865     TRACE_EVENT0("skia", TRACE_FUNC);
1866     if (bitmap.drawsNothing() || dst.isEmpty()) {
1867         return;
1868     }
1869     if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), center)) {
1870         this->onDrawBitmapNine(bitmap, center, dst, paint);
1871     } else {
1872         this->drawBitmapRect(bitmap, dst, paint);
1873     }
1874 }
1875 
drawBitmapLattice(const SkBitmap & bitmap,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)1876 void SkCanvas::drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
1877                                  const SkPaint* paint) {
1878     TRACE_EVENT0("skia", TRACE_FUNC);
1879     if (bitmap.drawsNothing() || dst.isEmpty()) {
1880         return;
1881     }
1882 
1883     SkIRect bounds;
1884     Lattice latticePlusBounds = lattice;
1885     if (!latticePlusBounds.fBounds) {
1886         bounds = SkIRect::MakeWH(bitmap.width(), bitmap.height());
1887         latticePlusBounds.fBounds = &bounds;
1888     }
1889 
1890     if (SkLatticeIter::Valid(bitmap.width(), bitmap.height(), latticePlusBounds)) {
1891         this->onDrawBitmapLattice(bitmap, latticePlusBounds, dst, paint);
1892     } else {
1893         this->drawBitmapRect(bitmap, dst, paint);
1894     }
1895 }
1896 
drawAtlas(const SkImage * atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode mode,const SkRect * cull,const SkPaint * paint)1897 void SkCanvas::drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
1898                          const SkColor colors[], int count, SkBlendMode mode,
1899                          const SkRect* cull, const SkPaint* paint) {
1900     TRACE_EVENT0("skia", TRACE_FUNC);
1901     RETURN_ON_NULL(atlas);
1902     if (count <= 0) {
1903         return;
1904     }
1905     SkASSERT(atlas);
1906     SkASSERT(tex);
1907     this->onDrawAtlas(atlas, xform, tex, colors, count, mode, cull, paint);
1908 }
1909 
drawAnnotation(const SkRect & rect,const char key[],SkData * value)1910 void SkCanvas::drawAnnotation(const SkRect& rect, const char key[], SkData* value) {
1911     TRACE_EVENT0("skia", TRACE_FUNC);
1912     if (key) {
1913         this->onDrawAnnotation(rect, key, value);
1914     }
1915 }
1916 
legacy_drawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1917 void SkCanvas::legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1918                                     const SkPaint* paint, SrcRectConstraint constraint) {
1919     if (src) {
1920         this->drawImageRect(image, *src, dst, paint, constraint);
1921     } else {
1922         this->drawImageRect(image, SkRect::MakeIWH(image->width(), image->height()),
1923                             dst, paint, constraint);
1924     }
1925 }
legacy_drawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)1926 void SkCanvas::legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1927                                      const SkPaint* paint, SrcRectConstraint constraint) {
1928     if (src) {
1929         this->drawBitmapRect(bitmap, *src, dst, paint, constraint);
1930     } else {
1931         this->drawBitmapRect(bitmap, SkRect::MakeIWH(bitmap.width(), bitmap.height()),
1932                              dst, paint, constraint);
1933     }
1934 }
1935 
private_draw_shadow_rec(const SkPath & path,const SkDrawShadowRec & rec)1936 void SkCanvas::private_draw_shadow_rec(const SkPath& path, const SkDrawShadowRec& rec) {
1937     TRACE_EVENT0("skia", TRACE_FUNC);
1938     this->onDrawShadowRec(path, rec);
1939 }
1940 
onDrawShadowRec(const SkPath & path,const SkDrawShadowRec & rec)1941 void SkCanvas::onDrawShadowRec(const SkPath& path, const SkDrawShadowRec& rec) {
1942     SkPaint paint;
1943     const SkRect& pathBounds = path.getBounds();
1944 
1945     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
1946     while (iter.next()) {
1947         iter.fDevice->drawShadow(path, rec);
1948     }
1949     LOOPER_END
1950 }
1951 
1952 //////////////////////////////////////////////////////////////////////////////
1953 //  These are the virtual drawing methods
1954 //////////////////////////////////////////////////////////////////////////////
1955 
onDiscard()1956 void SkCanvas::onDiscard() {
1957     if (fSurfaceBase) {
1958         fSurfaceBase->aboutToDraw(SkSurface::kDiscard_ContentChangeMode);
1959     }
1960 }
1961 
onDrawPaint(const SkPaint & paint)1962 void SkCanvas::onDrawPaint(const SkPaint& paint) {
1963     this->internalDrawPaint(paint);
1964 }
1965 
internalDrawPaint(const SkPaint & paint)1966 void SkCanvas::internalDrawPaint(const SkPaint& paint) {
1967     LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kPaint_Type, nullptr, false)
1968 
1969     while (iter.next()) {
1970         iter.fDevice->drawPaint(looper.paint());
1971     }
1972 
1973     LOOPER_END
1974 }
1975 
onDrawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)1976 void SkCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
1977                             const SkPaint& paint) {
1978     if ((long)count <= 0) {
1979         return;
1980     }
1981 
1982     SkRect r;
1983     const SkRect* bounds = nullptr;
1984     if (paint.canComputeFastBounds()) {
1985         // special-case 2 points (common for drawing a single line)
1986         if (2 == count) {
1987             r.set(pts[0], pts[1]);
1988         } else {
1989             r.set(pts, SkToInt(count));
1990         }
1991         if (!r.isFinite()) {
1992             return;
1993         }
1994         SkRect storage;
1995         if (this->quickReject(paint.computeFastStrokeBounds(r, &storage))) {
1996             return;
1997         }
1998         bounds = &r;
1999     }
2000 
2001     SkASSERT(pts != nullptr);
2002 
2003     LOOPER_BEGIN(paint, SkDrawFilter::kPoint_Type, bounds)
2004 
2005     while (iter.next()) {
2006         iter.fDevice->drawPoints(mode, count, pts, looper.paint());
2007     }
2008 
2009     LOOPER_END
2010 }
2011 
needs_autodrawlooper(SkCanvas * canvas,const SkPaint & paint)2012 static bool needs_autodrawlooper(SkCanvas* canvas, const SkPaint& paint) {
2013     return ((intptr_t)paint.getImageFilter()    |
2014 #ifdef SK_SUPPORT_LEGACY_DRAWFILTER
2015             (intptr_t)canvas->getDrawFilter()   |
2016 #endif
2017             (intptr_t)paint.getLooper()         ) != 0;
2018 }
2019 
onDrawRect(const SkRect & r,const SkPaint & paint)2020 void SkCanvas::onDrawRect(const SkRect& r, const SkPaint& paint) {
2021     SkASSERT(r.isSorted());
2022     if (paint.canComputeFastBounds()) {
2023         SkRect storage;
2024         if (this->quickReject(paint.computeFastBounds(r, &storage))) {
2025             return;
2026         }
2027     }
2028 
2029     if (needs_autodrawlooper(this, paint)) {
2030         LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(paint, SkDrawFilter::kRect_Type, &r, false)
2031 
2032         while (iter.next()) {
2033             iter.fDevice->drawRect(r, looper.paint());
2034         }
2035 
2036         LOOPER_END
2037     } else {
2038         this->predrawNotify(&r, &paint, false);
2039         SkDrawIter iter(this);
2040         while (iter.next()) {
2041             iter.fDevice->drawRect(r, paint);
2042         }
2043     }
2044 }
2045 
onDrawRegion(const SkRegion & region,const SkPaint & paint)2046 void SkCanvas::onDrawRegion(const SkRegion& region, const SkPaint& paint) {
2047     SkRect regionRect = SkRect::Make(region.getBounds());
2048     if (paint.canComputeFastBounds()) {
2049         SkRect storage;
2050         if (this->quickReject(paint.computeFastBounds(regionRect, &storage))) {
2051             return;
2052         }
2053     }
2054 
2055     LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, &regionRect)
2056 
2057     while (iter.next()) {
2058         iter.fDevice->drawRegion(region, looper.paint());
2059     }
2060 
2061     LOOPER_END
2062 }
2063 
onDrawOval(const SkRect & oval,const SkPaint & paint)2064 void SkCanvas::onDrawOval(const SkRect& oval, const SkPaint& paint) {
2065     SkASSERT(oval.isSorted());
2066     if (paint.canComputeFastBounds()) {
2067         SkRect storage;
2068         if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2069             return;
2070         }
2071     }
2072 
2073     LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2074 
2075     while (iter.next()) {
2076         iter.fDevice->drawOval(oval, looper.paint());
2077     }
2078 
2079     LOOPER_END
2080 }
2081 
onDrawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)2082 void SkCanvas::onDrawArc(const SkRect& oval, SkScalar startAngle,
2083                          SkScalar sweepAngle, bool useCenter,
2084                          const SkPaint& paint) {
2085     SkASSERT(oval.isSorted());
2086     if (paint.canComputeFastBounds()) {
2087         SkRect storage;
2088         // Note we're using the entire oval as the bounds.
2089         if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
2090             return;
2091         }
2092     }
2093 
2094     LOOPER_BEGIN(paint, SkDrawFilter::kOval_Type, &oval)
2095 
2096     while (iter.next()) {
2097         iter.fDevice->drawArc(oval, startAngle, sweepAngle, useCenter, looper.paint());
2098     }
2099 
2100     LOOPER_END
2101 }
2102 
onDrawRRect(const SkRRect & rrect,const SkPaint & paint)2103 void SkCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
2104     if (paint.canComputeFastBounds()) {
2105         SkRect storage;
2106         if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
2107             return;
2108         }
2109     }
2110 
2111     if (rrect.isRect()) {
2112         // call the non-virtual version
2113         this->SkCanvas::drawRect(rrect.getBounds(), paint);
2114         return;
2115     } else if (rrect.isOval()) {
2116         // call the non-virtual version
2117         this->SkCanvas::drawOval(rrect.getBounds(), paint);
2118         return;
2119     }
2120 
2121     LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &rrect.getBounds())
2122 
2123     while (iter.next()) {
2124         iter.fDevice->drawRRect(rrect, looper.paint());
2125     }
2126 
2127     LOOPER_END
2128 }
2129 
onDrawDRRect(const SkRRect & outer,const SkRRect & inner,const SkPaint & paint)2130 void SkCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint) {
2131     if (paint.canComputeFastBounds()) {
2132         SkRect storage;
2133         if (this->quickReject(paint.computeFastBounds(outer.getBounds(), &storage))) {
2134             return;
2135         }
2136     }
2137 
2138     LOOPER_BEGIN(paint, SkDrawFilter::kRRect_Type, &outer.getBounds())
2139 
2140     while (iter.next()) {
2141         iter.fDevice->drawDRRect(outer, inner, looper.paint());
2142     }
2143 
2144     LOOPER_END
2145 }
2146 
onDrawPath(const SkPath & path,const SkPaint & paint)2147 void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
2148     if (!path.isFinite()) {
2149         return;
2150     }
2151 
2152     const SkRect& pathBounds = path.getBounds();
2153     if (!path.isInverseFillType() && paint.canComputeFastBounds()) {
2154         SkRect storage;
2155         if (this->quickReject(paint.computeFastBounds(pathBounds, &storage))) {
2156             return;
2157         }
2158     }
2159 
2160     if (pathBounds.width() <= 0 && pathBounds.height() <= 0) {
2161         if (path.isInverseFillType()) {
2162             this->internalDrawPaint(paint);
2163             return;
2164         }
2165     }
2166 
2167     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, &pathBounds)
2168 
2169     while (iter.next()) {
2170         iter.fDevice->drawPath(path, looper.paint());
2171     }
2172 
2173     LOOPER_END
2174 }
2175 
canDrawBitmapAsSprite(SkScalar x,SkScalar y,int w,int h,const SkPaint & paint)2176 bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) {
2177     if (!paint.getImageFilter()) {
2178         return false;
2179     }
2180 
2181     const SkMatrix& ctm = this->getTotalMatrix();
2182     if (!SkTreatAsSprite(ctm, SkISize::Make(w, h), paint)) {
2183         return false;
2184     }
2185 
2186     // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds.
2187     // Once we can filter and the filter will return a result larger than itself, we should be
2188     // able to remove this constraint.
2189     // skbug.com/4526
2190     //
2191     SkPoint pt;
2192     ctm.mapXY(x, y, &pt);
2193     SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h);
2194     return ir.contains(fMCRec->fRasterClip.getBounds());
2195 }
2196 
onDrawImage(const SkImage * image,SkScalar x,SkScalar y,const SkPaint * paint)2197 void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) {
2198     SkRect bounds = SkRect::MakeXYWH(x, y,
2199                                      SkIntToScalar(image->width()), SkIntToScalar(image->height()));
2200     if (nullptr == paint || paint->canComputeFastBounds()) {
2201         SkRect tmp = bounds;
2202         if (paint) {
2203             paint->computeFastBounds(tmp, &tmp);
2204         }
2205         if (this->quickReject(tmp)) {
2206             return;
2207         }
2208     }
2209 
2210     SkLazyPaint lazy;
2211     if (nullptr == paint) {
2212         paint = lazy.init();
2213     }
2214 
2215     sk_sp<SkSpecialImage> special;
2216     bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(),
2217                                                     *paint);
2218     if (drawAsSprite && paint->getImageFilter()) {
2219         special = this->getDevice()->makeSpecial(image);
2220         if (!special) {
2221             drawAsSprite = false;
2222         }
2223     }
2224 
2225     LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2226 
2227     while (iter.next()) {
2228         const SkPaint& pnt = looper.paint();
2229         if (special) {
2230             SkPoint pt;
2231             iter.fDevice->ctm().mapXY(x, y, &pt);
2232             iter.fDevice->drawSpecial(special.get(),
2233                                       SkScalarRoundToInt(pt.fX),
2234                                       SkScalarRoundToInt(pt.fY), pnt,
2235                                       nullptr, SkMatrix::I());
2236         } else {
2237             iter.fDevice->drawImage(image, x, y, pnt);
2238         }
2239     }
2240 
2241     LOOPER_END
2242 }
2243 
onDrawImageRect(const SkImage * image,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)2244 void SkCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
2245                                const SkPaint* paint, SrcRectConstraint constraint) {
2246     if (nullptr == paint || paint->canComputeFastBounds()) {
2247         SkRect storage = dst;
2248         if (paint) {
2249             paint->computeFastBounds(dst, &storage);
2250         }
2251         if (this->quickReject(storage)) {
2252             return;
2253         }
2254     }
2255     SkLazyPaint lazy;
2256     if (nullptr == paint) {
2257         paint = lazy.init();
2258     }
2259 
2260     LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2261                                           image->isOpaque())
2262 
2263     while (iter.next()) {
2264         iter.fDevice->drawImageRect(image, src, dst, looper.paint(), constraint);
2265     }
2266 
2267     LOOPER_END
2268 }
2269 
onDrawBitmap(const SkBitmap & bitmap,SkScalar x,SkScalar y,const SkPaint * paint)2270 void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, const SkPaint* paint) {
2271     SkDEBUGCODE(bitmap.validate();)
2272 
2273     if (bitmap.drawsNothing()) {
2274         return;
2275     }
2276 
2277     SkLazyPaint lazy;
2278     if (nullptr == paint) {
2279         paint = lazy.init();
2280     }
2281 
2282     SkRect bounds;
2283     bitmap.getBounds(&bounds);
2284     bounds.offset(x, y);
2285     bool canFastBounds = paint->canComputeFastBounds();
2286     if (canFastBounds) {
2287         SkRect storage;
2288         if (this->quickReject(paint->computeFastBounds(bounds, &storage))) {
2289             return;
2290         }
2291     }
2292 
2293     sk_sp<SkSpecialImage> special;
2294     bool drawAsSprite = canFastBounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(),
2295                                                                      bitmap.height(), *paint);
2296     if (drawAsSprite && paint->getImageFilter()) {
2297         special = this->getDevice()->makeSpecial(bitmap);
2298         if (!special) {
2299             drawAsSprite = false;
2300         }
2301     }
2302 
2303     LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds)
2304 
2305     while (iter.next()) {
2306         const SkPaint& pnt = looper.paint();
2307         if (special) {
2308             SkPoint pt;
2309             iter.fDevice->ctm().mapXY(x, y, &pt);
2310             iter.fDevice->drawSpecial(special.get(),
2311                                       SkScalarRoundToInt(pt.fX),
2312                                       SkScalarRoundToInt(pt.fY), pnt,
2313                                       nullptr, SkMatrix::I());
2314         } else {
2315             iter.fDevice->drawBitmap(bitmap, x, y, looper.paint());
2316         }
2317     }
2318 
2319     LOOPER_END
2320 }
2321 
2322 // 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)2323 void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
2324                                       const SkRect& dst, const SkPaint* paint,
2325                                       SrcRectConstraint constraint) {
2326     if (bitmap.drawsNothing() || dst.isEmpty()) {
2327         return;
2328     }
2329 
2330     if (nullptr == paint || paint->canComputeFastBounds()) {
2331         SkRect storage;
2332         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2333             return;
2334         }
2335     }
2336 
2337     SkLazyPaint lazy;
2338     if (nullptr == paint) {
2339         paint = lazy.init();
2340     }
2341 
2342     LOOPER_BEGIN_CHECK_COMPLETE_OVERWRITE(*paint, SkDrawFilter::kBitmap_Type, &dst,
2343                                           bitmap.isOpaque())
2344 
2345     while (iter.next()) {
2346         iter.fDevice->drawBitmapRect(bitmap, src, dst, looper.paint(), constraint);
2347     }
2348 
2349     LOOPER_END
2350 }
2351 
onDrawBitmapRect(const SkBitmap & bitmap,const SkRect * src,const SkRect & dst,const SkPaint * paint,SrcRectConstraint constraint)2352 void SkCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
2353                                 const SkPaint* paint, SrcRectConstraint constraint) {
2354     SkDEBUGCODE(bitmap.validate();)
2355     this->internalDrawBitmapRect(bitmap, src, dst, paint, constraint);
2356 }
2357 
onDrawImageNine(const SkImage * image,const SkIRect & center,const SkRect & dst,const SkPaint * paint)2358 void SkCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
2359                                const SkPaint* paint) {
2360     if (nullptr == paint || paint->canComputeFastBounds()) {
2361         SkRect storage;
2362         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2363             return;
2364         }
2365     }
2366 
2367     SkLazyPaint lazy;
2368     if (nullptr == paint) {
2369         paint = lazy.init();
2370     }
2371 
2372     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2373 
2374     while (iter.next()) {
2375         iter.fDevice->drawImageNine(image, center, dst, looper.paint());
2376     }
2377 
2378     LOOPER_END
2379 }
2380 
onDrawBitmapNine(const SkBitmap & bitmap,const SkIRect & center,const SkRect & dst,const SkPaint * paint)2381 void SkCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
2382                                 const SkPaint* paint) {
2383     SkDEBUGCODE(bitmap.validate();)
2384 
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->drawBitmapNine(bitmap, center, dst, looper.paint());
2401     }
2402 
2403     LOOPER_END
2404 }
2405 
onDrawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)2406 void SkCanvas::onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
2407                                   const SkPaint* paint) {
2408     if (nullptr == paint || paint->canComputeFastBounds()) {
2409         SkRect storage;
2410         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2411             return;
2412         }
2413     }
2414 
2415     SkLazyPaint lazy;
2416     if (nullptr == paint) {
2417         paint = lazy.init();
2418     }
2419 
2420     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2421 
2422     while (iter.next()) {
2423         iter.fDevice->drawImageLattice(image, lattice, dst, looper.paint());
2424     }
2425 
2426     LOOPER_END
2427 }
2428 
onDrawBitmapLattice(const SkBitmap & bitmap,const Lattice & lattice,const SkRect & dst,const SkPaint * paint)2429 void SkCanvas::onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
2430                                    const SkRect& dst, const SkPaint* paint) {
2431     if (nullptr == paint || paint->canComputeFastBounds()) {
2432         SkRect storage;
2433         if (this->quickReject(paint ? paint->computeFastBounds(dst, &storage) : dst)) {
2434             return;
2435         }
2436     }
2437 
2438     SkLazyPaint lazy;
2439     if (nullptr == paint) {
2440         paint = lazy.init();
2441     }
2442 
2443     LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &dst)
2444 
2445     while (iter.next()) {
2446         iter.fDevice->drawBitmapLattice(bitmap, lattice, dst, looper.paint());
2447     }
2448 
2449     LOOPER_END
2450 }
2451 
2452 class SkDeviceFilteredPaint {
2453 public:
SkDeviceFilteredPaint(SkBaseDevice * device,const SkPaint & paint)2454     SkDeviceFilteredPaint(SkBaseDevice* device, const SkPaint& paint) {
2455         uint32_t filteredFlags = device->filterTextFlags(paint);
2456         if (filteredFlags != paint.getFlags()) {
2457             SkPaint* newPaint = fLazy.set(paint);
2458             newPaint->setFlags(filteredFlags);
2459             fPaint = newPaint;
2460         } else {
2461             fPaint = &paint;
2462         }
2463     }
2464 
paint() const2465     const SkPaint& paint() const { return *fPaint; }
2466 
2467 private:
2468     const SkPaint*  fPaint;
2469     SkLazyPaint     fLazy;
2470 };
2471 
onDrawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)2472 void SkCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2473                           const SkPaint& paint) {
2474     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2475 
2476     while (iter.next()) {
2477         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2478         iter.fDevice->drawText(text, byteLength, x, y, dfp.paint());
2479     }
2480 
2481     LOOPER_END
2482 }
2483 
onDrawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)2484 void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2485                              const SkPaint& paint) {
2486     SkPoint textOffset = SkPoint::Make(0, 0);
2487 
2488     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2489 
2490     while (iter.next()) {
2491         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2492         iter.fDevice->drawPosText(text, byteLength, &pos->fX, 2, textOffset,
2493                                   dfp.paint());
2494     }
2495 
2496     LOOPER_END
2497 }
2498 
onDrawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)2499 void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2500                               SkScalar constY, const SkPaint& paint) {
2501 
2502     SkPoint textOffset = SkPoint::Make(0, constY);
2503 
2504     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2505 
2506     while (iter.next()) {
2507         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2508         iter.fDevice->drawPosText(text, byteLength, xpos, 1, textOffset,
2509                                   dfp.paint());
2510     }
2511 
2512     LOOPER_END
2513 }
2514 
onDrawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)2515 void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2516                                 const SkMatrix* matrix, const SkPaint& paint) {
2517     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2518 
2519     while (iter.next()) {
2520         iter.fDevice->drawTextOnPath(text, byteLength, path,
2521                                      matrix, looper.paint());
2522     }
2523 
2524     LOOPER_END
2525 }
2526 
onDrawTextRSXform(const void * text,size_t byteLength,const SkRSXform xform[],const SkRect * cullRect,const SkPaint & paint)2527 void SkCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
2528                                  const SkRect* cullRect, const SkPaint& paint) {
2529     if (cullRect && this->quickReject(*cullRect)) {
2530         return;
2531     }
2532 
2533     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, nullptr)
2534 
2535     while (iter.next()) {
2536         iter.fDevice->drawTextRSXform(text, byteLength, xform, looper.paint());
2537     }
2538 
2539     LOOPER_END
2540 }
2541 
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)2542 void SkCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2543                               const SkPaint& paint) {
2544 
2545     SkRect storage;
2546     const SkRect* bounds = nullptr;
2547     if (paint.canComputeFastBounds()) {
2548         storage = blob->bounds().makeOffset(x, y);
2549         SkRect tmp;
2550         if (this->quickReject(paint.computeFastBounds(storage, &tmp))) {
2551             return;
2552         }
2553         bounds = &storage;
2554     }
2555 
2556     // We cannot filter in the looper as we normally do, because the paint is
2557     // incomplete at this point (text-related attributes are embedded within blob run paints).
2558     SkDrawFilter* drawFilter = fMCRec->fFilter;
2559     fMCRec->fFilter = nullptr;
2560 
2561     LOOPER_BEGIN(paint, SkDrawFilter::kText_Type, bounds)
2562 
2563     while (iter.next()) {
2564         SkDeviceFilteredPaint dfp(iter.fDevice, looper.paint());
2565         iter.fDevice->drawTextBlob(blob, x, y, dfp.paint(), drawFilter);
2566     }
2567 
2568     LOOPER_END
2569 
2570     fMCRec->fFilter = drawFilter;
2571 }
2572 
drawString(const SkString & string,SkScalar x,SkScalar y,const SkPaint & paint)2573 void SkCanvas::drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint) {
2574     this->drawText(string.c_str(), string.size(), x, y, paint);
2575 }
2576 
2577 // 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)2578 void SkCanvas::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
2579                         const SkPaint& paint) {
2580     TRACE_EVENT0("skia", TRACE_FUNC);
2581     if (byteLength) {
2582         sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2583         this->onDrawText(text, byteLength, x, y, paint);
2584     }
2585 }
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)2586 void SkCanvas::drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
2587                            const SkPaint& paint) {
2588     TRACE_EVENT0("skia", TRACE_FUNC);
2589     if (byteLength) {
2590         sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2591         this->onDrawPosText(text, byteLength, pos, paint);
2592     }
2593 }
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)2594 void SkCanvas::drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[],
2595                             SkScalar constY, const SkPaint& paint) {
2596     TRACE_EVENT0("skia", TRACE_FUNC);
2597     if (byteLength) {
2598         sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2599         this->onDrawPosTextH(text, byteLength, xpos, constY, paint);
2600     }
2601 }
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)2602 void SkCanvas::drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
2603                               const SkMatrix* matrix, const SkPaint& paint) {
2604     TRACE_EVENT0("skia", TRACE_FUNC);
2605     if (byteLength) {
2606         sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2607         this->onDrawTextOnPath(text, byteLength, path, matrix, paint);
2608     }
2609 }
drawTextRSXform(const void * text,size_t byteLength,const SkRSXform xform[],const SkRect * cullRect,const SkPaint & paint)2610 void SkCanvas::drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
2611                                const SkRect* cullRect, const SkPaint& paint) {
2612     TRACE_EVENT0("skia", TRACE_FUNC);
2613     if (byteLength) {
2614         sk_msan_assert_initialized(text, SkTAddOffset<const void>(text, byteLength));
2615         this->onDrawTextRSXform(text, byteLength, xform, cullRect, paint);
2616     }
2617 }
drawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)2618 void SkCanvas::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2619                             const SkPaint& paint) {
2620     TRACE_EVENT0("skia", TRACE_FUNC);
2621     RETURN_ON_NULL(blob);
2622     RETURN_ON_FALSE(blob->bounds().makeOffset(x, y).isFinite());
2623     this->onDrawTextBlob(blob, x, y, paint);
2624 }
2625 
onDrawVerticesObject(const SkVertices * vertices,SkBlendMode bmode,const SkPaint & paint)2626 void SkCanvas::onDrawVerticesObject(const SkVertices* vertices, SkBlendMode bmode,
2627                                     const SkPaint& paint) {
2628     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2629 
2630     while (iter.next()) {
2631         // In the common case of one iteration we could std::move vertices here.
2632         iter.fDevice->drawVertices(vertices, bmode, looper.paint());
2633     }
2634 
2635     LOOPER_END
2636 }
2637 
drawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)2638 void SkCanvas::drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2639                          const SkPoint texCoords[4], SkBlendMode bmode,
2640                          const SkPaint& paint) {
2641     TRACE_EVENT0("skia", TRACE_FUNC);
2642     if (nullptr == cubics) {
2643         return;
2644     }
2645 
2646     this->onDrawPatch(cubics, colors, texCoords, bmode, paint);
2647 }
2648 
onDrawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],SkBlendMode bmode,const SkPaint & paint)2649 void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2650                            const SkPoint texCoords[4], SkBlendMode bmode,
2651                            const SkPaint& paint) {
2652     // Since a patch is always within the convex hull of the control points, we discard it when its
2653     // bounding rectangle is completely outside the current clip.
2654     SkRect bounds;
2655     bounds.set(cubics, SkPatchUtils::kNumCtrlPts);
2656     if (this->quickReject(bounds)) {
2657         return;
2658     }
2659 
2660     const bool interpColorsLinearly = (this->imageInfo().colorSpace() != nullptr);
2661 
2662     LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type, nullptr)
2663 
2664     while (iter.next()) {
2665         iter.fDevice->drawPatch(cubics, colors, texCoords, bmode, interpColorsLinearly, paint);
2666     }
2667 
2668     LOOPER_END
2669 }
2670 
drawDrawable(SkDrawable * dr,SkScalar x,SkScalar y)2671 void SkCanvas::drawDrawable(SkDrawable* dr, SkScalar x, SkScalar y) {
2672 #ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
2673     TRACE_EVENT0("skia", TRACE_FUNC);
2674 #endif
2675     RETURN_ON_NULL(dr);
2676     if (x || y) {
2677         SkMatrix matrix = SkMatrix::MakeTrans(x, y);
2678         this->onDrawDrawable(dr, &matrix);
2679     } else {
2680         this->onDrawDrawable(dr, nullptr);
2681     }
2682 }
2683 
drawDrawable(SkDrawable * dr,const SkMatrix * matrix)2684 void SkCanvas::drawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2685 #ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
2686     TRACE_EVENT0("skia", TRACE_FUNC);
2687 #endif
2688     RETURN_ON_NULL(dr);
2689     if (matrix && matrix->isIdentity()) {
2690         matrix = nullptr;
2691     }
2692     this->onDrawDrawable(dr, matrix);
2693 }
2694 
onDrawDrawable(SkDrawable * dr,const SkMatrix * matrix)2695 void SkCanvas::onDrawDrawable(SkDrawable* dr, const SkMatrix* matrix) {
2696     // drawable bounds are no longer reliable (e.g. android displaylist)
2697     // so don't use them for quick-reject
2698     dr->draw(this, matrix);
2699 }
2700 
onDrawAtlas(const SkImage * atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode bmode,const SkRect * cull,const SkPaint * paint)2701 void SkCanvas::onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2702                            const SkColor colors[], int count, SkBlendMode bmode,
2703                            const SkRect* cull, const SkPaint* paint) {
2704     if (cull && this->quickReject(*cull)) {
2705         return;
2706     }
2707 
2708     SkPaint pnt;
2709     if (paint) {
2710         pnt = *paint;
2711     }
2712 
2713     LOOPER_BEGIN(pnt, SkDrawFilter::kPath_Type, nullptr)
2714     while (iter.next()) {
2715         iter.fDevice->drawAtlas(atlas, xform, tex, colors, count, bmode, pnt);
2716     }
2717     LOOPER_END
2718 }
2719 
onDrawAnnotation(const SkRect & rect,const char key[],SkData * value)2720 void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
2721     SkASSERT(key);
2722 
2723     SkPaint paint;
2724     LOOPER_BEGIN(paint, SkDrawFilter::kRect_Type, nullptr)
2725     while (iter.next()) {
2726         iter.fDevice->drawAnnotation(rect, key, value);
2727     }
2728     LOOPER_END
2729 }
2730 
2731 //////////////////////////////////////////////////////////////////////////////
2732 // These methods are NOT virtual, and therefore must call back into virtual
2733 // methods, rather than actually drawing themselves.
2734 //////////////////////////////////////////////////////////////////////////////
2735 
drawColor(SkColor c,SkBlendMode mode)2736 void SkCanvas::drawColor(SkColor c, SkBlendMode mode) {
2737     SkPaint paint;
2738     paint.setColor(c);
2739     paint.setBlendMode(mode);
2740     this->drawPaint(paint);
2741 }
2742 
drawPoint(SkScalar x,SkScalar y,const SkPaint & paint)2743 void SkCanvas::drawPoint(SkScalar x, SkScalar y, const SkPaint& paint) {
2744     const SkPoint pt = { x, y };
2745     this->drawPoints(kPoints_PointMode, 1, &pt, paint);
2746 }
2747 
drawLine(SkScalar x0,SkScalar y0,SkScalar x1,SkScalar y1,const SkPaint & paint)2748 void SkCanvas::drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint) {
2749     SkPoint pts[2];
2750     pts[0].set(x0, y0);
2751     pts[1].set(x1, y1);
2752     this->drawPoints(kLines_PointMode, 2, pts, paint);
2753 }
2754 
drawCircle(SkScalar cx,SkScalar cy,SkScalar radius,const SkPaint & paint)2755 void SkCanvas::drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint) {
2756     if (radius < 0) {
2757         radius = 0;
2758     }
2759 
2760     SkRect  r;
2761     r.set(cx - radius, cy - radius, cx + radius, cy + radius);
2762     this->drawOval(r, paint);
2763 }
2764 
drawRoundRect(const SkRect & r,SkScalar rx,SkScalar ry,const SkPaint & paint)2765 void SkCanvas::drawRoundRect(const SkRect& r, SkScalar rx, SkScalar ry,
2766                              const SkPaint& paint) {
2767     if (rx > 0 && ry > 0) {
2768         SkRRect rrect;
2769         rrect.setRectXY(r, rx, ry);
2770         this->drawRRect(rrect, paint);
2771     } else {
2772         this->drawRect(r, paint);
2773     }
2774 }
2775 
drawArc(const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const SkPaint & paint)2776 void SkCanvas::drawArc(const SkRect& oval, SkScalar startAngle,
2777                        SkScalar sweepAngle, bool useCenter,
2778                        const SkPaint& paint) {
2779     TRACE_EVENT0("skia", TRACE_FUNC);
2780     if (oval.isEmpty() || !sweepAngle) {
2781         return;
2782     }
2783     this->onDrawArc(oval, startAngle, sweepAngle, useCenter, paint);
2784 }
2785 
drawTextOnPathHV(const void * text,size_t byteLength,const SkPath & path,SkScalar hOffset,SkScalar vOffset,const SkPaint & paint)2786 void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength,
2787                                 const SkPath& path, SkScalar hOffset,
2788                                 SkScalar vOffset, const SkPaint& paint) {
2789     SkMatrix    matrix;
2790 
2791     matrix.setTranslate(hOffset, vOffset);
2792     this->drawTextOnPath(text, byteLength, path, &matrix, paint);
2793 }
2794 
2795 ///////////////////////////////////////////////////////////////////////////////
2796 
2797 /**
2798  *  This constant is trying to balance the speed of ref'ing a subpicture into a parent picture,
2799  *  against the playback cost of recursing into the subpicture to get at its actual ops.
2800  *
2801  *  For now we pick a conservatively small value, though measurement (and other heuristics like
2802  *  the type of ops contained) may justify changing this value.
2803  */
2804 #define kMaxPictureOpsToUnrollInsteadOfRef  1
2805 
drawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)2806 void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) {
2807     TRACE_EVENT0("skia", TRACE_FUNC);
2808     RETURN_ON_NULL(picture);
2809 
2810     if (matrix && matrix->isIdentity()) {
2811         matrix = nullptr;
2812     }
2813     if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) {
2814         SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2815         picture->playback(this);
2816     } else {
2817         this->onDrawPicture(picture, matrix, paint);
2818     }
2819 }
2820 
onDrawPicture(const SkPicture * picture,const SkMatrix * matrix,const SkPaint * paint)2821 void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2822                              const SkPaint* paint) {
2823     if (!paint || paint->canComputeFastBounds()) {
2824         SkRect bounds = picture->cullRect();
2825         if (paint) {
2826             paint->computeFastBounds(bounds, &bounds);
2827         }
2828         if (matrix) {
2829             matrix->mapRect(&bounds);
2830         }
2831         if (this->quickReject(bounds)) {
2832             return;
2833         }
2834     }
2835 
2836     SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
2837     picture->playback(this);
2838 }
2839 
2840 ///////////////////////////////////////////////////////////////////////////////
2841 ///////////////////////////////////////////////////////////////////////////////
2842 
LayerIter(SkCanvas * canvas)2843 SkCanvas::LayerIter::LayerIter(SkCanvas* canvas) {
2844     static_assert(sizeof(fStorage) >= sizeof(SkDrawIter), "fStorage_too_small");
2845 
2846     SkASSERT(canvas);
2847 
2848     fImpl = new (fStorage) SkDrawIter(canvas);
2849     fDone = !fImpl->next();
2850 }
2851 
~LayerIter()2852 SkCanvas::LayerIter::~LayerIter() {
2853     fImpl->~SkDrawIter();
2854 }
2855 
next()2856 void SkCanvas::LayerIter::next() {
2857     fDone = !fImpl->next();
2858 }
2859 
device() const2860 SkBaseDevice* SkCanvas::LayerIter::device() const {
2861     return fImpl->fDevice;
2862 }
2863 
matrix() const2864 const SkMatrix& SkCanvas::LayerIter::matrix() const {
2865     return fImpl->fDevice->ctm();
2866 }
2867 
paint() const2868 const SkPaint& SkCanvas::LayerIter::paint() const {
2869     const SkPaint* paint = fImpl->getPaint();
2870     if (nullptr == paint) {
2871         paint = &fDefaultPaint;
2872     }
2873     return *paint;
2874 }
2875 
clip(SkRegion * rgn) const2876 void SkCanvas::LayerIter::clip(SkRegion* rgn) const {
2877     return fImpl->fDevice->onAsRgnClip(rgn);
2878 }
2879 
x() const2880 int SkCanvas::LayerIter::x() const { return fImpl->getX(); }
y() const2881 int SkCanvas::LayerIter::y() const { return fImpl->getY(); }
2882 
2883 ///////////////////////////////////////////////////////////////////////////////
2884 
supported_for_raster_canvas(const SkImageInfo & info)2885 static bool supported_for_raster_canvas(const SkImageInfo& info) {
2886     switch (info.alphaType()) {
2887         case kPremul_SkAlphaType:
2888         case kOpaque_SkAlphaType:
2889             break;
2890         default:
2891             return false;
2892     }
2893 
2894     switch (info.colorType()) {
2895         case kAlpha_8_SkColorType:
2896         case kRGB_565_SkColorType:
2897         case kN32_SkColorType:
2898         case kRGBA_F16_SkColorType:
2899             break;
2900         default:
2901             return false;
2902     }
2903 
2904     return true;
2905 }
2906 
MakeRasterDirect(const SkImageInfo & info,void * pixels,size_t rowBytes,const SkSurfaceProps * props)2907 std::unique_ptr<SkCanvas> SkCanvas::MakeRasterDirect(const SkImageInfo& info, void* pixels,
2908                                                      size_t rowBytes, const SkSurfaceProps* props) {
2909     if (!supported_for_raster_canvas(info)) {
2910         return nullptr;
2911     }
2912 
2913     SkBitmap bitmap;
2914     if (!bitmap.installPixels(info, pixels, rowBytes)) {
2915         return nullptr;
2916     }
2917 
2918     return props ?
2919         skstd::make_unique<SkCanvas>(bitmap, *props) :
2920         skstd::make_unique<SkCanvas>(bitmap);
2921 }
2922 
2923 ///////////////////////////////////////////////////////////////////////////////
2924 
SkNoDrawCanvas(int width,int height)2925 SkNoDrawCanvas::SkNoDrawCanvas(int width, int height)
2926     : INHERITED(SkIRect::MakeWH(width, height), kConservativeRasterClip_InitFlag) {}
2927 
SkNoDrawCanvas(const SkIRect & bounds)2928 SkNoDrawCanvas::SkNoDrawCanvas(const SkIRect& bounds)
2929     : INHERITED(bounds, kConservativeRasterClip_InitFlag) {}
2930 
getSaveLayerStrategy(const SaveLayerRec & rec)2931 SkCanvas::SaveLayerStrategy SkNoDrawCanvas::getSaveLayerStrategy(const SaveLayerRec& rec) {
2932     (void)this->INHERITED::getSaveLayerStrategy(rec);
2933     return kNoLayer_SaveLayerStrategy;
2934 }
2935 
2936 ///////////////////////////////////////////////////////////////////////////////
2937 
2938 static_assert((int)SkRegion::kDifference_Op         == (int)kDifference_SkClipOp, "");
2939 static_assert((int)SkRegion::kIntersect_Op          == (int)kIntersect_SkClipOp, "");
2940 static_assert((int)SkRegion::kUnion_Op              == (int)kUnion_SkClipOp, "");
2941 static_assert((int)SkRegion::kXOR_Op                == (int)kXOR_SkClipOp, "");
2942 static_assert((int)SkRegion::kReverseDifference_Op  == (int)kReverseDifference_SkClipOp, "");
2943 static_assert((int)SkRegion::kReplace_Op            == (int)kReplace_SkClipOp, "");
2944 
2945 ///////////////////////////////////////////////////////////////////////////////////////////////////
2946 
accessTopRasterHandle() const2947 SkRasterHandleAllocator::Handle SkCanvas::accessTopRasterHandle() const {
2948     if (fAllocator && fMCRec->fTopLayer->fDevice) {
2949         const auto& dev = fMCRec->fTopLayer->fDevice;
2950         SkRasterHandleAllocator::Handle handle = dev->getRasterHandle();
2951         SkIPoint origin = dev->getOrigin();
2952         SkMatrix ctm = this->getTotalMatrix();
2953         ctm.preTranslate(SkIntToScalar(-origin.x()), SkIntToScalar(-origin.y()));
2954 
2955         SkIRect clip = fMCRec->fRasterClip.getBounds();
2956         clip.offset(-origin.x(), -origin.y());
2957         if (!clip.intersect(0, 0, dev->width(), dev->height())) {
2958             clip.setEmpty();
2959         }
2960 
2961         fAllocator->updateHandle(handle, ctm, clip);
2962         return handle;
2963     }
2964     return nullptr;
2965 }
2966 
install(SkBitmap * bm,const SkImageInfo & info,const SkRasterHandleAllocator::Rec & rec)2967 static bool install(SkBitmap* bm, const SkImageInfo& info,
2968                     const SkRasterHandleAllocator::Rec& rec) {
2969     return bm->installPixels(info, rec.fPixels, rec.fRowBytes, rec.fReleaseProc, rec.fReleaseCtx);
2970 }
2971 
allocBitmap(const SkImageInfo & info,SkBitmap * bm)2972 SkRasterHandleAllocator::Handle SkRasterHandleAllocator::allocBitmap(const SkImageInfo& info,
2973                                                                      SkBitmap* bm) {
2974     SkRasterHandleAllocator::Rec rec;
2975     if (!this->allocHandle(info, &rec) || !install(bm, info, rec)) {
2976         return nullptr;
2977     }
2978     return rec.fHandle;
2979 }
2980 
2981 std::unique_ptr<SkCanvas>
MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,const SkImageInfo & info,const Rec * rec)2982 SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> alloc,
2983                                     const SkImageInfo& info, const Rec* rec) {
2984     if (!alloc || !supported_for_raster_canvas(info)) {
2985         return nullptr;
2986     }
2987 
2988     SkBitmap bm;
2989     Handle hndl;
2990 
2991     if (rec) {
2992         hndl = install(&bm, info, *rec) ? rec->fHandle : nullptr;
2993     } else {
2994         hndl = alloc->allocBitmap(info, &bm);
2995     }
2996     return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr;
2997 }
2998 
2999 ///////////////////////////////////////////////////////////////////////////////////////////////////
3000 
3001 
3002