• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2006 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 #ifndef SkCanvas_DEFINED
9 #define SkCanvas_DEFINED
10 
11 #include "SkBlendMode.h"
12 #include "SkClipOp.h"
13 #include "SkDeque.h"
14 #include "SkPaint.h"
15 #include "SkRasterHandleAllocator.h"
16 #include "SkSurfaceProps.h"
17 
18 class GrContext;
19 class GrRenderTargetContext;
20 class SkBaseDevice;
21 class SkBitmap;
22 class SkClipStack;
23 class SkData;
24 class SkDraw;
25 class SkDrawable;
26 class SkDrawFilter;
27 struct SkDrawShadowRec;
28 class SkImage;
29 class SkImageFilter;
30 class SkLights;
31 class SkMetaData;
32 class SkPath;
33 class SkPicture;
34 class SkPixmap;
35 class SkRasterClip;
36 class SkRegion;
37 class SkRRect;
38 struct SkRSXform;
39 class SkSurface;
40 class SkSurface_Base;
41 class SkTextBlob;
42 class SkVertices;
43 
44 /** \class SkCanvas
45 
46     A Canvas encapsulates all of the state about drawing into a device (bitmap).
47     This includes a reference to the device itself, and a stack of matrix/clip
48     values. For any given draw call (e.g. drawRect), the geometry of the object
49     being drawn is transformed by the concatenation of all the matrices in the
50     stack. The transformed geometry is clipped by the intersection of all of
51     the clips in the stack.
52 
53     While the Canvas holds the state of the drawing device, the state (style)
54     of the object being drawn is held by the Paint, which is provided as a
55     parameter to each of the draw() methods. The Paint holds attributes such as
56     color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
57     etc.
58 */
59 class SK_API SkCanvas : SkNoncopyable {
60     enum PrivateSaveLayerFlags {
61         kDontClipToLayer_PrivateSaveLayerFlag   = 1U << 31,
62     };
63 
64 public:
65     /**
66      *  Attempt to allocate raster canvas, matching the ImageInfo, that will draw directly into the
67      *  specified pixels. To access the pixels after drawing to them, the caller should call
68      *  flush() or call peekPixels(...).
69      *
70      *  On failure, return NULL. This can fail for several reasons:
71      *  1. invalid ImageInfo (e.g. negative dimensions)
72      *  2. unsupported ImageInfo for a canvas
73      *      - kUnknown_SkColorType, kIndex_8_SkColorType
74      *      - kUnknown_SkAlphaType
75      *      - this list is not complete, so others may also be unsupported
76      *
77      *  Note: it is valid to request a supported ImageInfo, but with zero
78      *  dimensions.
79      */
80     static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels,
81                                                       size_t rowBytes);
82 
MakeRasterDirectN32(int width,int height,SkPMColor * pixels,size_t rowBytes)83     static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
84                                                          size_t rowBytes) {
85         return MakeRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
86     }
87 
88     /**
89      *  Creates an empty canvas with no backing device/pixels, and zero
90      *  dimensions.
91      */
92     SkCanvas();
93 
94     /**
95      *  Creates a canvas of the specified dimensions, but explicitly not backed
96      *  by any device/pixels. Typically this use used by subclasses who handle
97      *  the draw calls in some other way.
98      */
99     SkCanvas(int width, int height, const SkSurfaceProps* props = NULL);
100 
101     /** Construct a canvas with the specified device to draw into.
102 
103         @param device   Specifies a device for the canvas to draw into.
104     */
105     explicit SkCanvas(SkBaseDevice* device);
106 
107     /** Construct a canvas with the specified bitmap to draw into.
108         @param bitmap   Specifies a bitmap for the canvas to draw into. Its
109                         structure are copied to the canvas.
110     */
111     explicit SkCanvas(const SkBitmap& bitmap);
112 
113 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
114     enum class ColorBehavior {
115         kLegacy,
116     };
117 
118     /**
119      *  Android framework only constructor.
120      *  Allows the creation of a legacy SkCanvas even though the |bitmap|
121      *  and its pixel ref may have an SkColorSpace.
122      */
123     SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior);
124 #endif
125 
126     /** Construct a canvas with the specified bitmap to draw into.
127         @param bitmap   Specifies a bitmap for the canvas to draw into. Its
128                         structure are copied to the canvas.
129         @param props    New canvas surface properties.
130     */
131     SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
132 
133     virtual ~SkCanvas();
134 
135     SkMetaData& getMetaData();
136 
137     /**
138      *  Return ImageInfo for this canvas. If the canvas is not backed by pixels
139      *  (cpu or gpu), then the info's ColorType will be kUnknown_SkColorType.
140      */
141     SkImageInfo imageInfo() const;
142 
143     /**
144      *  If the canvas is backed by pixels (cpu or gpu), this writes a copy of the SurfaceProps
145      *  for the canvas to the location supplied by the caller, and returns true. Otherwise,
146      *  return false and leave the supplied props unchanged.
147      */
148     bool getProps(SkSurfaceProps* props) const;
149 
150     ///////////////////////////////////////////////////////////////////////////
151 
152     /**
153      *  Trigger the immediate execution of all pending draw operations. For the GPU
154      *  backend this will resolve all rendering to the GPU surface backing the
155      *  SkSurface that owns this canvas.
156      */
157     void flush();
158 
159     /**
160      * Gets the size of the base or root layer in global canvas coordinates. The
161      * origin of the base layer is always (0,0). The current drawable area may be
162      * smaller (due to clipping or saveLayer).
163      */
164     virtual SkISize getBaseLayerSize() const;
165 
166     /**
167      *  Create a new surface matching the specified info, one that attempts to
168      *  be maximally compatible when used with this canvas. If there is no matching Surface type,
169      *  NULL is returned.
170      *
171      *  If surfaceprops is specified, those are passed to the new surface, otherwise the new surface
172      *  inherits the properties of the surface that owns this canvas. If this canvas has no parent
173      *  surface, then the new surface is created with default properties.
174      */
175     sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr);
176 
177     /**
178      * Return the GPU context of the device that is associated with the canvas.
179      * For a canvas with non-GPU device, NULL is returned.
180      */
181     virtual GrContext* getGrContext();
182 
183     ///////////////////////////////////////////////////////////////////////////
184 
185     /**
186      *  If the canvas has writable pixels in its top layer (and is not recording to a picture
187      *  or other non-raster target) and has direct access to its pixels (i.e. they are in
188      *  local RAM) return the address of those pixels, and if not null,
189      *  return the ImageInfo, rowBytes and origin. The returned address is only valid
190      *  while the canvas object is in scope and unchanged. Any API calls made on
191      *  canvas (or its parent surface if any) will invalidate the
192      *  returned address (and associated information).
193      *
194      *  On failure, returns NULL and the info, rowBytes, and origin parameters are ignored.
195      */
196     void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = NULL);
197 
198     SkRasterHandleAllocator::Handle accessTopRasterHandle() const;
199 
200     /**
201      *  If the canvas has readable pixels in its base layer (and is not recording to a picture
202      *  or other non-raster target) and has direct access to its pixels (i.e. they are in
203      *  local RAM) return true, and if not null, return in the pixmap parameter information about
204      *  the pixels. The pixmap's pixel address is only valid
205      *  while the canvas object is in scope and unchanged. Any API calls made on
206      *  canvas (or its parent surface if any) will invalidate the pixel address
207      *  (and associated information).
208      *
209      *  On failure, returns false and the pixmap parameter will be ignored.
210      */
211     bool peekPixels(SkPixmap* pixmap);
212 
213     /**
214      *  Copy the pixels from the base-layer into the specified buffer (pixels + rowBytes),
215      *  converting them into the requested format (SkImageInfo). The base-layer pixels are read
216      *  starting at the specified (srcX,srcY) location in the coordinate system of the base-layer.
217      *
218      *  The specified ImageInfo and (srcX,srcY) offset specifies a source rectangle
219      *
220      *      srcR.setXYWH(srcX, srcY, dstInfo.width(), dstInfo.height());
221      *
222      *  srcR is intersected with the bounds of the base-layer. If this intersection is not empty,
223      *  then we have two sets of pixels (of equal size). Replace the dst pixels with the
224      *  corresponding src pixels, performing any colortype/alphatype transformations needed
225      *  (in the case where the src and dst have different colortypes or alphatypes).
226      *
227      *  This call can fail, returning false, for several reasons:
228      *  - If srcR does not intersect the base-layer bounds.
229      *  - If the requested colortype/alphatype cannot be converted from the base-layer's types.
230      *  - If this canvas is not backed by pixels (e.g. picture or PDF)
231      */
232     bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
233                     int srcX, int srcY);
234     bool readPixels(const SkPixmap& pixmap, int srcX, int srcY);
235     bool readPixels(const SkBitmap& bitmap, int srcX, int srcY);
236 
237     /**
238      *  This method affects the pixels in the base-layer, and operates in pixel coordinates,
239      *  ignoring the matrix and clip.
240      *
241      *  The specified ImageInfo and (x,y) offset specifies a rectangle: target.
242      *
243      *      target.setXYWH(x, y, info.width(), info.height());
244      *
245      *  Target is intersected with the bounds of the base-layer. If this intersection is not empty,
246      *  then we have two sets of pixels (of equal size), the "src" specified by info+pixels+rowBytes
247      *  and the "dst" by the canvas' backend. Replace the dst pixels with the corresponding src
248      *  pixels, performing any colortype/alphatype transformations needed (in the case where the
249      *  src and dst have different colortypes or alphatypes).
250      *
251      *  This call can fail, returning false, for several reasons:
252      *  - If the src colortype/alphatype cannot be converted to the canvas' types
253      *  - If this canvas is not backed by pixels (e.g. picture or PDF)
254      */
255     bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y);
256 
257     /**
258      *  Helper for calling writePixels(info, ...) by passing its pixels and rowbytes. If the bitmap
259      *  is just wrapping a texture, returns false and does nothing.
260      */
261     bool writePixels(const SkBitmap& bitmap, int x, int y);
262 
263     ///////////////////////////////////////////////////////////////////////////
264 
265     /** This call saves the current matrix, clip, and drawFilter, and pushes a
266         copy onto a private stack. Subsequent calls to translate, scale,
267         rotate, skew, concat or clipRect, clipPath, and setDrawFilter all
268         operate on this copy.
269         When the balancing call to restore() is made, the previous matrix, clip,
270         and drawFilter are restored.
271 
272         @return The value to pass to restoreToCount() to balance this save()
273     */
274     int save();
275 
276     /** This behaves the same as save(), but in addition it allocates an
277         offscreen bitmap. All drawing calls are directed there, and only when
278         the balancing call to restore() is made is that offscreen transfered to
279         the canvas (or the previous layer).
280         @param bounds (may be null) This rect, if non-null, is used as a hint to
281                       limit the size of the offscreen, and thus drawing may be
282                       clipped to it, though that clipping is not guaranteed to
283                       happen. If exact clipping is desired, use clipRect().
284         @param paint (may be null) This is copied, and is applied to the
285                      offscreen when restore() is called
286         @return The value to pass to restoreToCount() to balance this save()
287     */
288     int saveLayer(const SkRect* bounds, const SkPaint* paint);
saveLayer(const SkRect & bounds,const SkPaint * paint)289     int saveLayer(const SkRect& bounds, const SkPaint* paint) {
290         return this->saveLayer(&bounds, paint);
291     }
292 
293     /**
294      *  Temporary name.
295      *  Will allow any requests for LCD text to be respected, so the caller must be careful to
296      *  only draw on top of opaque sections of the layer to get good results.
297      */
298     int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint);
299 
300     /** This behaves the same as save(), but in addition it allocates an
301         offscreen bitmap. All drawing calls are directed there, and only when
302         the balancing call to restore() is made is that offscreen transfered to
303         the canvas (or the previous layer).
304         @param bounds (may be null) This rect, if non-null, is used as a hint to
305                       limit the size of the offscreen, and thus drawing may be
306                       clipped to it, though that clipping is not guaranteed to
307                       happen. If exact clipping is desired, use clipRect().
308         @param alpha  This is applied to the offscreen when restore() is called.
309         @return The value to pass to restoreToCount() to balance this save()
310     */
311     int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
312 
313     enum {
314         kIsOpaque_SaveLayerFlag         = 1 << 0,
315         kPreserveLCDText_SaveLayerFlag  = 1 << 1,
316 
317         /** initialize the new layer with the contents of the previous layer */
318         kInitWithPrevious_SaveLayerFlag = 1 << 2,
319 
320 #ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
321         kDontClipToLayer_Legacy_SaveLayerFlag = kDontClipToLayer_PrivateSaveLayerFlag,
322 #endif
323     };
324     typedef uint32_t SaveLayerFlags;
325 
326     struct SaveLayerRec {
SaveLayerRecSaveLayerRec327         SaveLayerRec() {}
328         SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
fBoundsSaveLayerRec329             : fBounds(bounds)
330             , fPaint(paint)
331             , fSaveLayerFlags(saveLayerFlags)
332         {}
SaveLayerRecSaveLayerRec333         SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
334                      SaveLayerFlags saveLayerFlags)
335             : fBounds(bounds)
336             , fPaint(paint)
337             , fBackdrop(backdrop)
338             , fSaveLayerFlags(saveLayerFlags)
339         {}
340 
341         // EXPERIMENTAL: not ready for general use.
SaveLayerRecSaveLayerRec342         SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
343                      const SkImage* clipMask, const SkMatrix* clipMatrix,
344                      SaveLayerFlags saveLayerFlags)
345             : fBounds(bounds)
346             , fPaint(paint)
347             , fBackdrop(backdrop)
348             , fClipMask(clipMask)
349             , fClipMatrix(clipMatrix)
350             , fSaveLayerFlags(saveLayerFlags)
351         {}
352 
353         const SkRect*           fBounds = nullptr;      // optional
354         const SkPaint*          fPaint = nullptr;       // optional
355         const SkImageFilter*    fBackdrop = nullptr;    // optional
356         const SkImage*          fClipMask = nullptr;    // optional
357         const SkMatrix*         fClipMatrix = nullptr;  // optional -- only used with fClipMask
358         SaveLayerFlags          fSaveLayerFlags = 0;
359     };
360 
361     int saveLayer(const SaveLayerRec& layerRec);
362 
363     /** This call balances a previous call to save(), and is used to remove all
364         modifications to the matrix/clip/drawFilter state since the last save
365         call.
366         It is an error to call restore() more times than save() was called.
367     */
368     void restore();
369 
370     /** Returns the number of matrix/clip states on the SkCanvas' private stack.
371         This will equal # save() calls - # restore() calls + 1. The save count on
372         a new canvas is 1.
373     */
374     int getSaveCount() const;
375 
376     /** Efficient way to pop any calls to save() that happened after the save
377         count reached saveCount. It is an error for saveCount to be greater than
378         getSaveCount(). To pop all the way back to the initial matrix/clip context
379         pass saveCount == 1.
380         @param saveCount    The number of save() levels to restore from
381     */
382     void restoreToCount(int saveCount);
383 
384     /** Preconcat the current matrix with the specified translation
385         @param dx   The distance to translate in X
386         @param dy   The distance to translate in Y
387     */
388     void translate(SkScalar dx, SkScalar dy);
389 
390     /** Preconcat the current matrix with the specified scale.
391         @param sx   The amount to scale in X
392         @param sy   The amount to scale in Y
393     */
394     void scale(SkScalar sx, SkScalar sy);
395 
396     /** Preconcat the current matrix with the specified rotation about the origin.
397         @param degrees  The amount to rotate, in degrees
398     */
399     void rotate(SkScalar degrees);
400 
401     /** Preconcat the current matrix with the specified rotation about a given point.
402         @param degrees  The amount to rotate, in degrees
403         @param px  The x coordinate of the point to rotate about.
404         @param py  The y coordinate of the point to rotate about.
405     */
406     void rotate(SkScalar degrees, SkScalar px, SkScalar py);
407 
408     /** Preconcat the current matrix with the specified skew.
409         @param sx   The amount to skew in X
410         @param sy   The amount to skew in Y
411     */
412     void skew(SkScalar sx, SkScalar sy);
413 
414     /** Preconcat the current matrix with the specified matrix.
415         @param matrix   The matrix to preconcatenate with the current matrix
416     */
417     void concat(const SkMatrix& matrix);
418 
419     /** Replace the current matrix with a copy of the specified matrix.
420         @param matrix The matrix that will be copied into the current matrix.
421     */
422     void setMatrix(const SkMatrix& matrix);
423 
424     /** Helper for setMatrix(identity). Sets the current matrix to identity.
425     */
426     void resetMatrix();
427 
428     /**
429      *  Modify the current clip with the specified rectangle.
430      *  @param rect The rect to combine with the current clip
431      *  @param op The region op to apply to the current clip
432      *  @param doAntiAlias true if the clip should be antialiased
433      */
434     void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias);
clipRect(const SkRect & rect,SkClipOp op)435     void clipRect(const SkRect& rect, SkClipOp op) {
436         this->clipRect(rect, op, false);
437     }
438     void clipRect(const SkRect& rect, bool doAntiAlias = false) {
439         this->clipRect(rect, SkClipOp::kIntersect, doAntiAlias);
440     }
441 
442     /**
443      * Sets the max clip rectangle, which can be set by clipRect, clipRRect and
444      * clipPath and intersect the current clip with the specified rect.
445      * The max clip affects only future ops (it is not retroactive).
446      * We DON'T record the clip restriction in pictures.
447      * This is private API to be used only by Android framework.
448      * @param rect   The maximum allowed clip in device coordinates.
449      *               Empty rect means max clip is not enforced.
450      */
451     void androidFramework_setDeviceClipRestriction(const SkIRect& rect);
452 
453     /**
454      *  Modify the current clip with the specified SkRRect.
455      *  @param rrect The rrect to combine with the current clip
456      *  @param op The region op to apply to the current clip
457      *  @param doAntiAlias true if the clip should be antialiased
458      */
459     void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias);
clipRRect(const SkRRect & rrect,SkClipOp op)460     void clipRRect(const SkRRect& rrect, SkClipOp op) {
461         this->clipRRect(rrect, op, false);
462     }
463     void clipRRect(const SkRRect& rrect, bool doAntiAlias = false) {
464         this->clipRRect(rrect, SkClipOp::kIntersect, doAntiAlias);
465     }
466 
467     /**
468      *  Modify the current clip with the specified path.
469      *  @param path The path to combine with the current clip
470      *  @param op The region op to apply to the current clip
471      *  @param doAntiAlias true if the clip should be antialiased
472      */
473     void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias);
clipPath(const SkPath & path,SkClipOp op)474     void clipPath(const SkPath& path, SkClipOp op) {
475         this->clipPath(path, op, false);
476     }
477     void clipPath(const SkPath& path, bool doAntiAlias = false) {
478         this->clipPath(path, SkClipOp::kIntersect, doAntiAlias);
479     }
480 
481     /** EXPERIMENTAL -- only used for testing
482         Set to simplify clip stack using path ops.
483      */
setAllowSimplifyClip(bool allow)484     void setAllowSimplifyClip(bool allow) {
485         fAllowSimplifyClip = allow;
486     }
487 
488     /** Modify the current clip with the specified region. Note that unlike
489         clipRect() and clipPath() which transform their arguments by the current
490         matrix, clipRegion() assumes its argument is already in device
491         coordinates, and so no transformation is performed.
492         @param deviceRgn    The region to apply to the current clip
493         @param op The region op to apply to the current clip
494     */
495     void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect);
496 
497     /** Return true if the specified rectangle, after being transformed by the
498         current matrix, would lie completely outside of the current clip. Call
499         this to check if an area you intend to draw into is clipped out (and
500         therefore you can skip making the draw calls).
501         @param rect the rect to compare with the current clip
502         @return true if the rect (transformed by the canvas' matrix) does not
503                      intersect with the canvas' clip
504     */
505     bool quickReject(const SkRect& rect) const;
506 
507     /** Return true if the specified path, after being transformed by the
508         current matrix, would lie completely outside of the current clip. Call
509         this to check if an area you intend to draw into is clipped out (and
510         therefore you can skip making the draw calls). Note, for speed it may
511         return false even if the path itself might not intersect the clip
512         (i.e. the bounds of the path intersects, but the path does not).
513         @param path The path to compare with the current clip
514         @return true if the path (transformed by the canvas' matrix) does not
515                      intersect with the canvas' clip
516     */
517     bool quickReject(const SkPath& path) const;
518 
519     /**
520      *  Return the bounds of the current clip in local coordinates. If the clip is empty,
521      *  return { 0, 0, 0, 0 }.
522      */
getLocalClipBounds()523     SkRect getLocalClipBounds() const { return this->onGetLocalClipBounds(); }
524 
525     /**
526      *  Returns true if the clip bounds are non-empty.
527      */
getLocalClipBounds(SkRect * bounds)528     bool getLocalClipBounds(SkRect* bounds) const {
529         *bounds = this->onGetLocalClipBounds();
530         return !bounds->isEmpty();
531     }
532 
533     /**
534      *  Return the bounds of the current clip in device coordinates. If the clip is empty,
535      *  return { 0, 0, 0, 0 }.
536      */
getDeviceClipBounds()537     SkIRect getDeviceClipBounds() const { return this->onGetDeviceClipBounds(); }
538 
539     /**
540      *  Returns true if the clip bounds are non-empty.
541      */
getDeviceClipBounds(SkIRect * bounds)542     bool getDeviceClipBounds(SkIRect* bounds) const {
543         *bounds = this->onGetDeviceClipBounds();
544         return !bounds->isEmpty();
545     }
546 
547     /** Fill the entire canvas' bitmap (restricted to the current clip) with the
548         specified color and mode.
549         @param color    the color to draw with
550         @param mode the mode to apply the color in (defaults to SrcOver)
551     */
552     void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver);
553 
554     /**
555      *  Helper method for drawing a color in SRC mode, completely replacing all the pixels
556      *  in the current clip with this color.
557      */
clear(SkColor color)558     void clear(SkColor color) {
559         this->drawColor(color, SkBlendMode::kSrc);
560     }
561 
562     /**
563      * This makes the contents of the canvas undefined. Subsequent calls that
564      * require reading the canvas contents will produce undefined results. Examples
565      * include blending and readPixels. The actual implementation is backend-
566      * dependent and one legal implementation is to do nothing. This method
567      * ignores the current clip.
568      *
569      * This function should only be called if the caller intends to subsequently
570      * draw to the canvas. The canvas may do real work at discard() time in order
571      * to optimize performance on subsequent draws. Thus, if you call this and then
572      * never draw to the canvas subsequently you may pay a perfomance penalty.
573      */
discard()574     void discard() { this->onDiscard(); }
575 
576     /**
577      *  Fill the entire canvas (restricted to the current clip) with the
578      *  specified paint.
579      *  @param paint    The paint used to fill the canvas
580      */
581     void drawPaint(const SkPaint& paint);
582 
583     enum PointMode {
584         /** drawPoints draws each point separately */
585         kPoints_PointMode,
586         /** drawPoints draws each pair of points as a line segment */
587         kLines_PointMode,
588         /** drawPoints draws the array of points as a polygon */
589         kPolygon_PointMode
590     };
591 
592     /** Draw a series of points, interpreted based on the PointMode mode. For
593         all modes, the count parameter is interpreted as the total number of
594         points. For kLine mode, count/2 line segments are drawn.
595         For kPoint mode, each point is drawn centered at its coordinate, and its
596         size is specified by the paint's stroke-width. It draws as a square,
597         unless the paint's cap-type is round, in which the points are drawn as
598         circles.
599         For kLine mode, each pair of points is drawn as a line segment,
600         respecting the paint's settings for cap/join/width.
601         For kPolygon mode, the entire array is drawn as a series of connected
602         line segments.
603         Note that, while similar, kLine and kPolygon modes draw slightly
604         differently than the equivalent path built with a series of moveto,
605         lineto calls, in that the path will draw all of its contours at once,
606         with no interactions if contours intersect each other (think XOR
607         xfermode). drawPoints always draws each element one at a time.
608         @param mode     PointMode specifying how to draw the array of points.
609         @param count    The number of points in the array
610         @param pts      Array of points to draw
611         @param paint    The paint used to draw the points
612     */
613     void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
614 
615     /** Helper method for drawing a single point. See drawPoints() for more details.
616      */
617     void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
drawPoint(SkPoint p,const SkPaint & paint)618     void drawPoint(SkPoint p, const SkPaint& paint) {
619         this->drawPoint(p.x(), p.y(), paint);
620     }
621 
622     /** Draw a line segment with the specified start and stop x,y coordinates,
623         using the specified paint. NOTE: since a line is always "framed", the
624         paint's Style is ignored.
625         @param x0    The x-coordinate of the start point of the line
626         @param y0    The y-coordinate of the start point of the line
627         @param x1    The x-coordinate of the end point of the line
628         @param y1    The y-coordinate of the end point of the line
629         @param paint The paint used to draw the line
630     */
631     void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint);
drawLine(SkPoint p0,SkPoint p1,const SkPaint & paint)632     void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint) {
633         this->drawLine(p0.x(), p0.y(), p1.x(), p1.y(), paint);
634     }
635 
636     /** Draw the specified rectangle using the specified paint. The rectangle
637         will be filled or stroked based on the Style in the paint.
638         @param rect     The rect to be drawn
639         @param paint    The paint used to draw the rect
640     */
641     void drawRect(const SkRect& rect, const SkPaint& paint);
642 
643     /** Draw the specified rectangle using the specified paint. The rectangle
644         will be filled or framed based on the Style in the paint.
645         @param rect     The rect to be drawn
646         @param paint    The paint used to draw the rect
647     */
drawIRect(const SkIRect & rect,const SkPaint & paint)648     void drawIRect(const SkIRect& rect, const SkPaint& paint) {
649         SkRect r;
650         r.set(rect);    // promotes the ints to scalars
651         this->drawRect(r, paint);
652     }
653 
654     /** Draw the outline of the specified region using the specified paint.
655         @param region   The region to be drawn
656         @param paint    The paint used to draw the region
657     */
658     void drawRegion(const SkRegion& region, const SkPaint& paint);
659 
660     /** Draw the specified oval using the specified paint. The oval will be
661         filled or framed based on the Style in the paint.
662         @param oval     The rectangle bounds of the oval to be drawn
663         @param paint    The paint used to draw the oval
664     */
665     void drawOval(const SkRect& oval, const SkPaint& paint);
666 
667     /**
668      *  Draw the specified RRect using the specified paint The rrect will be filled or stroked
669      *  based on the Style in the paint.
670      *
671      *  @param rrect    The round-rect to draw
672      *  @param paint    The paint used to draw the round-rect
673      */
674     void drawRRect(const SkRRect& rrect, const SkPaint& paint);
675 
676     /**
677      *  Draw the annulus formed by the outer and inner rrects. The results
678      *  are undefined if the outer does not contain the inner.
679      */
680     void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
681 
682     /** Draw the specified circle using the specified paint. If radius is <= 0,
683         then nothing will be drawn. The circle will be filled
684         or framed based on the Style in the paint.
685         @param cx       The x-coordinate of the center of the cirle to be drawn
686         @param cy       The y-coordinate of the center of the cirle to be drawn
687         @param radius   The radius of the cirle to be drawn
688         @param paint    The paint used to draw the circle
689     */
690     void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint);
drawCircle(SkPoint center,SkScalar radius,const SkPaint & paint)691     void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint) {
692         this->drawCircle(center.x(), center.y(), radius, paint);
693     }
694 
695     /** Draw the specified arc, which will be scaled to fit inside the
696         specified oval. Sweep angles are not treated as modulo 360 and thus can
697         exceed a full sweep of the oval. Note that this differs slightly from
698         SkPath::arcTo, which treats the sweep angle mod 360. If the oval is empty
699         or the sweep angle is zero nothing is drawn. If useCenter is true the oval
700         center is inserted into the implied path before the arc and the path is
701         closed back to the, center forming a wedge. Otherwise, the implied path
702         contains just the arc and is not closed.
703         @param oval The bounds of oval used to define the shape of the arc.
704         @param startAngle Starting angle (in degrees) where the arc begins
705         @param sweepAngle Sweep angle (in degrees) measured clockwise.
706         @param useCenter true means include the center of the oval.
707         @param paint    The paint used to draw the arc
708     */
709     void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
710                  bool useCenter, const SkPaint& paint);
711 
712     /** Draw the specified round-rect using the specified paint. The round-rect
713         will be filled or framed based on the Style in the paint.
714         @param rect     The rectangular bounds of the roundRect to be drawn
715         @param rx       The x-radius of the oval used to round the corners
716         @param ry       The y-radius of the oval used to round the corners
717         @param paint    The paint used to draw the roundRect
718     */
719     void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint);
720 
721     /** Draw the specified path using the specified paint. The path will be
722         filled or framed based on the Style in the paint.
723         @param path     The path to be drawn
724         @param paint    The paint used to draw the path
725     */
726     void drawPath(const SkPath& path, const SkPaint& paint);
727 
728     /** Draw the specified image, with its top/left corner at (x,y), using the
729         specified paint, transformed by the current matrix.
730 
731         @param image    The image to be drawn
732         @param left     The position of the left side of the image being drawn
733         @param top      The position of the top side of the image being drawn
734         @param paint    The paint used to draw the image, or NULL
735      */
736     void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = NULL);
737     void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
738                    const SkPaint* paint = NULL) {
739         this->drawImage(image.get(), left, top, paint);
740     }
741 
742     /**
743      *  Controls the behavior at the edge of the src-rect, when specified in drawImageRect,
744      *  trading off speed for exactness.
745      *
746      *  When filtering is enabled (in the Paint), skia may need to sample in a neighborhood around
747      *  the pixels in the image. If there is a src-rect specified, it is intended to restrict the
748      *  pixels that will be read. However, for performance reasons, some implementations may slow
749      *  down if they cannot read 1-pixel past the src-rect boundary at times.
750      *
751      *  This enum allows the caller to specify if such a 1-pixel "slop" will be visually acceptable.
752      *  If it is, the caller should pass kFast, and it may result in a faster draw. If the src-rect
753      *  must be strictly respected, the caller should pass kStrict.
754      */
755     enum SrcRectConstraint {
756         /**
757          *  If kStrict is specified, the implementation must respect the src-rect
758          *  (if specified) strictly, and will never sample outside of those bounds during sampling
759          *  even when filtering. This may be slower than kFast.
760          */
761         kStrict_SrcRectConstraint,
762 
763         /**
764          *  If kFast is specified, the implementation may sample outside of the src-rect
765          *  (if specified) by half the width of filter. This allows greater flexibility
766          *  to the implementation and can make the draw much faster.
767          */
768         kFast_SrcRectConstraint,
769     };
770 
771     /** Draw the specified image, scaling and translating so that it fills the specified
772      *  dst rect. If the src rect is non-null, only that subset of the image is transformed
773      *  and drawn.
774      *
775      *  @param image      The image to be drawn
776      *  @param src        Optional: specify the subset of the image to be drawn
777      *  @param dst        The destination rectangle where the scaled/translated
778      *                    image will be drawn
779      *  @param paint      The paint used to draw the image, or NULL
780      *  @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
781      */
782     void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
783                        const SkPaint* paint,
784                        SrcRectConstraint constraint = kStrict_SrcRectConstraint);
785     // variant that takes src SkIRect
786     void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
787                        const SkPaint* paint,
788                        SrcRectConstraint constraint = kStrict_SrcRectConstraint);
789     // variant that assumes src == image-bounds
790     void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
791                        SrcRectConstraint constraint = kStrict_SrcRectConstraint);
792 
793     void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
794                        const SkPaint* paint,
795                        SrcRectConstraint constraint = kStrict_SrcRectConstraint) {
796         this->drawImageRect(image.get(), src, dst, paint, constraint);
797     }
798     void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
799                        const SkPaint* paint,
800                        SrcRectConstraint constraint = kStrict_SrcRectConstraint) {
801         this->drawImageRect(image.get(), isrc, dst, paint, constraint);
802     }
803     void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint,
804                        SrcRectConstraint constraint = kStrict_SrcRectConstraint) {
805         this->drawImageRect(image.get(), dst, paint, constraint);
806     }
807 
808     /**
809      *  Draw the image stretched differentially to fit into dst.
810      *  center is a rect within the image, and logically divides the image
811      *  into 9 sections (3x3). For example, if the middle pixel of a [5x5]
812      *  image is the "center", then the center-rect should be [2, 2, 3, 3].
813      *
814      *  If the dst is >= the image size, then...
815      *  - The 4 corners are not stretched at all.
816      *  - The sides are stretched in only one axis.
817      *  - The center is stretched in both axes.
818      * Else, for each axis where dst < image,
819      *  - The corners shrink proportionally
820      *  - The sides (along the shrink axis) and center are not drawn
821      */
822     void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
823                        const SkPaint* paint = nullptr);
824     void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
825                        const SkPaint* paint = nullptr) {
826         this->drawImageNine(image.get(), center, dst, paint);
827     }
828 
829     /** Draw the specified bitmap, with its top/left corner at (x,y), using the
830         specified paint, transformed by the current matrix. Note: if the paint
831         contains a maskfilter that generates a mask which extends beyond the
832         bitmap's original width/height, then the bitmap will be drawn as if it
833         were in a Shader with CLAMP mode. Thus the color outside of the original
834         width/height will be the edge color replicated.
835 
836         If a shader is present on the paint it will be ignored, except in the
837         case where the bitmap is kAlpha_8_SkColorType. In that case, the color is
838         generated by the shader.
839 
840         @param bitmap   The bitmap to be drawn
841         @param left     The position of the left side of the bitmap being drawn
842         @param top      The position of the top side of the bitmap being drawn
843         @param paint    The paint used to draw the bitmap, or NULL
844     */
845     void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
846                     const SkPaint* paint = NULL);
847 
848     /** Draw the specified bitmap, scaling and translating so that it fills the specified
849      *  dst rect. If the src rect is non-null, only that subset of the bitmap is transformed
850      *  and drawn.
851      *
852      *  @param bitmap     The bitmap to be drawn
853      *  @param src        Optional: specify the subset of the bitmap to be drawn
854      *  @param dst        The destination rectangle where the scaled/translated
855      *                    bitmap will be drawn
856      *  @param paint      The paint used to draw the bitmap, or NULL
857      *  @param constraint Control the tradeoff between speed and exactness w.r.t. the src-rect.
858      */
859     void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
860                         const SkPaint* paint,
861                         SrcRectConstraint constraint = kStrict_SrcRectConstraint);
862     // variant where src is SkIRect
863     void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
864                         const SkPaint* paint,
865                         SrcRectConstraint constraint = kStrict_SrcRectConstraint);
866     void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
867                         SrcRectConstraint constraint = kStrict_SrcRectConstraint);
868 
869     /**
870      *  Draw the bitmap stretched or shrunk differentially to fit into dst.
871      *  center is a rect within the bitmap, and logically divides the bitmap
872      *  into 9 sections (3x3). For example, if the middle pixel of a [5x5]
873      *  bitmap is the "center", then the center-rect should be [2, 2, 3, 3].
874      *
875      *  If the dst is >= the bitmap size, then...
876      *  - The 4 corners are not stretched at all.
877      *  - The sides are stretched in only one axis.
878      *  - The center is stretched in both axes.
879      * Else, for each axis where dst < bitmap,
880      *  - The corners shrink proportionally
881      *  - The sides (along the shrink axis) and center are not drawn
882      */
883     void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
884                         const SkPaint* paint = NULL);
885 
886     /**
887      *  Specifies coordinates to divide a bitmap into (xCount*yCount) rects.
888      *
889      *  If the lattice divs or bounds are invalid, the entire lattice
890      *  struct will be ignored on the draw call.
891      */
892     struct Lattice {
893         enum Flags : uint8_t {
894             // If set, indicates that we should not draw corresponding rect.
895             kTransparent_Flags = 1 << 0,
896         };
897 
898         // An array of x-coordinates that divide the bitmap vertically.
899         // These must be unique, increasing, and in the set [fBounds.fLeft, fBounds.fRight).
900         // Does not have ownership.
901         const int*     fXDivs;
902 
903         // An array of y-coordinates that divide the bitmap horizontally.
904         // These must be unique, increasing, and in the set [fBounds.fTop, fBounds.fBottom).
905         // Does not have ownership.
906         const int*     fYDivs;
907 
908         // If non-null, the length of this array must be equal to
909         // (fXCount + 1) * (fYCount + 1).  Note that we allow the first rect
910         // in each direction to be empty (ex: fXDivs[0] = fBounds.fLeft).
911         // In this case, the caller still must specify a flag (as a placeholder)
912         // for these empty rects.
913         // The flags correspond to the rects in the lattice, first moving
914         // left to right and then top to bottom.
915         const Flags*   fFlags;
916 
917         // The number of fXDivs.
918         int            fXCount;
919 
920         // The number of fYDivs.
921         int            fYCount;
922 
923         // The bound to draw from.  Must be contained by the src that is being drawn,
924         // non-empty, and non-inverted.
925         // If nullptr, the bounds are the entire src.
926         const SkIRect* fBounds;
927     };
928 
929     /**
930      *  Draw the bitmap stretched or shrunk differentially to fit into dst.
931      *
932      *  Moving horizontally across the bitmap, alternating rects will be "scalable"
933      *  (in the x-dimension) to fit into dst or must be left "fixed".  The first rect
934      *  is treated as "fixed", but it's possible to specify an empty first rect by
935      *  making lattice.fXDivs[0] = 0.
936      *
937      *  The scale factor for all "scalable" rects will be the same, and may be greater
938      *  than or less than 1 (meaning we can stretch or shrink).  If the number of
939      *  "fixed" pixels is greater than the width of the dst, we will collapse all of
940      *  the "scalable" regions and appropriately downscale the "fixed" regions.
941      *
942      *  The same interpretation also applies to the y-dimension.
943      */
944     void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
945                            const SkPaint* paint = nullptr);
946     void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
947                           const SkPaint* paint = nullptr);
948 
949     /** Draw the text, with origin at (x,y), using the specified paint.
950         The origin is interpreted based on the Align setting in the paint.
951         @param text The text to be drawn
952         @param byteLength   The number of bytes to read from the text parameter
953         @param x        The x-coordinate of the origin of the text being drawn
954         @param y        The y-coordinate of the origin of the text being drawn
955         @param paint    The paint used for the text (e.g. color, size, style)
956     */
957     void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
958                   const SkPaint& paint);
959 
960     /** Draw null-terminated UTF-8 string, with origin at (x,y), using the specified paint.
961         The origin is interpreted based on the Align setting in the paint.
962         @param string   The null-terminated string to be drawn
963         @param x        The x-coordinate of the origin of the string being drawn
964         @param y        The y-coordinate of the origin of the string being drawn
965         @param paint    The paint used for the string (e.g. color, size, style)
966     */
drawString(const char * string,SkScalar x,SkScalar y,const SkPaint & paint)967     void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint) {
968         if (!string) {
969             return;
970         }
971         this->drawText(string, strlen(string), x, y, paint);
972     }
973 
974     /** Draw string, with origin at (x,y), using the specified paint.
975         The origin is interpreted based on the Align setting in the paint.
976         @param string   The string to be drawn
977         @param x        The x-coordinate of the origin of the string being drawn
978         @param y        The y-coordinate of the origin of the string being drawn
979         @param paint    The paint used for the string (e.g. color, size, style)
980     */
981     void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint);
982 
983     /** Draw the text, with each character/glyph origin specified by the pos[]
984         array. The origin is interpreted by the Align setting in the paint.
985         @param text The text to be drawn
986         @param byteLength   The number of bytes to read from the text parameter
987         @param pos      Array of positions, used to position each character
988         @param paint    The paint used for the text (e.g. color, size, style)
989         */
990     void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
991                      const SkPaint& paint);
992 
993     /** Draw the text, with each character/glyph origin specified by the x
994         coordinate taken from the xpos[] array, and the y from the constY param.
995         The origin is interpreted by the Align setting in the paint.
996         @param text The text to be drawn
997         @param byteLength   The number of bytes to read from the text parameter
998         @param xpos     Array of x-positions, used to position each character
999         @param constY   The shared Y coordinate for all of the positions
1000         @param paint    The paint used for the text (e.g. color, size, style)
1001         */
1002     void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
1003                       const SkPaint& paint);
1004 
1005     /** Draw the text, with origin at (x,y), using the specified paint, along
1006         the specified path. The paint's Align setting determins where along the
1007         path to start the text.
1008         @param text The text to be drawn
1009         @param byteLength   The number of bytes to read from the text parameter
1010         @param path         The path the text should follow for its baseline
1011         @param hOffset      The distance along the path to add to the text's
1012                             starting position
1013         @param vOffset      The distance above(-) or below(+) the path to
1014                             position the text
1015         @param paint        The paint used for the text
1016     */
1017     void drawTextOnPathHV(const void* text, size_t byteLength, const SkPath& path, SkScalar hOffset,
1018                           SkScalar vOffset, const SkPaint& paint);
1019 
1020     /** Draw the text, with origin at (x,y), using the specified paint, along
1021         the specified path. The paint's Align setting determins where along the
1022         path to start the text.
1023         @param text The text to be drawn
1024         @param byteLength   The number of bytes to read from the text parameter
1025         @param path         The path the text should follow for its baseline
1026         @param matrix       (may be null) Applied to the text before it is
1027                             mapped onto the path
1028         @param paint        The paint used for the text
1029         */
1030     void drawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
1031                         const SkMatrix* matrix, const SkPaint& paint);
1032 
1033     /**
1034      *  Draw the text with each character/glyph individually transformed by its xform.
1035      *  If cullRect is not null, it is a conservative bounds of what will be drawn
1036      *  taking into account the xforms and the paint, and will be used to accelerate culling.
1037      */
1038     void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
1039                          const SkRect* cullRect, const SkPaint& paint);
1040 
1041     /** Draw the text blob, offset by (x,y), using the specified paint.
1042         @param blob     The text blob to be drawn
1043         @param x        The x-offset of the text being drawn
1044         @param y        The y-offset of the text being drawn
1045         @param paint    The paint used for the text (e.g. color, size, style)
1046     */
1047     void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
drawTextBlob(const sk_sp<SkTextBlob> & blob,SkScalar x,SkScalar y,const SkPaint & paint)1048     void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint) {
1049         this->drawTextBlob(blob.get(), x, y, paint);
1050     }
1051 
1052     /** Draw the picture into this canvas. This method effective brackets the
1053         playback of the picture's draw calls with save/restore, so the state
1054         of this canvas will be unchanged after this call.
1055         @param picture The recorded drawing commands to playback into this
1056                        canvas.
1057     */
drawPicture(const SkPicture * picture)1058     void drawPicture(const SkPicture* picture) {
1059         this->drawPicture(picture, NULL, NULL);
1060     }
drawPicture(const sk_sp<SkPicture> & picture)1061     void drawPicture(const sk_sp<SkPicture>& picture) {
1062         this->drawPicture(picture.get());
1063     }
1064 
1065     /**
1066      *  Draw the picture into this canvas.
1067      *
1068      *  If matrix is non-null, apply that matrix to the CTM when drawing this picture. This is
1069      *  logically equivalent to
1070      *      save/concat/drawPicture/restore
1071      *
1072      *  If paint is non-null, draw the picture into a temporary buffer, and then apply the paint's
1073      *  alpha/colorfilter/imagefilter/xfermode to that buffer as it is drawn to the canvas.
1074      *  This is logically equivalent to
1075      *      saveLayer(paint)/drawPicture/restore
1076      */
1077     void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint);
drawPicture(const sk_sp<SkPicture> & picture,const SkMatrix * matrix,const SkPaint * paint)1078     void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint) {
1079         this->drawPicture(picture.get(), matrix, paint);
1080     }
1081 
1082     /** Draw vertices from an immutable SkVertices object.
1083 
1084         @param vertices The mesh to draw.
1085         @param mode Used if both texs and colors are present and paint has a
1086                     shader. In this case the colors are combined with the texture
1087                     using mode, before being drawn using the paint.
1088         @param paint Specifies the shader/texture if present.
1089      */
1090     void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint);
1091     void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint);
1092 
1093     /**
1094      Draw a cubic coons patch
1095 
1096      @param cubic specifies the 4 bounding cubic bezier curves of a patch with clockwise order
1097                     starting at the top left corner.
1098      @param colors specifies the colors for the corners which will be bilerp across the patch,
1099                     their order is clockwise starting at the top left corner.
1100      @param texCoords specifies the texture coordinates that will be bilerp across the patch,
1101                     their order is the same as the colors.
1102      @param mode specifies how are the colors and the textures combined if both of them are
1103                     present.
1104      @param paint Specifies the shader/texture if present.
1105      */
1106     void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
1107                    const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
drawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],const SkPaint & paint)1108     void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
1109                    const SkPoint texCoords[4], const SkPaint& paint) {
1110         this->drawPatch(cubics, colors, texCoords, SkBlendMode::kModulate, paint);
1111     }
1112 
1113     /**
1114      *  Draw a set of sprites from the atlas. Each is specified by a tex rectangle in the
1115      *  coordinate space of the atlas, and a corresponding xform which transforms the tex rectangle
1116      *  into a quad.
1117      *
1118      *      xform maps [0, 0, tex.width, tex.height] -> quad
1119      *
1120      *  The color array is optional. When specified, each color modulates the pixels in its
1121      *  corresponding quad (via the specified SkBlendMode).
1122      *
1123      *  The cullRect is optional. When specified, it must be a conservative bounds of all of the
1124      *  resulting transformed quads, allowing the canvas to skip drawing if the cullRect does not
1125      *  intersect the current clip.
1126      *
1127      *  The paint is optional. If specified, its antialiasing, alpha, color-filter, image-filter
1128      *  and blendmode are used to affect each of the quads.
1129      */
1130     void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
1131                    const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
1132                    const SkPaint* paint);
drawAtlas(const sk_sp<SkImage> & atlas,const SkRSXform xform[],const SkRect tex[],const SkColor colors[],int count,SkBlendMode mode,const SkRect * cullRect,const SkPaint * paint)1133     void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
1134                    const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
1135                    const SkPaint* paint) {
1136         this->drawAtlas(atlas.get(), xform, tex, colors, count, mode, cullRect, paint);
1137     }
drawAtlas(const SkImage * atlas,const SkRSXform xform[],const SkRect tex[],int count,const SkRect * cullRect,const SkPaint * paint)1138     void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
1139                    const SkRect* cullRect, const SkPaint* paint) {
1140         this->drawAtlas(atlas, xform, tex, nullptr, count, SkBlendMode::kDst, cullRect, paint);
1141     }
drawAtlas(const sk_sp<SkImage> & atlas,const SkRSXform xform[],const SkRect tex[],int count,const SkRect * cullRect,const SkPaint * paint)1142     void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
1143                    int count, const SkRect* cullRect, const SkPaint* paint) {
1144         this->drawAtlas(atlas.get(), xform, tex, nullptr, count, SkBlendMode::kDst,
1145                         cullRect, paint);
1146     }
1147 
1148     /**
1149      *  Draw the contents of this drawable into the canvas. If the canvas is async
1150      *  (e.g. it is recording into a picture) then the drawable will be referenced instead,
1151      *  to have its draw() method called when the picture is finalized.
1152      *
1153      *  If the intent is to force the contents of the drawable into this canvas immediately,
1154      *  then drawable->draw(canvas) may be called.
1155      */
1156     void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = NULL);
1157     void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y);
1158 
1159     /**
1160      *  Send an "annotation" to the canvas. The annotation is a key/value pair, where the key is
1161      *  a null-terminated utf8 string, and the value is a blob of data stored in an SkData
1162      *  (which may be null). The annotation is associated with the specified rectangle.
1163      *
1164      *  The caller still retains its ownership of the data (if any).
1165      *
1166      *  Note: on may canvas types, this information is ignored, but some canvases (e.g. recording
1167      *  a picture or drawing to a PDF document) will pass on this information.
1168      */
1169     void drawAnnotation(const SkRect& rect, const char key[], SkData* value);
drawAnnotation(const SkRect & rect,const char key[],const sk_sp<SkData> & value)1170     void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) {
1171         this->drawAnnotation(rect, key, value.get());
1172     }
1173 
1174     //////////////////////////////////////////////////////////////////////////
1175 
1176 #ifdef SK_SUPPORT_LEGACY_DRAWFILTER
1177     /** Get the current filter object. The filter's reference count is not
1178         affected. The filter is saved/restored, just like the matrix and clip.
1179         @return the canvas' filter (or NULL).
1180     */
1181     SkDrawFilter* getDrawFilter() const;
1182 
1183     /** Set the new filter (or NULL). Pass NULL to clear any existing filter.
1184         As a convenience, the parameter is returned. If an existing filter
1185         exists, its refcnt is decrement. If the new filter is not null, its
1186         refcnt is incremented. The filter is saved/restored, just like the
1187         matrix and clip.
1188         @param filter the new filter (or NULL)
1189         @return the new filter
1190     */
1191     virtual SkDrawFilter* setDrawFilter(SkDrawFilter* filter);
1192 #endif
1193     //////////////////////////////////////////////////////////////////////////
1194 
1195     /**
1196      *  Return true if the current clip is empty (i.e. nothing will draw).
1197      *  Note: this is not always a free call, so it should not be used
1198      *  more often than necessary. However, once the canvas has computed this
1199      *  result, subsequent calls will be cheap (until the clip state changes,
1200      *  which can happen on any clip..() or restore() call.
1201      */
1202     virtual bool isClipEmpty() const;
1203 
1204     /**
1205      *  Returns true if the current clip is just a (non-empty) rectangle.
1206      *  Returns false if the clip is empty, or if it is complex.
1207      */
1208     virtual bool isClipRect() const;
1209 
1210     /** Return the current matrix on the canvas.
1211         This does not account for the translate in any of the devices.
1212         @return The current matrix on the canvas.
1213     */
1214     const SkMatrix& getTotalMatrix() const;
1215 
1216     ///////////////////////////////////////////////////////////////////////////
1217 
1218     // don't call
1219     GrRenderTargetContext* internal_private_accessTopLayerRenderTargetContext();
1220 
1221     // don't call
1222     static void Internal_Private_SetIgnoreSaveLayerBounds(bool);
1223     static bool Internal_Private_GetIgnoreSaveLayerBounds();
1224     static void Internal_Private_SetTreatSpriteAsBitmap(bool);
1225     static bool Internal_Private_GetTreatSpriteAsBitmap();
1226 
1227     // TEMP helpers until we switch virtual over to const& for src-rect
1228     void legacy_drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1229                               const SkPaint* paint,
1230                               SrcRectConstraint constraint = kStrict_SrcRectConstraint);
1231     void legacy_drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1232                                const SkPaint* paint,
1233                                SrcRectConstraint constraint = kStrict_SrcRectConstraint);
1234 
1235     /**
1236      *  Returns the global clip as a region. If the clip contains AA, then only the bounds
1237      *  of the clip may be returned.
1238      */
1239     void temporary_internal_getRgnClip(SkRegion* region);
1240 
1241     void private_draw_shadow_rec(const SkPath&, const SkDrawShadowRec&);
1242 
1243 protected:
1244     // default impl defers to getDevice()->newSurface(info)
1245     virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props);
1246 
1247     // default impl defers to its device
1248     virtual bool onPeekPixels(SkPixmap* pixmap);
1249     virtual bool onAccessTopLayerPixels(SkPixmap* pixmap);
1250     virtual SkImageInfo onImageInfo() const;
1251     virtual bool onGetProps(SkSurfaceProps* props) const;
1252     virtual void onFlush();
1253 
1254     // Subclass save/restore notifiers.
1255     // Overriders should call the corresponding INHERITED method up the inheritance chain.
1256     // getSaveLayerStrategy()'s return value may suppress full layer allocation.
1257     enum SaveLayerStrategy {
1258         kFullLayer_SaveLayerStrategy,
1259         kNoLayer_SaveLayerStrategy,
1260     };
1261 
willSave()1262     virtual void willSave() {}
1263     // Overriders should call the corresponding INHERITED method up the inheritance chain.
getSaveLayerStrategy(const SaveLayerRec &)1264     virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& ) {
1265         return kFullLayer_SaveLayerStrategy;
1266     }
willRestore()1267     virtual void willRestore() {}
didRestore()1268     virtual void didRestore() {}
didConcat(const SkMatrix &)1269     virtual void didConcat(const SkMatrix& ) {}
didSetMatrix(const SkMatrix &)1270     virtual void didSetMatrix(const SkMatrix& ) {}
didTranslate(SkScalar dx,SkScalar dy)1271     virtual void didTranslate(SkScalar dx, SkScalar dy) {
1272         this->didConcat(SkMatrix::MakeTrans(dx, dy));
1273     }
1274 
1275     virtual SkRect onGetLocalClipBounds() const;
1276     virtual SkIRect onGetDeviceClipBounds() const;
1277 
1278 
1279     virtual void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value);
1280     virtual void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
1281 
1282     virtual void onDrawText(const void* text, size_t byteLength, SkScalar x,
1283                             SkScalar y, const SkPaint& paint);
1284 
1285     virtual void onDrawPosText(const void* text, size_t byteLength,
1286                                const SkPoint pos[], const SkPaint& paint);
1287 
1288     virtual void onDrawPosTextH(const void* text, size_t byteLength,
1289                                 const SkScalar xpos[], SkScalar constY,
1290                                 const SkPaint& paint);
1291 
1292     virtual void onDrawTextOnPath(const void* text, size_t byteLength,
1293                                   const SkPath& path, const SkMatrix* matrix,
1294                                   const SkPaint& paint);
1295     virtual void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
1296                                    const SkRect* cullRect, const SkPaint& paint);
1297 
1298     virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
1299                                 const SkPaint& paint);
1300 
1301     virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
1302                            const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
1303 
1304     virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix);
1305 
1306     virtual void onDrawPaint(const SkPaint& paint);
1307     virtual void onDrawRect(const SkRect& rect, const SkPaint& paint);
1308     virtual void onDrawRegion(const SkRegion& region, const SkPaint& paint);
1309     virtual void onDrawOval(const SkRect& rect, const SkPaint& paint);
1310     virtual void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
1311                            bool useCenter, const SkPaint& paint);
1312     virtual void onDrawRRect(const SkRRect& rrect, const SkPaint& paint);
1313     virtual void onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
1314                               const SkPaint& paint);
1315     virtual void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
1316                                       const SkPaint& paint);
1317     virtual void onDrawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect rect[],
1318                              const SkColor colors[], int count, SkBlendMode mode,
1319                              const SkRect* cull, const SkPaint* paint);
1320     virtual void onDrawPath(const SkPath& path, const SkPaint& paint);
1321     virtual void onDrawImage(const SkImage* image, SkScalar dx, SkScalar dy, const SkPaint* paint);
1322     virtual void onDrawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst,
1323                                  const SkPaint* paint, SrcRectConstraint constraint);
1324     virtual void onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
1325                                  const SkPaint* paint);
1326     virtual void onDrawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
1327                                     const SkPaint* paint);
1328 
1329     virtual void onDrawBitmap(const SkBitmap& bitmap, SkScalar dx, SkScalar dy,
1330                               const SkPaint* paint);
1331     virtual void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst,
1332                                   const SkPaint* paint, SrcRectConstraint constraint);
1333     virtual void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
1334                                   const SkPaint* paint);
1335     virtual void onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice,
1336                                      const SkRect& dst, const SkPaint* paint);
1337     virtual void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&);
1338 
1339     enum ClipEdgeStyle {
1340         kHard_ClipEdgeStyle,
1341         kSoft_ClipEdgeStyle
1342     };
1343 
1344     virtual void onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle);
1345     virtual void onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle);
1346     virtual void onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle);
1347     virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp op);
1348 
1349     virtual void onDiscard();
1350 
1351     virtual void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
1352                                const SkPaint* paint);
1353 
1354     // Clip rectangle bounds. Called internally by saveLayer.
1355     // returns false if the entire rectangle is entirely clipped out
1356     // If non-NULL, The imageFilter parameter will be used to expand the clip
1357     // and offscreen bounds for any margin required by the filter DAG.
1358     bool clipRectBounds(const SkRect* bounds, SaveLayerFlags flags, SkIRect* intersection,
1359                         const SkImageFilter* imageFilter = NULL);
1360 
1361 private:
1362     /** After calling saveLayer(), there can be any number of devices that make
1363      up the top-most drawing area. LayerIter can be used to iterate through
1364      those devices. Note that the iterator is only valid until the next API
1365      call made on the canvas. Ownership of all pointers in the iterator stays
1366      with the canvas, so none of them should be modified or deleted.
1367      */
1368     class LayerIter /*: SkNoncopyable*/ {
1369     public:
1370         /** Initialize iterator with canvas, and set values for 1st device */
1371         LayerIter(SkCanvas*);
1372         ~LayerIter();
1373 
1374         /** Return true if the iterator is done */
done()1375         bool done() const { return fDone; }
1376         /** Cycle to the next device */
1377         void next();
1378 
1379         // These reflect the current device in the iterator
1380 
1381         SkBaseDevice*   device() const;
1382         const SkMatrix& matrix() const;
1383         void clip(SkRegion*) const;
1384         const SkPaint&  paint() const;
1385         int             x() const;
1386         int             y() const;
1387 
1388     private:
1389         // used to embed the SkDrawIter object directly in our instance, w/o
1390         // having to expose that class def to the public. There is an assert
1391         // in our constructor to ensure that fStorage is large enough
1392         // (though needs to be a compile-time-assert!). We use intptr_t to work
1393         // safely with 32 and 64 bit machines (to ensure the storage is enough)
1394         intptr_t          fStorage[32];
1395         class SkDrawIter* fImpl;    // this points at fStorage
1396         SkPaint           fDefaultPaint;
1397         bool              fDone;
1398     };
1399 
1400     static bool BoundsAffectsClip(SaveLayerFlags);
1401     static SaveLayerFlags LegacySaveFlagsToSaveLayerFlags(uint32_t legacySaveFlags);
1402 
1403     static void DrawDeviceWithFilter(SkBaseDevice* src, const SkImageFilter* filter,
1404                                      SkBaseDevice* dst, const SkIPoint& dstOrigin,
1405                                      const SkMatrix& ctm);
1406 
1407     enum ShaderOverrideOpacity {
1408         kNone_ShaderOverrideOpacity,        //!< there is no overriding shader (bitmap or image)
1409         kOpaque_ShaderOverrideOpacity,      //!< the overriding shader is opaque
1410         kNotOpaque_ShaderOverrideOpacity,   //!< the overriding shader may not be opaque
1411     };
1412 
1413     // notify our surface (if we have one) that we are about to draw, so it
1414     // can perform copy-on-write or invalidate any cached images
1415     void predrawNotify(bool willOverwritesEntireSurface = false);
1416     void predrawNotify(const SkRect* rect, const SkPaint* paint, ShaderOverrideOpacity);
predrawNotify(const SkRect * rect,const SkPaint * paint,bool shaderOverrideIsOpaque)1417     void predrawNotify(const SkRect* rect, const SkPaint* paint, bool shaderOverrideIsOpaque) {
1418         this->predrawNotify(rect, paint, shaderOverrideIsOpaque ? kOpaque_ShaderOverrideOpacity
1419                                                                 : kNotOpaque_ShaderOverrideOpacity);
1420     }
1421 
1422     SkBaseDevice* getDevice() const;
1423     SkBaseDevice* getTopDevice() const;
1424 
1425     class MCRec;
1426 
1427     SkDeque     fMCStack;
1428     // points to top of stack
1429     MCRec*      fMCRec;
1430     // the first N recs that can fit here mean we won't call malloc
1431     enum {
1432         kMCRecSize      = 128,  // most recent measurement
1433         kMCRecCount     = 32,   // common depth for save/restores
1434         kDeviceCMSize   = 224,  // most recent measurement
1435     };
1436     intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
1437     intptr_t fDeviceCMStorage[kDeviceCMSize / sizeof(intptr_t)];
1438 
1439     const SkSurfaceProps fProps;
1440 
1441     int         fSaveCount;         // value returned by getSaveCount()
1442 
1443     SkMetaData* fMetaData;
1444     std::unique_ptr<SkRasterHandleAllocator> fAllocator;
1445 
1446     SkSurface_Base*  fSurfaceBase;
getSurfaceBase()1447     SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
setSurfaceBase(SkSurface_Base * sb)1448     void setSurfaceBase(SkSurface_Base* sb) {
1449         fSurfaceBase = sb;
1450     }
1451     friend class SkSurface_Base;
1452     friend class SkSurface_Gpu;
1453 
1454     SkIRect fClipRestrictionRect = SkIRect::MakeEmpty();
1455 
1456     void doSave();
1457     void checkForDeferredSave();
1458     void internalSetMatrix(const SkMatrix&);
1459 
1460     friend class SkDrawIter;        // needs setupDrawForLayerDevice()
1461     friend class AutoDrawLooper;
1462     friend class SkDebugCanvas;     // needs experimental fAllowSimplifyClip
1463     friend class SkSurface_Raster;  // needs getDevice()
1464     friend class SkNoDrawCanvas;    // InitFlags
1465     friend class SkPictureImageFilter;  // SkCanvas(SkBaseDevice*, SkSurfaceProps*, InitFlags)
1466     friend class SkPictureRecord;   // predrawNotify (why does it need it? <reed>)
1467     friend class SkPicturePlayback; // SaveFlagsToSaveLayerFlags
1468     friend class SkOverdrawCanvas;
1469     friend class SkRasterHandleAllocator;
1470 
1471     enum InitFlags {
1472         kDefault_InitFlags                  = 0,
1473         kConservativeRasterClip_InitFlag    = 1 << 0,
1474     };
1475     SkCanvas(const SkIRect& bounds, InitFlags);
1476     SkCanvas(SkBaseDevice* device, InitFlags);
1477     SkCanvas(const SkBitmap&, std::unique_ptr<SkRasterHandleAllocator>,
1478              SkRasterHandleAllocator::Handle);
1479 
1480     void resetForNextPicture(const SkIRect& bounds);
1481 
1482     // needs gettotalclip()
1483     friend class SkCanvasStateUtils;
1484 
1485     // call this each time we attach ourselves to a device
1486     //  - constructor
1487     //  - internalSaveLayer
1488     void setupDevice(SkBaseDevice*);
1489 
1490     SkBaseDevice* init(SkBaseDevice*, InitFlags);
1491 
1492     /**
1493      * Gets the bounds of the top level layer in global canvas coordinates. We don't want this
1494      * to be public because it exposes decisions about layer sizes that are internal to the canvas.
1495      */
1496     SkIRect getTopLayerBounds() const;
1497 
1498     void internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
1499                                 const SkRect& dst, const SkPaint* paint,
1500                                 SrcRectConstraint);
1501     void internalDrawPaint(const SkPaint& paint);
1502     void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
1503     void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*, SkImage* clipImage,
1504                             const SkMatrix& clipMatrix);
1505 
1506     // shared by save() and saveLayer()
1507     void internalSave();
1508     void internalRestore();
1509 
1510     /*
1511      *  Returns true if drawing the specified rect (or all if it is null) with the specified
1512      *  paint (or default if null) would overwrite the entire root device of the canvas
1513      *  (i.e. the canvas' surface if it had one).
1514      */
1515     bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
1516 
1517     /**
1518      *  Returns true if the paint's imagefilter can be invoked directly, without needed a layer.
1519      */
1520     bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint&);
1521 
1522     /**
1523      *  Returns true if the clip (for any active layer) contains antialiasing.
1524      *  If the clip is empty, this will return false.
1525      */
1526     bool androidFramework_isClipAA() const;
1527 
1528     /**
1529      *  Keep track of the device clip bounds and if the matrix is scale-translate.  This allows
1530      *  us to do a fast quick reject in the common case.
1531      */
1532     bool   fIsScaleTranslate;
1533     SkRect fDeviceClipBounds;
1534 
1535     bool fAllowSoftClip;
1536     bool fAllowSimplifyClip;
1537 
1538     class AutoValidateClip : ::SkNoncopyable {
1539     public:
AutoValidateClip(SkCanvas * canvas)1540         explicit AutoValidateClip(SkCanvas* canvas) : fCanvas(canvas) {
1541             fCanvas->validateClip();
1542         }
~AutoValidateClip()1543         ~AutoValidateClip() { fCanvas->validateClip(); }
1544 
1545     private:
1546         const SkCanvas* fCanvas;
1547     };
1548 
1549 #ifdef SK_DEBUG
1550     void validateClip() const;
1551 #else
validateClip()1552     void validateClip() const {}
1553 #endif
1554 
1555     typedef SkRefCnt INHERITED;
1556 };
1557 
1558 /** Stack helper class to automatically call restoreToCount() on the canvas
1559     when this object goes out of scope. Use this to guarantee that the canvas
1560     is restored to a known state.
1561 */
1562 class SkAutoCanvasRestore : SkNoncopyable {
1563 public:
SkAutoCanvasRestore(SkCanvas * canvas,bool doSave)1564     SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
1565         if (fCanvas) {
1566             fSaveCount = canvas->getSaveCount();
1567             if (doSave) {
1568                 canvas->save();
1569             }
1570         }
1571     }
~SkAutoCanvasRestore()1572     ~SkAutoCanvasRestore() {
1573         if (fCanvas) {
1574             fCanvas->restoreToCount(fSaveCount);
1575         }
1576     }
1577 
1578     /**
1579      *  Perform the restore now, instead of waiting for the destructor. Will
1580      *  only do this once.
1581      */
restore()1582     void restore() {
1583         if (fCanvas) {
1584             fCanvas->restoreToCount(fSaveCount);
1585             fCanvas = NULL;
1586         }
1587     }
1588 
1589 private:
1590     SkCanvas*   fCanvas;
1591     int         fSaveCount;
1592 };
1593 #define SkAutoCanvasRestore(...) SK_REQUIRE_LOCAL_VAR(SkAutoCanvasRestore)
1594 
1595 #endif
1596