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