• 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 "include/core/SkBlendMode.h"
12 #include "include/core/SkClipOp.h"
13 #include "include/core/SkColor.h"
14 #include "include/core/SkFontTypes.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkM44.h"
17 #include "include/core/SkMatrix.h"
18 #include "include/core/SkPaint.h"
19 #include "include/core/SkPoint.h"
20 #include "include/core/SkRasterHandleAllocator.h"
21 #include "include/core/SkRect.h"
22 #include "include/core/SkRefCnt.h"
23 #include "include/core/SkSamplingOptions.h"
24 #include "include/core/SkScalar.h"
25 #include "include/core/SkSize.h"
26 #include "include/core/SkString.h"
27 #include "include/core/SkSurfaceProps.h"
28 #include "include/core/SkTypes.h"
29 #include "include/private/SkDeque.h"
30 #include "include/private/SkMacros.h"
31 
32 #include <cstring>
33 #include <memory>
34 #include <vector>
35 
36 #ifndef SK_SUPPORT_LEGACY_GETTOTALMATRIX
37 #define SK_SUPPORT_LEGACY_GETTOTALMATRIX
38 #endif
39 
40 class AutoLayerForImageFilter;
41 class GrBackendRenderTarget;
42 class GrRecordingContext;
43 class SkBaseDevice;
44 class SkBitmap;
45 class SkData;
46 class SkDrawable;
47 struct SkDrawShadowRec;
48 class SkFont;
49 class SkGlyphRunBuilder;
50 class SkGlyphRunList;
51 class SkImage;
52 class SkImageFilter;
53 class SkMarkerStack;
54 class SkPaintFilterCanvas;
55 class SkPath;
56 class SkPicture;
57 class SkPixmap;
58 class SkRegion;
59 class SkRRect;
60 struct SkRSXform;
61 class SkSpecialImage;
62 class SkSurface;
63 class SkSurface_Base;
64 class SkTextBlob;
65 class SkVertices;
66 
67 class HMSymbolData;
68 class HMSymbol;
69 
70 namespace skstd {
71     template<typename T> class optional;
72 }
73 
74 /** \class SkCanvas
75     SkCanvas provides an interface for drawing, and how the drawing is clipped and transformed.
76     SkCanvas contains a stack of SkMatrix and clip values.
77 
78     SkCanvas and SkPaint together provide the state to draw into SkSurface or SkBaseDevice.
79     Each SkCanvas draw call transforms the geometry of the object by the concatenation of all
80     SkMatrix values in the stack. The transformed geometry is clipped by the intersection
81     of all of clip values in the stack. The SkCanvas draw calls use SkPaint to supply drawing
82     state such as color, SkTypeface, text size, stroke width, SkShader and so on.
83 
84     To draw to a pixel-based destination, create raster surface or GPU surface.
85     Request SkCanvas from SkSurface to obtain the interface to draw.
86     SkCanvas generated by raster surface draws to memory visible to the CPU.
87     SkCanvas generated by GPU surface uses Vulkan or OpenGL to draw to the GPU.
88 
89     To draw to a document, obtain SkCanvas from SVG canvas, document PDF, or SkPictureRecorder.
90     SkDocument based SkCanvas and other SkCanvas subclasses reference SkBaseDevice describing the
91     destination.
92 
93     SkCanvas can be constructed to draw to SkBitmap without first creating raster surface.
94     This approach may be deprecated in the future.
95 */
96 class SK_API SkCanvas {
97 public:
98 
99     /** Allocates raster SkCanvas that will draw directly into pixels.
100 
101         SkCanvas is returned if all parameters are valid.
102         Valid parameters include:
103         info dimensions are zero or positive;
104         info contains SkColorType and SkAlphaType supported by raster surface;
105         pixels is not nullptr;
106         rowBytes is zero or large enough to contain info width pixels of SkColorType.
107 
108         Pass zero for rowBytes to compute rowBytes from info width and size of pixel.
109         If rowBytes is greater than zero, it must be equal to or greater than
110         info width times bytes required for SkColorType.
111 
112         Pixel buffer size should be info height times computed rowBytes.
113         Pixels are not initialized.
114         To access pixels after drawing, call flush() or peekPixels().
115 
116         @param info      width, height, SkColorType, SkAlphaType, SkColorSpace, of raster surface;
117                          width, or height, or both, may be zero
118         @param pixels    pointer to destination pixels buffer
119         @param rowBytes  interval from one SkSurface row to the next, or zero
120         @param props     LCD striping orientation and setting for device independent fonts;
121                          may be nullptr
122         @return          SkCanvas if all parameters are valid; otherwise, nullptr
123     */
124     static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels,
125                                                       size_t rowBytes,
126                                                       const SkSurfaceProps* props = nullptr);
127 
128     /** Allocates raster SkCanvas specified by inline image specification. Subsequent SkCanvas
129         calls draw into pixels.
130         SkColorType is set to kN32_SkColorType.
131         SkAlphaType is set to kPremul_SkAlphaType.
132         To access pixels after drawing, call flush() or peekPixels().
133 
134         SkCanvas is returned if all parameters are valid.
135         Valid parameters include:
136         width and height are zero or positive;
137         pixels is not nullptr;
138         rowBytes is zero or large enough to contain width pixels of kN32_SkColorType.
139 
140         Pass zero for rowBytes to compute rowBytes from width and size of pixel.
141         If rowBytes is greater than zero, it must be equal to or greater than
142         width times bytes required for SkColorType.
143 
144         Pixel buffer size should be height times rowBytes.
145 
146         @param width     pixel column count on raster surface created; must be zero or greater
147         @param height    pixel row count on raster surface created; must be zero or greater
148         @param pixels    pointer to destination pixels buffer; buffer size should be height
149                          times rowBytes
150         @param rowBytes  interval from one SkSurface row to the next, or zero
151         @return          SkCanvas if all parameters are valid; otherwise, nullptr
152     */
MakeRasterDirectN32(int width,int height,SkPMColor * pixels,size_t rowBytes)153     static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
154                                                          size_t rowBytes) {
155         return MakeRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
156     }
157 
158     /** Creates an empty SkCanvas with no backing device or pixels, with
159         a width and height of zero.
160 
161         @return  empty SkCanvas
162 
163         example: https://fiddle.skia.org/c/@Canvas_empty_constructor
164     */
165     SkCanvas();
166 
167     /** Creates SkCanvas of the specified dimensions without a SkSurface.
168         Used by subclasses with custom implementations for draw member functions.
169 
170         If props equals nullptr, SkSurfaceProps are created with
171         SkSurfaceProps::InitType settings, which choose the pixel striping
172         direction and order. Since a platform may dynamically change its direction when
173         the device is rotated, and since a platform may have multiple monitors with
174         different characteristics, it is best not to rely on this legacy behavior.
175 
176         @param width   zero or greater
177         @param height  zero or greater
178         @param props   LCD striping orientation and setting for device independent fonts;
179                        may be nullptr
180         @return        SkCanvas placeholder with dimensions
181 
182         example: https://fiddle.skia.org/c/@Canvas_int_int_const_SkSurfaceProps_star
183     */
184     SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr);
185 
186     /** Private. For internal use only.
187     */
188     explicit SkCanvas(sk_sp<SkBaseDevice> device);
189 
190     /** Constructs a canvas that draws into bitmap.
191         Sets kUnknown_SkPixelGeometry in constructed SkSurface.
192 
193         SkBitmap is copied so that subsequently editing bitmap will not affect
194         constructed SkCanvas.
195 
196         May be deprecated in the future.
197 
198         @param bitmap  width, height, SkColorType, SkAlphaType, and pixel
199                        storage of raster surface
200         @return        SkCanvas that can be used to draw into bitmap
201 
202         example: https://fiddle.skia.org/c/@Canvas_copy_const_SkBitmap
203     */
204     explicit SkCanvas(const SkBitmap& bitmap);
205 
206 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
207     /** Private.
208      */
209     enum class ColorBehavior {
210         kLegacy, //!< placeholder
211     };
212 
213     /** Private. For use by Android framework only.
214 
215         @param bitmap    specifies a bitmap for the canvas to draw into
216         @param behavior  specializes this constructor; value is unused
217         @return          SkCanvas that can be used to draw into bitmap
218     */
219     SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior);
220 #endif
221 
222     /** Constructs a canvas that draws into bitmap.
223         Use props to match the device characteristics, like LCD striping.
224 
225         bitmap is copied so that subsequently editing bitmap will not affect
226         constructed SkCanvas.
227 
228         @param bitmap  width, height, SkColorType, SkAlphaType,
229                        and pixel storage of raster surface
230         @param props   order and orientation of RGB striping; and whether to use
231                        device independent fonts
232         @return        SkCanvas that can be used to draw into bitmap
233 
234         example: https://fiddle.skia.org/c/@Canvas_const_SkBitmap_const_SkSurfaceProps
235     */
236     SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
237 
238     /** Draws saved layers, if any.
239         Frees up resources used by SkCanvas.
240 
241         example: https://fiddle.skia.org/c/@Canvas_destructor
242     */
243     virtual ~SkCanvas();
244 
245     /** Returns SkImageInfo for SkCanvas. If SkCanvas is not associated with raster surface or
246         GPU surface, returned SkColorType is set to kUnknown_SkColorType.
247 
248         @return  dimensions and SkColorType of SkCanvas
249 
250         example: https://fiddle.skia.org/c/@Canvas_imageInfo
251     */
252     SkImageInfo imageInfo() const;
253 
254     /** Copies SkSurfaceProps, if SkCanvas is associated with raster surface or
255         GPU surface, and returns true. Otherwise, returns false and leave props unchanged.
256 
257         @param props  storage for writable SkSurfaceProps
258         @return       true if SkSurfaceProps was copied
259 
260         example: https://fiddle.skia.org/c/@Canvas_getProps
261     */
262     bool getProps(SkSurfaceProps* props) const;
263 
264     /** Triggers the immediate execution of all pending draw operations.
265         If SkCanvas is associated with GPU surface, resolves all pending GPU operations.
266         If SkCanvas is associated with raster surface, has no effect; raster draw
267         operations are never deferred.
268 
269         DEPRECATED: Replace usage with GrDirectContext::flush()
270     */
271     void flush();
272 
273     /** Gets the size of the base or root layer in global canvas coordinates. The
274         origin of the base layer is always (0,0). The area available for drawing may be
275         smaller (due to clipping or saveLayer).
276 
277         @return  integral width and height of base layer
278 
279         example: https://fiddle.skia.org/c/@Canvas_getBaseLayerSize
280     */
281     virtual SkISize getBaseLayerSize() const;
282 
283     /** Creates SkSurface matching info and props, and associates it with SkCanvas.
284         Returns nullptr if no match found.
285 
286         If props is nullptr, matches SkSurfaceProps in SkCanvas. If props is nullptr and SkCanvas
287         does not have SkSurfaceProps, creates SkSurface with default SkSurfaceProps.
288 
289         @param info   width, height, SkColorType, SkAlphaType, and SkColorSpace
290         @param props  SkSurfaceProps to match; may be nullptr to match SkCanvas
291         @return       SkSurface matching info and props, or nullptr if no match is available
292 
293         example: https://fiddle.skia.org/c/@Canvas_makeSurface
294     */
295     sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr);
296 
297     /** Returns GPU context of the GPU surface associated with SkCanvas.
298 
299         @return  GPU context, if available; nullptr otherwise
300 
301         example: https://fiddle.skia.org/c/@Canvas_recordingContext
302      */
303     virtual GrRecordingContext* recordingContext();
304 
305     /** Sometimes a canvas is owned by a surface. If it is, getSurface() will return a bare
306      *  pointer to that surface, else this will return nullptr.
307      */
308     SkSurface* getSurface() const;
309 
310     /** Returns the pixel base address, SkImageInfo, rowBytes, and origin if the pixels
311         can be read directly. The returned address is only valid
312         while SkCanvas is in scope and unchanged. Any SkCanvas call or SkSurface call
313         may invalidate the returned address and other returned values.
314 
315         If pixels are inaccessible, info, rowBytes, and origin are unchanged.
316 
317         @param info      storage for writable pixels' SkImageInfo; may be nullptr
318         @param rowBytes  storage for writable pixels' row bytes; may be nullptr
319         @param origin    storage for SkCanvas top layer origin, its top-left corner;
320                          may be nullptr
321         @return          address of pixels, or nullptr if inaccessible
322 
323         example: https://fiddle.skia.org/c/@Canvas_accessTopLayerPixels_a
324         example: https://fiddle.skia.org/c/@Canvas_accessTopLayerPixels_b
325     */
326     void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr);
327 
328     /** Returns custom context that tracks the SkMatrix and clip.
329 
330         Use SkRasterHandleAllocator to blend Skia drawing with custom drawing, typically performed
331         by the host platform user interface. The custom context returned is generated by
332         SkRasterHandleAllocator::MakeCanvas, which creates a custom canvas with raster storage for
333         the drawing destination.
334 
335         @return  context of custom allocation
336 
337         example: https://fiddle.skia.org/c/@Canvas_accessTopRasterHandle
338     */
339     SkRasterHandleAllocator::Handle accessTopRasterHandle() const;
340 
341     /** Returns true if SkCanvas has direct access to its pixels.
342 
343         Pixels are readable when SkBaseDevice is raster. Pixels are not readable when SkCanvas
344         is returned from GPU surface, returned by SkDocument::beginPage, returned by
345         SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility class
346         like DebugCanvas.
347 
348         pixmap is valid only while SkCanvas is in scope and unchanged. Any
349         SkCanvas or SkSurface call may invalidate the pixmap values.
350 
351         @param pixmap  storage for pixel state if pixels are readable; otherwise, ignored
352         @return        true if SkCanvas has direct access to pixels
353 
354         example: https://fiddle.skia.org/c/@Canvas_peekPixels
355     */
356     bool peekPixels(SkPixmap* pixmap);
357 
358     /** Copies SkRect of pixels from SkCanvas into dstPixels. SkMatrix and clip are
359         ignored.
360 
361         Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
362         Destination SkRect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).
363         Copies each readable pixel intersecting both rectangles, without scaling,
364         converting to dstInfo.colorType() and dstInfo.alphaType() if required.
365 
366         Pixels are readable when SkBaseDevice is raster, or backed by a GPU.
367         Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
368         returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
369         class like DebugCanvas.
370 
371         The destination pixel storage must be allocated by the caller.
372 
373         Pixel values are converted only if SkColorType and SkAlphaType
374         do not match. Only pixels within both source and destination rectangles
375         are copied. dstPixels contents outside SkRect intersection are unchanged.
376 
377         Pass negative values for srcX or srcY to offset pixels across or down destination.
378 
379         Does not copy, and returns false if:
380         - Source and destination rectangles do not intersect.
381         - SkCanvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType().
382         - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.
383         - dstRowBytes is too small to contain one row of pixels.
384 
385         @param dstInfo      width, height, SkColorType, and SkAlphaType of dstPixels
386         @param dstPixels    storage for pixels; dstInfo.height() times dstRowBytes, or larger
387         @param dstRowBytes  size of one destination row; dstInfo.width() times pixel size, or larger
388         @param srcX         offset into readable pixels on x-axis; may be negative
389         @param srcY         offset into readable pixels on y-axis; may be negative
390         @return             true if pixels were copied
391     */
392     bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
393                     int srcX, int srcY);
394 
395     /** Copies SkRect of pixels from SkCanvas into pixmap. SkMatrix and clip are
396         ignored.
397 
398         Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
399         Destination SkRect corners are (0, 0) and (pixmap.width(), pixmap.height()).
400         Copies each readable pixel intersecting both rectangles, without scaling,
401         converting to pixmap.colorType() and pixmap.alphaType() if required.
402 
403         Pixels are readable when SkBaseDevice is raster, or backed by a GPU.
404         Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
405         returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
406         class like DebugCanvas.
407 
408         Caller must allocate pixel storage in pixmap if needed.
409 
410         Pixel values are converted only if SkColorType and SkAlphaType
411         do not match. Only pixels within both source and destination SkRect
412         are copied. pixmap pixels contents outside SkRect intersection are unchanged.
413 
414         Pass negative values for srcX or srcY to offset pixels across or down pixmap.
415 
416         Does not copy, and returns false if:
417         - Source and destination rectangles do not intersect.
418         - SkCanvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType().
419         - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.
420         - SkPixmap pixels could not be allocated.
421         - pixmap.rowBytes() is too small to contain one row of pixels.
422 
423         @param pixmap  storage for pixels copied from SkCanvas
424         @param srcX    offset into readable pixels on x-axis; may be negative
425         @param srcY    offset into readable pixels on y-axis; may be negative
426         @return        true if pixels were copied
427 
428         example: https://fiddle.skia.org/c/@Canvas_readPixels_2
429     */
430     bool readPixels(const SkPixmap& pixmap, int srcX, int srcY);
431 
432     /** Copies SkRect of pixels from SkCanvas into bitmap. SkMatrix and clip are
433         ignored.
434 
435         Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
436         Destination SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()).
437         Copies each readable pixel intersecting both rectangles, without scaling,
438         converting to bitmap.colorType() and bitmap.alphaType() if required.
439 
440         Pixels are readable when SkBaseDevice is raster, or backed by a GPU.
441         Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
442         returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
443         class like DebugCanvas.
444 
445         Caller must allocate pixel storage in bitmap if needed.
446 
447         SkBitmap values are converted only if SkColorType and SkAlphaType
448         do not match. Only pixels within both source and destination rectangles
449         are copied. SkBitmap pixels outside SkRect intersection are unchanged.
450 
451         Pass negative values for srcX or srcY to offset pixels across or down bitmap.
452 
453         Does not copy, and returns false if:
454         - Source and destination rectangles do not intersect.
455         - SkCanvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType().
456         - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.
457         - bitmap pixels could not be allocated.
458         - bitmap.rowBytes() is too small to contain one row of pixels.
459 
460         @param bitmap  storage for pixels copied from SkCanvas
461         @param srcX    offset into readable pixels on x-axis; may be negative
462         @param srcY    offset into readable pixels on y-axis; may be negative
463         @return        true if pixels were copied
464 
465         example: https://fiddle.skia.org/c/@Canvas_readPixels_3
466     */
467     bool readPixels(const SkBitmap& bitmap, int srcX, int srcY);
468 
469     /** Copies SkRect from pixels to SkCanvas. SkMatrix and clip are ignored.
470         Source SkRect corners are (0, 0) and (info.width(), info.height()).
471         Destination SkRect corners are (x, y) and
472         (imageInfo().width(), imageInfo().height()).
473 
474         Copies each readable pixel intersecting both rectangles, without scaling,
475         converting to imageInfo().colorType() and imageInfo().alphaType() if required.
476 
477         Pixels are writable when SkBaseDevice is raster, or backed by a GPU.
478         Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
479         returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
480         class like DebugCanvas.
481 
482         Pixel values are converted only if SkColorType and SkAlphaType
483         do not match. Only pixels within both source and destination rectangles
484         are copied. SkCanvas pixels outside SkRect intersection are unchanged.
485 
486         Pass negative values for x or y to offset pixels to the left or
487         above SkCanvas pixels.
488 
489         Does not copy, and returns false if:
490         - Source and destination rectangles do not intersect.
491         - pixels could not be converted to SkCanvas imageInfo().colorType() or
492         imageInfo().alphaType().
493         - SkCanvas pixels are not writable; for instance, SkCanvas is document-based.
494         - rowBytes is too small to contain one row of pixels.
495 
496         @param info      width, height, SkColorType, and SkAlphaType of pixels
497         @param pixels    pixels to copy, of size info.height() times rowBytes, or larger
498         @param rowBytes  size of one row of pixels; info.width() times pixel size, or larger
499         @param x         offset into SkCanvas writable pixels on x-axis; may be negative
500         @param y         offset into SkCanvas writable pixels on y-axis; may be negative
501         @return          true if pixels were written to SkCanvas
502 
503         example: https://fiddle.skia.org/c/@Canvas_writePixels
504     */
505     bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y);
506 
507     /** Copies SkRect from pixels to SkCanvas. SkMatrix and clip are ignored.
508         Source SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()).
509 
510         Destination SkRect corners are (x, y) and
511         (imageInfo().width(), imageInfo().height()).
512 
513         Copies each readable pixel intersecting both rectangles, without scaling,
514         converting to imageInfo().colorType() and imageInfo().alphaType() if required.
515 
516         Pixels are writable when SkBaseDevice is raster, or backed by a GPU.
517         Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
518         returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
519         class like DebugCanvas.
520 
521         Pixel values are converted only if SkColorType and SkAlphaType
522         do not match. Only pixels within both source and destination rectangles
523         are copied. SkCanvas pixels outside SkRect intersection are unchanged.
524 
525         Pass negative values for x or y to offset pixels to the left or
526         above SkCanvas pixels.
527 
528         Does not copy, and returns false if:
529         - Source and destination rectangles do not intersect.
530         - bitmap does not have allocated pixels.
531         - bitmap pixels could not be converted to SkCanvas imageInfo().colorType() or
532         imageInfo().alphaType().
533         - SkCanvas pixels are not writable; for instance, SkCanvas is document based.
534         - bitmap pixels are inaccessible; for instance, bitmap wraps a texture.
535 
536         @param bitmap  contains pixels copied to SkCanvas
537         @param x       offset into SkCanvas writable pixels on x-axis; may be negative
538         @param y       offset into SkCanvas writable pixels on y-axis; may be negative
539         @return        true if pixels were written to SkCanvas
540 
541         example: https://fiddle.skia.org/c/@Canvas_writePixels_2
542         example: https://fiddle.skia.org/c/@State_Stack_a
543         example: https://fiddle.skia.org/c/@State_Stack_b
544     */
545     bool writePixels(const SkBitmap& bitmap, int x, int y);
546 
547     /** Saves SkMatrix and clip.
548         Calling restore() discards changes to SkMatrix and clip,
549         restoring the SkMatrix and clip to their state when save() was called.
550 
551         SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix(),
552         and resetMatrix(). Clip may be changed by clipRect(), clipRRect(), clipPath(), clipRegion().
553 
554         Saved SkCanvas state is put on a stack; multiple calls to save() should be balance
555         by an equal number of calls to restore().
556 
557         Call restoreToCount() with result to restore this and subsequent saves.
558 
559         @return  depth of saved stack
560 
561         example: https://fiddle.skia.org/c/@Canvas_save
562     */
563     int save();
564 
565     /** Saves SkMatrix and clip, and allocates a SkBitmap for subsequent drawing.
566         Calling restore() discards changes to SkMatrix and clip, and draws the SkBitmap.
567 
568         SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
569         setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
570         clipPath(), clipRegion().
571 
572         SkRect bounds suggests but does not define the SkBitmap size. To clip drawing to
573         a specific rectangle, use clipRect().
574 
575         Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and
576         SkBlendMode when restore() is called.
577 
578         Call restoreToCount() with returned value to restore this and subsequent saves.
579 
580         @param bounds  hint to limit the size of the layer; may be nullptr
581         @param paint   graphics state for layer; may be nullptr
582         @return        depth of saved stack
583 
584         example: https://fiddle.skia.org/c/@Canvas_saveLayer
585         example: https://fiddle.skia.org/c/@Canvas_saveLayer_4
586     */
587     int saveLayer(const SkRect* bounds, const SkPaint* paint);
588 
589     /** Saves SkMatrix and clip, and allocates a SkBitmap for subsequent drawing.
590         Calling restore() discards changes to SkMatrix and clip, and draws the SkBitmap.
591 
592         SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
593         setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
594         clipPath(), clipRegion().
595 
596         SkRect bounds suggests but does not define the layer size. To clip drawing to
597         a specific rectangle, use clipRect().
598 
599         Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and
600         SkBlendMode when restore() is called.
601 
602         Call restoreToCount() with returned value to restore this and subsequent saves.
603 
604         @param bounds  hint to limit the size of layer; may be nullptr
605         @param paint   graphics state for layer; may be nullptr
606         @return        depth of saved stack
607     */
saveLayer(const SkRect & bounds,const SkPaint * paint)608     int saveLayer(const SkRect& bounds, const SkPaint* paint) {
609         return this->saveLayer(&bounds, paint);
610     }
611 
612     /** Saves SkMatrix and clip, and allocates SkBitmap for subsequent drawing.
613 
614         Calling restore() discards changes to SkMatrix and clip,
615         and blends layer with alpha opacity onto prior layer.
616 
617         SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
618         setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
619         clipPath(), clipRegion().
620 
621         SkRect bounds suggests but does not define layer size. To clip drawing to
622         a specific rectangle, use clipRect().
623 
624         alpha of zero is fully transparent, 255 is fully opaque.
625 
626         Call restoreToCount() with returned value to restore this and subsequent saves.
627 
628         @param bounds  hint to limit the size of layer; may be nullptr
629         @param alpha   opacity of layer
630         @return        depth of saved stack
631 
632         example: https://fiddle.skia.org/c/@Canvas_saveLayerAlpha
633     */
634     int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
635 
636     /** \enum SkCanvas::SaveLayerFlagsSet
637         SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
638         defining how layer allocated by saveLayer() operates. It may be set to zero,
639         kPreserveLCDText_SaveLayerFlag, kInitWithPrevious_SaveLayerFlag, or both flags.
640     */
641     enum SaveLayerFlagsSet {
642         kPreserveLCDText_SaveLayerFlag  = 1 << 1,
643         kInitWithPrevious_SaveLayerFlag = 1 << 2, //!< initializes with previous contents
644         kMaskAgainstCoverage_EXPERIMENTAL_DONT_USE_SaveLayerFlag =
645                                           1 << 3, //!< experimental: do not use
646         // instead of matching previous layer's colortype, use F16
647         kF16ColorType                   = 1 << 4,
648     };
649 
650     typedef uint32_t SaveLayerFlags;
651 
652     /** \struct SkCanvas::SaveLayerRec
653         SaveLayerRec contains the state used to create the layer.
654     */
655     struct SaveLayerRec {
656         /** Sets fBounds, fPaint, and fBackdrop to nullptr. Clears fSaveLayerFlags.
657 
658             @return  empty SaveLayerRec
659         */
SaveLayerRecSaveLayerRec660         SaveLayerRec() {}
661 
662         /** Sets fBounds, fPaint, and fSaveLayerFlags; sets fBackdrop to nullptr.
663 
664             @param bounds          layer dimensions; may be nullptr
665             @param paint           applied to layer when overlaying prior layer; may be nullptr
666             @param saveLayerFlags  SaveLayerRec options to modify layer
667             @return                SaveLayerRec with empty fBackdrop
668         */
669         SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
670             : SaveLayerRec(bounds, paint, nullptr, 1.f, saveLayerFlags) {}
671 
672         /** Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags.
673 
674             @param bounds          layer dimensions; may be nullptr
675             @param paint           applied to layer when overlaying prior layer;
676                                    may be nullptr
677             @param backdrop        If not null, this causes the current layer to be filtered by
678                                    backdrop, and then drawn into the new layer
679                                    (respecting the current clip).
680                                    If null, the new layer is initialized with transparent-black.
681             @param saveLayerFlags  SaveLayerRec options to modify layer
682             @return                SaveLayerRec fully specified
683         */
SaveLayerRecSaveLayerRec684         SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
685                      SaveLayerFlags saveLayerFlags)
686             : SaveLayerRec(bounds, paint, backdrop, 1.f, saveLayerFlags) {}
687 
688         /** hints at layer size limit */
689         const SkRect*        fBounds         = nullptr;
690 
691         /** modifies overlay */
692         const SkPaint*       fPaint          = nullptr;
693 
694         /**
695          *  If not null, this triggers the same initialization behavior as setting
696          *  kInitWithPrevious_SaveLayerFlag on fSaveLayerFlags: the current layer is copied into
697          *  the new layer, rather than initializing the new layer with transparent-black.
698          *  This is then filtered by fBackdrop (respecting the current clip).
699          */
700         const SkImageFilter* fBackdrop       = nullptr;
701 
702         /** preserves LCD text, creates with prior layer contents */
703         SaveLayerFlags       fSaveLayerFlags = 0;
704 
705     private:
706         friend class SkCanvas;
707         friend class SkCanvasPriv;
708 
SaveLayerRecSaveLayerRec709         SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
710                      SkScalar backdropScale, SaveLayerFlags saveLayerFlags)
711             : fBounds(bounds)
712             , fPaint(paint)
713             , fBackdrop(backdrop)
714             , fSaveLayerFlags(saveLayerFlags)
715             , fExperimentalBackdropScale(backdropScale) {}
716 
717         // Relative scale factor that the image content used to initialize the layer when the
718         // kInitFromPrevious flag or a backdrop filter is used.
719         SkScalar             fExperimentalBackdropScale = 1.f;
720     };
721 
722     /** Saves SkMatrix and clip, and allocates SkBitmap for subsequent drawing.
723 
724         Calling restore() discards changes to SkMatrix and clip,
725         and blends SkBitmap with alpha opacity onto the prior layer.
726 
727         SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
728         setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
729         clipPath(), clipRegion().
730 
731         SaveLayerRec contains the state used to create the layer.
732 
733         Call restoreToCount() with returned value to restore this and subsequent saves.
734 
735         @param layerRec  layer state
736         @return          depth of save state stack before this call was made.
737 
738         example: https://fiddle.skia.org/c/@Canvas_saveLayer_3
739     */
740     int saveLayer(const SaveLayerRec& layerRec);
741 
742     /** Removes changes to SkMatrix and clip since SkCanvas state was
743         last saved. The state is removed from the stack.
744 
745         Does nothing if the stack is empty.
746 
747         example: https://fiddle.skia.org/c/@AutoCanvasRestore_restore
748 
749         example: https://fiddle.skia.org/c/@Canvas_restore
750     */
751     void restore();
752 
753     /** Returns the number of saved states, each containing: SkMatrix and clip.
754         Equals the number of save() calls less the number of restore() calls plus one.
755         The save count of a new canvas is one.
756 
757         @return  depth of save state stack
758 
759         example: https://fiddle.skia.org/c/@Canvas_getSaveCount
760     */
761     int getSaveCount() const;
762 
763     /** Restores state to SkMatrix and clip values when save(), saveLayer(),
764         saveLayerPreserveLCDTextRequests(), or saveLayerAlpha() returned saveCount.
765 
766         Does nothing if saveCount is greater than state stack count.
767         Restores state to initial values if saveCount is less than or equal to one.
768 
769         @param saveCount  depth of state stack to restore
770 
771         example: https://fiddle.skia.org/c/@Canvas_restoreToCount
772     */
773     void restoreToCount(int saveCount);
774 
775     /** Translates SkMatrix by dx along the x-axis and dy along the y-axis.
776 
777         Mathematically, replaces SkMatrix with a translation matrix
778         premultiplied with SkMatrix.
779 
780         This has the effect of moving the drawing by (dx, dy) before transforming
781         the result with SkMatrix.
782 
783         @param dx  distance to translate on x-axis
784         @param dy  distance to translate on y-axis
785 
786         example: https://fiddle.skia.org/c/@Canvas_translate
787     */
788     void translate(SkScalar dx, SkScalar dy);
789 
790     /** Scales SkMatrix by sx on the x-axis and sy on the y-axis.
791 
792         Mathematically, replaces SkMatrix with a scale matrix
793         premultiplied with SkMatrix.
794 
795         This has the effect of scaling the drawing by (sx, sy) before transforming
796         the result with SkMatrix.
797 
798         @param sx  amount to scale on x-axis
799         @param sy  amount to scale on y-axis
800 
801         example: https://fiddle.skia.org/c/@Canvas_scale
802     */
803     void scale(SkScalar sx, SkScalar sy);
804 
805     /** Rotates SkMatrix by degrees. Positive degrees rotates clockwise.
806 
807         Mathematically, replaces SkMatrix with a rotation matrix
808         premultiplied with SkMatrix.
809 
810         This has the effect of rotating the drawing by degrees before transforming
811         the result with SkMatrix.
812 
813         @param degrees  amount to rotate, in degrees
814 
815         example: https://fiddle.skia.org/c/@Canvas_rotate
816     */
817     void rotate(SkScalar degrees);
818 
819     /** Rotates SkMatrix by degrees about a point at (px, py). Positive degrees rotates
820         clockwise.
821 
822         Mathematically, constructs a rotation matrix; premultiplies the rotation matrix by
823         a translation matrix; then replaces SkMatrix with the resulting matrix
824         premultiplied with SkMatrix.
825 
826         This has the effect of rotating the drawing about a given point before
827         transforming the result with SkMatrix.
828 
829         @param degrees  amount to rotate, in degrees
830         @param px       x-axis value of the point to rotate about
831         @param py       y-axis value of the point to rotate about
832 
833         example: https://fiddle.skia.org/c/@Canvas_rotate_2
834     */
835     void rotate(SkScalar degrees, SkScalar px, SkScalar py);
836 
837     /** Skews SkMatrix by sx on the x-axis and sy on the y-axis. A positive value of sx
838         skews the drawing right as y-axis values increase; a positive value of sy skews
839         the drawing down as x-axis values increase.
840 
841         Mathematically, replaces SkMatrix with a skew matrix premultiplied with SkMatrix.
842 
843         This has the effect of skewing the drawing by (sx, sy) before transforming
844         the result with SkMatrix.
845 
846         @param sx  amount to skew on x-axis
847         @param sy  amount to skew on y-axis
848 
849         example: https://fiddle.skia.org/c/@Canvas_skew
850     */
851     void skew(SkScalar sx, SkScalar sy);
852 
853     /** Replaces SkMatrix with matrix premultiplied with existing SkMatrix.
854 
855         This has the effect of transforming the drawn geometry by matrix, before
856         transforming the result with existing SkMatrix.
857 
858         @param matrix  matrix to premultiply with existing SkMatrix
859 
860         example: https://fiddle.skia.org/c/@Canvas_concat
861     */
862     void concat(const SkMatrix& matrix);
863     void concat(const SkM44&);
864 
865     /**
866      *  Record a marker (provided by caller) for the current CTM. This does not change anything
867      *  about the ctm or clip, but does "name" this matrix value, so it can be referenced by
868      *  custom effects (who access it by specifying the same name).
869      *
870      *  Within a save frame, marking with the same name more than once just replaces the previous
871      *  value. However, between save frames, marking with the same name does not lose the marker
872      *  in the previous save frame. It is "visible" when the current save() is balanced with
873      *  a restore().
874      */
875     void markCTM(const char* name);
876 
877     bool findMarkedCTM(const char* name, SkM44*) const;
878 
879     /** Replaces SkMatrix with matrix.
880         Unlike concat(), any prior matrix state is overwritten.
881 
882         @param matrix  matrix to copy, replacing existing SkMatrix
883 
884         example: https://fiddle.skia.org/c/@Canvas_setMatrix
885     */
886     void setMatrix(const SkM44& matrix);
887 
888     // DEPRECATED -- use SkM44 version
889     void setMatrix(const SkMatrix& matrix);
890 
891     /** Sets SkMatrix to the identity matrix.
892         Any prior matrix state is overwritten.
893 
894         example: https://fiddle.skia.org/c/@Canvas_resetMatrix
895     */
896     void resetMatrix();
897 
898     /** Replaces clip with the intersection or difference of clip and rect,
899         with an aliased or anti-aliased clip edge. rect is transformed by SkMatrix
900         before it is combined with clip.
901 
902         @param rect         SkRect to combine with clip
903         @param op           SkClipOp to apply to clip
904         @param doAntiAlias  true if clip is to be anti-aliased
905 
906         example: https://fiddle.skia.org/c/@Canvas_clipRect
907     */
908     void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias);
909 
910     /** Replaces clip with the intersection or difference of clip and rect.
911         Resulting clip is aliased; pixels are fully contained by the clip.
912         rect is transformed by SkMatrix before it is combined with clip.
913 
914         @param rect  SkRect to combine with clip
915         @param op    SkClipOp to apply to clip
916     */
clipRect(const SkRect & rect,SkClipOp op)917     void clipRect(const SkRect& rect, SkClipOp op) {
918         this->clipRect(rect, op, false);
919     }
920 
921     /** Replaces clip with the intersection of clip and rect.
922         Resulting clip is aliased; pixels are fully contained by the clip.
923         rect is transformed by SkMatrix
924         before it is combined with clip.
925 
926         @param rect         SkRect to combine with clip
927         @param doAntiAlias  true if clip is to be anti-aliased
928     */
929     void clipRect(const SkRect& rect, bool doAntiAlias = false) {
930         this->clipRect(rect, SkClipOp::kIntersect, doAntiAlias);
931     }
932 
933     void clipIRect(const SkIRect& irect, SkClipOp op = SkClipOp::kIntersect) {
934         this->clipRect(SkRect::Make(irect), op, false);
935     }
936 
937     /** Sets the maximum clip rectangle, which can be set by clipRect(), clipRRect() and
938         clipPath() and intersect the current clip with the specified rect.
939         The maximum clip affects only future clipping operations; it is not retroactive.
940         The clip restriction is not recorded in pictures.
941 
942         Pass an empty rect to disable maximum clip.
943         This private API is for use by Android framework only.
944 
945         DEPRECATED: Replace usage with SkAndroidFrameworkUtils::replaceClip()
946 
947         @param rect  maximum allowed clip in device coordinates
948     */
949     void androidFramework_setDeviceClipRestriction(const SkIRect& rect);
950 
951     /** Replaces clip with the intersection or difference of clip and rrect,
952         with an aliased or anti-aliased clip edge.
953         rrect is transformed by SkMatrix
954         before it is combined with clip.
955 
956         @param rrect        SkRRect to combine with clip
957         @param op           SkClipOp to apply to clip
958         @param doAntiAlias  true if clip is to be anti-aliased
959 
960         example: https://fiddle.skia.org/c/@Canvas_clipRRect
961     */
962     void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias);
963 
964     /** Replaces clip with the intersection or difference of clip and rrect.
965         Resulting clip is aliased; pixels are fully contained by the clip.
966         rrect is transformed by SkMatrix before it is combined with clip.
967 
968         @param rrect  SkRRect to combine with clip
969         @param op     SkClipOp to apply to clip
970     */
clipRRect(const SkRRect & rrect,SkClipOp op)971     void clipRRect(const SkRRect& rrect, SkClipOp op) {
972         this->clipRRect(rrect, op, false);
973     }
974 
975     /** Replaces clip with the intersection of clip and rrect,
976         with an aliased or anti-aliased clip edge.
977         rrect is transformed by SkMatrix before it is combined with clip.
978 
979         @param rrect        SkRRect to combine with clip
980         @param doAntiAlias  true if clip is to be anti-aliased
981     */
982     void clipRRect(const SkRRect& rrect, bool doAntiAlias = false) {
983         this->clipRRect(rrect, SkClipOp::kIntersect, doAntiAlias);
984     }
985 
986     /** Replaces clip with the intersection or difference of clip and path,
987         with an aliased or anti-aliased clip edge. SkPath::FillType determines if path
988         describes the area inside or outside its contours; and if path contour overlaps
989         itself or another path contour, whether the overlaps form part of the area.
990         path is transformed by SkMatrix before it is combined with clip.
991 
992         @param path         SkPath to combine with clip
993         @param op           SkClipOp to apply to clip
994         @param doAntiAlias  true if clip is to be anti-aliased
995 
996         example: https://fiddle.skia.org/c/@Canvas_clipPath
997     */
998     void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias);
999 
1000     /** Replaces clip with the intersection or difference of clip and path.
1001         Resulting clip is aliased; pixels are fully contained by the clip.
1002         SkPath::FillType determines if path
1003         describes the area inside or outside its contours; and if path contour overlaps
1004         itself or another path contour, whether the overlaps form part of the area.
1005         path is transformed by SkMatrix
1006         before it is combined with clip.
1007 
1008         @param path  SkPath to combine with clip
1009         @param op    SkClipOp to apply to clip
1010     */
clipPath(const SkPath & path,SkClipOp op)1011     void clipPath(const SkPath& path, SkClipOp op) {
1012         this->clipPath(path, op, false);
1013     }
1014 
1015     /** Replaces clip with the intersection of clip and path.
1016         Resulting clip is aliased; pixels are fully contained by the clip.
1017         SkPath::FillType determines if path
1018         describes the area inside or outside its contours; and if path contour overlaps
1019         itself or another path contour, whether the overlaps form part of the area.
1020         path is transformed by SkMatrix before it is combined with clip.
1021 
1022         @param path         SkPath to combine with clip
1023         @param doAntiAlias  true if clip is to be anti-aliased
1024     */
1025     void clipPath(const SkPath& path, bool doAntiAlias = false) {
1026         this->clipPath(path, SkClipOp::kIntersect, doAntiAlias);
1027     }
1028 
1029     void clipShader(sk_sp<SkShader>, SkClipOp = SkClipOp::kIntersect);
1030 
1031     /** Replaces clip with the intersection or difference of clip and SkRegion deviceRgn.
1032         Resulting clip is aliased; pixels are fully contained by the clip.
1033         deviceRgn is unaffected by SkMatrix.
1034 
1035         @param deviceRgn  SkRegion to combine with clip
1036         @param op         SkClipOp to apply to clip
1037 
1038         example: https://fiddle.skia.org/c/@Canvas_clipRegion
1039     */
1040     void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect);
1041 
1042     /** Returns true if SkRect rect, transformed by SkMatrix, can be quickly determined to be
1043         outside of clip. May return false even though rect is outside of clip.
1044 
1045         Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
1046 
1047         @param rect  SkRect to compare with clip
1048         @return      true if rect, transformed by SkMatrix, does not intersect clip
1049 
1050         example: https://fiddle.skia.org/c/@Canvas_quickReject
1051     */
1052     bool quickReject(const SkRect& rect) const;
1053 
1054     /** Returns true if path, transformed by SkMatrix, can be quickly determined to be
1055         outside of clip. May return false even though path is outside of clip.
1056 
1057         Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
1058 
1059         @param path  SkPath to compare with clip
1060         @return      true if path, transformed by SkMatrix, does not intersect clip
1061 
1062         example: https://fiddle.skia.org/c/@Canvas_quickReject_2
1063     */
1064     bool quickReject(const SkPath& path) const;
1065 
1066     /** Returns bounds of clip, transformed by inverse of SkMatrix. If clip is empty,
1067         return SkRect::MakeEmpty, where all SkRect sides equal zero.
1068 
1069         SkRect returned is outset by one to account for partial pixel coverage if clip
1070         is anti-aliased.
1071 
1072         @return  bounds of clip in local coordinates
1073 
1074         example: https://fiddle.skia.org/c/@Canvas_getLocalClipBounds
1075     */
1076     SkRect getLocalClipBounds() const;
1077 
1078     /** Returns bounds of clip, transformed by inverse of SkMatrix. If clip is empty,
1079         return false, and set bounds to SkRect::MakeEmpty, where all SkRect sides equal zero.
1080 
1081         bounds is outset by one to account for partial pixel coverage if clip
1082         is anti-aliased.
1083 
1084         @param bounds  SkRect of clip in local coordinates
1085         @return        true if clip bounds is not empty
1086     */
getLocalClipBounds(SkRect * bounds)1087     bool getLocalClipBounds(SkRect* bounds) const {
1088         *bounds = this->getLocalClipBounds();
1089         return !bounds->isEmpty();
1090     }
1091 
1092     /** Returns SkIRect bounds of clip, unaffected by SkMatrix. If clip is empty,
1093         return SkRect::MakeEmpty, where all SkRect sides equal zero.
1094 
1095         Unlike getLocalClipBounds(), returned SkIRect is not outset.
1096 
1097         @return  bounds of clip in SkBaseDevice coordinates
1098 
1099         example: https://fiddle.skia.org/c/@Canvas_getDeviceClipBounds
1100     */
1101     SkIRect getDeviceClipBounds() const;
1102 
1103     /** Returns SkIRect bounds of clip, unaffected by SkMatrix. If clip is empty,
1104         return false, and set bounds to SkRect::MakeEmpty, where all SkRect sides equal zero.
1105 
1106         Unlike getLocalClipBounds(), bounds is not outset.
1107 
1108         @param bounds  SkRect of clip in device coordinates
1109         @return        true if clip bounds is not empty
1110     */
getDeviceClipBounds(SkIRect * bounds)1111     bool getDeviceClipBounds(SkIRect* bounds) const {
1112         *bounds = this->getDeviceClipBounds();
1113         return !bounds->isEmpty();
1114     }
1115 
1116     /** Fills clip with color color.
1117         mode determines how ARGB is combined with destination.
1118 
1119         @param color  unpremultiplied ARGB
1120         @param mode   SkBlendMode used to combine source color and destination
1121 
1122         example: https://fiddle.skia.org/c/@Canvas_drawColor
1123     */
1124     void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver) {
1125         this->drawColor(SkColor4f::FromColor(color), mode);
1126     }
1127 
1128     /** Fills clip with color color.
1129         mode determines how ARGB is combined with destination.
1130 
1131         @param color  SkColor4f representing unpremultiplied color.
1132         @param mode   SkBlendMode used to combine source color and destination
1133     */
1134     void drawColor(const SkColor4f& color, SkBlendMode mode = SkBlendMode::kSrcOver);
1135 
1136     /** Fills clip with color color using SkBlendMode::kSrc.
1137         This has the effect of replacing all pixels contained by clip with color.
1138 
1139         @param color  unpremultiplied ARGB
1140     */
clear(SkColor color)1141     void clear(SkColor color) {
1142         this->clear(SkColor4f::FromColor(color));
1143     }
1144 
1145     /** Fills clip with color color using SkBlendMode::kSrc.
1146         This has the effect of replacing all pixels contained by clip with color.
1147 
1148         @param color  SkColor4f representing unpremultiplied color.
1149     */
clear(const SkColor4f & color)1150     void clear(const SkColor4f& color) {
1151         this->drawColor(color, SkBlendMode::kSrc);
1152     }
1153 
1154     /** Makes SkCanvas contents undefined. Subsequent calls that read SkCanvas pixels,
1155         such as drawing with SkBlendMode, return undefined results. discard() does
1156         not change clip or SkMatrix.
1157 
1158         discard() may do nothing, depending on the implementation of SkSurface or SkBaseDevice
1159         that created SkCanvas.
1160 
1161         discard() allows optimized performance on subsequent draws by removing
1162         cached data associated with SkSurface or SkBaseDevice.
1163         It is not necessary to call discard() once done with SkCanvas;
1164         any cached data is deleted when owning SkSurface or SkBaseDevice is deleted.
1165     */
discard()1166     void discard() { this->onDiscard(); }
1167 
1168     /** Fills clip with SkPaint paint. SkPaint components, SkShader,
1169         SkColorFilter, SkImageFilter, and SkBlendMode affect drawing;
1170         SkMaskFilter and SkPathEffect in paint are ignored.
1171 
1172         @param paint  graphics state used to fill SkCanvas
1173 
1174         example: https://fiddle.skia.org/c/@Canvas_drawPaint
1175     */
1176     void drawPaint(const SkPaint& paint);
1177 
1178     /** \enum SkCanvas::PointMode
1179         Selects if an array of points are drawn as discrete points, as lines, or as
1180         an open polygon.
1181     */
1182     enum PointMode {
1183         kPoints_PointMode,  //!< draw each point separately
1184         kLines_PointMode,   //!< draw each pair of points as a line segment
1185         kPolygon_PointMode, //!< draw the array of points as a open polygon
1186     };
1187 
1188     /** Draws pts using clip, SkMatrix and SkPaint paint.
1189         count is the number of points; if count is less than one, has no effect.
1190         mode may be one of: kPoints_PointMode, kLines_PointMode, or kPolygon_PointMode.
1191 
1192         If mode is kPoints_PointMode, the shape of point drawn depends on paint
1193         SkPaint::Cap. If paint is set to SkPaint::kRound_Cap, each point draws a
1194         circle of diameter SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap
1195         or SkPaint::kButt_Cap, each point draws a square of width and height
1196         SkPaint stroke width.
1197 
1198         If mode is kLines_PointMode, each pair of points draws a line segment.
1199         One line is drawn for every two points; each point is used once. If count is odd,
1200         the final point is ignored.
1201 
1202         If mode is kPolygon_PointMode, each adjacent pair of points draws a line segment.
1203         count minus one lines are drawn; the first and last point are used once.
1204 
1205         Each line segment respects paint SkPaint::Cap and SkPaint stroke width.
1206         SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
1207 
1208         Always draws each element one at a time; is not affected by
1209         SkPaint::Join, and unlike drawPath(), does not create a mask from all points
1210         and lines before drawing.
1211 
1212         @param mode   whether pts draws points or lines
1213         @param count  number of points in the array
1214         @param pts    array of points to draw
1215         @param paint  stroke, blend, color, and so on, used to draw
1216 
1217         example: https://fiddle.skia.org/c/@Canvas_drawPoints
1218     */
1219     void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
1220 
1221     /** Draws point at (x, y) using clip, SkMatrix and SkPaint paint.
1222 
1223         The shape of point drawn depends on paint SkPaint::Cap.
1224         If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
1225         SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
1226         draw a square of width and height SkPaint stroke width.
1227         SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
1228 
1229         @param x      left edge of circle or square
1230         @param y      top edge of circle or square
1231         @param paint  stroke, blend, color, and so on, used to draw
1232 
1233         example: https://fiddle.skia.org/c/@Canvas_drawPoint
1234     */
1235     void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
1236 
1237     /** Draws point p using clip, SkMatrix and SkPaint paint.
1238 
1239         The shape of point drawn depends on paint SkPaint::Cap.
1240         If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
1241         SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
1242         draw a square of width and height SkPaint stroke width.
1243         SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
1244 
1245         @param p      top-left edge of circle or square
1246         @param paint  stroke, blend, color, and so on, used to draw
1247     */
drawPoint(SkPoint p,const SkPaint & paint)1248     void drawPoint(SkPoint p, const SkPaint& paint) {
1249         this->drawPoint(p.x(), p.y(), paint);
1250     }
1251 
1252     /** Draws line segment from (x0, y0) to (x1, y1) using clip, SkMatrix, and SkPaint paint.
1253         In paint: SkPaint stroke width describes the line thickness;
1254         SkPaint::Cap draws the end rounded or square;
1255         SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
1256 
1257         @param x0     start of line segment on x-axis
1258         @param y0     start of line segment on y-axis
1259         @param x1     end of line segment on x-axis
1260         @param y1     end of line segment on y-axis
1261         @param paint  stroke, blend, color, and so on, used to draw
1262 
1263         example: https://fiddle.skia.org/c/@Canvas_drawLine
1264     */
1265     void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint);
1266 
1267     /** Draws line segment from p0 to p1 using clip, SkMatrix, and SkPaint paint.
1268         In paint: SkPaint stroke width describes the line thickness;
1269         SkPaint::Cap draws the end rounded or square;
1270         SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
1271 
1272         @param p0     start of line segment
1273         @param p1     end of line segment
1274         @param paint  stroke, blend, color, and so on, used to draw
1275     */
drawLine(SkPoint p0,SkPoint p1,const SkPaint & paint)1276     void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint) {
1277         this->drawLine(p0.x(), p0.y(), p1.x(), p1.y(), paint);
1278     }
1279 
1280     /** Draws SkRect rect using clip, SkMatrix, and SkPaint paint.
1281         In paint: SkPaint::Style determines if rectangle is stroked or filled;
1282         if stroked, SkPaint stroke width describes the line thickness, and
1283         SkPaint::Join draws the corners rounded or square.
1284 
1285         @param rect   rectangle to draw
1286         @param paint  stroke or fill, blend, color, and so on, used to draw
1287 
1288         example: https://fiddle.skia.org/c/@Canvas_drawRect
1289     */
1290     void drawRect(const SkRect& rect, const SkPaint& paint);
1291 
1292     /** Draws SkIRect rect using clip, SkMatrix, and SkPaint paint.
1293         In paint: SkPaint::Style determines if rectangle is stroked or filled;
1294         if stroked, SkPaint stroke width describes the line thickness, and
1295         SkPaint::Join draws the corners rounded or square.
1296 
1297         @param rect   rectangle to draw
1298         @param paint  stroke or fill, blend, color, and so on, used to draw
1299     */
drawIRect(const SkIRect & rect,const SkPaint & paint)1300     void drawIRect(const SkIRect& rect, const SkPaint& paint) {
1301         SkRect r;
1302         r.set(rect);    // promotes the ints to scalars
1303         this->drawRect(r, paint);
1304     }
1305 
1306     /** Draws SkRegion region using clip, SkMatrix, and SkPaint paint.
1307         In paint: SkPaint::Style determines if rectangle is stroked or filled;
1308         if stroked, SkPaint stroke width describes the line thickness, and
1309         SkPaint::Join draws the corners rounded or square.
1310 
1311         @param region  region to draw
1312         @param paint   SkPaint stroke or fill, blend, color, and so on, used to draw
1313 
1314         example: https://fiddle.skia.org/c/@Canvas_drawRegion
1315     */
1316     void drawRegion(const SkRegion& region, const SkPaint& paint);
1317 
1318     /** Draws oval oval using clip, SkMatrix, and SkPaint.
1319         In paint: SkPaint::Style determines if oval is stroked or filled;
1320         if stroked, SkPaint stroke width describes the line thickness.
1321 
1322         @param oval   SkRect bounds of oval
1323         @param paint  SkPaint stroke or fill, blend, color, and so on, used to draw
1324 
1325         example: https://fiddle.skia.org/c/@Canvas_drawOval
1326     */
1327     void drawOval(const SkRect& oval, const SkPaint& paint);
1328 
1329     /** Draws SkRRect rrect using clip, SkMatrix, and SkPaint paint.
1330         In paint: SkPaint::Style determines if rrect is stroked or filled;
1331         if stroked, SkPaint stroke width describes the line thickness.
1332 
1333         rrect may represent a rectangle, circle, oval, uniformly rounded rectangle, or
1334         may have any combination of positive non-square radii for the four corners.
1335 
1336         @param rrect  SkRRect with up to eight corner radii to draw
1337         @param paint  SkPaint stroke or fill, blend, color, and so on, used to draw
1338 
1339         example: https://fiddle.skia.org/c/@Canvas_drawRRect
1340     */
1341     void drawRRect(const SkRRect& rrect, const SkPaint& paint);
1342 
1343     /** Draws SkRRect outer and inner
1344         using clip, SkMatrix, and SkPaint paint.
1345         outer must contain inner or the drawing is undefined.
1346         In paint: SkPaint::Style determines if SkRRect is stroked or filled;
1347         if stroked, SkPaint stroke width describes the line thickness.
1348         If stroked and SkRRect corner has zero length radii, SkPaint::Join can
1349         draw corners rounded or square.
1350 
1351         GPU-backed platforms optimize drawing when both outer and inner are
1352         concave and outer contains inner. These platforms may not be able to draw
1353         SkPath built with identical data as fast.
1354 
1355         @param outer  SkRRect outer bounds to draw
1356         @param inner  SkRRect inner bounds to draw
1357         @param paint  SkPaint stroke or fill, blend, color, and so on, used to draw
1358 
1359         example: https://fiddle.skia.org/c/@Canvas_drawDRRect_a
1360         example: https://fiddle.skia.org/c/@Canvas_drawDRRect_b
1361     */
1362     void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
1363 
1364     /** Draws circle at (cx, cy) with radius using clip, SkMatrix, and SkPaint paint.
1365         If radius is zero or less, nothing is drawn.
1366         In paint: SkPaint::Style determines if circle is stroked or filled;
1367         if stroked, SkPaint stroke width describes the line thickness.
1368 
1369         @param cx      circle center on the x-axis
1370         @param cy      circle center on the y-axis
1371         @param radius  half the diameter of circle
1372         @param paint   SkPaint stroke or fill, blend, color, and so on, used to draw
1373 
1374         example: https://fiddle.skia.org/c/@Canvas_drawCircle
1375     */
1376     void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint);
1377 
1378     /** Draws circle at center with radius using clip, SkMatrix, and SkPaint paint.
1379         If radius is zero or less, nothing is drawn.
1380         In paint: SkPaint::Style determines if circle is stroked or filled;
1381         if stroked, SkPaint stroke width describes the line thickness.
1382 
1383         @param center  circle center
1384         @param radius  half the diameter of circle
1385         @param paint   SkPaint stroke or fill, blend, color, and so on, used to draw
1386     */
drawCircle(SkPoint center,SkScalar radius,const SkPaint & paint)1387     void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint) {
1388         this->drawCircle(center.x(), center.y(), radius, paint);
1389     }
1390 
1391     /** Draws arc using clip, SkMatrix, and SkPaint paint.
1392 
1393         Arc is part of oval bounded by oval, sweeping from startAngle to startAngle plus
1394         sweepAngle. startAngle and sweepAngle are in degrees.
1395 
1396         startAngle of zero places start point at the right middle edge of oval.
1397         A positive sweepAngle places arc end point clockwise from start point;
1398         a negative sweepAngle places arc end point counterclockwise from start point.
1399         sweepAngle may exceed 360 degrees, a full circle.
1400         If useCenter is true, draw a wedge that includes lines from oval
1401         center to arc end points. If useCenter is false, draw arc between end points.
1402 
1403         If SkRect oval is empty or sweepAngle is zero, nothing is drawn.
1404 
1405         @param oval        SkRect bounds of oval containing arc to draw
1406         @param startAngle  angle in degrees where arc begins
1407         @param sweepAngle  sweep angle in degrees; positive is clockwise
1408         @param useCenter   if true, include the center of the oval
1409         @param paint       SkPaint stroke or fill, blend, color, and so on, used to draw
1410     */
1411     void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
1412                  bool useCenter, const SkPaint& paint);
1413 
1414     /** Draws SkRRect bounded by SkRect rect, with corner radii (rx, ry) using clip,
1415         SkMatrix, and SkPaint paint.
1416 
1417         In paint: SkPaint::Style determines if SkRRect is stroked or filled;
1418         if stroked, SkPaint stroke width describes the line thickness.
1419         If rx or ry are less than zero, they are treated as if they are zero.
1420         If rx plus ry exceeds rect width or rect height, radii are scaled down to fit.
1421         If rx and ry are zero, SkRRect is drawn as SkRect and if stroked is affected by
1422         SkPaint::Join.
1423 
1424         @param rect   SkRect bounds of SkRRect to draw
1425         @param rx     axis length on x-axis of oval describing rounded corners
1426         @param ry     axis length on y-axis of oval describing rounded corners
1427         @param paint  stroke, blend, color, and so on, used to draw
1428 
1429         example: https://fiddle.skia.org/c/@Canvas_drawRoundRect
1430     */
1431     void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint);
1432 
1433     /** Draws SkPath path using clip, SkMatrix, and SkPaint paint.
1434         SkPath contains an array of path contour, each of which may be open or closed.
1435 
1436         In paint: SkPaint::Style determines if SkRRect is stroked or filled:
1437         if filled, SkPath::FillType determines whether path contour describes inside or
1438         outside of fill; if stroked, SkPaint stroke width describes the line thickness,
1439         SkPaint::Cap describes line ends, and SkPaint::Join describes how
1440         corners are drawn.
1441 
1442         @param path   SkPath to draw
1443         @param paint  stroke, blend, color, and so on, used to draw
1444 
1445         example: https://fiddle.skia.org/c/@Canvas_drawPath
1446     */
1447     void drawPath(const SkPath& path, const SkPaint& paint);
1448 
drawImage(const SkImage * image,SkScalar left,SkScalar top)1449     void drawImage(const SkImage* image, SkScalar left, SkScalar top) {
1450         this->drawImage(image, left, top, SkSamplingOptions(), nullptr);
1451     }
drawImage(const sk_sp<SkImage> & image,SkScalar left,SkScalar top)1452     void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top) {
1453         this->drawImage(image.get(), left, top, SkSamplingOptions(), nullptr);
1454     }
1455 
1456     /** \enum SkCanvas::SrcRectConstraint
1457         SrcRectConstraint controls the behavior at the edge of source SkRect,
1458         provided to drawImageRect() when there is any filtering. If kStrict is set,
1459         then extra code is used to ensure it nevers samples outside of the src-rect.
1460     */
1461     enum SrcRectConstraint {
1462         kStrict_SrcRectConstraint, //!< sample only inside bounds; slower
1463         kFast_SrcRectConstraint,   //!< sample outside bounds; faster
1464     };
1465 
1466     void drawImage(const SkImage*, SkScalar x, SkScalar y, const SkSamplingOptions&,
1467                    const SkPaint* = nullptr);
1468     void drawImage(const sk_sp<SkImage>& image, SkScalar x, SkScalar y,
1469                    const SkSamplingOptions& sampling, const SkPaint* paint = nullptr) {
1470         this->drawImage(image.get(), x, y, sampling, paint);
1471     }
1472     void drawImageRect(const SkImage*, const SkRect& src, const SkRect& dst,
1473                        const SkSamplingOptions&, const SkPaint*, SrcRectConstraint);
1474     void drawImageRect(const SkImage*, const SkRect& dst, const SkSamplingOptions&,
1475                        const SkPaint* = nullptr);
drawImageRect(const sk_sp<SkImage> & image,const SkRect & src,const SkRect & dst,const SkSamplingOptions & sampling,const SkPaint * paint,SrcRectConstraint constraint)1476     void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
1477                        const SkSamplingOptions& sampling, const SkPaint* paint,
1478                        SrcRectConstraint constraint) {
1479         this->drawImageRect(image.get(), src, dst, sampling, paint, constraint);
1480     }
1481     void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst,
1482                        const SkSamplingOptions& sampling, const SkPaint* paint = nullptr) {
1483         this->drawImageRect(image.get(), dst, sampling, paint);
1484     }
1485 
1486     /** Draws SkImage image stretched proportionally to fit into SkRect dst.
1487         SkIRect center divides the image into nine sections: four sides, four corners, and
1488         the center. Corners are unmodified or scaled down proportionately if their sides
1489         are larger than dst; center and four sides are scaled to fit remaining space, if any.
1490 
1491         Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
1492 
1493         If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
1494         SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
1495         If paint contains SkMaskFilter, generate mask from image bounds.
1496         Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.
1497 
1498         If generated mask extends beyond image bounds, replicate image edge colors, just
1499         as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
1500         replicates the image edge color when it samples outside of its bounds.
1501 
1502         @param image   SkImage containing pixels, dimensions, and format
1503         @param center  SkIRect edge of image corners and sides
1504         @param dst     destination SkRect of image to draw to
1505         @param filter  what technique to use when sampling the image
1506         @param paint   SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
1507                        and so on; or nullptr
1508     */
1509     void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
1510                        SkFilterMode filter, const SkPaint* paint = nullptr);
1511 
1512     /** \struct SkCanvas::Lattice
1513         SkCanvas::Lattice divides SkBitmap or SkImage into a rectangular grid.
1514         Grid entries on even columns and even rows are fixed; these entries are
1515         always drawn at their original size if the destination is large enough.
1516         If the destination side is too small to hold the fixed entries, all fixed
1517         entries are proportionately scaled down to fit.
1518         The grid entries not on even columns and rows are scaled to fit the
1519         remaining space, if any.
1520     */
1521     struct Lattice {
1522 
1523         /** \enum SkCanvas::Lattice::RectType
1524             Optional setting per rectangular grid entry to make it transparent,
1525             or to fill the grid entry with a color.
1526         */
1527         enum RectType : uint8_t {
1528             kDefault     = 0, //!< draws SkBitmap into lattice rectangle
1529             kTransparent,     //!< skips lattice rectangle by making it transparent
1530             kFixedColor,      //!< draws one of fColors into lattice rectangle
1531         };
1532 
1533         const int*      fXDivs;     //!< x-axis values dividing bitmap
1534         const int*      fYDivs;     //!< y-axis values dividing bitmap
1535         const RectType* fRectTypes; //!< array of fill types
1536         int             fXCount;    //!< number of x-coordinates
1537         int             fYCount;    //!< number of y-coordinates
1538         const SkIRect*  fBounds;    //!< source bounds to draw from
1539         const SkColor*  fColors;    //!< array of colors
1540     };
1541 
1542     /** Draws SkImage image stretched proportionally to fit into SkRect dst.
1543 
1544         SkCanvas::Lattice lattice divides image into a rectangular grid.
1545         Each intersection of an even-numbered row and column is fixed;
1546         fixed lattice elements never scale larger than their initial
1547         size and shrink proportionately when all fixed elements exceed the bitmap
1548         dimension. All other grid elements scale to fill the available space, if any.
1549 
1550         Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
1551 
1552         If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
1553         SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
1554         If paint contains SkMaskFilter, generate mask from image bounds.
1555         Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.
1556 
1557         If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
1558         just as SkShader made from SkShader::MakeBitmapShader with
1559         SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
1560         outside of its bounds.
1561 
1562         @param image    SkImage containing pixels, dimensions, and format
1563         @param lattice  division of bitmap into fixed and variable rectangles
1564         @param dst      destination SkRect of image to draw to
1565         @param filter   what technique to use when sampling the image
1566         @param paint    SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
1567                         and so on; or nullptr
1568     */
1569     void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
1570                           SkFilterMode filter, const SkPaint* paint = nullptr);
drawImageLattice(const SkImage * image,const Lattice & lattice,const SkRect & dst)1571     void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst) {
1572         this->drawImageLattice(image, lattice, dst, SkFilterMode::kNearest, nullptr);
1573     }
1574 
1575     /**
1576      * Experimental. Controls anti-aliasing of each edge of images in an image-set.
1577      */
1578     enum QuadAAFlags : unsigned {
1579         kLeft_QuadAAFlag    = 0b0001,
1580         kTop_QuadAAFlag     = 0b0010,
1581         kRight_QuadAAFlag   = 0b0100,
1582         kBottom_QuadAAFlag  = 0b1000,
1583 
1584         kNone_QuadAAFlags   = 0b0000,
1585         kAll_QuadAAFlags    = 0b1111,
1586     };
1587 
1588     /** This is used by the experimental API below. */
1589     struct SK_API ImageSetEntry {
1590         ImageSetEntry(sk_sp<const SkImage> image, const SkRect& srcRect, const SkRect& dstRect,
1591                       int matrixIndex, float alpha, unsigned aaFlags, bool hasClip);
1592 
1593         ImageSetEntry(sk_sp<const SkImage> image, const SkRect& srcRect, const SkRect& dstRect,
1594                       float alpha, unsigned aaFlags);
1595 
1596         ImageSetEntry();
1597         ~ImageSetEntry();
1598         ImageSetEntry(const ImageSetEntry&);
1599         ImageSetEntry& operator=(const ImageSetEntry&);
1600 
1601         sk_sp<const SkImage> fImage;
1602         SkRect fSrcRect;
1603         SkRect fDstRect;
1604         int fMatrixIndex = -1; // Index into the preViewMatrices arg, or < 0
1605         float fAlpha = 1.f;
1606         unsigned fAAFlags = kNone_QuadAAFlags; // QuadAAFlags
1607         bool fHasClip = false; // True to use next 4 points in dstClip arg as quad
1608     };
1609 
1610     /**
1611      * This is an experimental API for the SkiaRenderer Chromium project, and its API will surely
1612      * evolve if it is not removed outright.
1613      *
1614      * This behaves very similarly to drawRect() combined with a clipPath() formed by clip
1615      * quadrilateral. 'rect' and 'clip' are in the same coordinate space. If 'clip' is null, then it
1616      * is as if the rectangle was not clipped (or, alternatively, clipped to itself). If not null,
1617      * then it must provide 4 points.
1618      *
1619      * In addition to combining the draw and clipping into one operation, this function adds the
1620      * additional capability of controlling each of the rectangle's edges anti-aliasing
1621      * independently.  The edges of the clip will respect the per-edge AA flags. It is required that
1622      * 'clip' be contained inside 'rect'. In terms of mapping to edge labels, the 'clip' points
1623      * should be ordered top-left, top-right, bottom-right, bottom-left so that the edge between [0]
1624      * and [1] is "top", [1] and [2] is "right", [2] and [3] is "bottom", and [3] and [0] is "left".
1625      * This ordering matches SkRect::toQuad().
1626      *
1627      * This API only draws solid color, filled rectangles so it does not accept a full SkPaint.
1628      */
1629     void experimental_DrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], QuadAAFlags aaFlags,
1630                                      const SkColor4f& color, SkBlendMode mode);
experimental_DrawEdgeAAQuad(const SkRect & rect,const SkPoint clip[4],QuadAAFlags aaFlags,SkColor color,SkBlendMode mode)1631     void experimental_DrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], QuadAAFlags aaFlags,
1632                                      SkColor color, SkBlendMode mode) {
1633         this->experimental_DrawEdgeAAQuad(rect, clip, aaFlags, SkColor4f::FromColor(color), mode);
1634     }
1635 
1636     /**
1637      * This is an bulk variant of experimental_DrawEdgeAAQuad() that renders 'cnt' textured quads.
1638      * For each entry, 'fDstRect' is rendered with its clip (determined by entry's 'fHasClip' and
1639      * the current index in 'dstClip'). The entry's fImage is applied to the destination rectangle
1640      * by sampling from 'fSrcRect' sub-image.  The corners of 'fSrcRect' map to the corners of
1641      * 'fDstRect', just like in drawImageRect(), and they will be properly interpolated when
1642      * applying a clip.
1643      *
1644      * Like experimental_DrawEdgeAAQuad(), each entry can specify edge AA flags that apply to both
1645      * the destination rect and its clip.
1646      *
1647      * If provided, the 'dstClips' array must have length equal 4 * the number of entries with
1648      * fHasClip true. If 'dstClips' is null, every entry must have 'fHasClip' set to false. The
1649      * destination clip coordinates will be read consecutively with the image set entries, advancing
1650      * by 4 points every time an entry with fHasClip is passed.
1651      *
1652      * This entry point supports per-entry manipulations to the canvas's current matrix. If an
1653      * entry provides 'fMatrixIndex' >= 0, it will be drawn as if the canvas's CTM was
1654      * canvas->getTotalMatrix() * preViewMatrices[fMatrixIndex]. If 'fMatrixIndex' is less than 0,
1655      * the pre-view matrix transform is implicitly the identity, so it will be drawn using just the
1656      * current canvas matrix. The pre-view matrix modifies the canvas's view matrix, it does not
1657      * affect the local coordinates of each entry.
1658      *
1659      * An optional paint may be provided, which supports the same subset of features usable with
1660      * drawImageRect (i.e. assumed to be filled and no path effects). When a paint is provided, the
1661      * image set is drawn as if each image used the applied paint independently, so each is affected
1662      * by the image, color, and/or mask filter.
1663      */
1664     void experimental_DrawEdgeAAImageSet(const ImageSetEntry imageSet[], int cnt,
1665                                          const SkPoint dstClips[], const SkMatrix preViewMatrices[],
1666                                          const SkSamplingOptions&, const SkPaint* paint = nullptr,
1667                                          SrcRectConstraint constraint = kStrict_SrcRectConstraint);
1668 
1669     /** Draws text, with origin at (x, y), using clip, SkMatrix, SkFont font,
1670         and SkPaint paint.
1671 
1672         When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
1673         SkTextEncoding::kUTF32, this function uses the default
1674         character-to-glyph mapping from the SkTypeface in font.  It does not
1675         perform typeface fallback for characters not found in the SkTypeface.
1676         It does not perform kerning or other complex shaping; glyphs are
1677         positioned based on their default advances.
1678 
1679         Text meaning depends on SkTextEncoding.
1680 
1681         Text size is affected by SkMatrix and SkFont text size. Default text
1682         size is 12 point.
1683 
1684         All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
1685         SkColorFilter, and SkImageFilter; apply to text. By
1686         default, draws filled black glyphs.
1687 
1688         @param text        character code points or glyphs drawn
1689         @param byteLength  byte length of text array
1690         @param encoding    text encoding used in the text array
1691         @param x           start of text on x-axis
1692         @param y           start of text on y-axis
1693         @param font        typeface, text size and so, used to describe the text
1694         @param paint       blend, color, and so on, used to draw
1695     */
1696     void drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding,
1697                         SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint);
1698 
1699     /** Draws null terminated string, with origin at (x, y), using clip, SkMatrix,
1700         SkFont font, and SkPaint paint.
1701 
1702         This function uses the default character-to-glyph mapping from the
1703         SkTypeface in font.  It does not perform typeface fallback for
1704         characters not found in the SkTypeface.  It does not perform kerning;
1705         glyphs are positioned based on their default advances.
1706 
1707         String str is encoded as UTF-8.
1708 
1709         Text size is affected by SkMatrix and font text size. Default text
1710         size is 12 point.
1711 
1712         All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
1713         SkColorFilter, and SkImageFilter; apply to text. By
1714         default, draws filled black glyphs.
1715 
1716         @param str     character code points drawn,
1717                        ending with a char value of zero
1718         @param x       start of string on x-axis
1719         @param y       start of string on y-axis
1720         @param font    typeface, text size and so, used to describe the text
1721         @param paint   blend, color, and so on, used to draw
1722     */
drawString(const char str[],SkScalar x,SkScalar y,const SkFont & font,const SkPaint & paint)1723     void drawString(const char str[], SkScalar x, SkScalar y, const SkFont& font,
1724                     const SkPaint& paint) {
1725         this->drawSimpleText(str, strlen(str), SkTextEncoding::kUTF8, x, y, font, paint);
1726     }
1727 
1728     /** Draws SkString, with origin at (x, y), using clip, SkMatrix, SkFont font,
1729         and SkPaint paint.
1730 
1731         This function uses the default character-to-glyph mapping from the
1732         SkTypeface in font.  It does not perform typeface fallback for
1733         characters not found in the SkTypeface.  It does not perform kerning;
1734         glyphs are positioned based on their default advances.
1735 
1736         SkString str is encoded as UTF-8.
1737 
1738         Text size is affected by SkMatrix and SkFont text size. Default text
1739         size is 12 point.
1740 
1741         All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
1742         SkColorFilter, and SkImageFilter; apply to text. By
1743         default, draws filled black glyphs.
1744 
1745         @param str     character code points drawn,
1746                        ending with a char value of zero
1747         @param x       start of string on x-axis
1748         @param y       start of string on y-axis
1749         @param font    typeface, text size and so, used to describe the text
1750         @param paint   blend, color, and so on, used to draw
1751     */
drawString(const SkString & str,SkScalar x,SkScalar y,const SkFont & font,const SkPaint & paint)1752     void drawString(const SkString& str, SkScalar x, SkScalar y, const SkFont& font,
1753                     const SkPaint& paint) {
1754         this->drawSimpleText(str.c_str(), str.size(), SkTextEncoding::kUTF8, x, y, font, paint);
1755     }
1756 
1757     /** Draws count glyphs, at positions relative to origin styled with font and paint with
1758         supporting utf8 and cluster information.
1759 
1760        This function draw glyphs at the given positions relative to the given origin.
1761        It does not perform typeface fallback for glyphs not found in the SkTypeface in font.
1762 
1763        The drawing obeys the current transform matrix and clipping.
1764 
1765        All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
1766        SkColorFilter, and SkImageFilter; apply to text. By
1767        default, draws filled black glyphs.
1768 
1769        @param count           number of glyphs to draw
1770        @param glyphs          the array of glyphIDs to draw
1771        @param positions       where to draw each glyph relative to origin
1772        @param clusters        array of size count of cluster information
1773        @param textByteCount   size of the utf8text
1774        @param utf8text        utf8text supporting information for the glyphs
1775        @param origin          the origin of all the positions
1776        @param font            typeface, text size and so, used to describe the text
1777        @param paint           blend, color, and so on, used to draw
1778     */
1779     void drawGlyphs(int count, const SkGlyphID glyphs[], const SkPoint positions[],
1780                     const uint32_t clusters[], int textByteCount, const char utf8text[],
1781                     SkPoint origin, const SkFont& font, const SkPaint& paint);
1782 
1783     /** Draws count glyphs, at positions relative to origin styled with font and paint.
1784 
1785         This function draw glyphs at the given positions relative to the given origin.
1786         It does not perform typeface fallback for glyphs not found in the SkTypeface in font.
1787 
1788         The drawing obeys the current transform matrix and clipping.
1789 
1790         All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
1791         SkColorFilter, and SkImageFilter; apply to text. By
1792         default, draws filled black glyphs.
1793 
1794         @param count       number of glyphs to draw
1795         @param glyphs      the array of glyphIDs to draw
1796         @param positions   where to draw each glyph relative to origin
1797         @param origin      the origin of all the positions
1798         @param font        typeface, text size and so, used to describe the text
1799         @param paint       blend, color, and so on, used to draw
1800     */
1801     void drawGlyphs(int count, const SkGlyphID glyphs[], const SkPoint positions[],
1802                     SkPoint origin, const SkFont& font, const SkPaint& paint);
1803 
1804     /** Draws count glyphs, at positions relative to origin styled with font and paint.
1805 
1806         This function draw glyphs using the given scaling and rotations. They are positioned
1807         relative to the given origin. It does not perform typeface fallback for glyphs not found
1808         in the SkTypeface in font.
1809 
1810         The drawing obeys the current transform matrix and clipping.
1811 
1812         All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
1813         SkColorFilter, and SkImageFilter; apply to text. By
1814         default, draws filled black glyphs.
1815 
1816         @param count    number of glyphs to draw
1817         @param glyphs   the array of glyphIDs to draw
1818         @param xforms   where to draw and orient each glyph
1819         @param origin   the origin of all the positions
1820         @param font     typeface, text size and so, used to describe the text
1821         @param paint    blend, color, and so on, used to draw
1822     */
1823     void drawGlyphs(int count, const SkGlyphID glyphs[], const SkRSXform xforms[],
1824                     SkPoint origin, const SkFont& font, const SkPaint& paint);
1825 
1826     /** Draws SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint.
1827 
1828         blob contains glyphs, their positions, and paint attributes specific to text:
1829         SkTypeface, SkPaint text size, SkPaint text scale x,
1830         SkPaint text skew x, SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold,
1831         SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text,
1832         and SkPaint subpixel text.
1833 
1834         SkTextEncoding must be set to SkTextEncoding::kGlyphID.
1835 
1836         Elements of paint: anti-alias, SkBlendMode, color including alpha,
1837         SkColorFilter, SkPaint dither, SkMaskFilter, SkPathEffect, SkShader, and
1838         SkPaint::Style; apply to blob. If SkPaint contains SkPaint::kStroke_Style:
1839         SkPaint miter limit, SkPaint::Cap, SkPaint::Join, and SkPaint stroke width;
1840         apply to SkPath created from blob.
1841 
1842         @param blob   glyphs, positions, and their paints' text size, typeface, and so on
1843         @param x      horizontal offset applied to blob
1844         @param y      vertical offset applied to blob
1845         @param paint  blend, color, stroking, and so on, used to draw
1846 
1847         example: https://fiddle.skia.org/c/@Canvas_drawTextBlob
1848     */
1849     void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
1850 
1851     /** Draws SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint.
1852 
1853         blob contains glyphs, their positions, and paint attributes specific to text:
1854         SkTypeface, SkPaint text size, SkPaint text scale x,
1855         SkPaint text skew x, SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold,
1856         SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text,
1857         and SkPaint subpixel text.
1858 
1859         SkTextEncoding must be set to SkTextEncoding::kGlyphID.
1860 
1861         Elements of paint: SkPathEffect, SkMaskFilter, SkShader, SkColorFilter,
1862         and SkImageFilter; apply to blob.
1863 
1864         @param blob   glyphs, positions, and their paints' text size, typeface, and so on
1865         @param x      horizontal offset applied to blob
1866         @param y      vertical offset applied to blob
1867         @param paint  blend, color, stroking, and so on, used to draw
1868     */
drawTextBlob(const sk_sp<SkTextBlob> & blob,SkScalar x,SkScalar y,const SkPaint & paint)1869     void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint) {
1870         this->drawTextBlob(blob.get(), x, y, paint);
1871     }
1872 
1873     /** Draws HMSymbol at locate wih paint.
1874         @param symbol  HMSymbol information
1875         @param locate  draw locate
1876         @param paint  blend, color, stroking, and so on, used to draw
1877     */
drawSymbol(const HMSymbolData & symbol,SkPoint locate,const SkPaint & paint)1878     void drawSymbol(const HMSymbolData& symbol, SkPoint locate, const SkPaint& paint) {
1879         this->onDrawSymbol(symbol, locate, paint);
1880     }
1881 
1882     /** Draws SkPicture picture, using clip and SkMatrix.
1883         Clip and SkMatrix are unchanged by picture contents, as if
1884         save() was called before and restore() was called after drawPicture().
1885 
1886         SkPicture records a series of draw commands for later playback.
1887 
1888         @param picture  recorded drawing commands to play
1889     */
drawPicture(const SkPicture * picture)1890     void drawPicture(const SkPicture* picture) {
1891         this->drawPicture(picture, nullptr, nullptr);
1892     }
1893 
1894     /** Draws SkPicture picture, using clip and SkMatrix.
1895         Clip and SkMatrix are unchanged by picture contents, as if
1896         save() was called before and restore() was called after drawPicture().
1897 
1898         SkPicture records a series of draw commands for later playback.
1899 
1900         @param picture  recorded drawing commands to play
1901     */
drawPicture(const sk_sp<SkPicture> & picture)1902     void drawPicture(const sk_sp<SkPicture>& picture) {
1903         this->drawPicture(picture.get());
1904     }
1905 
1906     /** Draws SkPicture picture, using clip and SkMatrix; transforming picture with
1907         SkMatrix matrix, if provided; and use SkPaint paint alpha, SkColorFilter,
1908         SkImageFilter, and SkBlendMode, if provided.
1909 
1910         If paint is non-null, then the picture is always drawn into a temporary layer before
1911         actually landing on the canvas. Note that drawing into a layer can also change its
1912         appearance if there are any non-associative blendModes inside any of the pictures elements.
1913 
1914         @param picture  recorded drawing commands to play
1915         @param matrix   SkMatrix to rotate, scale, translate, and so on; may be nullptr
1916         @param paint    SkPaint to apply transparency, filtering, and so on; may be nullptr
1917 
1918         example: https://fiddle.skia.org/c/@Canvas_drawPicture_3
1919     */
1920     void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint);
1921 
1922     /** Draws SkPicture picture, using clip and SkMatrix; transforming picture with
1923         SkMatrix matrix, if provided; and use SkPaint paint alpha, SkColorFilter,
1924         SkImageFilter, and SkBlendMode, if provided.
1925 
1926         If paint is non-null, then the picture is always drawn into a temporary layer before
1927         actually landing on the canvas. Note that drawing into a layer can also change its
1928         appearance if there are any non-associative blendModes inside any of the pictures elements.
1929 
1930         @param picture  recorded drawing commands to play
1931         @param matrix   SkMatrix to rotate, scale, translate, and so on; may be nullptr
1932         @param paint    SkPaint to apply transparency, filtering, and so on; may be nullptr
1933     */
drawPicture(const sk_sp<SkPicture> & picture,const SkMatrix * matrix,const SkPaint * paint)1934     void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix,
1935                      const SkPaint* paint) {
1936         this->drawPicture(picture.get(), matrix, paint);
1937     }
1938 
1939     /** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix.
1940         If paint contains an SkShader and vertices does not contain texCoords, the shader
1941         is mapped using the vertices' positions.
1942 
1943         If vertices colors are defined in vertices, and SkPaint paint contains SkShader,
1944         SkBlendMode mode combines vertices colors with SkShader.
1945 
1946         SkMaskFilter and SkPathEffect on paint are ignored.
1947 
1948         @param vertices  triangle mesh to draw
1949         @param mode      combines vertices colors with SkShader, if both are present
1950         @param paint     specifies the SkShader, used as SkVertices texture; may be nullptr
1951 
1952         example: https://fiddle.skia.org/c/@Canvas_drawVertices
1953     */
1954     void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint);
1955 
1956     /** Variant of 3-parameter drawVertices, using the default of Modulate for the blend
1957      *  parameter. Note that SkVertices that include per-vertex-data ignore this mode parameter.
1958      */
drawVertices(const SkVertices * vertices,const SkPaint & paint)1959     void drawVertices(const SkVertices* vertices, const SkPaint& paint) {
1960         this->drawVertices(vertices, SkBlendMode::kModulate, paint);
1961     }
1962 
1963     /** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix.
1964         If paint contains an SkShader and vertices does not contain texCoords, the shader
1965         is mapped using the vertices' positions.
1966 
1967         If vertices colors are defined in vertices, and SkPaint paint contains SkShader,
1968         SkBlendMode mode combines vertices colors with SkShader.
1969 
1970         SkMaskFilter and SkPathEffect on paint are ignored.
1971 
1972         @param vertices  triangle mesh to draw
1973         @param mode      combines vertices colors with SkShader, if both are present
1974         @param paint     specifies the SkShader, used as SkVertices texture, may be nullptr
1975 
1976         example: https://fiddle.skia.org/c/@Canvas_drawVertices_2
1977     */
1978     void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint);
1979 
1980     /** Variant of 3-parameter drawVertices, using the default of Modulate for the blend
1981      *  parameter. Note that SkVertices that include per-vertex-data ignore this mode parameter.
1982      */
drawVertices(const sk_sp<SkVertices> & vertices,const SkPaint & paint)1983     void drawVertices(const sk_sp<SkVertices>& vertices, const SkPaint& paint) {
1984         this->drawVertices(vertices, SkBlendMode::kModulate, paint);
1985     }
1986 
1987     /** Draws a Coons patch: the interpolation of four cubics with shared corners,
1988         associating a color, and optionally a texture SkPoint, with each corner.
1989 
1990         Coons patch uses clip and SkMatrix, paint SkShader, SkColorFilter,
1991         alpha, SkImageFilter, and SkBlendMode. If SkShader is provided it is treated
1992         as Coons patch texture; SkBlendMode mode combines color colors and SkShader if
1993         both are provided.
1994 
1995         SkPoint array cubics specifies four SkPath cubic starting at the top-left corner,
1996         in clockwise order, sharing every fourth point. The last SkPath cubic ends at the
1997         first point.
1998 
1999         Color array color associates colors with corners in top-left, top-right,
2000         bottom-right, bottom-left order.
2001 
2002         If paint contains SkShader, SkPoint array texCoords maps SkShader as texture to
2003         corners in top-left, top-right, bottom-right, bottom-left order. If texCoords is
2004         nullptr, SkShader is mapped using positions (derived from cubics).
2005 
2006         SkMaskFilter and SkPathEffect on paint are ignored.
2007 
2008         @param cubics     SkPath cubic array, sharing common points
2009         @param colors     color array, one for each corner
2010         @param texCoords  SkPoint array of texture coordinates, mapping SkShader to corners;
2011                           may be nullptr
2012         @param mode       SkBlendMode for colors, and for SkShader if paint has one
2013         @param paint      SkShader, SkColorFilter, SkBlendMode, used to draw
2014     */
2015     void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2016                    const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
2017 
2018     /** Draws SkPath cubic Coons patch: the interpolation of four cubics with shared corners,
2019         associating a color, and optionally a texture SkPoint, with each corner.
2020 
2021         Coons patch uses clip and SkMatrix, paint SkShader, SkColorFilter,
2022         alpha, SkImageFilter, and SkBlendMode. If SkShader is provided it is treated
2023         as Coons patch texture; SkBlendMode mode combines color colors and SkShader if
2024         both are provided.
2025 
2026         SkPoint array cubics specifies four SkPath cubic starting at the top-left corner,
2027         in clockwise order, sharing every fourth point. The last SkPath cubic ends at the
2028         first point.
2029 
2030         Color array color associates colors with corners in top-left, top-right,
2031         bottom-right, bottom-left order.
2032 
2033         If paint contains SkShader, SkPoint array texCoords maps SkShader as texture to
2034         corners in top-left, top-right, bottom-right, bottom-left order. If texCoords is
2035         nullptr, SkShader is mapped using positions (derived from cubics).
2036 
2037         SkMaskFilter and SkPathEffect on paint are ignored.
2038 
2039         @param cubics     SkPath cubic array, sharing common points
2040         @param colors     color array, one for each corner
2041         @param texCoords  SkPoint array of texture coordinates, mapping SkShader to corners;
2042                           may be nullptr
2043         @param paint      SkShader, SkColorFilter, SkBlendMode, used to draw
2044     */
drawPatch(const SkPoint cubics[12],const SkColor colors[4],const SkPoint texCoords[4],const SkPaint & paint)2045     void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
2046                    const SkPoint texCoords[4], const SkPaint& paint) {
2047         this->drawPatch(cubics, colors, texCoords, SkBlendMode::kModulate, paint);
2048     }
2049 
2050     /** Draws a set of sprites from atlas, using clip, SkMatrix, and optional SkPaint paint.
2051         paint uses anti-alias, alpha, SkColorFilter, SkImageFilter, and SkBlendMode
2052         to draw, if present. For each entry in the array, SkRect tex locates sprite in
2053         atlas, and SkRSXform xform transforms it into destination space.
2054 
2055         SkMaskFilter and SkPathEffect on paint are ignored.
2056 
2057         xform, tex, and colors if present, must contain count entries.
2058         Optional colors are applied for each sprite using SkBlendMode mode, treating
2059         sprite as source and colors as destination.
2060         Optional cullRect is a conservative bounds of all transformed sprites.
2061         If cullRect is outside of clip, canvas can skip drawing.
2062 
2063         If atlas is nullptr, this draws nothing.
2064 
2065         @param atlas     SkImage containing sprites
2066         @param xform     SkRSXform mappings for sprites in atlas
2067         @param tex       SkRect locations of sprites in atlas
2068         @param colors    one per sprite, blended with sprite using SkBlendMode; may be nullptr
2069         @param count     number of sprites to draw
2070         @param mode      SkBlendMode combining colors and sprites
2071         @param sampling  SkSamplingOptions used when sampling from the atlas image
2072         @param cullRect  bounds of transformed sprites for efficient clipping; may be nullptr
2073         @param paint     SkColorFilter, SkImageFilter, SkBlendMode, and so on; may be nullptr
2074     */
2075     void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
2076                    const SkColor colors[], int count, SkBlendMode mode,
2077                    const SkSamplingOptions& sampling, const SkRect* cullRect, const SkPaint* paint);
2078 
2079     /** Draws SkDrawable drawable using clip and SkMatrix, concatenated with
2080         optional matrix.
2081 
2082         If SkCanvas has an asynchronous implementation, as is the case
2083         when it is recording into SkPicture, then drawable will be referenced,
2084         so that SkDrawable::draw() can be called when the operation is finalized. To force
2085         immediate drawing, call SkDrawable::draw() instead.
2086 
2087         @param drawable  custom struct encapsulating drawing commands
2088         @param matrix    transformation applied to drawing; may be nullptr
2089 
2090         example: https://fiddle.skia.org/c/@Canvas_drawDrawable
2091     */
2092     void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr);
2093 
2094     /** Draws SkDrawable drawable using clip and SkMatrix, offset by (x, y).
2095 
2096         If SkCanvas has an asynchronous implementation, as is the case
2097         when it is recording into SkPicture, then drawable will be referenced,
2098         so that SkDrawable::draw() can be called when the operation is finalized. To force
2099         immediate drawing, call SkDrawable::draw() instead.
2100 
2101         @param drawable  custom struct encapsulating drawing commands
2102         @param x         offset into SkCanvas writable pixels on x-axis
2103         @param y         offset into SkCanvas writable pixels on y-axis
2104 
2105         example: https://fiddle.skia.org/c/@Canvas_drawDrawable_2
2106     */
2107     void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y);
2108 
2109     /** Associates SkRect on SkCanvas with an annotation; a key-value pair, where the key is
2110         a null-terminated UTF-8 string, and optional value is stored as SkData.
2111 
2112         Only some canvas implementations, such as recording to SkPicture, or drawing to
2113         document PDF, use annotations.
2114 
2115         @param rect   SkRect extent of canvas to annotate
2116         @param key    string used for lookup
2117         @param value  data holding value stored in annotation
2118 
2119         example: https://fiddle.skia.org/c/@Canvas_drawAnnotation_2
2120     */
2121     void drawAnnotation(const SkRect& rect, const char key[], SkData* value);
2122 
2123     /** Associates SkRect on SkCanvas when an annotation; a key-value pair, where the key is
2124         a null-terminated UTF-8 string, and optional value is stored as SkData.
2125 
2126         Only some canvas implementations, such as recording to SkPicture, or drawing to
2127         document PDF, use annotations.
2128 
2129         @param rect   SkRect extent of canvas to annotate
2130         @param key    string used for lookup
2131         @param value  data holding value stored in annotation
2132     */
drawAnnotation(const SkRect & rect,const char key[],const sk_sp<SkData> & value)2133     void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) {
2134         this->drawAnnotation(rect, key, value.get());
2135     }
2136 
2137     /** Returns true if clip is empty; that is, nothing will draw.
2138 
2139         May do work when called; it should not be called
2140         more often than needed. However, once called, subsequent calls perform no
2141         work until clip changes.
2142 
2143         @return  true if clip is empty
2144 
2145         example: https://fiddle.skia.org/c/@Canvas_isClipEmpty
2146     */
2147     virtual bool isClipEmpty() const;
2148 
2149     /** Returns true if clip is SkRect and not empty.
2150         Returns false if the clip is empty, or if it is not SkRect.
2151 
2152         @return  true if clip is SkRect and not empty
2153 
2154         example: https://fiddle.skia.org/c/@Canvas_isClipRect
2155     */
2156     virtual bool isClipRect() const;
2157 
2158     /** Returns the current transform from local coordinates to the 'device', which for most
2159      *  purposes means pixels.
2160      *
2161      *  @return transformation from local coordinates to device / pixels.
2162      */
2163     SkM44 getLocalToDevice() const;
2164 
2165     /**
2166      *  Throws away the 3rd row and column in the matrix, so be warned.
2167      */
getLocalToDeviceAs3x3()2168     SkMatrix getLocalToDeviceAs3x3() const {
2169         return this->getLocalToDevice().asM33();
2170     }
2171 
2172 #ifdef SK_SUPPORT_LEGACY_GETTOTALMATRIX
2173     /** DEPRECATED
2174      *  Legacy version of getLocalToDevice(), which strips away any Z information, and
2175      *  just returns a 3x3 version.
2176      *
2177      *  @return 3x3 version of getLocalToDevice()
2178      *
2179      *  example: https://fiddle.skia.org/c/@Canvas_getTotalMatrix
2180      *  example: https://fiddle.skia.org/c/@Clip
2181      */
2182     SkMatrix getTotalMatrix() const;
2183 #endif
2184 
2185     ///////////////////////////////////////////////////////////////////////////
2186 
2187 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && SK_SUPPORT_GPU
2188     // These methods exist to support WebView in Android Framework.
2189     SkIRect topLayerBounds() const;
2190     GrBackendRenderTarget topLayerBackendRenderTarget() const;
2191 #endif
2192 
2193     /**
2194      *  Returns the global clip as a region. If the clip contains AA, then only the bounds
2195      *  of the clip may be returned.
2196      */
2197     void temporary_internal_getRgnClip(SkRegion* region);
2198 
2199     void private_draw_shadow_rec(const SkPath&, const SkDrawShadowRec&);
2200 
2201 
2202 protected:
2203     // default impl defers to getDevice()->newSurface(info)
2204     virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props);
2205 
2206     // default impl defers to its device
2207     virtual bool onPeekPixels(SkPixmap* pixmap);
2208     virtual bool onAccessTopLayerPixels(SkPixmap* pixmap);
2209     virtual SkImageInfo onImageInfo() const;
2210     virtual bool onGetProps(SkSurfaceProps* props) const;
2211     virtual void onFlush();
2212 
2213     // Subclass save/restore notifiers.
2214     // Overriders should call the corresponding INHERITED method up the inheritance chain.
2215     // getSaveLayerStrategy()'s return value may suppress full layer allocation.
2216     enum SaveLayerStrategy {
2217         kFullLayer_SaveLayerStrategy,
2218         kNoLayer_SaveLayerStrategy,
2219     };
2220 
willSave()2221     virtual void willSave() {}
2222     // Overriders should call the corresponding INHERITED method up the inheritance chain.
getSaveLayerStrategy(const SaveLayerRec &)2223     virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& ) {
2224         return kFullLayer_SaveLayerStrategy;
2225     }
2226 
2227     // returns true if we should actually perform the saveBehind, or false if we should just save.
onDoSaveBehind(const SkRect *)2228     virtual bool onDoSaveBehind(const SkRect*) { return true; }
willRestore()2229     virtual void willRestore() {}
didRestore()2230     virtual void didRestore() {}
2231 
onMarkCTM(const char *)2232     virtual void onMarkCTM(const char*) {}
didConcat44(const SkM44 &)2233     virtual void didConcat44(const SkM44&) {}
didSetM44(const SkM44 &)2234     virtual void didSetM44(const SkM44&) {}
didTranslate(SkScalar,SkScalar)2235     virtual void didTranslate(SkScalar, SkScalar) {}
didScale(SkScalar,SkScalar)2236     virtual void didScale(SkScalar, SkScalar) {}
2237 
2238     // NOTE: If you are adding a new onDraw virtual to SkCanvas, PLEASE add an override to
2239     // SkCanvasVirtualEnforcer (in SkCanvasVirtualEnforcer.h). This ensures that subclasses using
2240     // that mechanism  will be required to implement the new function.
2241     virtual void onDrawPaint(const SkPaint& paint);
2242     virtual void onDrawBehind(const SkPaint& paint);
2243     virtual void onDrawRect(const SkRect& rect, const SkPaint& paint);
2244     virtual void onDrawRRect(const SkRRect& rrect, const SkPaint& paint);
2245     virtual void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
2246     virtual void onDrawOval(const SkRect& rect, const SkPaint& paint);
2247     virtual void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
2248                            bool useCenter, const SkPaint& paint);
2249     virtual void onDrawPath(const SkPath& path, const SkPaint& paint);
2250     virtual void onDrawRegion(const SkRegion& region, const SkPaint& paint);
2251 
2252     virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
2253                                 const SkPaint& paint);
2254 
onDrawSymbol(const HMSymbolData & symbol,SkPoint locate,const SkPaint & paint)2255     virtual void onDrawSymbol(const HMSymbolData& symbol, SkPoint locate, const SkPaint& paint) {}
2256 
2257     virtual void onDrawGlyphRunList(const SkGlyphRunList& glyphRunList, const SkPaint& paint);
2258 
2259     virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
2260                            const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
2261     virtual void onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
2262                               const SkPaint& paint);
2263 
2264     virtual void onDrawImage2(const SkImage*, SkScalar dx, SkScalar dy, const SkSamplingOptions&,
2265                               const SkPaint*);
2266     virtual void onDrawImageRect2(const SkImage*, const SkRect& src, const SkRect& dst,
2267                                   const SkSamplingOptions&, const SkPaint*, SrcRectConstraint);
2268     virtual void onDrawImageLattice2(const SkImage*, const Lattice&, const SkRect& dst,
2269                                      SkFilterMode, const SkPaint*);
2270     virtual void onDrawAtlas2(const SkImage*, const SkRSXform[], const SkRect src[],
2271                               const SkColor[], int count, SkBlendMode, const SkSamplingOptions&,
2272                               const SkRect* cull, const SkPaint*);
2273     virtual void onDrawEdgeAAImageSet2(const ImageSetEntry imageSet[], int count,
2274                                        const SkPoint dstClips[], const SkMatrix preViewMatrices[],
2275                                        const SkSamplingOptions&, const SkPaint*,
2276                                        SrcRectConstraint);
2277 
2278     virtual void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
2279                                       const SkPaint& paint);
2280 
2281     virtual void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value);
2282     virtual void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&);
2283 
2284     virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix);
2285     virtual void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
2286                                const SkPaint* paint);
2287 
2288     virtual void onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], QuadAAFlags aaFlags,
2289                                   const SkColor4f& color, SkBlendMode mode);
2290 
2291     enum ClipEdgeStyle {
2292         kHard_ClipEdgeStyle,
2293         kSoft_ClipEdgeStyle
2294     };
2295 
2296     virtual void onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle);
2297     virtual void onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle);
2298     virtual void onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle);
2299     virtual void onClipShader(sk_sp<SkShader>, SkClipOp);
2300     virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp op);
2301     virtual void onResetClip();
2302 
2303     virtual void onDiscard();
2304 
2305 private:
2306 
2307     enum ShaderOverrideOpacity {
2308         kNone_ShaderOverrideOpacity,        //!< there is no overriding shader (bitmap or image)
2309         kOpaque_ShaderOverrideOpacity,      //!< the overriding shader is opaque
2310         kNotOpaque_ShaderOverrideOpacity,   //!< the overriding shader may not be opaque
2311     };
2312 
2313     // notify our surface (if we have one) that we are about to draw, so it
2314     // can perform copy-on-write or invalidate any cached images
2315     // returns false if the copy failed
2316     bool SK_WARN_UNUSED_RESULT predrawNotify(bool willOverwritesEntireSurface = false);
2317     bool SK_WARN_UNUSED_RESULT predrawNotify(const SkRect*, const SkPaint*, ShaderOverrideOpacity);
2318 
2319     enum class CheckForOverwrite : bool {
2320         kNo = false,
2321         kYes = true
2322     };
2323     // call the appropriate predrawNotify and create a layer if needed.
2324     skstd::optional<AutoLayerForImageFilter> aboutToDraw(
2325         SkCanvas* canvas,
2326         const SkPaint& paint,
2327         const SkRect* rawBounds = nullptr,
2328         CheckForOverwrite = CheckForOverwrite::kNo,
2329         ShaderOverrideOpacity = kNone_ShaderOverrideOpacity);
2330 
2331     // The bottom-most device in the stack, only changed by init(). Image properties and the final
2332     // canvas pixels are determined by this device.
baseDevice()2333     SkBaseDevice* baseDevice() const {
2334         SkASSERT(fBaseDevice);
2335         return fBaseDevice.get();
2336     }
2337 
2338     // The top-most device in the stack, will change within saveLayer()'s. All drawing and clipping
2339     // operations should route to this device.
2340     SkBaseDevice* topDevice() const;
2341 
2342     // Canvases maintain a sparse stack of layers, where the top-most layer receives the drawing,
2343     // clip, and matrix commands. There is a layer per call to saveLayer() using the
2344     // kFullLayer_SaveLayerStrategy.
2345     struct Layer {
2346         sk_sp<SkBaseDevice>  fDevice;
2347         sk_sp<SkImageFilter> fImageFilter; // applied to layer *before* being drawn by paint
2348         SkPaint              fPaint;
2349         bool                 fDiscard;
2350 
2351         Layer(sk_sp<SkBaseDevice> device, sk_sp<SkImageFilter> imageFilter, const SkPaint& paint);
2352     };
2353 
2354     // Encapsulate state needed to restore from saveBehind()
2355     struct BackImage {
2356         sk_sp<SkSpecialImage> fImage;
2357         SkIPoint              fLoc;
2358     };
2359 
2360     class MCRec {
2361     public:
2362         // If not null, this MCRec corresponds with the saveLayer() record that made the layer.
2363         // The base "layer" is not stored here, since it is stored inline in SkCanvas and has no
2364         // restoration behavior.
2365         std::unique_ptr<Layer> fLayer;
2366 
2367         // This points to the device of the top-most layer (which may be lower in the stack), or
2368         // to the canvas's fBaseDevice. The MCRec does not own the device.
2369         SkBaseDevice* fDevice;
2370 
2371         std::unique_ptr<BackImage> fBackImage;
2372         SkM44 fMatrix;
2373         int fDeferredSaveCount = 0;
2374 
2375         MCRec(SkBaseDevice* device);
2376         MCRec(const MCRec* prev);
2377         ~MCRec();
2378 
2379         void newLayer(sk_sp<SkBaseDevice> layerDevice,
2380                       sk_sp<SkImageFilter> filter,
2381                       const SkPaint& restorePaint);
2382 
2383         void reset(SkBaseDevice* device);
2384     };
2385 
2386     SkDeque     fMCStack;
2387     // points to top of stack
2388     MCRec*      fMCRec;
2389 
2390     sk_sp<SkMarkerStack> fMarkerStack;
2391 
2392     // the first N recs that can fit here mean we won't call malloc
2393     static constexpr int kMCRecSize      = 96; // most recent measurement
2394     static constexpr int kMCRecCount     = 32; // common depth for save/restores
2395 
2396     intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
2397 
2398     // Installed via init()
2399     sk_sp<SkBaseDevice> fBaseDevice;
2400     const SkSurfaceProps fProps;
2401 
2402     int         fSaveCount;         // value returned by getSaveCount()
2403 
2404     std::unique_ptr<SkRasterHandleAllocator> fAllocator;
2405 
2406     SkSurface_Base*  fSurfaceBase;
getSurfaceBase()2407     SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
setSurfaceBase(SkSurface_Base * sb)2408     void setSurfaceBase(SkSurface_Base* sb) {
2409         fSurfaceBase = sb;
2410     }
2411     friend class SkSurface_Base;
2412     friend class SkSurface_Gpu;
2413 
2414     SkIRect fClipRestrictionRect = SkIRect::MakeEmpty();
2415     int fClipRestrictionSaveCount = -1;
2416 
2417     void doSave();
2418     void checkForDeferredSave();
2419     void internalSetMatrix(const SkM44&);
2420 
2421     friend class SkAndroidFrameworkUtils;
2422     friend class SkCanvasPriv;      // needs to expose android functions for testing outside android
2423     friend class AutoLayerForImageFilter;
2424     friend class SkSurface_Raster;  // needs getDevice()
2425     friend class SkNoDrawCanvas;    // needs resetForNextPicture()
2426     friend class SkNWayCanvas;
2427     friend class SkPictureRecord;   // predrawNotify (why does it need it? <reed>)
2428     friend class SkOverdrawCanvas;
2429     friend class SkRasterHandleAllocator;
2430 protected:
2431     // For use by SkNoDrawCanvas (via SkCanvasVirtualEnforcer, which can't be a friend)
2432     SkCanvas(const SkIRect& bounds);
2433 private:
2434     SkCanvas(const SkBitmap&, std::unique_ptr<SkRasterHandleAllocator>,
2435              SkRasterHandleAllocator::Handle);
2436 
2437     SkCanvas(SkCanvas&&) = delete;
2438     SkCanvas(const SkCanvas&) = delete;
2439     SkCanvas& operator=(SkCanvas&&) = delete;
2440     SkCanvas& operator=(const SkCanvas&) = delete;
2441 
2442     /** Experimental
2443      *  Saves the specified subset of the current pixels in the current layer,
2444      *  and then clears those pixels to transparent black.
2445      *  Restores the pixels on restore() by drawing them in SkBlendMode::kDstOver.
2446      *
2447      *  @param subset   conservative bounds of the area to be saved / restored.
2448      *  @return depth of save state stack before this call was made.
2449      */
2450     int only_axis_aligned_saveBehind(const SkRect* subset);
2451 
2452     /**
2453      *  Like drawPaint, but magically clipped to the most recent saveBehind buffer rectangle.
2454      *  If there is no active saveBehind, then this draws nothing.
2455      */
2456     void drawClippedToSaveBehind(const SkPaint&);
2457 
2458     void resetForNextPicture(const SkIRect& bounds);
2459 
2460     // needs gettotalclip()
2461     friend class SkCanvasStateUtils;
2462 
2463     void init(sk_sp<SkBaseDevice>);
2464 
2465     // All base onDrawX() functions should call this and skip drawing if it returns true.
2466     // If 'matrix' is non-null, it maps the paint's fast bounds before checking for quick rejection
2467     bool internalQuickReject(const SkRect& bounds, const SkPaint& paint,
2468                              const SkMatrix* matrix = nullptr);
2469 
2470     void internalDrawPaint(const SkPaint& paint);
2471     void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
2472     void internalSaveBehind(const SkRect*);
2473 
2474     void internalConcat44(const SkM44&);
2475 
2476     // shared by save() and saveLayer()
2477     void internalSave();
2478     void internalRestore();
2479 
2480     enum class DeviceCompatibleWithFilter : bool {
2481         // Check the src device's local-to-device matrix for compatibility with the filter, and if
2482         // it is not compatible, introduce an intermediate image and transformation that allows the
2483         // filter to be evaluated on the modified src content.
2484         kUnknown = false,
2485         // Assume that the src device's local-to-device matrix is compatible with the filter.
2486         kYes     = true
2487     };
2488     /**
2489      * Filters the contents of 'src' and draws the result into 'dst'. The filter is evaluated
2490      * relative to the current canvas matrix, and src is drawn to dst using their relative transform
2491      * 'paint' is applied after the filter and must not have a mask or image filter of its own.
2492      * A null 'filter' behaves as if the identity filter were used.
2493      *
2494      * 'scaleFactor' is an extra uniform scale transform applied to downscale the 'src' image
2495      * before any filtering, or as part of the copy, and is then drawn with 1/scaleFactor to 'dst'.
2496      * Must be 1.0 if 'compat' is kYes (i.e. any scale factor has already been baked into the
2497      * relative transforms between the devices).
2498      */
2499     void internalDrawDeviceWithFilter(SkBaseDevice* src, SkBaseDevice* dst,
2500                                       const SkImageFilter* filter, const SkPaint& paint,
2501                                       DeviceCompatibleWithFilter compat,
2502                                       SkScalar scaleFactor = 1.f);
2503 
2504     /*
2505      *  Returns true if drawing the specified rect (or all if it is null) with the specified
2506      *  paint (or default if null) would overwrite the entire root device of the canvas
2507      *  (i.e. the canvas' surface if it had one).
2508      */
2509     bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
2510 
2511     /**
2512      *  Returns true if the paint's imagefilter can be invoked directly, without needed a layer.
2513      */
2514     bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkSamplingOptions&,
2515                                const SkPaint&);
2516 
2517     /**
2518      *  Returns true if the clip (for any active layer) contains antialiasing.
2519      *  If the clip is empty, this will return false.
2520      */
2521     bool androidFramework_isClipAA() const;
2522 
2523     /**
2524      * Reset the clip to be wide-open (modulo any separately specified device clip restriction).
2525      * This operate within the save/restore clip stack so it can be undone by restoring to an
2526      * earlier save point.
2527      */
2528     void internal_private_resetClip();
2529 
internal_private_asPaintFilterCanvas()2530     virtual SkPaintFilterCanvas* internal_private_asPaintFilterCanvas() const { return nullptr; }
2531 
2532     // Keep track of the device clip bounds in the canvas' global space to reject draws before
2533     // invoking the top-level device.
2534     SkRect fQuickRejectBounds;
2535 
2536     // Compute the clip's bounds based on all clipped SkDevice's reported device bounds transformed
2537     // into the canvas' global space.
2538     SkRect computeDeviceClipBounds(bool outsetForAA=true) const;
2539 
2540     class AutoUpdateQRBounds;
2541     void validateClip() const;
2542 
2543     std::unique_ptr<SkGlyphRunBuilder> fScratchGlyphRunBuilder;
2544 
2545     using INHERITED = SkRefCnt;
2546 };
2547 
2548 /** \class SkAutoCanvasRestore
2549     Stack helper class calls SkCanvas::restoreToCount when SkAutoCanvasRestore
2550     goes out of scope. Use this to guarantee that the canvas is restored to a known
2551     state.
2552 */
2553 class SkAutoCanvasRestore {
2554 public:
2555 
2556     /** Preserves SkCanvas::save() count. Optionally saves SkCanvas clip and SkCanvas matrix.
2557 
2558         @param canvas  SkCanvas to guard
2559         @param doSave  call SkCanvas::save()
2560         @return        utility to restore SkCanvas state on destructor
2561     */
SkAutoCanvasRestore(SkCanvas * canvas,bool doSave)2562     SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
2563         if (fCanvas) {
2564             fSaveCount = canvas->getSaveCount();
2565             if (doSave) {
2566                 canvas->save();
2567             }
2568         }
2569     }
2570 
2571     /** Restores SkCanvas to saved state. Destructor is called when container goes out of
2572         scope.
2573     */
~SkAutoCanvasRestore()2574     ~SkAutoCanvasRestore() {
2575         if (fCanvas) {
2576             fCanvas->restoreToCount(fSaveCount);
2577         }
2578     }
2579 
2580     /** Restores SkCanvas to saved state immediately. Subsequent calls and
2581         ~SkAutoCanvasRestore() have no effect.
2582     */
restore()2583     void restore() {
2584         if (fCanvas) {
2585             fCanvas->restoreToCount(fSaveCount);
2586             fCanvas = nullptr;
2587         }
2588     }
2589 
2590 private:
2591     SkCanvas*   fCanvas;
2592     int         fSaveCount;
2593 
2594     SkAutoCanvasRestore(SkAutoCanvasRestore&&) = delete;
2595     SkAutoCanvasRestore(const SkAutoCanvasRestore&) = delete;
2596     SkAutoCanvasRestore& operator=(SkAutoCanvasRestore&&) = delete;
2597     SkAutoCanvasRestore& operator=(const SkAutoCanvasRestore&) = delete;
2598 };
2599 
2600 #endif
2601