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