Coverage Report

Created: 2024-09-14 07:19

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