aboutsummaryrefslogtreecommitdiff
path: root/src/deps/skia/include/core/SkCanvas.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/deps/skia/include/core/SkCanvas.h')
-rw-r--r--src/deps/skia/include/core/SkCanvas.h2583
1 files changed, 2583 insertions, 0 deletions
diff --git a/src/deps/skia/include/core/SkCanvas.h b/src/deps/skia/include/core/SkCanvas.h
new file mode 100644
index 000000000..a2867f9bb
--- /dev/null
+++ b/src/deps/skia/include/core/SkCanvas.h
@@ -0,0 +1,2583 @@
+/*
+ * Copyright 2006 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkCanvas_DEFINED
+#define SkCanvas_DEFINED
+
+#include "include/core/SkBlendMode.h"
+#include "include/core/SkClipOp.h"
+#include "include/core/SkColor.h"
+#include "include/core/SkFontTypes.h"
+#include "include/core/SkImageInfo.h"
+#include "include/core/SkM44.h"
+#include "include/core/SkMatrix.h"
+#include "include/core/SkPaint.h"
+#include "include/core/SkPoint.h"
+#include "include/core/SkRasterHandleAllocator.h"
+#include "include/core/SkRect.h"
+#include "include/core/SkRefCnt.h"
+#include "include/core/SkSamplingOptions.h"
+#include "include/core/SkScalar.h"
+#include "include/core/SkSize.h"
+#include "include/core/SkString.h"
+#include "include/core/SkSurfaceProps.h"
+#include "include/core/SkTypes.h"
+#include "include/private/SkDeque.h"
+#include "include/private/SkMacros.h"
+
+#include <cstring>
+#include <memory>
+#include <vector>
+
+#ifndef SK_SUPPORT_LEGACY_GETTOTALMATRIX
+#define SK_SUPPORT_LEGACY_GETTOTALMATRIX
+#endif
+
+class AutoLayerForImageFilter;
+class GrBackendRenderTarget;
+class GrRecordingContext;
+class GrSlug;
+class SkBaseDevice;
+class SkBitmap;
+class SkData;
+class SkDrawable;
+struct SkDrawShadowRec;
+class SkFont;
+class SkGlyphRunBuilder;
+class SkGlyphRunList;
+class SkImage;
+class SkImageFilter;
+class SkPaintFilterCanvas;
+class SkPath;
+class SkPicture;
+class SkPixmap;
+class SkRegion;
+class SkRRect;
+struct SkRSXform;
+struct SkCustomMesh;
+class SkSpecialImage;
+class SkSurface;
+class SkSurface_Base;
+class SkTextBlob;
+class SkVertices;
+
+namespace skstd {
+ template<typename T> class optional;
+}
+
+/** \class SkCanvas
+ SkCanvas provides an interface for drawing, and how the drawing is clipped and transformed.
+ SkCanvas contains a stack of SkMatrix and clip values.
+
+ SkCanvas and SkPaint together provide the state to draw into SkSurface or SkBaseDevice.
+ Each SkCanvas draw call transforms the geometry of the object by the concatenation of all
+ SkMatrix values in the stack. The transformed geometry is clipped by the intersection
+ of all of clip values in the stack. The SkCanvas draw calls use SkPaint to supply drawing
+ state such as color, SkTypeface, text size, stroke width, SkShader and so on.
+
+ To draw to a pixel-based destination, create raster surface or GPU surface.
+ Request SkCanvas from SkSurface to obtain the interface to draw.
+ SkCanvas generated by raster surface draws to memory visible to the CPU.
+ SkCanvas generated by GPU surface uses Vulkan or OpenGL to draw to the GPU.
+
+ To draw to a document, obtain SkCanvas from SVG canvas, document PDF, or SkPictureRecorder.
+ SkDocument based SkCanvas and other SkCanvas subclasses reference SkBaseDevice describing the
+ destination.
+
+ SkCanvas can be constructed to draw to SkBitmap without first creating raster surface.
+ This approach may be deprecated in the future.
+*/
+class SK_API SkCanvas {
+public:
+
+ /** Allocates raster SkCanvas that will draw directly into pixels.
+
+ SkCanvas is returned if all parameters are valid.
+ Valid parameters include:
+ info dimensions are zero or positive;
+ info contains SkColorType and SkAlphaType supported by raster surface;
+ pixels is not nullptr;
+ rowBytes is zero or large enough to contain info width pixels of SkColorType.
+
+ Pass zero for rowBytes to compute rowBytes from info width and size of pixel.
+ If rowBytes is greater than zero, it must be equal to or greater than
+ info width times bytes required for SkColorType.
+
+ Pixel buffer size should be info height times computed rowBytes.
+ Pixels are not initialized.
+ To access pixels after drawing, call flush() or peekPixels().
+
+ @param info width, height, SkColorType, SkAlphaType, SkColorSpace, of raster surface;
+ width, or height, or both, may be zero
+ @param pixels pointer to destination pixels buffer
+ @param rowBytes interval from one SkSurface row to the next, or zero
+ @param props LCD striping orientation and setting for device independent fonts;
+ may be nullptr
+ @return SkCanvas if all parameters are valid; otherwise, nullptr
+ */
+ static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels,
+ size_t rowBytes,
+ const SkSurfaceProps* props = nullptr);
+
+ /** Allocates raster SkCanvas specified by inline image specification. Subsequent SkCanvas
+ calls draw into pixels.
+ SkColorType is set to kN32_SkColorType.
+ SkAlphaType is set to kPremul_SkAlphaType.
+ To access pixels after drawing, call flush() or peekPixels().
+
+ SkCanvas is returned if all parameters are valid.
+ Valid parameters include:
+ width and height are zero or positive;
+ pixels is not nullptr;
+ rowBytes is zero or large enough to contain width pixels of kN32_SkColorType.
+
+ Pass zero for rowBytes to compute rowBytes from width and size of pixel.
+ If rowBytes is greater than zero, it must be equal to or greater than
+ width times bytes required for SkColorType.
+
+ Pixel buffer size should be height times rowBytes.
+
+ @param width pixel column count on raster surface created; must be zero or greater
+ @param height pixel row count on raster surface created; must be zero or greater
+ @param pixels pointer to destination pixels buffer; buffer size should be height
+ times rowBytes
+ @param rowBytes interval from one SkSurface row to the next, or zero
+ @return SkCanvas if all parameters are valid; otherwise, nullptr
+ */
+ static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
+ size_t rowBytes) {
+ return MakeRasterDirect(SkImageInfo::MakeN32Premul(width, height), pixels, rowBytes);
+ }
+
+ /** Creates an empty SkCanvas with no backing device or pixels, with
+ a width and height of zero.
+
+ @return empty SkCanvas
+
+ example: https://fiddle.skia.org/c/@Canvas_empty_constructor
+ */
+ SkCanvas();
+
+ /** Creates SkCanvas of the specified dimensions without a SkSurface.
+ Used by subclasses with custom implementations for draw member functions.
+
+ If props equals nullptr, SkSurfaceProps are created with
+ SkSurfaceProps::InitType settings, which choose the pixel striping
+ direction and order. Since a platform may dynamically change its direction when
+ the device is rotated, and since a platform may have multiple monitors with
+ different characteristics, it is best not to rely on this legacy behavior.
+
+ @param width zero or greater
+ @param height zero or greater
+ @param props LCD striping orientation and setting for device independent fonts;
+ may be nullptr
+ @return SkCanvas placeholder with dimensions
+
+ example: https://fiddle.skia.org/c/@Canvas_int_int_const_SkSurfaceProps_star
+ */
+ SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr);
+
+ /** Private. For internal use only.
+ */
+ explicit SkCanvas(sk_sp<SkBaseDevice> device);
+
+ /** Constructs a canvas that draws into bitmap.
+ Sets kUnknown_SkPixelGeometry in constructed SkSurface.
+
+ SkBitmap is copied so that subsequently editing bitmap will not affect
+ constructed SkCanvas.
+
+ May be deprecated in the future.
+
+ @param bitmap width, height, SkColorType, SkAlphaType, and pixel
+ storage of raster surface
+ @return SkCanvas that can be used to draw into bitmap
+
+ example: https://fiddle.skia.org/c/@Canvas_copy_const_SkBitmap
+ */
+ explicit SkCanvas(const SkBitmap& bitmap);
+
+#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
+ /** Private.
+ */
+ enum class ColorBehavior {
+ kLegacy, //!< placeholder
+ };
+
+ /** Private. For use by Android framework only.
+
+ @param bitmap specifies a bitmap for the canvas to draw into
+ @param behavior specializes this constructor; value is unused
+ @return SkCanvas that can be used to draw into bitmap
+ */
+ SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior);
+#endif
+
+ /** Constructs a canvas that draws into bitmap.
+ Use props to match the device characteristics, like LCD striping.
+
+ bitmap is copied so that subsequently editing bitmap will not affect
+ constructed SkCanvas.
+
+ @param bitmap width, height, SkColorType, SkAlphaType,
+ and pixel storage of raster surface
+ @param props order and orientation of RGB striping; and whether to use
+ device independent fonts
+ @return SkCanvas that can be used to draw into bitmap
+
+ example: https://fiddle.skia.org/c/@Canvas_const_SkBitmap_const_SkSurfaceProps
+ */
+ SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props);
+
+ /** Draws saved layers, if any.
+ Frees up resources used by SkCanvas.
+
+ example: https://fiddle.skia.org/c/@Canvas_destructor
+ */
+ virtual ~SkCanvas();
+
+ /** Returns SkImageInfo for SkCanvas. If SkCanvas is not associated with raster surface or
+ GPU surface, returned SkColorType is set to kUnknown_SkColorType.
+
+ @return dimensions and SkColorType of SkCanvas
+
+ example: https://fiddle.skia.org/c/@Canvas_imageInfo
+ */
+ SkImageInfo imageInfo() const;
+
+ /** Copies SkSurfaceProps, if SkCanvas is associated with raster surface or
+ GPU surface, and returns true. Otherwise, returns false and leave props unchanged.
+
+ @param props storage for writable SkSurfaceProps
+ @return true if SkSurfaceProps was copied
+
+ example: https://fiddle.skia.org/c/@Canvas_getProps
+ */
+ bool getProps(SkSurfaceProps* props) const;
+
+ /** Triggers the immediate execution of all pending draw operations.
+ If SkCanvas is associated with GPU surface, resolves all pending GPU operations.
+ If SkCanvas is associated with raster surface, has no effect; raster draw
+ operations are never deferred.
+
+ DEPRECATED: Replace usage with GrDirectContext::flush()
+ */
+ void flush();
+
+ /** Gets the size of the base or root layer in global canvas coordinates. The
+ origin of the base layer is always (0,0). The area available for drawing may be
+ smaller (due to clipping or saveLayer).
+
+ @return integral width and height of base layer
+
+ example: https://fiddle.skia.org/c/@Canvas_getBaseLayerSize
+ */
+ virtual SkISize getBaseLayerSize() const;
+
+ /** Creates SkSurface matching info and props, and associates it with SkCanvas.
+ Returns nullptr if no match found.
+
+ If props is nullptr, matches SkSurfaceProps in SkCanvas. If props is nullptr and SkCanvas
+ does not have SkSurfaceProps, creates SkSurface with default SkSurfaceProps.
+
+ @param info width, height, SkColorType, SkAlphaType, and SkColorSpace
+ @param props SkSurfaceProps to match; may be nullptr to match SkCanvas
+ @return SkSurface matching info and props, or nullptr if no match is available
+
+ example: https://fiddle.skia.org/c/@Canvas_makeSurface
+ */
+ sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr);
+
+ /** Returns GPU context of the GPU surface associated with SkCanvas.
+
+ @return GPU context, if available; nullptr otherwise
+
+ example: https://fiddle.skia.org/c/@Canvas_recordingContext
+ */
+ virtual GrRecordingContext* recordingContext();
+
+ /** Sometimes a canvas is owned by a surface. If it is, getSurface() will return a bare
+ * pointer to that surface, else this will return nullptr.
+ */
+ SkSurface* getSurface() const;
+
+ /** Returns the pixel base address, SkImageInfo, rowBytes, and origin if the pixels
+ can be read directly. The returned address is only valid
+ while SkCanvas is in scope and unchanged. Any SkCanvas call or SkSurface call
+ may invalidate the returned address and other returned values.
+
+ If pixels are inaccessible, info, rowBytes, and origin are unchanged.
+
+ @param info storage for writable pixels' SkImageInfo; may be nullptr
+ @param rowBytes storage for writable pixels' row bytes; may be nullptr
+ @param origin storage for SkCanvas top layer origin, its top-left corner;
+ may be nullptr
+ @return address of pixels, or nullptr if inaccessible
+
+ example: https://fiddle.skia.org/c/@Canvas_accessTopLayerPixels_a
+ example: https://fiddle.skia.org/c/@Canvas_accessTopLayerPixels_b
+ */
+ void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr);
+
+ /** Returns custom context that tracks the SkMatrix and clip.
+
+ Use SkRasterHandleAllocator to blend Skia drawing with custom drawing, typically performed
+ by the host platform user interface. The custom context returned is generated by
+ SkRasterHandleAllocator::MakeCanvas, which creates a custom canvas with raster storage for
+ the drawing destination.
+
+ @return context of custom allocation
+
+ example: https://fiddle.skia.org/c/@Canvas_accessTopRasterHandle
+ */
+ SkRasterHandleAllocator::Handle accessTopRasterHandle() const;
+
+ /** Returns true if SkCanvas has direct access to its pixels.
+
+ Pixels are readable when SkBaseDevice is raster. Pixels are not readable when SkCanvas
+ is returned from GPU surface, returned by SkDocument::beginPage, returned by
+ SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility class
+ like DebugCanvas.
+
+ pixmap is valid only while SkCanvas is in scope and unchanged. Any
+ SkCanvas or SkSurface call may invalidate the pixmap values.
+
+ @param pixmap storage for pixel state if pixels are readable; otherwise, ignored
+ @return true if SkCanvas has direct access to pixels
+
+ example: https://fiddle.skia.org/c/@Canvas_peekPixels
+ */
+ bool peekPixels(SkPixmap* pixmap);
+
+ /** Copies SkRect of pixels from SkCanvas into dstPixels. SkMatrix and clip are
+ ignored.
+
+ Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
+ Destination SkRect corners are (0, 0) and (dstInfo.width(), dstInfo.height()).
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to dstInfo.colorType() and dstInfo.alphaType() if required.
+
+ Pixels are readable when SkBaseDevice is raster, or backed by a GPU.
+ Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
+ returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+ class like DebugCanvas.
+
+ The destination pixel storage must be allocated by the caller.
+
+ Pixel values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination rectangles
+ are copied. dstPixels contents outside SkRect intersection are unchanged.
+
+ Pass negative values for srcX or srcY to offset pixels across or down destination.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - SkCanvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType().
+ - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.
+ - dstRowBytes is too small to contain one row of pixels.
+
+ @param dstInfo width, height, SkColorType, and SkAlphaType of dstPixels
+ @param dstPixels storage for pixels; dstInfo.height() times dstRowBytes, or larger
+ @param dstRowBytes size of one destination row; dstInfo.width() times pixel size, or larger
+ @param srcX offset into readable pixels on x-axis; may be negative
+ @param srcY offset into readable pixels on y-axis; may be negative
+ @return true if pixels were copied
+ */
+ bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ int srcX, int srcY);
+
+ /** Copies SkRect of pixels from SkCanvas into pixmap. SkMatrix and clip are
+ ignored.
+
+ Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
+ Destination SkRect corners are (0, 0) and (pixmap.width(), pixmap.height()).
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to pixmap.colorType() and pixmap.alphaType() if required.
+
+ Pixels are readable when SkBaseDevice is raster, or backed by a GPU.
+ Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
+ returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+ class like DebugCanvas.
+
+ Caller must allocate pixel storage in pixmap if needed.
+
+ Pixel values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination SkRect
+ are copied. pixmap pixels contents outside SkRect intersection are unchanged.
+
+ Pass negative values for srcX or srcY to offset pixels across or down pixmap.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - SkCanvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType().
+ - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.
+ - SkPixmap pixels could not be allocated.
+ - pixmap.rowBytes() is too small to contain one row of pixels.
+
+ @param pixmap storage for pixels copied from SkCanvas
+ @param srcX offset into readable pixels on x-axis; may be negative
+ @param srcY offset into readable pixels on y-axis; may be negative
+ @return true if pixels were copied
+
+ example: https://fiddle.skia.org/c/@Canvas_readPixels_2
+ */
+ bool readPixels(const SkPixmap& pixmap, int srcX, int srcY);
+
+ /** Copies SkRect of pixels from SkCanvas into bitmap. SkMatrix and clip are
+ ignored.
+
+ Source SkRect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
+ Destination SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()).
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to bitmap.colorType() and bitmap.alphaType() if required.
+
+ Pixels are readable when SkBaseDevice is raster, or backed by a GPU.
+ Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
+ returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+ class like DebugCanvas.
+
+ Caller must allocate pixel storage in bitmap if needed.
+
+ SkBitmap values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination rectangles
+ are copied. SkBitmap pixels outside SkRect intersection are unchanged.
+
+ Pass negative values for srcX or srcY to offset pixels across or down bitmap.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - SkCanvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType().
+ - SkCanvas pixels are not readable; for instance, SkCanvas is document-based.
+ - bitmap pixels could not be allocated.
+ - bitmap.rowBytes() is too small to contain one row of pixels.
+
+ @param bitmap storage for pixels copied from SkCanvas
+ @param srcX offset into readable pixels on x-axis; may be negative
+ @param srcY offset into readable pixels on y-axis; may be negative
+ @return true if pixels were copied
+
+ example: https://fiddle.skia.org/c/@Canvas_readPixels_3
+ */
+ bool readPixels(const SkBitmap& bitmap, int srcX, int srcY);
+
+ /** Copies SkRect from pixels to SkCanvas. SkMatrix and clip are ignored.
+ Source SkRect corners are (0, 0) and (info.width(), info.height()).
+ Destination SkRect corners are (x, y) and
+ (imageInfo().width(), imageInfo().height()).
+
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to imageInfo().colorType() and imageInfo().alphaType() if required.
+
+ Pixels are writable when SkBaseDevice is raster, or backed by a GPU.
+ Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
+ returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+ class like DebugCanvas.
+
+ Pixel values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination rectangles
+ are copied. SkCanvas pixels outside SkRect intersection are unchanged.
+
+ Pass negative values for x or y to offset pixels to the left or
+ above SkCanvas pixels.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - pixels could not be converted to SkCanvas imageInfo().colorType() or
+ imageInfo().alphaType().
+ - SkCanvas pixels are not writable; for instance, SkCanvas is document-based.
+ - rowBytes is too small to contain one row of pixels.
+
+ @param info width, height, SkColorType, and SkAlphaType of pixels
+ @param pixels pixels to copy, of size info.height() times rowBytes, or larger
+ @param rowBytes size of one row of pixels; info.width() times pixel size, or larger
+ @param x offset into SkCanvas writable pixels on x-axis; may be negative
+ @param y offset into SkCanvas writable pixels on y-axis; may be negative
+ @return true if pixels were written to SkCanvas
+
+ example: https://fiddle.skia.org/c/@Canvas_writePixels
+ */
+ bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y);
+
+ /** Copies SkRect from pixels to SkCanvas. SkMatrix and clip are ignored.
+ Source SkRect corners are (0, 0) and (bitmap.width(), bitmap.height()).
+
+ Destination SkRect corners are (x, y) and
+ (imageInfo().width(), imageInfo().height()).
+
+ Copies each readable pixel intersecting both rectangles, without scaling,
+ converting to imageInfo().colorType() and imageInfo().alphaType() if required.
+
+ Pixels are writable when SkBaseDevice is raster, or backed by a GPU.
+ Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
+ returned by SkPictureRecorder::beginRecording, or SkCanvas is the base of a utility
+ class like DebugCanvas.
+
+ Pixel values are converted only if SkColorType and SkAlphaType
+ do not match. Only pixels within both source and destination rectangles
+ are copied. SkCanvas pixels outside SkRect intersection are unchanged.
+
+ Pass negative values for x or y to offset pixels to the left or
+ above SkCanvas pixels.
+
+ Does not copy, and returns false if:
+ - Source and destination rectangles do not intersect.
+ - bitmap does not have allocated pixels.
+ - bitmap pixels could not be converted to SkCanvas imageInfo().colorType() or
+ imageInfo().alphaType().
+ - SkCanvas pixels are not writable; for instance, SkCanvas is document based.
+ - bitmap pixels are inaccessible; for instance, bitmap wraps a texture.
+
+ @param bitmap contains pixels copied to SkCanvas
+ @param x offset into SkCanvas writable pixels on x-axis; may be negative
+ @param y offset into SkCanvas writable pixels on y-axis; may be negative
+ @return true if pixels were written to SkCanvas
+
+ example: https://fiddle.skia.org/c/@Canvas_writePixels_2
+ example: https://fiddle.skia.org/c/@State_Stack_a
+ example: https://fiddle.skia.org/c/@State_Stack_b
+ */
+ bool writePixels(const SkBitmap& bitmap, int x, int y);
+
+ /** Saves SkMatrix and clip.
+ Calling restore() discards changes to SkMatrix and clip,
+ restoring the SkMatrix and clip to their state when save() was called.
+
+ SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix(),
+ and resetMatrix(). Clip may be changed by clipRect(), clipRRect(), clipPath(), clipRegion().
+
+ Saved SkCanvas state is put on a stack; multiple calls to save() should be balance
+ by an equal number of calls to restore().
+
+ Call restoreToCount() with result to restore this and subsequent saves.
+
+ @return depth of saved stack
+
+ example: https://fiddle.skia.org/c/@Canvas_save
+ */
+ int save();
+
+ /** Saves SkMatrix and clip, and allocates a SkBitmap for subsequent drawing.
+ Calling restore() discards changes to SkMatrix and clip, and draws the SkBitmap.
+
+ SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+ setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+ clipPath(), clipRegion().
+
+ SkRect bounds suggests but does not define the SkBitmap size. To clip drawing to
+ a specific rectangle, use clipRect().
+
+ Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and
+ SkBlendMode when restore() is called.
+
+ Call restoreToCount() with returned value to restore this and subsequent saves.
+
+ @param bounds hint to limit the size of the layer; may be nullptr
+ @param paint graphics state for layer; may be nullptr
+ @return depth of saved stack
+
+ example: https://fiddle.skia.org/c/@Canvas_saveLayer
+ example: https://fiddle.skia.org/c/@Canvas_saveLayer_4
+ */
+ int saveLayer(const SkRect* bounds, const SkPaint* paint);
+
+ /** Saves SkMatrix and clip, and allocates a SkBitmap for subsequent drawing.
+ Calling restore() discards changes to SkMatrix and clip, and draws the SkBitmap.
+
+ SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+ setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+ clipPath(), clipRegion().
+
+ SkRect bounds suggests but does not define the layer size. To clip drawing to
+ a specific rectangle, use clipRect().
+
+ Optional SkPaint paint applies alpha, SkColorFilter, SkImageFilter, and
+ SkBlendMode when restore() is called.
+
+ Call restoreToCount() with returned value to restore this and subsequent saves.
+
+ @param bounds hint to limit the size of layer; may be nullptr
+ @param paint graphics state for layer; may be nullptr
+ @return depth of saved stack
+ */
+ int saveLayer(const SkRect& bounds, const SkPaint* paint) {
+ return this->saveLayer(&bounds, paint);
+ }
+
+ /** Saves SkMatrix and clip, and allocates SkBitmap for subsequent drawing.
+
+ Calling restore() discards changes to SkMatrix and clip,
+ and blends layer with alpha opacity onto prior layer.
+
+ SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+ setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+ clipPath(), clipRegion().
+
+ SkRect bounds suggests but does not define layer size. To clip drawing to
+ a specific rectangle, use clipRect().
+
+ alpha of zero is fully transparent, 255 is fully opaque.
+
+ Call restoreToCount() with returned value to restore this and subsequent saves.
+
+ @param bounds hint to limit the size of layer; may be nullptr
+ @param alpha opacity of layer
+ @return depth of saved stack
+
+ example: https://fiddle.skia.org/c/@Canvas_saveLayerAlpha
+ */
+ int saveLayerAlpha(const SkRect* bounds, U8CPU alpha);
+
+ /** \enum SkCanvas::SaveLayerFlagsSet
+ SaveLayerFlags provides options that may be used in any combination in SaveLayerRec,
+ defining how layer allocated by saveLayer() operates. It may be set to zero,
+ kPreserveLCDText_SaveLayerFlag, kInitWithPrevious_SaveLayerFlag, or both flags.
+ */
+ enum SaveLayerFlagsSet {
+ kPreserveLCDText_SaveLayerFlag = 1 << 1,
+ kInitWithPrevious_SaveLayerFlag = 1 << 2, //!< initializes with previous contents
+ // instead of matching previous layer's colortype, use F16
+ kF16ColorType = 1 << 4,
+ };
+
+ typedef uint32_t SaveLayerFlags;
+
+ /** \struct SkCanvas::SaveLayerRec
+ SaveLayerRec contains the state used to create the layer.
+ */
+ struct SaveLayerRec {
+ /** Sets fBounds, fPaint, and fBackdrop to nullptr. Clears fSaveLayerFlags.
+
+ @return empty SaveLayerRec
+ */
+ SaveLayerRec() {}
+
+ /** Sets fBounds, fPaint, and fSaveLayerFlags; sets fBackdrop to nullptr.
+
+ @param bounds layer dimensions; may be nullptr
+ @param paint applied to layer when overlaying prior layer; may be nullptr
+ @param saveLayerFlags SaveLayerRec options to modify layer
+ @return SaveLayerRec with empty fBackdrop
+ */
+ SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
+ : SaveLayerRec(bounds, paint, nullptr, 1.f, saveLayerFlags) {}
+
+ /** Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags.
+
+ @param bounds layer dimensions; may be nullptr
+ @param paint applied to layer when overlaying prior layer;
+ may be nullptr
+ @param backdrop If not null, this causes the current layer to be filtered by
+ backdrop, and then drawn into the new layer
+ (respecting the current clip).
+ If null, the new layer is initialized with transparent-black.
+ @param saveLayerFlags SaveLayerRec options to modify layer
+ @return SaveLayerRec fully specified
+ */
+ SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
+ SaveLayerFlags saveLayerFlags)
+ : SaveLayerRec(bounds, paint, backdrop, 1.f, saveLayerFlags) {}
+
+ /** hints at layer size limit */
+ const SkRect* fBounds = nullptr;
+
+ /** modifies overlay */
+ const SkPaint* fPaint = nullptr;
+
+ /**
+ * If not null, this triggers the same initialization behavior as setting
+ * kInitWithPrevious_SaveLayerFlag on fSaveLayerFlags: the current layer is copied into
+ * the new layer, rather than initializing the new layer with transparent-black.
+ * This is then filtered by fBackdrop (respecting the current clip).
+ */
+ const SkImageFilter* fBackdrop = nullptr;
+
+ /** preserves LCD text, creates with prior layer contents */
+ SaveLayerFlags fSaveLayerFlags = 0;
+
+ private:
+ friend class SkCanvas;
+ friend class SkCanvasPriv;
+
+ SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
+ SkScalar backdropScale, SaveLayerFlags saveLayerFlags)
+ : fBounds(bounds)
+ , fPaint(paint)
+ , fBackdrop(backdrop)
+ , fSaveLayerFlags(saveLayerFlags)
+ , fExperimentalBackdropScale(backdropScale) {}
+
+ // Relative scale factor that the image content used to initialize the layer when the
+ // kInitFromPrevious flag or a backdrop filter is used.
+ SkScalar fExperimentalBackdropScale = 1.f;
+ };
+
+ /** Saves SkMatrix and clip, and allocates SkBitmap for subsequent drawing.
+
+ Calling restore() discards changes to SkMatrix and clip,
+ and blends SkBitmap with alpha opacity onto the prior layer.
+
+ SkMatrix may be changed by translate(), scale(), rotate(), skew(), concat(),
+ setMatrix(), and resetMatrix(). Clip may be changed by clipRect(), clipRRect(),
+ clipPath(), clipRegion().
+
+ SaveLayerRec contains the state used to create the layer.
+
+ Call restoreToCount() with returned value to restore this and subsequent saves.
+
+ @param layerRec layer state
+ @return depth of save state stack before this call was made.
+
+ example: https://fiddle.skia.org/c/@Canvas_saveLayer_3
+ */
+ int saveLayer(const SaveLayerRec& layerRec);
+
+ /** Removes changes to SkMatrix and clip since SkCanvas state was
+ last saved. The state is removed from the stack.
+
+ Does nothing if the stack is empty.
+
+ example: https://fiddle.skia.org/c/@AutoCanvasRestore_restore
+
+ example: https://fiddle.skia.org/c/@Canvas_restore
+ */
+ void restore();
+
+ /** Returns the number of saved states, each containing: SkMatrix and clip.
+ Equals the number of save() calls less the number of restore() calls plus one.
+ The save count of a new canvas is one.
+
+ @return depth of save state stack
+
+ example: https://fiddle.skia.org/c/@Canvas_getSaveCount
+ */
+ int getSaveCount() const;
+
+ /** Restores state to SkMatrix and clip values when save(), saveLayer(),
+ saveLayerPreserveLCDTextRequests(), or saveLayerAlpha() returned saveCount.
+
+ Does nothing if saveCount is greater than state stack count.
+ Restores state to initial values if saveCount is less than or equal to one.
+
+ @param saveCount depth of state stack to restore
+
+ example: https://fiddle.skia.org/c/@Canvas_restoreToCount
+ */
+ void restoreToCount(int saveCount);
+
+ /** Translates SkMatrix by dx along the x-axis and dy along the y-axis.
+
+ Mathematically, replaces SkMatrix with a translation matrix
+ premultiplied with SkMatrix.
+
+ This has the effect of moving the drawing by (dx, dy) before transforming
+ the result with SkMatrix.
+
+ @param dx distance to translate on x-axis
+ @param dy distance to translate on y-axis
+
+ example: https://fiddle.skia.org/c/@Canvas_translate
+ */
+ void translate(SkScalar dx, SkScalar dy);
+
+ /** Scales SkMatrix by sx on the x-axis and sy on the y-axis.
+
+ Mathematically, replaces SkMatrix with a scale matrix
+ premultiplied with SkMatrix.
+
+ This has the effect of scaling the drawing by (sx, sy) before transforming
+ the result with SkMatrix.
+
+ @param sx amount to scale on x-axis
+ @param sy amount to scale on y-axis
+
+ example: https://fiddle.skia.org/c/@Canvas_scale
+ */
+ void scale(SkScalar sx, SkScalar sy);
+
+ /** Rotates SkMatrix by degrees. Positive degrees rotates clockwise.
+
+ Mathematically, replaces SkMatrix with a rotation matrix
+ premultiplied with SkMatrix.
+
+ This has the effect of rotating the drawing by degrees before transforming
+ the result with SkMatrix.
+
+ @param degrees amount to rotate, in degrees
+
+ example: https://fiddle.skia.org/c/@Canvas_rotate
+ */
+ void rotate(SkScalar degrees);
+
+ /** Rotates SkMatrix by degrees about a point at (px, py). Positive degrees rotates
+ clockwise.
+
+ Mathematically, constructs a rotation matrix; premultiplies the rotation matrix by
+ a translation matrix; then replaces SkMatrix with the resulting matrix
+ premultiplied with SkMatrix.
+
+ This has the effect of rotating the drawing about a given point before
+ transforming the result with SkMatrix.
+
+ @param degrees amount to rotate, in degrees
+ @param px x-axis value of the point to rotate about
+ @param py y-axis value of the point to rotate about
+
+ example: https://fiddle.skia.org/c/@Canvas_rotate_2
+ */
+ void rotate(SkScalar degrees, SkScalar px, SkScalar py);
+
+ /** Skews SkMatrix by sx on the x-axis and sy on the y-axis. A positive value of sx
+ skews the drawing right as y-axis values increase; a positive value of sy skews
+ the drawing down as x-axis values increase.
+
+ Mathematically, replaces SkMatrix with a skew matrix premultiplied with SkMatrix.
+
+ This has the effect of skewing the drawing by (sx, sy) before transforming
+ the result with SkMatrix.
+
+ @param sx amount to skew on x-axis
+ @param sy amount to skew on y-axis
+
+ example: https://fiddle.skia.org/c/@Canvas_skew
+ */
+ void skew(SkScalar sx, SkScalar sy);
+
+ /** Replaces SkMatrix with matrix premultiplied with existing SkMatrix.
+
+ This has the effect of transforming the drawn geometry by matrix, before
+ transforming the result with existing SkMatrix.
+
+ @param matrix matrix to premultiply with existing SkMatrix
+
+ example: https://fiddle.skia.org/c/@Canvas_concat
+ */
+ void concat(const SkMatrix& matrix);
+ void concat(const SkM44&);
+
+ /** Replaces SkMatrix with matrix.
+ Unlike concat(), any prior matrix state is overwritten.
+
+ @param matrix matrix to copy, replacing existing SkMatrix
+
+ example: https://fiddle.skia.org/c/@Canvas_setMatrix
+ */
+ void setMatrix(const SkM44& matrix);
+
+ // DEPRECATED -- use SkM44 version
+ void setMatrix(const SkMatrix& matrix);
+
+ /** Sets SkMatrix to the identity matrix.
+ Any prior matrix state is overwritten.
+
+ example: https://fiddle.skia.org/c/@Canvas_resetMatrix
+ */
+ void resetMatrix();
+
+ /** Replaces clip with the intersection or difference of clip and rect,
+ with an aliased or anti-aliased clip edge. rect is transformed by SkMatrix
+ before it is combined with clip.
+
+ @param rect SkRect to combine with clip
+ @param op SkClipOp to apply to clip
+ @param doAntiAlias true if clip is to be anti-aliased
+
+ example: https://fiddle.skia.org/c/@Canvas_clipRect
+ */
+ void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias);
+
+ /** Replaces clip with the intersection or difference of clip and rect.
+ Resulting clip is aliased; pixels are fully contained by the clip.
+ rect is transformed by SkMatrix before it is combined with clip.
+
+ @param rect SkRect to combine with clip
+ @param op SkClipOp to apply to clip
+ */
+ void clipRect(const SkRect& rect, SkClipOp op) {
+ this->clipRect(rect, op, false);
+ }
+
+ /** Replaces clip with the intersection of clip and rect.
+ Resulting clip is aliased; pixels are fully contained by the clip.
+ rect is transformed by SkMatrix
+ before it is combined with clip.
+
+ @param rect SkRect to combine with clip
+ @param doAntiAlias true if clip is to be anti-aliased
+ */
+ void clipRect(const SkRect& rect, bool doAntiAlias = false) {
+ this->clipRect(rect, SkClipOp::kIntersect, doAntiAlias);
+ }
+
+ void clipIRect(const SkIRect& irect, SkClipOp op = SkClipOp::kIntersect) {
+ this->clipRect(SkRect::Make(irect), op, false);
+ }
+
+ /** Sets the maximum clip rectangle, which can be set by clipRect(), clipRRect() and
+ clipPath() and intersect the current clip with the specified rect.
+ The maximum clip affects only future clipping operations; it is not retroactive.
+ The clip restriction is not recorded in pictures.
+
+ Pass an empty rect to disable maximum clip.
+ This private API is for use by Android framework only.
+
+ DEPRECATED: Replace usage with SkAndroidFrameworkUtils::replaceClip()
+
+ @param rect maximum allowed clip in device coordinates
+ */
+ void androidFramework_setDeviceClipRestriction(const SkIRect& rect);
+
+ /** Replaces clip with the intersection or difference of clip and rrect,
+ with an aliased or anti-aliased clip edge.
+ rrect is transformed by SkMatrix
+ before it is combined with clip.
+
+ @param rrect SkRRect to combine with clip
+ @param op SkClipOp to apply to clip
+ @param doAntiAlias true if clip is to be anti-aliased
+
+ example: https://fiddle.skia.org/c/@Canvas_clipRRect
+ */
+ void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias);
+
+ /** Replaces clip with the intersection or difference of clip and rrect.
+ Resulting clip is aliased; pixels are fully contained by the clip.
+ rrect is transformed by SkMatrix before it is combined with clip.
+
+ @param rrect SkRRect to combine with clip
+ @param op SkClipOp to apply to clip
+ */
+ void clipRRect(const SkRRect& rrect, SkClipOp op) {
+ this->clipRRect(rrect, op, false);
+ }
+
+ /** Replaces clip with the intersection of clip and rrect,
+ with an aliased or anti-aliased clip edge.
+ rrect is transformed by SkMatrix before it is combined with clip.
+
+ @param rrect SkRRect to combine with clip
+ @param doAntiAlias true if clip is to be anti-aliased
+ */
+ void clipRRect(const SkRRect& rrect, bool doAntiAlias = false) {
+ this->clipRRect(rrect, SkClipOp::kIntersect, doAntiAlias);
+ }
+
+ /** Replaces clip with the intersection or difference of clip and path,
+ with an aliased or anti-aliased clip edge. SkPath::FillType determines if path
+ describes the area inside or outside its contours; and if path contour overlaps
+ itself or another path contour, whether the overlaps form part of the area.
+ path is transformed by SkMatrix before it is combined with clip.
+
+ @param path SkPath to combine with clip
+ @param op SkClipOp to apply to clip
+ @param doAntiAlias true if clip is to be anti-aliased
+
+ example: https://fiddle.skia.org/c/@Canvas_clipPath
+ */
+ void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias);
+
+ /** Replaces clip with the intersection or difference of clip and path.
+ Resulting clip is aliased; pixels are fully contained by the clip.
+ SkPath::FillType determines if path
+ describes the area inside or outside its contours; and if path contour overlaps
+ itself or another path contour, whether the overlaps form part of the area.
+ path is transformed by SkMatrix
+ before it is combined with clip.
+
+ @param path SkPath to combine with clip
+ @param op SkClipOp to apply to clip
+ */
+ void clipPath(const SkPath& path, SkClipOp op) {
+ this->clipPath(path, op, false);
+ }
+
+ /** Replaces clip with the intersection of clip and path.
+ Resulting clip is aliased; pixels are fully contained by the clip.
+ SkPath::FillType determines if path
+ describes the area inside or outside its contours; and if path contour overlaps
+ itself or another path contour, whether the overlaps form part of the area.
+ path is transformed by SkMatrix before it is combined with clip.
+
+ @param path SkPath to combine with clip
+ @param doAntiAlias true if clip is to be anti-aliased
+ */
+ void clipPath(const SkPath& path, bool doAntiAlias = false) {
+ this->clipPath(path, SkClipOp::kIntersect, doAntiAlias);
+ }
+
+ void clipShader(sk_sp<SkShader>, SkClipOp = SkClipOp::kIntersect);
+
+ /** Replaces clip with the intersection or difference of clip and SkRegion deviceRgn.
+ Resulting clip is aliased; pixels are fully contained by the clip.
+ deviceRgn is unaffected by SkMatrix.
+
+ @param deviceRgn SkRegion to combine with clip
+ @param op SkClipOp to apply to clip
+
+ example: https://fiddle.skia.org/c/@Canvas_clipRegion
+ */
+ void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect);
+
+ /** Returns true if SkRect rect, transformed by SkMatrix, can be quickly determined to be
+ outside of clip. May return false even though rect is outside of clip.
+
+ Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
+
+ @param rect SkRect to compare with clip
+ @return true if rect, transformed by SkMatrix, does not intersect clip
+
+ example: https://fiddle.skia.org/c/@Canvas_quickReject
+ */
+ bool quickReject(const SkRect& rect) const;
+
+ /** Returns true if path, transformed by SkMatrix, can be quickly determined to be
+ outside of clip. May return false even though path is outside of clip.
+
+ Use to check if an area to be drawn is clipped out, to skip subsequent draw calls.
+
+ @param path SkPath to compare with clip
+ @return true if path, transformed by SkMatrix, does not intersect clip
+
+ example: https://fiddle.skia.org/c/@Canvas_quickReject_2
+ */
+ bool quickReject(const SkPath& path) const;
+
+ /** Returns bounds of clip, transformed by inverse of SkMatrix. If clip is empty,
+ return SkRect::MakeEmpty, where all SkRect sides equal zero.
+
+ SkRect returned is outset by one to account for partial pixel coverage if clip
+ is anti-aliased.
+
+ @return bounds of clip in local coordinates
+
+ example: https://fiddle.skia.org/c/@Canvas_getLocalClipBounds
+ */
+ SkRect getLocalClipBounds() const;
+
+ /** Returns bounds of clip, transformed by inverse of SkMatrix. If clip is empty,
+ return false, and set bounds to SkRect::MakeEmpty, where all SkRect sides equal zero.
+
+ bounds is outset by one to account for partial pixel coverage if clip
+ is anti-aliased.
+
+ @param bounds SkRect of clip in local coordinates
+ @return true if clip bounds is not empty
+ */
+ bool getLocalClipBounds(SkRect* bounds) const {
+ *bounds = this->getLocalClipBounds();
+ return !bounds->isEmpty();
+ }
+
+ /** Returns SkIRect bounds of clip, unaffected by SkMatrix. If clip is empty,
+ return SkRect::MakeEmpty, where all SkRect sides equal zero.
+
+ Unlike getLocalClipBounds(), returned SkIRect is not outset.
+
+ @return bounds of clip in SkBaseDevice coordinates
+
+ example: https://fiddle.skia.org/c/@Canvas_getDeviceClipBounds
+ */
+ SkIRect getDeviceClipBounds() const;
+
+ /** Returns SkIRect bounds of clip, unaffected by SkMatrix. If clip is empty,
+ return false, and set bounds to SkRect::MakeEmpty, where all SkRect sides equal zero.
+
+ Unlike getLocalClipBounds(), bounds is not outset.
+
+ @param bounds SkRect of clip in device coordinates
+ @return true if clip bounds is not empty
+ */
+ bool getDeviceClipBounds(SkIRect* bounds) const {
+ *bounds = this->getDeviceClipBounds();
+ return !bounds->isEmpty();
+ }
+
+ /** Fills clip with color color.
+ mode determines how ARGB is combined with destination.
+
+ @param color unpremultiplied ARGB
+ @param mode SkBlendMode used to combine source color and destination
+
+ example: https://fiddle.skia.org/c/@Canvas_drawColor
+ */
+ void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver) {
+ this->drawColor(SkColor4f::FromColor(color), mode);
+ }
+
+ /** Fills clip with color color.
+ mode determines how ARGB is combined with destination.
+
+ @param color SkColor4f representing unpremultiplied color.
+ @param mode SkBlendMode used to combine source color and destination
+ */
+ void drawColor(const SkColor4f& color, SkBlendMode mode = SkBlendMode::kSrcOver);
+
+ /** Fills clip with color color using SkBlendMode::kSrc.
+ This has the effect of replacing all pixels contained by clip with color.
+
+ @param color unpremultiplied ARGB
+ */
+ void clear(SkColor color) {
+ this->clear(SkColor4f::FromColor(color));
+ }
+
+ /** Fills clip with color color using SkBlendMode::kSrc.
+ This has the effect of replacing all pixels contained by clip with color.
+
+ @param color SkColor4f representing unpremultiplied color.
+ */
+ void clear(const SkColor4f& color) {
+ this->drawColor(color, SkBlendMode::kSrc);
+ }
+
+ /** Makes SkCanvas contents undefined. Subsequent calls that read SkCanvas pixels,
+ such as drawing with SkBlendMode, return undefined results. discard() does
+ not change clip or SkMatrix.
+
+ discard() may do nothing, depending on the implementation of SkSurface or SkBaseDevice
+ that created SkCanvas.
+
+ discard() allows optimized performance on subsequent draws by removing
+ cached data associated with SkSurface or SkBaseDevice.
+ It is not necessary to call discard() once done with SkCanvas;
+ any cached data is deleted when owning SkSurface or SkBaseDevice is deleted.
+ */
+ void discard() { this->onDiscard(); }
+
+ /** Fills clip with SkPaint paint. SkPaint components, SkShader,
+ SkColorFilter, SkImageFilter, and SkBlendMode affect drawing;
+ SkMaskFilter and SkPathEffect in paint are ignored.
+
+ @param paint graphics state used to fill SkCanvas
+
+ example: https://fiddle.skia.org/c/@Canvas_drawPaint
+ */
+ void drawPaint(const SkPaint& paint);
+
+ /** \enum SkCanvas::PointMode
+ Selects if an array of points are drawn as discrete points, as lines, or as
+ an open polygon.
+ */
+ enum PointMode {
+ kPoints_PointMode, //!< draw each point separately
+ kLines_PointMode, //!< draw each pair of points as a line segment
+ kPolygon_PointMode, //!< draw the array of points as a open polygon
+ };
+
+ /** Draws pts using clip, SkMatrix and SkPaint paint.
+ count is the number of points; if count is less than one, has no effect.
+ mode may be one of: kPoints_PointMode, kLines_PointMode, or kPolygon_PointMode.
+
+ If mode is kPoints_PointMode, the shape of point drawn depends on paint
+ SkPaint::Cap. If paint is set to SkPaint::kRound_Cap, each point draws a
+ circle of diameter SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap
+ or SkPaint::kButt_Cap, each point draws a square of width and height
+ SkPaint stroke width.
+
+ If mode is kLines_PointMode, each pair of points draws a line segment.
+ One line is drawn for every two points; each point is used once. If count is odd,
+ the final point is ignored.
+
+ If mode is kPolygon_PointMode, each adjacent pair of points draws a line segment.
+ count minus one lines are drawn; the first and last point are used once.
+
+ Each line segment respects paint SkPaint::Cap and SkPaint stroke width.
+ SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+ Always draws each element one at a time; is not affected by
+ SkPaint::Join, and unlike drawPath(), does not create a mask from all points
+ and lines before drawing.
+
+ @param mode whether pts draws points or lines
+ @param count number of points in the array
+ @param pts array of points to draw
+ @param paint stroke, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawPoints
+ */
+ void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint);
+
+ /** Draws point at (x, y) using clip, SkMatrix and SkPaint paint.
+
+ The shape of point drawn depends on paint SkPaint::Cap.
+ If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
+ SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
+ draw a square of width and height SkPaint stroke width.
+ SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+ @param x left edge of circle or square
+ @param y top edge of circle or square
+ @param paint stroke, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawPoint
+ */
+ void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint);
+
+ /** Draws point p using clip, SkMatrix and SkPaint paint.
+
+ The shape of point drawn depends on paint SkPaint::Cap.
+ If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
+ SkPaint stroke width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
+ draw a square of width and height SkPaint stroke width.
+ SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+ @param p top-left edge of circle or square
+ @param paint stroke, blend, color, and so on, used to draw
+ */
+ void drawPoint(SkPoint p, const SkPaint& paint) {
+ this->drawPoint(p.x(), p.y(), paint);
+ }
+
+ /** Draws line segment from (x0, y0) to (x1, y1) using clip, SkMatrix, and SkPaint paint.
+ In paint: SkPaint stroke width describes the line thickness;
+ SkPaint::Cap draws the end rounded or square;
+ SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+ @param x0 start of line segment on x-axis
+ @param y0 start of line segment on y-axis
+ @param x1 end of line segment on x-axis
+ @param y1 end of line segment on y-axis
+ @param paint stroke, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawLine
+ */
+ void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint);
+
+ /** Draws line segment from p0 to p1 using clip, SkMatrix, and SkPaint paint.
+ In paint: SkPaint stroke width describes the line thickness;
+ SkPaint::Cap draws the end rounded or square;
+ SkPaint::Style is ignored, as if were set to SkPaint::kStroke_Style.
+
+ @param p0 start of line segment
+ @param p1 end of line segment
+ @param paint stroke, blend, color, and so on, used to draw
+ */
+ void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint) {
+ this->drawLine(p0.x(), p0.y(), p1.x(), p1.y(), paint);
+ }
+
+ /** Draws SkRect rect using clip, SkMatrix, and SkPaint paint.
+ In paint: SkPaint::Style determines if rectangle is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness, and
+ SkPaint::Join draws the corners rounded or square.
+
+ @param rect rectangle to draw
+ @param paint stroke or fill, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawRect
+ */
+ void drawRect(const SkRect& rect, const SkPaint& paint);
+
+ /** Draws SkIRect rect using clip, SkMatrix, and SkPaint paint.
+ In paint: SkPaint::Style determines if rectangle is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness, and
+ SkPaint::Join draws the corners rounded or square.
+
+ @param rect rectangle to draw
+ @param paint stroke or fill, blend, color, and so on, used to draw
+ */
+ void drawIRect(const SkIRect& rect, const SkPaint& paint) {
+ SkRect r;
+ r.set(rect); // promotes the ints to scalars
+ this->drawRect(r, paint);
+ }
+
+ /** Draws SkRegion region using clip, SkMatrix, and SkPaint paint.
+ In paint: SkPaint::Style determines if rectangle is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness, and
+ SkPaint::Join draws the corners rounded or square.
+
+ @param region region to draw
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawRegion
+ */
+ void drawRegion(const SkRegion& region, const SkPaint& paint);
+
+ /** Draws oval oval using clip, SkMatrix, and SkPaint.
+ In paint: SkPaint::Style determines if oval is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness.
+
+ @param oval SkRect bounds of oval
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawOval
+ */
+ void drawOval(const SkRect& oval, const SkPaint& paint);
+
+ /** Draws SkRRect rrect using clip, SkMatrix, and SkPaint paint.
+ In paint: SkPaint::Style determines if rrect is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness.
+
+ rrect may represent a rectangle, circle, oval, uniformly rounded rectangle, or
+ may have any combination of positive non-square radii for the four corners.
+
+ @param rrect SkRRect with up to eight corner radii to draw
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawRRect
+ */
+ void drawRRect(const SkRRect& rrect, const SkPaint& paint);
+
+ /** Draws SkRRect outer and inner
+ using clip, SkMatrix, and SkPaint paint.
+ outer must contain inner or the drawing is undefined.
+ In paint: SkPaint::Style determines if SkRRect is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness.
+ If stroked and SkRRect corner has zero length radii, SkPaint::Join can
+ draw corners rounded or square.
+
+ GPU-backed platforms optimize drawing when both outer and inner are
+ concave and outer contains inner. These platforms may not be able to draw
+ SkPath built with identical data as fast.
+
+ @param outer SkRRect outer bounds to draw
+ @param inner SkRRect inner bounds to draw
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawDRRect_a
+ example: https://fiddle.skia.org/c/@Canvas_drawDRRect_b
+ */
+ void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
+
+ /** Draws circle at (cx, cy) with radius using clip, SkMatrix, and SkPaint paint.
+ If radius is zero or less, nothing is drawn.
+ In paint: SkPaint::Style determines if circle is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness.
+
+ @param cx circle center on the x-axis
+ @param cy circle center on the y-axis
+ @param radius half the diameter of circle
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawCircle
+ */
+ void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint);
+
+ /** Draws circle at center with radius using clip, SkMatrix, and SkPaint paint.
+ If radius is zero or less, nothing is drawn.
+ In paint: SkPaint::Style determines if circle is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness.
+
+ @param center circle center
+ @param radius half the diameter of circle
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+ */
+ void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint) {
+ this->drawCircle(center.x(), center.y(), radius, paint);
+ }
+
+ /** Draws arc using clip, SkMatrix, and SkPaint paint.
+
+ Arc is part of oval bounded by oval, sweeping from startAngle to startAngle plus
+ sweepAngle. startAngle and sweepAngle are in degrees.
+
+ startAngle of zero places start point at the right middle edge of oval.
+ A positive sweepAngle places arc end point clockwise from start point;
+ a negative sweepAngle places arc end point counterclockwise from start point.
+ sweepAngle may exceed 360 degrees, a full circle.
+ If useCenter is true, draw a wedge that includes lines from oval
+ center to arc end points. If useCenter is false, draw arc between end points.
+
+ If SkRect oval is empty or sweepAngle is zero, nothing is drawn.
+
+ @param oval SkRect bounds of oval containing arc to draw
+ @param startAngle angle in degrees where arc begins
+ @param sweepAngle sweep angle in degrees; positive is clockwise
+ @param useCenter if true, include the center of the oval
+ @param paint SkPaint stroke or fill, blend, color, and so on, used to draw
+ */
+ void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
+ bool useCenter, const SkPaint& paint);
+
+ /** Draws SkRRect bounded by SkRect rect, with corner radii (rx, ry) using clip,
+ SkMatrix, and SkPaint paint.
+
+ In paint: SkPaint::Style determines if SkRRect is stroked or filled;
+ if stroked, SkPaint stroke width describes the line thickness.
+ If rx or ry are less than zero, they are treated as if they are zero.
+ If rx plus ry exceeds rect width or rect height, radii are scaled down to fit.
+ If rx and ry are zero, SkRRect is drawn as SkRect and if stroked is affected by
+ SkPaint::Join.
+
+ @param rect SkRect bounds of SkRRect to draw
+ @param rx axis length on x-axis of oval describing rounded corners
+ @param ry axis length on y-axis of oval describing rounded corners
+ @param paint stroke, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawRoundRect
+ */
+ void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint);
+
+ /** Draws SkPath path using clip, SkMatrix, and SkPaint paint.
+ SkPath contains an array of path contour, each of which may be open or closed.
+
+ In paint: SkPaint::Style determines if SkRRect is stroked or filled:
+ if filled, SkPath::FillType determines whether path contour describes inside or
+ outside of fill; if stroked, SkPaint stroke width describes the line thickness,
+ SkPaint::Cap describes line ends, and SkPaint::Join describes how
+ corners are drawn.
+
+ @param path SkPath to draw
+ @param paint stroke, blend, color, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawPath
+ */
+ void drawPath(const SkPath& path, const SkPaint& paint);
+
+ void drawImage(const SkImage* image, SkScalar left, SkScalar top) {
+ this->drawImage(image, left, top, SkSamplingOptions(), nullptr);
+ }
+ void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top) {
+ this->drawImage(image.get(), left, top, SkSamplingOptions(), nullptr);
+ }
+
+ /** \enum SkCanvas::SrcRectConstraint
+ SrcRectConstraint controls the behavior at the edge of source SkRect,
+ provided to drawImageRect() when there is any filtering. If kStrict is set,
+ then extra code is used to ensure it nevers samples outside of the src-rect.
+ */
+ enum SrcRectConstraint {
+ kStrict_SrcRectConstraint, //!< sample only inside bounds; slower
+ kFast_SrcRectConstraint, //!< sample outside bounds; faster
+ };
+
+ void drawImage(const SkImage*, SkScalar x, SkScalar y, const SkSamplingOptions&,
+ const SkPaint* = nullptr);
+ void drawImage(const sk_sp<SkImage>& image, SkScalar x, SkScalar y,
+ const SkSamplingOptions& sampling, const SkPaint* paint = nullptr) {
+ this->drawImage(image.get(), x, y, sampling, paint);
+ }
+ void drawImageRect(const SkImage*, const SkRect& src, const SkRect& dst,
+ const SkSamplingOptions&, const SkPaint*, SrcRectConstraint);
+ void drawImageRect(const SkImage*, const SkRect& dst, const SkSamplingOptions&,
+ const SkPaint* = nullptr);
+ void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
+ const SkSamplingOptions& sampling, const SkPaint* paint,
+ SrcRectConstraint constraint) {
+ this->drawImageRect(image.get(), src, dst, sampling, paint, constraint);
+ }
+ void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst,
+ const SkSamplingOptions& sampling, const SkPaint* paint = nullptr) {
+ this->drawImageRect(image.get(), dst, sampling, paint);
+ }
+
+ /** Draws SkImage image stretched proportionally to fit into SkRect dst.
+ SkIRect center divides the image into nine sections: four sides, four corners, and
+ the center. Corners are unmodified or scaled down proportionately if their sides
+ are larger than dst; center and four sides are scaled to fit remaining space, if any.
+
+ Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
+ If paint contains SkMaskFilter, generate mask from image bounds.
+ Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.
+
+ If generated mask extends beyond image bounds, replicate image edge colors, just
+ as SkShader made from SkImage::makeShader with SkShader::kClamp_TileMode set
+ replicates the image edge color when it samples outside of its bounds.
+
+ @param image SkImage containing pixels, dimensions, and format
+ @param center SkIRect edge of image corners and sides
+ @param dst destination SkRect of image to draw to
+ @param filter what technique to use when sampling the image
+ @param paint SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+ and so on; or nullptr
+ */
+ void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
+ SkFilterMode filter, const SkPaint* paint = nullptr);
+
+ /** \struct SkCanvas::Lattice
+ SkCanvas::Lattice divides SkBitmap or SkImage into a rectangular grid.
+ Grid entries on even columns and even rows are fixed; these entries are
+ always drawn at their original size if the destination is large enough.
+ If the destination side is too small to hold the fixed entries, all fixed
+ entries are proportionately scaled down to fit.
+ The grid entries not on even columns and rows are scaled to fit the
+ remaining space, if any.
+ */
+ struct Lattice {
+
+ /** \enum SkCanvas::Lattice::RectType
+ Optional setting per rectangular grid entry to make it transparent,
+ or to fill the grid entry with a color.
+ */
+ enum RectType : uint8_t {
+ kDefault = 0, //!< draws SkBitmap into lattice rectangle
+ kTransparent, //!< skips lattice rectangle by making it transparent
+ kFixedColor, //!< draws one of fColors into lattice rectangle
+ };
+
+ const int* fXDivs; //!< x-axis values dividing bitmap
+ const int* fYDivs; //!< y-axis values dividing bitmap
+ const RectType* fRectTypes; //!< array of fill types
+ int fXCount; //!< number of x-coordinates
+ int fYCount; //!< number of y-coordinates
+ const SkIRect* fBounds; //!< source bounds to draw from
+ const SkColor* fColors; //!< array of colors
+ };
+
+ /** Draws SkImage image stretched proportionally to fit into SkRect dst.
+
+ SkCanvas::Lattice lattice divides image into a rectangular grid.
+ Each intersection of an even-numbered row and column is fixed;
+ fixed lattice elements never scale larger than their initial
+ size and shrink proportionately when all fixed elements exceed the bitmap
+ dimension. All other grid elements scale to fill the available space, if any.
+
+ Additionally transform draw using clip, SkMatrix, and optional SkPaint paint.
+
+ If SkPaint paint is supplied, apply SkColorFilter, alpha, SkImageFilter, and
+ SkBlendMode. If image is kAlpha_8_SkColorType, apply SkShader.
+ If paint contains SkMaskFilter, generate mask from image bounds.
+ Any SkMaskFilter on paint is ignored as is paint anti-aliasing state.
+
+ If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
+ just as SkShader made from SkShader::MakeBitmapShader with
+ SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
+ outside of its bounds.
+
+ @param image SkImage containing pixels, dimensions, and format
+ @param lattice division of bitmap into fixed and variable rectangles
+ @param dst destination SkRect of image to draw to
+ @param filter what technique to use when sampling the image
+ @param paint SkPaint containing SkBlendMode, SkColorFilter, SkImageFilter,
+ and so on; or nullptr
+ */
+ void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
+ SkFilterMode filter, const SkPaint* paint = nullptr);
+ void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst) {
+ this->drawImageLattice(image, lattice, dst, SkFilterMode::kNearest, nullptr);
+ }
+
+ /**
+ * Experimental. Controls anti-aliasing of each edge of images in an image-set.
+ */
+ enum QuadAAFlags : unsigned {
+ kLeft_QuadAAFlag = 0b0001,
+ kTop_QuadAAFlag = 0b0010,
+ kRight_QuadAAFlag = 0b0100,
+ kBottom_QuadAAFlag = 0b1000,
+
+ kNone_QuadAAFlags = 0b0000,
+ kAll_QuadAAFlags = 0b1111,
+ };
+
+ /** This is used by the experimental API below. */
+ struct SK_API ImageSetEntry {
+ ImageSetEntry(sk_sp<const SkImage> image, const SkRect& srcRect, const SkRect& dstRect,
+ int matrixIndex, float alpha, unsigned aaFlags, bool hasClip);
+
+ ImageSetEntry(sk_sp<const SkImage> image, const SkRect& srcRect, const SkRect& dstRect,
+ float alpha, unsigned aaFlags);
+
+ ImageSetEntry();
+ ~ImageSetEntry();
+ ImageSetEntry(const ImageSetEntry&);
+ ImageSetEntry& operator=(const ImageSetEntry&);
+
+ sk_sp<const SkImage> fImage;
+ SkRect fSrcRect;
+ SkRect fDstRect;
+ int fMatrixIndex = -1; // Index into the preViewMatrices arg, or < 0
+ float fAlpha = 1.f;
+ unsigned fAAFlags = kNone_QuadAAFlags; // QuadAAFlags
+ bool fHasClip = false; // True to use next 4 points in dstClip arg as quad
+ };
+
+ /**
+ * This is an experimental API for the SkiaRenderer Chromium project, and its API will surely
+ * evolve if it is not removed outright.
+ *
+ * This behaves very similarly to drawRect() combined with a clipPath() formed by clip
+ * quadrilateral. 'rect' and 'clip' are in the same coordinate space. If 'clip' is null, then it
+ * is as if the rectangle was not clipped (or, alternatively, clipped to itself). If not null,
+ * then it must provide 4 points.
+ *
+ * In addition to combining the draw and clipping into one operation, this function adds the
+ * additional capability of controlling each of the rectangle's edges anti-aliasing
+ * independently. The edges of the clip will respect the per-edge AA flags. It is required that
+ * 'clip' be contained inside 'rect'. In terms of mapping to edge labels, the 'clip' points
+ * should be ordered top-left, top-right, bottom-right, bottom-left so that the edge between [0]
+ * and [1] is "top", [1] and [2] is "right", [2] and [3] is "bottom", and [3] and [0] is "left".
+ * This ordering matches SkRect::toQuad().
+ *
+ * This API only draws solid color, filled rectangles so it does not accept a full SkPaint.
+ */
+ void experimental_DrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], QuadAAFlags aaFlags,
+ const SkColor4f& color, SkBlendMode mode);
+ void experimental_DrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], QuadAAFlags aaFlags,
+ SkColor color, SkBlendMode mode) {
+ this->experimental_DrawEdgeAAQuad(rect, clip, aaFlags, SkColor4f::FromColor(color), mode);
+ }
+
+ /**
+ * This is an bulk variant of experimental_DrawEdgeAAQuad() that renders 'cnt' textured quads.
+ * For each entry, 'fDstRect' is rendered with its clip (determined by entry's 'fHasClip' and
+ * the current index in 'dstClip'). The entry's fImage is applied to the destination rectangle
+ * by sampling from 'fSrcRect' sub-image. The corners of 'fSrcRect' map to the corners of
+ * 'fDstRect', just like in drawImageRect(), and they will be properly interpolated when
+ * applying a clip.
+ *
+ * Like experimental_DrawEdgeAAQuad(), each entry can specify edge AA flags that apply to both
+ * the destination rect and its clip.
+ *
+ * If provided, the 'dstClips' array must have length equal 4 * the number of entries with
+ * fHasClip true. If 'dstClips' is null, every entry must have 'fHasClip' set to false. The
+ * destination clip coordinates will be read consecutively with the image set entries, advancing
+ * by 4 points every time an entry with fHasClip is passed.
+ *
+ * This entry point supports per-entry manipulations to the canvas's current matrix. If an
+ * entry provides 'fMatrixIndex' >= 0, it will be drawn as if the canvas's CTM was
+ * canvas->getTotalMatrix() * preViewMatrices[fMatrixIndex]. If 'fMatrixIndex' is less than 0,
+ * the pre-view matrix transform is implicitly the identity, so it will be drawn using just the
+ * current canvas matrix. The pre-view matrix modifies the canvas's view matrix, it does not
+ * affect the local coordinates of each entry.
+ *
+ * An optional paint may be provided, which supports the same subset of features usable with
+ * drawImageRect (i.e. assumed to be filled and no path effects). When a paint is provided, the
+ * image set is drawn as if each image used the applied paint independently, so each is affected
+ * by the image, color, and/or mask filter.
+ */
+ void experimental_DrawEdgeAAImageSet(const ImageSetEntry imageSet[], int cnt,
+ const SkPoint dstClips[], const SkMatrix preViewMatrices[],
+ const SkSamplingOptions&, const SkPaint* paint = nullptr,
+ SrcRectConstraint constraint = kStrict_SrcRectConstraint);
+
+ /** Draws text, with origin at (x, y), using clip, SkMatrix, SkFont font,
+ and SkPaint paint.
+
+ When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or
+ SkTextEncoding::kUTF32, this function uses the default
+ character-to-glyph mapping from the SkTypeface in font. It does not
+ perform typeface fallback for characters not found in the SkTypeface.
+ It does not perform kerning or other complex shaping; glyphs are
+ positioned based on their default advances.
+
+ Text meaning depends on SkTextEncoding.
+
+ Text size is affected by SkMatrix and SkFont text size. Default text
+ size is 12 point.
+
+ All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+ SkColorFilter, and SkImageFilter; apply to text. By
+ default, draws filled black glyphs.
+
+ @param text character code points or glyphs drawn
+ @param byteLength byte length of text array
+ @param encoding text encoding used in the text array
+ @param x start of text on x-axis
+ @param y start of text on y-axis
+ @param font typeface, text size and so, used to describe the text
+ @param paint blend, color, and so on, used to draw
+ */
+ void drawSimpleText(const void* text, size_t byteLength, SkTextEncoding encoding,
+ SkScalar x, SkScalar y, const SkFont& font, const SkPaint& paint);
+
+ /** Draws null terminated string, with origin at (x, y), using clip, SkMatrix,
+ SkFont font, and SkPaint paint.
+
+ This function uses the default character-to-glyph mapping from the
+ SkTypeface in font. It does not perform typeface fallback for
+ characters not found in the SkTypeface. It does not perform kerning;
+ glyphs are positioned based on their default advances.
+
+ String str is encoded as UTF-8.
+
+ Text size is affected by SkMatrix and font text size. Default text
+ size is 12 point.
+
+ All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+ SkColorFilter, and SkImageFilter; apply to text. By
+ default, draws filled black glyphs.
+
+ @param str character code points drawn,
+ ending with a char value of zero
+ @param x start of string on x-axis
+ @param y start of string on y-axis
+ @param font typeface, text size and so, used to describe the text
+ @param paint blend, color, and so on, used to draw
+ */
+ void drawString(const char str[], SkScalar x, SkScalar y, const SkFont& font,
+ const SkPaint& paint) {
+ this->drawSimpleText(str, strlen(str), SkTextEncoding::kUTF8, x, y, font, paint);
+ }
+
+ /** Draws SkString, with origin at (x, y), using clip, SkMatrix, SkFont font,
+ and SkPaint paint.
+
+ This function uses the default character-to-glyph mapping from the
+ SkTypeface in font. It does not perform typeface fallback for
+ characters not found in the SkTypeface. It does not perform kerning;
+ glyphs are positioned based on their default advances.
+
+ SkString str is encoded as UTF-8.
+
+ Text size is affected by SkMatrix and SkFont text size. Default text
+ size is 12 point.
+
+ All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+ SkColorFilter, and SkImageFilter; apply to text. By
+ default, draws filled black glyphs.
+
+ @param str character code points drawn,
+ ending with a char value of zero
+ @param x start of string on x-axis
+ @param y start of string on y-axis
+ @param font typeface, text size and so, used to describe the text
+ @param paint blend, color, and so on, used to draw
+ */
+ void drawString(const SkString& str, SkScalar x, SkScalar y, const SkFont& font,
+ const SkPaint& paint) {
+ this->drawSimpleText(str.c_str(), str.size(), SkTextEncoding::kUTF8, x, y, font, paint);
+ }
+
+ /** Draws count glyphs, at positions relative to origin styled with font and paint with
+ supporting utf8 and cluster information.
+
+ This function draw glyphs at the given positions relative to the given origin.
+ It does not perform typeface fallback for glyphs not found in the SkTypeface in font.
+
+ The drawing obeys the current transform matrix and clipping.
+
+ All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+ SkColorFilter, and SkImageFilter; apply to text. By
+ default, draws filled black glyphs.
+
+ @param count number of glyphs to draw
+ @param glyphs the array of glyphIDs to draw
+ @param positions where to draw each glyph relative to origin
+ @param clusters array of size count of cluster information
+ @param textByteCount size of the utf8text
+ @param utf8text utf8text supporting information for the glyphs
+ @param origin the origin of all the positions
+ @param font typeface, text size and so, used to describe the text
+ @param paint blend, color, and so on, used to draw
+ */
+ void drawGlyphs(int count, const SkGlyphID glyphs[], const SkPoint positions[],
+ const uint32_t clusters[], int textByteCount, const char utf8text[],
+ SkPoint origin, const SkFont& font, const SkPaint& paint);
+
+ /** Draws count glyphs, at positions relative to origin styled with font and paint.
+
+ This function draw glyphs at the given positions relative to the given origin.
+ It does not perform typeface fallback for glyphs not found in the SkTypeface in font.
+
+ The drawing obeys the current transform matrix and clipping.
+
+ All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+ SkColorFilter, and SkImageFilter; apply to text. By
+ default, draws filled black glyphs.
+
+ @param count number of glyphs to draw
+ @param glyphs the array of glyphIDs to draw
+ @param positions where to draw each glyph relative to origin
+ @param origin the origin of all the positions
+ @param font typeface, text size and so, used to describe the text
+ @param paint blend, color, and so on, used to draw
+ */
+ void drawGlyphs(int count, const SkGlyphID glyphs[], const SkPoint positions[],
+ SkPoint origin, const SkFont& font, const SkPaint& paint);
+
+ /** Draws count glyphs, at positions relative to origin styled with font and paint.
+
+ This function draw glyphs using the given scaling and rotations. They are positioned
+ relative to the given origin. It does not perform typeface fallback for glyphs not found
+ in the SkTypeface in font.
+
+ The drawing obeys the current transform matrix and clipping.
+
+ All elements of paint: SkPathEffect, SkMaskFilter, SkShader,
+ SkColorFilter, and SkImageFilter; apply to text. By
+ default, draws filled black glyphs.
+
+ @param count number of glyphs to draw
+ @param glyphs the array of glyphIDs to draw
+ @param xforms where to draw and orient each glyph
+ @param origin the origin of all the positions
+ @param font typeface, text size and so, used to describe the text
+ @param paint blend, color, and so on, used to draw
+ */
+ void drawGlyphs(int count, const SkGlyphID glyphs[], const SkRSXform xforms[],
+ SkPoint origin, const SkFont& font, const SkPaint& paint);
+
+ /** Draws SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint.
+
+ blob contains glyphs, their positions, and paint attributes specific to text:
+ SkTypeface, SkPaint text size, SkPaint text scale x,
+ SkPaint text skew x, SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold,
+ SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text,
+ and SkPaint subpixel text.
+
+ SkTextEncoding must be set to SkTextEncoding::kGlyphID.
+
+ Elements of paint: anti-alias, SkBlendMode, color including alpha,
+ SkColorFilter, SkPaint dither, SkMaskFilter, SkPathEffect, SkShader, and
+ SkPaint::Style; apply to blob. If SkPaint contains SkPaint::kStroke_Style:
+ SkPaint miter limit, SkPaint::Cap, SkPaint::Join, and SkPaint stroke width;
+ apply to SkPath created from blob.
+
+ @param blob glyphs, positions, and their paints' text size, typeface, and so on
+ @param x horizontal offset applied to blob
+ @param y vertical offset applied to blob
+ @param paint blend, color, stroking, and so on, used to draw
+
+ example: https://fiddle.skia.org/c/@Canvas_drawTextBlob
+ */
+ void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint);
+
+ /** Draws SkTextBlob blob at (x, y), using clip, SkMatrix, and SkPaint paint.
+
+ blob contains glyphs, their positions, and paint attributes specific to text:
+ SkTypeface, SkPaint text size, SkPaint text scale x,
+ SkPaint text skew x, SkPaint::Align, SkPaint::Hinting, anti-alias, SkPaint fake bold,
+ SkPaint font embedded bitmaps, SkPaint full hinting spacing, LCD text, SkPaint linear text,
+ and SkPaint subpixel text.
+
+ SkTextEncoding must be set to SkTextEncoding::kGlyphID.
+
+ Elements of paint: SkPathEffect, SkMaskFilter, SkShader, SkColorFilter,
+ and SkImageFilter; apply to blob.
+
+ @param blob glyphs, positions, and their paints' text size, typeface, and so on
+ @param x horizontal offset applied to blob
+ @param y vertical offset applied to blob
+ @param paint blend, color, stroking, and so on, used to draw
+ */
+ void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint) {
+ this->drawTextBlob(blob.get(), x, y, paint);
+ }
+
+ /** Draws SkPicture picture, using clip and SkMatrix.
+ Clip and SkMatrix are unchanged by picture contents, as if
+ save() was called before and restore() was called after drawPicture().
+
+ SkPicture records a series of draw commands for later playback.
+
+ @param picture recorded drawing commands to play
+ */
+ void drawPicture(const SkPicture* picture) {
+ this->drawPicture(picture, nullptr, nullptr);
+ }
+
+ /** Draws SkPicture picture, using clip and SkMatrix.
+ Clip and SkMatrix are unchanged by picture contents, as if
+ save() was called before and restore() was called after drawPicture().
+
+ SkPicture records a series of draw commands for later playback.
+
+ @param picture recorded drawing commands to play
+ */
+ void drawPicture(const sk_sp<SkPicture>& picture) {
+ this->drawPicture(picture.get());
+ }
+
+ /** Draws SkPicture picture, using clip and SkMatrix; transforming picture with
+ SkMatrix matrix, if provided; and use SkPaint paint alpha, SkColorFilter,
+ SkImageFilter, and SkBlendMode, if provided.
+
+ If paint is non-null, then the picture is always drawn into a temporary layer before
+ actually landing on the canvas. Note that drawing into a layer can also change its
+ appearance if there are any non-associative blendModes inside any of the pictures elements.
+
+ @param picture recorded drawing commands to play
+ @param matrix SkMatrix to rotate, scale, translate, and so on; may be nullptr
+ @param paint SkPaint to apply transparency, filtering, and so on; may be nullptr
+
+ example: https://fiddle.skia.org/c/@Canvas_drawPicture_3
+ */
+ void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint);
+
+ /** Draws SkPicture picture, using clip and SkMatrix; transforming picture with
+ SkMatrix matrix, if provided; and use SkPaint paint alpha, SkColorFilter,
+ SkImageFilter, and SkBlendMode, if provided.
+
+ If paint is non-null, then the picture is always drawn into a temporary layer before
+ actually landing on the canvas. Note that drawing into a layer can also change its
+ appearance if there are any non-associative blendModes inside any of the pictures elements.
+
+ @param picture recorded drawing commands to play
+ @param matrix SkMatrix to rotate, scale, translate, and so on; may be nullptr
+ @param paint SkPaint to apply transparency, filtering, and so on; may be nullptr
+ */
+ void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix,
+ const SkPaint* paint) {
+ this->drawPicture(picture.get(), matrix, paint);
+ }
+
+ /** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix.
+ If paint contains an SkShader and vertices does not contain texCoords, the shader
+ is mapped using the vertices' positions.
+
+ SkBlendMode is ignored if SkVertices does not have colors. Otherwise, it combines
+ - the SkShader if SkPaint contains SkShader
+ - or the opaque SkPaint color if SkPaint does not contain SkShader
+ as the src of the blend and the interpolated vertex colors as the dst.
+
+ SkMaskFilter, SkPathEffect, and antialiasing on SkPaint are ignored.
+
+ @param vertices triangle mesh to draw
+ @param mode combines vertices' colors with SkShader if present or SkPaint opaque color
+ if not. Ignored if the vertices do not contain color.
+ @param paint specifies the SkShader, used as SkVertices texture, and SkColorFilter.
+
+ example: https://fiddle.skia.org/c/@Canvas_drawVertices
+ */
+ void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint);
+
+ /** Draws SkVertices vertices, a triangle mesh, using clip and SkMatrix.
+ If paint contains an SkShader and vertices does not contain texCoords, the shader
+ is mapped using the vertices' positions.
+
+ SkBlendMode is ignored if SkVertices does not have colors. Otherwise, it combines
+ - the SkShader if SkPaint contains SkShader
+ - or the opaque SkPaint color if SkPaint does not contain SkShader
+ as the src of the blend and the interpolated vertex colors as the dst.
+
+ SkMaskFilter, SkPathEffect, and antialiasing on SkPaint are ignored.
+
+ @param vertices triangle mesh to draw
+ @param mode combines vertices' colors with SkShader if present or SkPaint opaque color
+ if not. Ignored if the vertices do not contain color.
+ @param paint specifies the SkShader, used as SkVertices texture, may be nullptr
+
+ example: https://fiddle.skia.org/c/@Canvas_drawVertices_2
+ */
+ void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint);
+
+#if defined(SK_ENABLE_EXPERIMENTAL_CUSTOM_MESH) && defined(SK_ENABLE_SKSL)
+ /**
+ Experimental, under active development, and subject to change without notice.
+
+ Draws a mesh using a user-defined specification (see SkCustomMeshSpecification).
+
+ SkBlender is ignored if SkCustomMesh's specification does not output fragment shader color.
+ Otherwise, it combines
+ - the SkShader if SkPaint contains SkShader
+ - or the opaque SkPaint color if SkPaint does not contain SkShader
+ as the src of the blend and the mesh's fragment color as the dst.
+
+ SkMaskFilter, SkPathEffect, and antialiasing on SkPaint are ignored.
+
+ @param cm the custom mesh vertices and compatible specification.
+ @param blender combines vertices colors with SkShader if present or SkPaint opaque color
+ if not. Ignored if the custom mesh does not output color. Defaults to
+ SkBlendMode::kModulate if nullptr.
+ @param paint specifies the SkShader, used as SkVertices texture, may be nullptr
+ */
+ void drawCustomMesh(SkCustomMesh cm, sk_sp<SkBlender> blender, const SkPaint& paint);
+#endif
+
+ /** Draws a Coons patch: the interpolation of four cubics with shared corners,
+ associating a color, and optionally a texture SkPoint, with each corner.
+
+ SkPoint array cubics specifies four SkPath cubic starting at the top-left corner,
+ in clockwise order, sharing every fourth point. The last SkPath cubic ends at the
+ first point.
+
+ Color array color associates colors with corners in top-left, top-right,
+ bottom-right, bottom-left order.
+
+ If paint contains SkShader, SkPoint array texCoords maps SkShader as texture to
+ corners in top-left, top-right, bottom-right, bottom-left order. If texCoords is
+ nullptr, SkShader is mapped using positions (derived from cubics).
+
+ SkBlendMode is ignored if colors is null. Otherwise, it combines
+ - the SkShader if SkPaint contains SkShader
+ - or the opaque SkPaint color if SkPaint does not contain SkShader
+ as the src of the blend and the interpolated patch colors as the dst.
+
+ SkMaskFilter, SkPathEffect, and antialiasing on SkPaint are ignored.
+
+ @param cubics SkPath cubic array, sharing common points
+ @param colors color array, one for each corner
+ @param texCoords SkPoint array of texture coordinates, mapping SkShader to corners;
+ may be nullptr
+ @param mode combines patch's colors with SkShader if present or SkPaint opaque color
+ if not. Ignored if colors is null.
+ @param paint SkShader, SkColorFilter, SkBlendMode, used to draw
+ */
+ void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
+
+ /** Draws a set of sprites from atlas, using clip, SkMatrix, and optional SkPaint paint.
+ paint uses anti-alias, alpha, SkColorFilter, SkImageFilter, and SkBlendMode
+ to draw, if present. For each entry in the array, SkRect tex locates sprite in
+ atlas, and SkRSXform xform transforms it into destination space.
+
+ SkMaskFilter and SkPathEffect on paint are ignored.
+
+ xform, tex, and colors if present, must contain count entries.
+ Optional colors are applied for each sprite using SkBlendMode mode, treating
+ sprite as source and colors as destination.
+ Optional cullRect is a conservative bounds of all transformed sprites.
+ If cullRect is outside of clip, canvas can skip drawing.
+
+ If atlas is nullptr, this draws nothing.
+
+ @param atlas SkImage containing sprites
+ @param xform SkRSXform mappings for sprites in atlas
+ @param tex SkRect locations of sprites in atlas
+ @param colors one per sprite, blended with sprite using SkBlendMode; may be nullptr
+ @param count number of sprites to draw
+ @param mode SkBlendMode combining colors and sprites
+ @param sampling SkSamplingOptions used when sampling from the atlas image
+ @param cullRect bounds of transformed sprites for efficient clipping; may be nullptr
+ @param paint SkColorFilter, SkImageFilter, SkBlendMode, and so on; may be nullptr
+ */
+ void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
+ const SkColor colors[], int count, SkBlendMode mode,
+ const SkSamplingOptions& sampling, const SkRect* cullRect, const SkPaint* paint);
+
+ /** Draws SkDrawable drawable using clip and SkMatrix, concatenated with
+ optional matrix.
+
+ If SkCanvas has an asynchronous implementation, as is the case
+ when it is recording into SkPicture, then drawable will be referenced,
+ so that SkDrawable::draw() can be called when the operation is finalized. To force
+ immediate drawing, call SkDrawable::draw() instead.
+
+ @param drawable custom struct encapsulating drawing commands
+ @param matrix transformation applied to drawing; may be nullptr
+
+ example: https://fiddle.skia.org/c/@Canvas_drawDrawable
+ */
+ void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr);
+
+ /** Draws SkDrawable drawable using clip and SkMatrix, offset by (x, y).
+
+ If SkCanvas has an asynchronous implementation, as is the case
+ when it is recording into SkPicture, then drawable will be referenced,
+ so that SkDrawable::draw() can be called when the operation is finalized. To force
+ immediate drawing, call SkDrawable::draw() instead.
+
+ @param drawable custom struct encapsulating drawing commands
+ @param x offset into SkCanvas writable pixels on x-axis
+ @param y offset into SkCanvas writable pixels on y-axis
+
+ example: https://fiddle.skia.org/c/@Canvas_drawDrawable_2
+ */
+ void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y);
+
+ /** Associates SkRect on SkCanvas with an annotation; a key-value pair, where the key is
+ a null-terminated UTF-8 string, and optional value is stored as SkData.
+
+ Only some canvas implementations, such as recording to SkPicture, or drawing to
+ document PDF, use annotations.
+
+ @param rect SkRect extent of canvas to annotate
+ @param key string used for lookup
+ @param value data holding value stored in annotation
+
+ example: https://fiddle.skia.org/c/@Canvas_drawAnnotation_2
+ */
+ void drawAnnotation(const SkRect& rect, const char key[], SkData* value);
+
+ /** Associates SkRect on SkCanvas when an annotation; a key-value pair, where the key is
+ a null-terminated UTF-8 string, and optional value is stored as SkData.
+
+ Only some canvas implementations, such as recording to SkPicture, or drawing to
+ document PDF, use annotations.
+
+ @param rect SkRect extent of canvas to annotate
+ @param key string used for lookup
+ @param value data holding value stored in annotation
+ */
+ void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value) {
+ this->drawAnnotation(rect, key, value.get());
+ }
+
+ /** Returns true if clip is empty; that is, nothing will draw.
+
+ May do work when called; it should not be called
+ more often than needed. However, once called, subsequent calls perform no
+ work until clip changes.
+
+ @return true if clip is empty
+
+ example: https://fiddle.skia.org/c/@Canvas_isClipEmpty
+ */
+ virtual bool isClipEmpty() const;
+
+ /** Returns true if clip is SkRect and not empty.
+ Returns false if the clip is empty, or if it is not SkRect.
+
+ @return true if clip is SkRect and not empty
+
+ example: https://fiddle.skia.org/c/@Canvas_isClipRect
+ */
+ virtual bool isClipRect() const;
+
+ /** Returns the current transform from local coordinates to the 'device', which for most
+ * purposes means pixels.
+ *
+ * @return transformation from local coordinates to device / pixels.
+ */
+ SkM44 getLocalToDevice() const;
+
+ /**
+ * Throws away the 3rd row and column in the matrix, so be warned.
+ */
+ SkMatrix getLocalToDeviceAs3x3() const {
+ return this->getLocalToDevice().asM33();
+ }
+
+#ifdef SK_SUPPORT_LEGACY_GETTOTALMATRIX
+ /** DEPRECATED
+ * Legacy version of getLocalToDevice(), which strips away any Z information, and
+ * just returns a 3x3 version.
+ *
+ * @return 3x3 version of getLocalToDevice()
+ *
+ * example: https://fiddle.skia.org/c/@Canvas_getTotalMatrix
+ * example: https://fiddle.skia.org/c/@Clip
+ */
+ SkMatrix getTotalMatrix() const;
+#endif
+
+ ///////////////////////////////////////////////////////////////////////////
+
+#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && SK_SUPPORT_GPU
+ // These methods exist to support WebView in Android Framework.
+ SkIRect topLayerBounds() const;
+ GrBackendRenderTarget topLayerBackendRenderTarget() const;
+#endif
+
+ /**
+ * Returns the global clip as a region. If the clip contains AA, then only the bounds
+ * of the clip may be returned.
+ */
+ void temporary_internal_getRgnClip(SkRegion* region);
+
+ void private_draw_shadow_rec(const SkPath&, const SkDrawShadowRec&);
+
+
+protected:
+ // default impl defers to getDevice()->newSurface(info)
+ virtual sk_sp<SkSurface> onNewSurface(const SkImageInfo& info, const SkSurfaceProps& props);
+
+ // default impl defers to its device
+ virtual bool onPeekPixels(SkPixmap* pixmap);
+ virtual bool onAccessTopLayerPixels(SkPixmap* pixmap);
+ virtual SkImageInfo onImageInfo() const;
+ virtual bool onGetProps(SkSurfaceProps* props) const;
+ virtual void onFlush();
+
+ // Subclass save/restore notifiers.
+ // Overriders should call the corresponding INHERITED method up the inheritance chain.
+ // getSaveLayerStrategy()'s return value may suppress full layer allocation.
+ enum SaveLayerStrategy {
+ kFullLayer_SaveLayerStrategy,
+ kNoLayer_SaveLayerStrategy,
+ };
+
+ virtual void willSave() {}
+ // Overriders should call the corresponding INHERITED method up the inheritance chain.
+ virtual SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& ) {
+ return kFullLayer_SaveLayerStrategy;
+ }
+
+ // returns true if we should actually perform the saveBehind, or false if we should just save.
+ virtual bool onDoSaveBehind(const SkRect*) { return true; }
+ virtual void willRestore() {}
+ virtual void didRestore() {}
+
+ virtual void didConcat44(const SkM44&) {}
+ virtual void didSetM44(const SkM44&) {}
+ virtual void didTranslate(SkScalar, SkScalar) {}
+ virtual void didScale(SkScalar, SkScalar) {}
+
+#ifndef SK_ENABLE_EXPERIMENTAL_CUSTOM_MESH
+ // Define this in protected so we can still access internally for testing.
+ void drawCustomMesh(SkCustomMesh cm, sk_sp<SkBlender> blender, const SkPaint& paint);
+#endif
+
+ // NOTE: If you are adding a new onDraw virtual to SkCanvas, PLEASE add an override to
+ // SkCanvasVirtualEnforcer (in SkCanvasVirtualEnforcer.h). This ensures that subclasses using
+ // that mechanism will be required to implement the new function.
+ virtual void onDrawPaint(const SkPaint& paint);
+ virtual void onDrawBehind(const SkPaint& paint);
+ virtual void onDrawRect(const SkRect& rect, const SkPaint& paint);
+ virtual void onDrawRRect(const SkRRect& rrect, const SkPaint& paint);
+ virtual void onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint);
+ virtual void onDrawOval(const SkRect& rect, const SkPaint& paint);
+ virtual void onDrawArc(const SkRect& rect, SkScalar startAngle, SkScalar sweepAngle,
+ bool useCenter, const SkPaint& paint);
+ virtual void onDrawPath(const SkPath& path, const SkPaint& paint);
+ virtual void onDrawRegion(const SkRegion& region, const SkPaint& paint);
+
+ virtual void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
+ const SkPaint& paint);
+
+ virtual void onDrawGlyphRunList(const SkGlyphRunList& glyphRunList, const SkPaint& paint);
+
+ virtual void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
+ const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint);
+ virtual void onDrawPoints(PointMode mode, size_t count, const SkPoint pts[],
+ const SkPaint& paint);
+
+ virtual void onDrawImage2(const SkImage*, SkScalar dx, SkScalar dy, const SkSamplingOptions&,
+ const SkPaint*);
+ virtual void onDrawImageRect2(const SkImage*, const SkRect& src, const SkRect& dst,
+ const SkSamplingOptions&, const SkPaint*, SrcRectConstraint);
+ virtual void onDrawImageLattice2(const SkImage*, const Lattice&, const SkRect& dst,
+ SkFilterMode, const SkPaint*);
+ virtual void onDrawAtlas2(const SkImage*, const SkRSXform[], const SkRect src[],
+ const SkColor[], int count, SkBlendMode, const SkSamplingOptions&,
+ const SkRect* cull, const SkPaint*);
+ virtual void onDrawEdgeAAImageSet2(const ImageSetEntry imageSet[], int count,
+ const SkPoint dstClips[], const SkMatrix preViewMatrices[],
+ const SkSamplingOptions&, const SkPaint*,
+ SrcRectConstraint);
+
+ virtual void onDrawVerticesObject(const SkVertices* vertices, SkBlendMode mode,
+ const SkPaint& paint);
+#ifdef SK_ENABLE_SKSL
+ virtual void onDrawCustomMesh(SkCustomMesh, sk_sp<SkBlender>, const SkPaint&);
+#endif
+ virtual void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value);
+ virtual void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&);
+
+ virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix);
+ virtual void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
+ const SkPaint* paint);
+
+ virtual void onDrawEdgeAAQuad(const SkRect& rect, const SkPoint clip[4], QuadAAFlags aaFlags,
+ const SkColor4f& color, SkBlendMode mode);
+
+ enum ClipEdgeStyle {
+ kHard_ClipEdgeStyle,
+ kSoft_ClipEdgeStyle
+ };
+
+ virtual void onClipRect(const SkRect& rect, SkClipOp op, ClipEdgeStyle edgeStyle);
+ virtual void onClipRRect(const SkRRect& rrect, SkClipOp op, ClipEdgeStyle edgeStyle);
+ virtual void onClipPath(const SkPath& path, SkClipOp op, ClipEdgeStyle edgeStyle);
+ virtual void onClipShader(sk_sp<SkShader>, SkClipOp);
+ virtual void onClipRegion(const SkRegion& deviceRgn, SkClipOp op);
+ virtual void onResetClip();
+
+ virtual void onDiscard();
+
+#if SK_SUPPORT_GPU
+ /** Experimental
+ */
+ virtual sk_sp<GrSlug> doConvertBlobToSlug(
+ const SkTextBlob& blob, SkPoint origin, const SkPaint& paint);
+
+ /** Experimental
+ */
+ virtual void doDrawSlug(GrSlug* slug);
+#endif
+
+private:
+
+ enum ShaderOverrideOpacity {
+ kNone_ShaderOverrideOpacity, //!< there is no overriding shader (bitmap or image)
+ kOpaque_ShaderOverrideOpacity, //!< the overriding shader is opaque
+ kNotOpaque_ShaderOverrideOpacity, //!< the overriding shader may not be opaque
+ };
+
+ // notify our surface (if we have one) that we are about to draw, so it
+ // can perform copy-on-write or invalidate any cached images
+ // returns false if the copy failed
+ bool SK_WARN_UNUSED_RESULT predrawNotify(bool willOverwritesEntireSurface = false);
+ bool SK_WARN_UNUSED_RESULT predrawNotify(const SkRect*, const SkPaint*, ShaderOverrideOpacity);
+
+ enum class CheckForOverwrite : bool {
+ kNo = false,
+ kYes = true
+ };
+ // call the appropriate predrawNotify and create a layer if needed.
+ skstd::optional<AutoLayerForImageFilter> aboutToDraw(
+ SkCanvas* canvas,
+ const SkPaint& paint,
+ const SkRect* rawBounds = nullptr,
+ CheckForOverwrite = CheckForOverwrite::kNo,
+ ShaderOverrideOpacity = kNone_ShaderOverrideOpacity);
+
+ // The bottom-most device in the stack, only changed by init(). Image properties and the final
+ // canvas pixels are determined by this device.
+ SkBaseDevice* baseDevice() const {
+ SkASSERT(fBaseDevice);
+ return fBaseDevice.get();
+ }
+
+ // The top-most device in the stack, will change within saveLayer()'s. All drawing and clipping
+ // operations should route to this device.
+ SkBaseDevice* topDevice() const;
+
+ // Canvases maintain a sparse stack of layers, where the top-most layer receives the drawing,
+ // clip, and matrix commands. There is a layer per call to saveLayer() using the
+ // kFullLayer_SaveLayerStrategy.
+ struct Layer {
+ sk_sp<SkBaseDevice> fDevice;
+ sk_sp<SkImageFilter> fImageFilter; // applied to layer *before* being drawn by paint
+ SkPaint fPaint;
+ bool fDiscard;
+
+ Layer(sk_sp<SkBaseDevice> device, sk_sp<SkImageFilter> imageFilter, const SkPaint& paint);
+ };
+
+ // Encapsulate state needed to restore from saveBehind()
+ struct BackImage {
+ sk_sp<SkSpecialImage> fImage;
+ SkIPoint fLoc;
+ };
+
+ class MCRec {
+ public:
+ // If not null, this MCRec corresponds with the saveLayer() record that made the layer.
+ // The base "layer" is not stored here, since it is stored inline in SkCanvas and has no
+ // restoration behavior.
+ std::unique_ptr<Layer> fLayer;
+
+ // This points to the device of the top-most layer (which may be lower in the stack), or
+ // to the canvas's fBaseDevice. The MCRec does not own the device.
+ SkBaseDevice* fDevice;
+
+ std::unique_ptr<BackImage> fBackImage;
+ SkM44 fMatrix;
+ int fDeferredSaveCount = 0;
+
+ MCRec(SkBaseDevice* device);
+ MCRec(const MCRec* prev);
+ ~MCRec();
+
+ void newLayer(sk_sp<SkBaseDevice> layerDevice,
+ sk_sp<SkImageFilter> filter,
+ const SkPaint& restorePaint);
+
+ void reset(SkBaseDevice* device);
+ };
+
+ SkDeque fMCStack;
+ // points to top of stack
+ MCRec* fMCRec;
+
+ // the first N recs that can fit here mean we won't call malloc
+ static constexpr int kMCRecSize = 96; // most recent measurement
+ static constexpr int kMCRecCount = 32; // common depth for save/restores
+
+ intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
+
+ // Installed via init()
+ sk_sp<SkBaseDevice> fBaseDevice;
+ const SkSurfaceProps fProps;
+
+ int fSaveCount; // value returned by getSaveCount()
+
+ std::unique_ptr<SkRasterHandleAllocator> fAllocator;
+
+ SkSurface_Base* fSurfaceBase;
+ SkSurface_Base* getSurfaceBase() const { return fSurfaceBase; }
+ void setSurfaceBase(SkSurface_Base* sb) {
+ fSurfaceBase = sb;
+ }
+ friend class SkSurface_Base;
+ friend class SkSurface_Gpu;
+
+ SkIRect fClipRestrictionRect = SkIRect::MakeEmpty();
+ int fClipRestrictionSaveCount = -1;
+
+ void doSave();
+ void checkForDeferredSave();
+ void internalSetMatrix(const SkM44&);
+
+ friend class SkAndroidFrameworkUtils;
+ friend class SkCanvasPriv; // needs to expose android functions for testing outside android
+ friend class AutoLayerForImageFilter;
+ friend class SkSurface_Raster; // needs getDevice()
+ friend class SkNoDrawCanvas; // needs resetForNextPicture()
+ friend class SkNWayCanvas;
+ friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
+ friend class SkOverdrawCanvas;
+ friend class SkRasterHandleAllocator;
+protected:
+ // For use by SkNoDrawCanvas (via SkCanvasVirtualEnforcer, which can't be a friend)
+ SkCanvas(const SkIRect& bounds);
+private:
+ SkCanvas(const SkBitmap&, std::unique_ptr<SkRasterHandleAllocator>,
+ SkRasterHandleAllocator::Handle);
+
+ SkCanvas(SkCanvas&&) = delete;
+ SkCanvas(const SkCanvas&) = delete;
+ SkCanvas& operator=(SkCanvas&&) = delete;
+ SkCanvas& operator=(const SkCanvas&) = delete;
+
+#if SK_SUPPORT_GPU
+ friend class GrSlug;
+ /** Experimental
+ * Convert a SkTextBlob to a GrSlug using the current canvas state.
+ */
+ sk_sp<GrSlug> convertBlobToSlug(const SkTextBlob& blob, SkPoint origin, const SkPaint& paint);
+
+ /** Experimental
+ * Draw an GrSlug given the current canvas state.
+ */
+ void drawSlug(GrSlug* slug);
+#endif
+
+ /** Experimental
+ * Saves the specified subset of the current pixels in the current layer,
+ * and then clears those pixels to transparent black.
+ * Restores the pixels on restore() by drawing them in SkBlendMode::kDstOver.
+ *
+ * @param subset conservative bounds of the area to be saved / restored.
+ * @return depth of save state stack before this call was made.
+ */
+ int only_axis_aligned_saveBehind(const SkRect* subset);
+
+ /**
+ * Like drawPaint, but magically clipped to the most recent saveBehind buffer rectangle.
+ * If there is no active saveBehind, then this draws nothing.
+ */
+ void drawClippedToSaveBehind(const SkPaint&);
+
+ void resetForNextPicture(const SkIRect& bounds);
+
+ // needs gettotalclip()
+ friend class SkCanvasStateUtils;
+
+ void init(sk_sp<SkBaseDevice>);
+
+ // All base onDrawX() functions should call this and skip drawing if it returns true.
+ // If 'matrix' is non-null, it maps the paint's fast bounds before checking for quick rejection
+ bool internalQuickReject(const SkRect& bounds, const SkPaint& paint,
+ const SkMatrix* matrix = nullptr);
+
+ void internalDrawPaint(const SkPaint& paint);
+ void internalSaveLayer(const SaveLayerRec&, SaveLayerStrategy);
+ void internalSaveBehind(const SkRect*);
+
+ void internalConcat44(const SkM44&);
+
+ // shared by save() and saveLayer()
+ void internalSave();
+ void internalRestore();
+
+ enum class DeviceCompatibleWithFilter : bool {
+ // Check the src device's local-to-device matrix for compatibility with the filter, and if
+ // it is not compatible, introduce an intermediate image and transformation that allows the
+ // filter to be evaluated on the modified src content.
+ kUnknown = false,
+ // Assume that the src device's local-to-device matrix is compatible with the filter.
+ kYes = true
+ };
+ /**
+ * Filters the contents of 'src' and draws the result into 'dst'. The filter is evaluated
+ * relative to the current canvas matrix, and src is drawn to dst using their relative transform
+ * 'paint' is applied after the filter and must not have a mask or image filter of its own.
+ * A null 'filter' behaves as if the identity filter were used.
+ *
+ * 'scaleFactor' is an extra uniform scale transform applied to downscale the 'src' image
+ * before any filtering, or as part of the copy, and is then drawn with 1/scaleFactor to 'dst'.
+ * Must be 1.0 if 'compat' is kYes (i.e. any scale factor has already been baked into the
+ * relative transforms between the devices).
+ */
+ void internalDrawDeviceWithFilter(SkBaseDevice* src, SkBaseDevice* dst,
+ const SkImageFilter* filter, const SkPaint& paint,
+ DeviceCompatibleWithFilter compat,
+ SkScalar scaleFactor = 1.f);
+
+ /*
+ * Returns true if drawing the specified rect (or all if it is null) with the specified
+ * paint (or default if null) would overwrite the entire root device of the canvas
+ * (i.e. the canvas' surface if it had one).
+ */
+ bool wouldOverwriteEntireSurface(const SkRect*, const SkPaint*, ShaderOverrideOpacity) const;
+
+ /**
+ * Returns true if the paint's imagefilter can be invoked directly, without needed a layer.
+ */
+ bool canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkSamplingOptions&,
+ const SkPaint&);
+
+ /**
+ * Returns true if the clip (for any active layer) contains antialiasing.
+ * If the clip is empty, this will return false.
+ */
+ bool androidFramework_isClipAA() const;
+
+ /**
+ * Reset the clip to be wide-open (modulo any separately specified device clip restriction).
+ * This operate within the save/restore clip stack so it can be undone by restoring to an
+ * earlier save point.
+ */
+ void internal_private_resetClip();
+
+ virtual SkPaintFilterCanvas* internal_private_asPaintFilterCanvas() const { return nullptr; }
+
+ // Keep track of the device clip bounds in the canvas' global space to reject draws before
+ // invoking the top-level device.
+ SkRect fQuickRejectBounds;
+
+ // Compute the clip's bounds based on all clipped SkDevice's reported device bounds transformed
+ // into the canvas' global space.
+ SkRect computeDeviceClipBounds(bool outsetForAA=true) const;
+
+ class AutoUpdateQRBounds;
+ void validateClip() const;
+
+ std::unique_ptr<SkGlyphRunBuilder> fScratchGlyphRunBuilder;
+
+ using INHERITED = SkRefCnt;
+};
+
+/** \class SkAutoCanvasRestore
+ Stack helper class calls SkCanvas::restoreToCount when SkAutoCanvasRestore
+ goes out of scope. Use this to guarantee that the canvas is restored to a known
+ state.
+*/
+class SkAutoCanvasRestore {
+public:
+
+ /** Preserves SkCanvas::save() count. Optionally saves SkCanvas clip and SkCanvas matrix.
+
+ @param canvas SkCanvas to guard
+ @param doSave call SkCanvas::save()
+ @return utility to restore SkCanvas state on destructor
+ */
+ SkAutoCanvasRestore(SkCanvas* canvas, bool doSave) : fCanvas(canvas), fSaveCount(0) {
+ if (fCanvas) {
+ fSaveCount = canvas->getSaveCount();
+ if (doSave) {
+ canvas->save();
+ }
+ }
+ }
+
+ /** Restores SkCanvas to saved state. Destructor is called when container goes out of
+ scope.
+ */
+ ~SkAutoCanvasRestore() {
+ if (fCanvas) {
+ fCanvas->restoreToCount(fSaveCount);
+ }
+ }
+
+ /** Restores SkCanvas to saved state immediately. Subsequent calls and
+ ~SkAutoCanvasRestore() have no effect.
+ */
+ void restore() {
+ if (fCanvas) {
+ fCanvas->restoreToCount(fSaveCount);
+ fCanvas = nullptr;
+ }
+ }
+
+private:
+ SkCanvas* fCanvas;
+ int fSaveCount;
+
+ SkAutoCanvasRestore(SkAutoCanvasRestore&&) = delete;
+ SkAutoCanvasRestore(const SkAutoCanvasRestore&) = delete;
+ SkAutoCanvasRestore& operator=(SkAutoCanvasRestore&&) = delete;
+ SkAutoCanvasRestore& operator=(const SkAutoCanvasRestore&) = delete;
+};
+
+#endif