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