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