Coverage Report

Created: 2024-05-20 07:14

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