/*
* 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/SkArc.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkClipOp.h"
#include "include/core/SkColor.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkImageFilter.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/SkRSXform.h" // IWYU pragma: keep (for unspanned apis)
#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/SkSpan.h"
#include "include/core/SkString.h"
#include "include/core/SkSurfaceProps.h"
#include "include/core/SkTileMode.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkCPUTypes.h"
#include "include/private/base/SkDeque.h"
#include "include/private/base/SkTArray.h"
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <optional>
#ifndef SK_SUPPORT_LEGACY_GETTOTALMATRIX
#define SK_SUPPORT_LEGACY_GETTOTALMATRIX
#endif
namespace sktext {
class GlyphRunBuilder;
class GlyphRunList;
}
class AutoLayerForImageFilter;
class GrRecordingContext;
class SkBitmap;
class SkBlender;
class SkBlurMaskFilterImpl;
class SkColorSpace;
class SkData;
class SkDevice;
class SkDrawable;
class SkFont;
class SkImage;
class SkMesh;
class SkPaintFilterCanvas;
class SkPath;
class SkPicture;
class SkPixmap;
class SkRRect;
class SkRegion;
class SkRecorder;
class SkShader;
class SkSpecialImage;
class SkSurface;
class SkSurface_Base;
class SkTextBlob;
class SkVertices;
struct SkDrawShadowRec;
template <typename E>
class SkEnumBitMask;
namespace skgpu::graphite { class Recorder; }
namespace sktext::gpu { class Slug; }
namespace SkRecords { class Draw; }
namespace skiatest {
template <typename Key>
class TestCanvas;// IWYU pragma: keep
}
/** \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 SkDevice .
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 SkDevice 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<SkDevice> 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
DEPRECATED : Replace usage with getBaseProps ( ) or getTopProps ( )
example : https : //fiddle.skia.org/c/@Canvas_getProps
*/
bool getProps(SkSurfaceProps* props) const ;
/** Returns the SkSurfaceProps associated with the canvas (i.e., at the base of the layer
stack ) .
@ return base SkSurfaceProps
*/
SkSurfaceProps getBaseProps() const ;
/** Returns the SkSurfaceProps associated with the canvas that are currently active (i.e., at
the top of the layer stack ) . This can differ from getBaseProps depending on the flags
passed to saveLayer ( see SaveLayerFlagsSet ) .
@ return SkSurfaceProps active in the current / top layer
*/
SkSurfaceProps getTopProps() const ;
/** 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 Ganesh 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() const ;
/** Returns Recorder for the GPU surface associated with SkCanvas.
@ return Recorder , if available ; nullptr otherwise
*/
virtual skgpu::graphite::Recorder* recorder() const ;
/** Returns Recorder for the surface associated with SkCanvas.
@ return Recorder , should be non - null
*/
virtual SkRecorder* baseRecorder() const ;
/** 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 SkDevice 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 SkDevice 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 SkDevice 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 SkDevice 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 SkDevice 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 SkDevice 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 SkSurface for subsequent drawing.
Calling restore ( ) discards changes to SkMatrix and clip , and draws the SkSurface .
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 SkSurface 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 SkSurface for subsequent drawing.
Calling restore ( ) discards changes to SkMatrix and clip , and draws the SkSurface .
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 SkSurface 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 , 1 . 0 f 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 saveLayerAlphaf(const SkRect* bounds, float alpha);
// Helper that accepts an int between 0 and 255, and divides it by 255.0
int saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
return this ->saveLayerAlphaf(bounds, alpha * (1 .0 f / 255 ));
}
/** \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 ,
};
using SaveLayerFlags = uint32_t;
using FilterSpan = SkSpan<sk_sp<SkImageFilter>>;
static constexpr int kMaxFiltersPerLayer = 16 ;
/** \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, nullptr, 1 .f, SkTileMode::kClamp,
saveLayerFlags, /*filters=*/{}) {}
/** 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, nullptr, 1 .f, SkTileMode::kClamp,
saveLayerFlags, /*filters=*/{}) {}
/** Sets fBounds, fBackdrop, fColorSpace, 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 colorSpace If not null , when the layer is restored , a color space
conversion will be applied from this color space to the
parent ' s color space . The restore paint and backdrop filters will
be applied in this color space .
If null , the new layer will inherit the color space from its
parent .
@ param saveLayerFlags SaveLayerRec options to modify layer
@ return SaveLayerRec fully specified
*/
SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
const SkColorSpace* colorSpace, SaveLayerFlags saveLayerFlags)
: SaveLayerRec(bounds, paint, backdrop, colorSpace, 1 .f, SkTileMode::kClamp,
saveLayerFlags, /*filters=*/{}) {}
/** Sets fBounds, fBackdrop, fBackdropTileMode, fColorSpace, 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 backdropTileMode If the ' backdrop ' is not null , or ' saveLayerFlags ' has
kInitWithPrevious set , this tile mode is used when the new layer
would read outside the backdrop image ' s available content .
@ param colorSpace If not null , when the layer is restored , a color space
conversion will be applied from this color space to the parent ' s
color space . The restore paint and backdrop filters will be
applied in this color space .
If null , the new layer will inherit the color space from its
parent .
@ param saveLayerFlags SaveLayerRec options to modify layer
@ return SaveLayerRec fully specified
*/
SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
SkTileMode backdropTileMode, const SkColorSpace* colorSpace,
SaveLayerFlags saveLayerFlags)
: SaveLayerRec(bounds, paint, backdrop, colorSpace, 1 .f, backdropTileMode,
saveLayerFlags, /*filters=*/{}) {}
/** hints at layer size limit */
const SkRect* fBounds = nullptr;
/** modifies overlay */
const SkPaint* fPaint = nullptr;
FilterSpan fFilters = {};
/**
* 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;
/**
* If the layer is initialized with prior content ( and / or with a backdrop filter ) and this
* would require sampling outside of the available backdrop , this is the tilemode applied
* to the boundary of the prior layer ' s image .
*/
SkTileMode fBackdropTileMode = SkTileMode::kClamp;
/**
* If not null , this triggers a color space conversion when the layer is restored . It
* will be as if the layer ' s contents are drawn in this color space . Filters from
* fBackdrop and fPaint will be applied in this color space .
*/
const SkColorSpace* fColorSpace = 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,
const SkColorSpace* colorSpace,
SkScalar backdropScale,
SkTileMode backdropTileMode,
SaveLayerFlags saveLayerFlags,
FilterSpan filters)
: fBounds(bounds)
, fPaint(paint)
, fFilters(filters)
, fBackdrop(backdrop)
, fBackdropTileMode(backdropTileMode)
, fColorSpace(colorSpace)
, fSaveLayerFlags(saveLayerFlags)
, fExperimentalBackdropScale(backdropScale) {
// We only allow the paint's image filter or the side-car list of filters -- not both.
SkASSERT(fFilters.empty() || !paint || !paint->getImageFilter());
// To keep things reasonable (during deserialization), we limit filter list size.
SkASSERT(fFilters.size() <= kMaxFiltersPerLayer);
}
// 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 SkSurface for subsequent drawing.
Calling restore ( ) discards changes to SkMatrix and clip ,
and blends SkSurface 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 base device 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 SkDevice
that created SkCanvas .
discard ( ) allows optimized performance on subsequent draws by removing
cached data associated with SkSurface or SkDevice .
It is not necessary to call discard ( ) once done with SkCanvas ;
any cached data is deleted when owning SkSurface or SkDevice 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, SkSpan<const SkPoint>, 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 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 arc SkArc specifying oval , startAngle , sweepAngle , and arc - vs - wedge
@ param paint SkPaint stroke or fill , blend , color , and so on , used to draw
*/
void drawArc(const SkArc& arc, const SkPaint& paint) {
this ->drawArc(arc.fOval, arc.fStartAngle, arc.fSweepAngle, arc.isWedge(), 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 never samples outside of the src - rect .
kStrict_SrcRectConstraint disables the use of mipmaps and anisotropic filtering .
*/
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 = 0 b0001,
kTop_QuadAAFlag = 0 b0010,
kRight_QuadAAFlag = 0 b0100,
kBottom_QuadAAFlag = 0 b1000,
kNone_QuadAAFlags = 0 b0000,
kAll_QuadAAFlags = 0 b1111,
};
/** 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 glyphs the span of glyphIDs to draw
@ param positions where to draw each glyph relative to origin
@ param clusters cluster information
@ 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(SkSpan<const SkGlyphID> glyphs, SkSpan<const SkPoint> positions,
SkSpan<const uint32_t> clusters, SkSpan<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(SkSpan<const SkGlyphID> glyphs, SkSpan<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 drawGlyphsRSXform(SkSpan<const SkGlyphID> glyphs, SkSpan<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);
/**
Experimental , under active development , and subject to change without notice .
Draws a mesh using a user - defined specification ( see SkMeshSpecification ) . Requires
a GPU backend or SkSL to be compiled in .
SkBlender is ignored if SkMesh ' 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 mesh the 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 drawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint);
/** 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 .
For non - empty spans , the number of draws will be the min of
xform . size ( ) , tex . size ( ) , and ( if not empty ) colors . size ( ) .
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 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, SkSpan<const SkRSXform> xform,
SkSpan<const SkRect> tex, SkSpan<const SkColor> colors, 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 3 rd 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 3 x3 version .
*
* @ return 3 x3 version of getLocalToDevice ( )
*
* example : https : //fiddle.skia.org/c/@Canvas_getTotalMatrix
* example : https : //fiddle.skia.org/c/@Clip
*/
SkMatrix getTotalMatrix() 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, bool top) const ;
// 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) {}
// 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 sktext::GlyphRunList& 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);
virtual void onDrawMesh(const SkMesh&, sk_sp<SkBlender>, const SkPaint&);
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();
/**
*/
virtual sk_sp<sktext::gpu::Slug> onConvertGlyphRunListToSlug(
const sktext::GlyphRunList& glyphRunList, const SkPaint& paint);
/**
*/
virtual void onDrawSlug(const sktext::gpu::Slug* slug, const SkPaint& paint);
private :
enum class PredrawFlags : unsigned {
kNone = 0 ,
kOpaqueShaderOverride = 1 , // The paint's shader is overridden with an opaque image
kNonOpaqueShaderOverride = 2 , // The paint's shader is overridden but is not opaque
kCheckForOverwrite = 4 , // Check if the draw would overwrite the entire surface
kSkipMaskFilterAutoLayer = 8 , // Do not apply mask filters in the AutoLayer
};
// Inlined SK_DECL_BITMASK_OPS_FRIENDS to avoid including SkEnumBitMask.h
friend constexpr SkEnumBitMask<PredrawFlags> operator |(PredrawFlags, PredrawFlags);
friend constexpr SkEnumBitMask<PredrawFlags> operator &(PredrawFlags, PredrawFlags);
friend constexpr SkEnumBitMask<PredrawFlags> operator ^(PredrawFlags, PredrawFlags);
friend constexpr SkEnumBitMask<PredrawFlags> operator ~(PredrawFlags);
// 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
[[nodiscard]] bool predrawNotify(bool willOverwritesEntireSurface = false );
[[nodiscard]] bool predrawNotify(const SkRect*, const SkPaint*, SkEnumBitMask<PredrawFlags>);
// call the appropriate predrawNotify and create a layer if needed.
std::optional<AutoLayerForImageFilter> aboutToDraw(
const SkPaint& paint,
const SkRect* rawBounds,
SkEnumBitMask<PredrawFlags> flags);
std::optional<AutoLayerForImageFilter> aboutToDraw(
const SkPaint& paint,
const SkRect* rawBounds = nullptr);
// The bottom-most device in the stack, only changed by init(). Image properties and the final
// canvas pixels are determined by this device.
SkDevice* rootDevice() const {
SkASSERT(fRootDevice);
return fRootDevice.get();
}
// The top-most device in the stack, will change within saveLayer()'s. All drawing and clipping
// operations should route to this device.
SkDevice* 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<SkDevice> fDevice;
skia_private::STArray<1 , sk_sp<SkImageFilter>> fImageFilters;
SkPaint fPaint;
bool fIsCoverage;
bool fDiscard;
// If true, the layer image is sized to include a 1px buffer that remains transparent
// to allow for faster linear filtering under complex transforms.
bool fIncludesPadding;
Layer(sk_sp<SkDevice> device,
FilterSpan imageFilters,
const SkPaint& paint,
bool isCoverage,
bool includesPadding);
};
// Encapsulate state needed to restore from saveBehind()
struct BackImage {
// Out of line to avoid including SkSpecialImage.h
BackImage(sk_sp<SkSpecialImage>, SkIPoint);
BackImage(const BackImage&);
BackImage(BackImage&&);
BackImage& operator =(const BackImage&);
~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 fRootDevice. The MCRec does not own the device.
SkDevice* fDevice;
std::unique_ptr<BackImage> fBackImage;
SkM44 fMatrix;
int fDeferredSaveCount = 0 ;
MCRec(SkDevice* device);
MCRec(const MCRec* prev);
~MCRec();
void newLayer(sk_sp<SkDevice> layerDevice,
FilterSpan filters,
const SkPaint& restorePaint,
bool layerIsCoverage,
bool includesPadding);
void reset(SkDevice* device);
};
#if defined (SK_CANVAS_SAVE_RESTORE_PREALLOC_COUNT)
static constexpr int kMCRecCount = SK_CANVAS_SAVE_RESTORE_PREALLOC_COUNT;
#else
static constexpr int kMCRecCount = 32 ; // common depth for save/restores
#endif
// This stack allocation of memory will be used to house the first kMCRecCount
// layers without need to call malloc.
alignas(MCRec) std::byte fMCRecStorage[sizeof (MCRec) * kMCRecCount];
SkDeque fMCStack; // uses the stack memory
MCRec* fMCRec; // points to top of stack for convenience
// Installed via init()
sk_sp<SkDevice> fRootDevice;
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_Ganesh;
SkIRect fClipRestrictionRect = SkIRect::MakeEmpty();
int fClipRestrictionSaveCount = -1 ;
void doSave();
void checkForDeferredSave();
void internalSetMatrix(const SkM44&);
virtual void onSurfaceDelete() {}
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;
friend class SkRecords::Draw;
template <typename Key>
friend class skiatest::TestCanvas;
protected :
// For use by SkNoDrawCanvas (via SkCanvasVirtualEnforcer, which can't be a friend)
explicit SkCanvas(const SkIRect& bounds);
private :
SkCanvas(const SkBitmap&, std::unique_ptr<SkRasterHandleAllocator>,
SkRasterHandleAllocator::Handle, const SkSurfaceProps* props);
SkCanvas(SkCanvas&&) = delete ;
SkCanvas(const SkCanvas&) = delete ;
SkCanvas& operator =(SkCanvas&&) = delete ;
SkCanvas& operator =(const SkCanvas&) = delete ;
friend class sktext::gpu::Slug;
friend class SkPicturePlayback;
/**
* Convert a SkTextBlob to a sktext : : gpu : : Slug using the current canvas state .
*/
sk_sp<sktext::gpu::Slug> convertBlobToSlug(const SkTextBlob& blob, SkPoint origin,
const SkPaint& paint);
/**
* Draw an sktext : : gpu : : Slug given the current canvas state .
*/
void drawSlug(const sktext::gpu::Slug* slug, const SkPaint& paint);
/** 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<SkDevice>);
bool nothingToDraw(const SkPaint& paint) const ;
// 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, bool coverageOnly=false );
void internalSaveBehind(const SkRect*);
void internalConcat44(const SkM44&);
// shared by save() and saveLayer()
void internalSave();
void internalRestore();
enum class DeviceCompatibleWithFilter : int {
// 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,
// Assume that the src device's local-to-device matrix is compatible with the filter.
kYes,
// Assume that the src device's local-to-device matrix is compatible with the filter,
// *and* the source image has a 1px buffer of padding.
kYesWithPadding
};
/**
* 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 ) .
*
* ' srcTileMode ' is the tile mode to apply to the boundary of the ' src ' image when insufficient
* content is available . It defaults to kDecal for the regular saveLayer ( ) case .
*/
void internalDrawDeviceWithFilter(SkDevice* src, SkDevice* dst,
FilterSpan filters, const SkPaint& paint,
DeviceCompatibleWithFilter compat,
const SkColorInfo& filterColorInfo,
SkScalar scaleFactor = 1 .f,
SkTileMode srcTileMode = SkTileMode::kDecal,
bool srcIsCoverageLayer = false );
/*
* 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*,
SkEnumBitMask<PredrawFlags>) const ;
/**
* 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 ;
// Returns the paint's mask filter if it can be used to draw an rrect with an analytic blur, and
// returns null otherwise.
const SkBlurMaskFilterImpl* canAttemptBlurredRRectDraw(const SkPaint&) const ;
// Attempt to draw a rrect with an analytic blur. If the draw succeeds or predrawNotify fails,
// nullopt is returned indicating that nothing further should be drawn.
std::optional<AutoLayerForImageFilter> attemptBlurredRRectDraw(const SkRRect&,
const SkBlurMaskFilterImpl*,
const SkPaint&,
SkEnumBitMask<PredrawFlags>);
class AutoUpdateQRBounds;
void validateClip() const ;
std::unique_ptr<sktext::GlyphRunBuilder> fScratchGlyphRunBuilder;
};
/** \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 [[nodiscard]] 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
Messung V0.5 in Prozent C=89 H=100 G=94
¤ Dauer der Verarbeitung: 0.161 Sekunden
(vorverarbeitet am 2026-08-23)
¤
*© Formatika GbR, Deutschland