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