5d87892d2c
Bug: skia:8444 Change-Id: I0c021be8a24ceb62bd0436ec37c159b500498f8a Reviewed-on: https://skia-review.googlesource.com/c/161829 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
6256 lines
214 KiB
Plaintext
6256 lines
214 KiB
Plaintext
#Topic Canvas
|
|
#Alias Canvas_Reference ##
|
|
|
|
#Class SkCanvas
|
|
|
|
#Code
|
|
#Populate
|
|
##
|
|
|
|
Canvas provides an interface for drawing, and how the drawing is clipped and transformed.
|
|
Canvas contains a stack of Matrix and Clip values.
|
|
|
|
Canvas and Paint together provide the state to draw into Surface or Device.
|
|
Each Canvas draw call transforms the geometry of the object by the concatenation of all
|
|
Matrix values in the stack. The transformed geometry is clipped by the intersection
|
|
of all of Clip values in the stack. The Canvas draw calls use Paint to supply drawing
|
|
state such as Color, Typeface, text size, stroke width, Shader and so on.
|
|
|
|
To draw to a pixel-based destination, create Raster_Surface or GPU_Surface.
|
|
Request Canvas from Surface to obtain the interface to draw.
|
|
Canvas generated by Raster_Surface draws to memory visible to the CPU.
|
|
Canvas generated by GPU_Surface uses Vulkan or OpenGL to draw to the GPU.
|
|
|
|
To draw to a document, obtain Canvas from SVG_Canvas, Document_PDF, or Picture_Recorder.
|
|
Document based Canvas and other Canvas Subclasses reference Device describing the
|
|
destination.
|
|
|
|
Canvas can be constructed to draw to Bitmap without first creating Raster_Surface.
|
|
This approach may be deprecated in the future.
|
|
|
|
#Subtopic Constructors
|
|
|
|
Create the desired type of Surface to obtain its Canvas when possible. Useful
|
|
when no Surface is required, and some helpers implicitly create Raster_Surface.
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method static std::unique_ptr<SkCanvas> MakeRasterDirect(const SkImageInfo& info, void* pixels,
|
|
size_t rowBytes,
|
|
const SkSurfaceProps* props = nullptr)
|
|
#In Constructors
|
|
#Line # creates from SkImageInfo and Pixel_Storage ##
|
|
|
|
Allocates raster Canvas that will draw directly into pixels.
|
|
|
|
Canvas is returned if all parameters are valid.
|
|
Valid parameters include:
|
|
info dimensions are zero or positive;
|
|
info contains Color_Type and Alpha_Type supported by Raster_Surface;
|
|
pixels is not nullptr;
|
|
rowBytes is zero or large enough to contain info width pixels of Color_Type.
|
|
|
|
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 Color_Type.
|
|
|
|
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, Color_Type, Alpha_Type, Color_Space, of Raster_Surface;
|
|
width, or height, or both, may be zero
|
|
##
|
|
#Param pixels pointer to destination pixels buffer
|
|
##
|
|
#Param rowBytes interval from one Surface row to the next, or zero
|
|
##
|
|
#Param props LCD striping orientation and setting for device independent fonts;
|
|
may be nullptr
|
|
##
|
|
|
|
#Return Canvas if all parameters are valid; otherwise, nullptr ##
|
|
|
|
#Example
|
|
#Description
|
|
Allocates a three by three bitmap, clears it to white, and draws a black pixel
|
|
in the center.
|
|
##
|
|
void draw(SkCanvas* ) {
|
|
SkImageInfo info = SkImageInfo::MakeN32Premul(3, 3); // device aligned, 32 bpp, Premultiplied
|
|
const size_t minRowBytes = info.minRowBytes(); // bytes used by one bitmap row
|
|
const size_t size = info.computeMinByteSize(); // bytes used by all rows
|
|
SkAutoTMalloc<SkPMColor> storage(size); // allocate storage for pixels
|
|
SkPMColor* pixels = storage.get(); // get pointer to allocated storage
|
|
// create a SkCanvas backed by a raster device, and delete it when the
|
|
// function goes out of scope.
|
|
std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirect(info, pixels, minRowBytes);
|
|
canvas->clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
|
|
canvas->flush(); // ensure that pixels are cleared
|
|
SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
|
|
SkPaint paint; // by default, draws black
|
|
canvas->drawPoint(1, 1, paint); // draw in the center
|
|
canvas->flush(); // ensure that point was drawn
|
|
for (int y = 0; y < info.height(); ++y) {
|
|
for (int x = 0; x < info.width(); ++x) {
|
|
SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
|
|
}
|
|
SkDebugf("\n");
|
|
}
|
|
}
|
|
#StdOut
|
|
---
|
|
-x-
|
|
---
|
|
##
|
|
##
|
|
|
|
#SeeAlso MakeRasterDirectN32 SkSurface::MakeRasterDirect
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method static std::unique_ptr<SkCanvas> MakeRasterDirectN32(int width, int height, SkPMColor* pixels,
|
|
size_t rowBytes)
|
|
#In Constructors
|
|
#Line # creates from image data and Pixel_Storage ##
|
|
|
|
Allocates raster Canvas specified by inline image specification. Subsequent Canvas
|
|
calls draw into pixels.
|
|
Color_Type is set to kN32_SkColorType.
|
|
Alpha_Type is set to kPremul_SkAlphaType.
|
|
To access pixels after drawing, call flush() or peekPixels.
|
|
|
|
Canvas 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 Color_Type.
|
|
|
|
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 Surface row to the next, or zero
|
|
##
|
|
|
|
#Return Canvas if all parameters are valid; otherwise, nullptr ##
|
|
|
|
#Example
|
|
#Description
|
|
Allocates a three by three bitmap, clears it to white, and draws a black pixel
|
|
in the center.
|
|
##
|
|
void draw(SkCanvas* ) {
|
|
const int width = 3;
|
|
const int height = 3;
|
|
SkPMColor pixels[height][width]; // allocate a 3x3 Premultiplied bitmap on the stack
|
|
// create a SkCanvas backed by a raster device, and delete it when the
|
|
// function goes out of scope.
|
|
std::unique_ptr<SkCanvas> canvas = SkCanvas::MakeRasterDirectN32(
|
|
width,
|
|
height,
|
|
pixels[0], // top-left of the bitmap
|
|
sizeof(pixels[0])); // byte width of the each row
|
|
// write a Premultiplied value for white into all pixels in the bitmap
|
|
canvas->clear(SK_ColorWHITE);
|
|
SkPMColor pmWhite = pixels[0][0]; // the Premultiplied format may vary
|
|
SkPaint paint; // by default, draws black
|
|
canvas->drawPoint(1, 1, paint); // draw in the center
|
|
canvas->flush(); // ensure that pixels is ready to be read
|
|
for (int y = 0; y < height; ++y) {
|
|
for (int x = 0; x < width; ++x) {
|
|
SkDebugf("%c", pixels[y][x] == pmWhite ? '-' : 'x');
|
|
}
|
|
SkDebugf("\n");
|
|
}
|
|
}
|
|
#StdOut
|
|
---
|
|
-x-
|
|
---
|
|
##
|
|
##
|
|
|
|
#SeeAlso MakeRasterDirect SkSurface::MakeRasterDirect SkImageInfo::MakeN32Premul
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method SkCanvas()
|
|
|
|
#Line # creates with no Surface, no dimensions ##
|
|
Creates an empty Canvas with no backing device or pixels, with
|
|
a width and height of zero.
|
|
|
|
#Return empty Canvas ##
|
|
|
|
#Example
|
|
|
|
#Description
|
|
Passes a placeholder to a function that requires one.
|
|
##
|
|
|
|
#Function
|
|
// Returns true if either the canvas rotates the text by 90 degrees, or the paint does.
|
|
static void check_for_up_and_down_text(const SkCanvas* canvas, const SkPaint& paint) {
|
|
bool paintHasVertical = paint.isVerticalText();
|
|
const SkMatrix& matrix = canvas->getTotalMatrix();
|
|
bool matrixIsVertical = matrix.preservesRightAngles() && !matrix.isScaleTranslate();
|
|
SkDebugf("paint draws text %s\n", paintHasVertical != matrixIsVertical ?
|
|
"top to bottom" : "left to right");
|
|
}
|
|
|
|
static void check_for_up_and_down_text(const SkPaint& paint) {
|
|
SkCanvas canvas; // placeholder only, does not have an associated device
|
|
check_for_up_and_down_text(&canvas, paint);
|
|
}
|
|
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
check_for_up_and_down_text(paint); // paint draws text left to right
|
|
paint.setVerticalText(true);
|
|
check_for_up_and_down_text(paint); // paint draws text top to bottom
|
|
paint.setVerticalText(false);
|
|
canvas->rotate(90);
|
|
check_for_up_and_down_text(canvas, paint); // paint draws text top to bottom
|
|
}
|
|
|
|
#StdOut
|
|
paint draws text left to right
|
|
paint draws text top to bottom
|
|
paint draws text top to bottom
|
|
##
|
|
##
|
|
|
|
#SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method SkCanvas(int width, int height, const SkSurfaceProps* props = nullptr)
|
|
|
|
#Line # creates with no Surface, set dimensions, Surface_Properties ##
|
|
Creates Canvas of the specified dimensions without a Surface.
|
|
Used by Subclasses with custom implementations for draw member functions.
|
|
|
|
If props equals nullptr, Surface_Properties are created with
|
|
Surface_Properties_Legacy_Font_Host 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 Canvas placeholder with dimensions ##
|
|
|
|
#Example
|
|
SkCanvas canvas(10, 20); // 10 units wide, 20 units high
|
|
canvas.clipRect(SkRect::MakeXYWH(30, 40, 5, 10)); // clip is outside canvas' device
|
|
SkDebugf("canvas %s empty\n", canvas.getDeviceClipBounds().isEmpty() ? "is" : "is not");
|
|
|
|
#StdOut
|
|
canvas is empty
|
|
##
|
|
##
|
|
|
|
#SeeAlso MakeRasterDirect SkSurfaceProps SkPixelGeometry SkCreateColorSpaceXformCanvas
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method explicit SkCanvas(sk_sp<SkBaseDevice> device)
|
|
#Deprecated soon
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method explicit SkCanvas(const SkBitmap& bitmap)
|
|
|
|
#Line # uses existing Bitmap ##
|
|
Constructs a canvas that draws into bitmap.
|
|
Sets SkSurfaceProps::kLegacyFontHost_InitType in constructed Surface.
|
|
|
|
Bitmap is copied so that subsequently editing bitmap will not affect
|
|
constructed Canvas.
|
|
|
|
May be deprecated in the future.
|
|
|
|
#ToDo Should be deprecated? ##
|
|
|
|
#Param bitmap width, height, Color_Type, Alpha_Type, and pixel
|
|
storage of Raster_Surface
|
|
##
|
|
|
|
#Return Canvas that can be used to draw into bitmap ##
|
|
|
|
#Example
|
|
#Description
|
|
The actual output depends on the installed fonts.
|
|
##
|
|
SkBitmap bitmap;
|
|
// create a bitmap 5 wide and 11 high
|
|
bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
|
|
SkCanvas canvas(bitmap);
|
|
canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
|
|
SkPixmap pixmap; // provides guaranteed access to the drawn pixels
|
|
if (!canvas.peekPixels(&pixmap)) {
|
|
SkDebugf("peekPixels should never fail.\n");
|
|
}
|
|
const SkPMColor* pixels = pixmap.addr32(); // points to top-left of bitmap
|
|
SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
|
|
SkPaint paint; // by default, draws black, 12 point text
|
|
canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10)
|
|
for (int y = 0; y < bitmap.height(); ++y) {
|
|
for (int x = 0; x < bitmap.width(); ++x) {
|
|
SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
|
|
}
|
|
SkDebugf("\n");
|
|
}
|
|
|
|
#StdOut
|
|
-----
|
|
---x-
|
|
---x-
|
|
---x-
|
|
---x-
|
|
---x-
|
|
---x-
|
|
-----
|
|
---x-
|
|
---x-
|
|
-----
|
|
#StdOut ##
|
|
##
|
|
|
|
#SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
|
|
|
|
##
|
|
|
|
#EnumClass ColorBehavior
|
|
#Line # exists for Android framework only ##
|
|
#Private
|
|
Android framework only.
|
|
##
|
|
|
|
#Code
|
|
#Populate
|
|
##
|
|
#Const kLegacy 0
|
|
#Line # placeholder ##
|
|
Is a placeholder to allow specialized constructor; has no meaning.
|
|
##
|
|
##
|
|
|
|
#Method SkCanvas(const SkBitmap& bitmap, ColorBehavior behavior)
|
|
|
|
#Line # exists for Android framework only ##
|
|
|
|
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 Canvas that can be used to draw into bitmap ##
|
|
|
|
#NoExample
|
|
##
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
|
|
|
|
#Line # uses existing Bitmap and Surface_Properties ##
|
|
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 Canvas.
|
|
|
|
#Param bitmap width, height, Color_Type, Alpha_Type,
|
|
and pixel storage of Raster_Surface
|
|
##
|
|
#Param props order and orientation of RGB striping; and whether to use
|
|
device independent fonts
|
|
##
|
|
|
|
#Return Canvas that can be used to draw into bitmap ##
|
|
|
|
#Example
|
|
#Description
|
|
The actual output depends on the installed fonts.
|
|
##
|
|
SkBitmap bitmap;
|
|
// create a bitmap 5 wide and 11 high
|
|
bitmap.allocPixels(SkImageInfo::MakeN32Premul(5, 11));
|
|
SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
|
|
canvas.clear(SK_ColorWHITE); // white is Unpremultiplied, in ARGB order
|
|
SkPixmap pixmap; // provides guaranteed access to the drawn pixels
|
|
if (!canvas.peekPixels(&pixmap)) {
|
|
SkDebugf("peekPixels should never fail.\n");
|
|
}
|
|
const SkPMColor* pixels = pixmap.addr32(); // points to top-left of bitmap
|
|
SkPMColor pmWhite = pixels[0]; // the Premultiplied format may vary
|
|
SkPaint paint; // by default, draws black, 12 point text
|
|
canvas.drawString("!", 1, 10, paint); // 1 char at baseline (1, 10)
|
|
for (int y = 0; y < bitmap.height(); ++y) {
|
|
for (int x = 0; x < bitmap.width(); ++x) {
|
|
SkDebugf("%c", *pixels++ == pmWhite ? '-' : 'x');
|
|
}
|
|
SkDebugf("\n");
|
|
}
|
|
|
|
#StdOut
|
|
-----
|
|
---x-
|
|
---x-
|
|
---x-
|
|
---x-
|
|
---x-
|
|
---x-
|
|
-----
|
|
---x-
|
|
---x-
|
|
-----
|
|
#StdOut ##
|
|
##
|
|
|
|
#SeeAlso MakeRasterDirect SkRasterHandleAllocator::MakeCanvas SkSurface::getCanvas SkCreateColorSpaceXformCanvas
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method virtual ~SkCanvas()
|
|
|
|
#Line # draws saved Layers, frees resources ##
|
|
Draws saved Layers, if any.
|
|
Frees up resources used by Canvas.
|
|
|
|
#Example
|
|
#Description
|
|
Canvas Layer draws into bitmap. saveLayerAlpha sets up an additional
|
|
drawing surface that blends with the bitmap. When Layer goes out of
|
|
scope, Layer Destructor is called. The saved Layer is restored, drawing
|
|
transparent letters.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkBitmap bitmap;
|
|
bitmap.allocPixels(SkImageInfo::MakeN32Premul(200, 200));
|
|
{
|
|
SkCanvas offscreen(bitmap);
|
|
SkPaint paint;
|
|
paint.setTextSize(100);
|
|
offscreen.drawString("ABC", 20, 160, paint);
|
|
SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
|
|
offscreen.saveLayerAlpha(&layerBounds, 128);
|
|
offscreen.clear(SK_ColorWHITE);
|
|
offscreen.drawString("DEF", 20, 160, paint);
|
|
}
|
|
canvas->drawBitmap(bitmap, 0, 0, nullptr);
|
|
}
|
|
##
|
|
|
|
#SeeAlso State_Stack
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
#Subtopic Property
|
|
#Line # metrics and attributes ##
|
|
##
|
|
|
|
#Method SkMetaData& getMetaData()
|
|
#In Property
|
|
#In Utility
|
|
#Line # associates additional data with the canvas ##
|
|
Returns storage to associate additional data with the canvas.
|
|
The storage is freed when Canvas is deleted.
|
|
|
|
#Return storage that can be read from and written to ##
|
|
|
|
#Example
|
|
const char* kHelloMetaData = "HelloMetaData";
|
|
SkCanvas canvas;
|
|
SkMetaData& metaData = canvas.getMetaData();
|
|
SkDebugf("before: %s\n", metaData.findString(kHelloMetaData));
|
|
metaData.setString(kHelloMetaData, "Hello!");
|
|
SkDebugf("during: %s\n", metaData.findString(kHelloMetaData));
|
|
metaData.removeString(kHelloMetaData);
|
|
SkDebugf("after: %s\n", metaData.findString(kHelloMetaData));
|
|
|
|
#StdOut
|
|
before: (null)
|
|
during: Hello!
|
|
after: (null)
|
|
#StdOut ##
|
|
##
|
|
|
|
#SeeAlso SkMetaData
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method SkImageInfo imageInfo() const
|
|
#In Property
|
|
#Line # returns Image_Info for Canvas ##
|
|
Returns Image_Info for Canvas. If Canvas is not associated with Raster_Surface or
|
|
GPU_Surface, returned Color_Type is set to kUnknown_SkColorType.
|
|
|
|
#Return dimensions and Color_Type of Canvas ##
|
|
|
|
#Example
|
|
SkCanvas emptyCanvas;
|
|
SkImageInfo canvasInfo = emptyCanvas.imageInfo();
|
|
SkImageInfo emptyInfo;
|
|
SkDebugf("emptyInfo %c= canvasInfo\n", emptyInfo == canvasInfo ? '=' : '!');
|
|
|
|
#StdOut
|
|
emptyInfo == canvasInfo
|
|
##
|
|
##
|
|
|
|
#SeeAlso SkImageInfo MakeRasterDirect makeSurface
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method bool getProps(SkSurfaceProps* props) const
|
|
#In Property
|
|
#Line # copies Surface_Properties if available ##
|
|
Copies Surface_Properties, if Canvas 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 Surface_Properties was copied ##
|
|
|
|
#ToDo This seems old style. Deprecate? ##
|
|
|
|
#Example
|
|
SkBitmap bitmap;
|
|
SkCanvas canvas(bitmap, SkSurfaceProps(0, kRGB_V_SkPixelGeometry));
|
|
SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry);
|
|
SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
|
|
if (!canvas.getProps(&surfaceProps)) {
|
|
SkDebugf("getProps failed unexpectedly.\n");
|
|
}
|
|
SkDebugf("isRGB:%d\n", SkPixelGeometryIsRGB(surfaceProps.pixelGeometry()));
|
|
|
|
#StdOut
|
|
isRGB:0
|
|
isRGB:1
|
|
#StdOut ##
|
|
##
|
|
|
|
#SeeAlso SkSurfaceProps makeSurface
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
#Subtopic Utility
|
|
#Line # rarely called management functions ##
|
|
##
|
|
|
|
#Method void flush()
|
|
#In Utility
|
|
#Line # triggers execution of all pending draw operations ##
|
|
Triggers the immediate execution of all pending draw operations.
|
|
If Canvas is associated with GPU_Surface, resolves all pending GPU operations.
|
|
If Canvas is associated with Raster_Surface, has no effect; raster draw
|
|
operations are never deferred.
|
|
|
|
#ToDo
|
|
In an overview section on managing the GPU, include:
|
|
- flush should never change what is drawn
|
|
- call to kick off gpu work
|
|
- calling too much impacts performance
|
|
- some calls (peekPixels, prepareForExternalIO) call it internally
|
|
- canvas call is local, GrContext::flush is global
|
|
- diffentiate between flush, flushAndSignalSemaphores
|
|
- normally never needs to be called
|
|
- call it when sharing gpu resources, feeling memory pressure, swapping out app, and before
|
|
abandoning context
|
|
- also call to say "I'm finished drawing here", e.g., when drawing to a GPU-backed offscreen surface
|
|
(created with SkSurface::MakeRenderTarget)
|
|
|
|
for posterity: this doesn't show a difference: fiddle.skia.org/c/@flushfail
|
|
##
|
|
|
|
#ToDo haven't thought of a useful example to put here ##
|
|
#NoExample
|
|
##
|
|
|
|
#SeeAlso peekPixels SkSurface::flush() GrContext::flush() SkSurface::prepareForExternalIO GrContext::abandonContext()
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method virtual SkISize getBaseLayerSize() const
|
|
#In Property
|
|
#Line # returns size of base Layer in global coordinates ##
|
|
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
|
|
SkBitmap bitmap;
|
|
bitmap.allocPixels(SkImageInfo::MakeN32Premul(20, 30));
|
|
SkCanvas canvas(bitmap, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
|
|
canvas.clipRect(SkRect::MakeWH(10, 40));
|
|
SkIRect clipDeviceBounds = canvas.getDeviceClipBounds();
|
|
if (clipDeviceBounds.isEmpty()) {
|
|
SkDebugf("Empty clip bounds is unexpected!\n");
|
|
}
|
|
SkDebugf("clip=%d,%d\n", clipDeviceBounds.width(), clipDeviceBounds.height());
|
|
SkISize baseLayerSize = canvas.getBaseLayerSize();
|
|
SkDebugf("size=%d,%d\n", baseLayerSize.width(), baseLayerSize.height());
|
|
|
|
#StdOut
|
|
clip=10,30
|
|
size=20,30
|
|
##
|
|
##
|
|
|
|
#ToDo is this the same as the width and height of surface? ##
|
|
|
|
#SeeAlso getDeviceClipBounds
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method sk_sp<SkSurface> makeSurface(const SkImageInfo& info, const SkSurfaceProps* props = nullptr)
|
|
#In Constructors
|
|
#Line # creates Surface matching SkImageInfo and SkSurfaceProps ##
|
|
Creates Surface matching info and props, and associates it with Canvas.
|
|
Returns nullptr if no match found.
|
|
|
|
If props is nullptr, matches Surface_Properties in Canvas. If props is nullptr and Canvas
|
|
does not have Surface_Properties, creates Surface with default Surface_Properties.
|
|
|
|
#Param info width, height, Color_Type, Alpha_Type, and Color_Space ##
|
|
#Param props Surface_Properties to match; may be nullptr to match Canvas ##
|
|
|
|
#Return Surface matching info and props, or nullptr if no match is available ##
|
|
|
|
#Example
|
|
sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(5, 6);
|
|
SkCanvas* smallCanvas = surface->getCanvas();
|
|
SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(3, 4);
|
|
sk_sp<SkSurface> compatible = smallCanvas->makeSurface(imageInfo);
|
|
SkDebugf("compatible %c= nullptr\n", compatible == nullptr ? '=' : '!');
|
|
SkDebugf("size = %d, %d\n", compatible->width(), compatible->height());
|
|
|
|
#StdOut
|
|
compatible != nullptr
|
|
size = 3, 4
|
|
##
|
|
##
|
|
|
|
#SeeAlso SkSurface SkSurface::makeSurface SkImageInfo SkSurfaceProps
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method virtual GrContext* getGrContext()
|
|
#In Property
|
|
#Line # returns GPU_Context of the GPU_Surface ##
|
|
Returns GPU_Context of the GPU_Surface associated with Canvas.
|
|
|
|
#Return GPU_Context, if available; nullptr otherwise ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
if (canvas->getGrContext()) {
|
|
canvas->clear(SK_ColorRED);
|
|
} else {
|
|
canvas->clear(SK_ColorBLUE);
|
|
}
|
|
}
|
|
##
|
|
|
|
#ToDo fiddle should show both CPU and GPU out ##
|
|
|
|
#SeeAlso GrContext
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void* accessTopLayerPixels(SkImageInfo* info, size_t* rowBytes, SkIPoint* origin = nullptr)
|
|
#In Utility
|
|
#In Property
|
|
#Line # returns writable pixel access if available ##
|
|
Returns the pixel base address, Image_Info, rowBytes, and origin if the pixels
|
|
can be read directly. The returned address is only valid
|
|
while Canvas is in scope and unchanged. Any Canvas call or Surface 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' Image_Info; may be nullptr ##
|
|
#Param rowBytes storage for writable pixels' row bytes; may be nullptr ##
|
|
#Param origin storage for Canvas top Layer origin, its top-left corner;
|
|
may be nullptr
|
|
##
|
|
|
|
#Return address of pixels, or nullptr if inaccessible ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
if (canvas->accessTopLayerPixels(nullptr, nullptr)) {
|
|
canvas->clear(SK_ColorRED);
|
|
} else {
|
|
canvas->clear(SK_ColorBLUE);
|
|
}
|
|
}
|
|
##
|
|
|
|
#Example
|
|
#Description
|
|
Draws "ABC" on the device. Then draws "DEF" in Layer, and reads
|
|
Layer to add a large dotted "DEF". Finally blends Layer with the
|
|
device.
|
|
|
|
The Layer and blended result appear on the CPU and GPU but the large dotted
|
|
"DEF" appear only on the CPU.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setTextSize(100);
|
|
canvas->drawString("ABC", 20, 160, paint);
|
|
SkRect layerBounds = SkRect::MakeXYWH(32, 32, 192, 192);
|
|
canvas->saveLayerAlpha(&layerBounds, 128);
|
|
canvas->clear(SK_ColorWHITE);
|
|
canvas->drawString("DEF", 20, 160, paint);
|
|
SkImageInfo imageInfo;
|
|
size_t rowBytes;
|
|
SkIPoint origin;
|
|
uint32_t* access = (uint32_t*) canvas->accessTopLayerPixels(&imageInfo, &rowBytes, &origin);
|
|
if (access) {
|
|
int h = imageInfo.height();
|
|
int v = imageInfo.width();
|
|
int rowWords = rowBytes / sizeof(uint32_t);
|
|
for (int y = 0; y < h; ++y) {
|
|
int newY = (y - h / 2) * 2 + h / 2;
|
|
if (newY < 0 || newY >= h) {
|
|
continue;
|
|
}
|
|
for (int x = 0; x < v; ++x) {
|
|
int newX = (x - v / 2) * 2 + v / 2;
|
|
if (newX < 0 || newX >= v) {
|
|
continue;
|
|
}
|
|
if (access[y * rowWords + x] == SK_ColorBLACK) {
|
|
access[newY * rowWords + newX] = SK_ColorGRAY;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
canvas->restore();
|
|
}
|
|
##
|
|
|
|
#ToDo there are no callers of this that I can find. Deprecate? ##
|
|
#ToDo fiddle should show both CPU and GPU out ##
|
|
|
|
#SeeAlso SkImageInfo SkPixmap
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method SkRasterHandleAllocator::Handle accessTopRasterHandle() const
|
|
#In Utility
|
|
#In Property
|
|
#Line # returns context that tracks Clip and Matrix ##
|
|
Returns custom context that tracks the Matrix and Clip.
|
|
|
|
Use Raster_Handle_Allocator 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
|
|
#Description
|
|
#ToDo ##
|
|
##
|
|
#Function
|
|
static void DeleteCallback(void*, void* context) {
|
|
delete (char*) context;
|
|
}
|
|
|
|
class CustomAllocator : public SkRasterHandleAllocator {
|
|
public:
|
|
bool allocHandle(const SkImageInfo& info, Rec* rec) override {
|
|
char* context = new char[4]{'s', 'k', 'i', 'a'};
|
|
rec->fReleaseProc = DeleteCallback;
|
|
rec->fReleaseCtx = context;
|
|
rec->fHandle = context;
|
|
rec->fPixels = context;
|
|
rec->fRowBytes = 4;
|
|
return true;
|
|
}
|
|
|
|
void updateHandle(Handle handle, const SkMatrix& ctm, const SkIRect& clip_bounds) override {
|
|
// apply canvas matrix and clip to custom environment
|
|
}
|
|
};
|
|
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
const SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
|
|
std::unique_ptr<SkCanvas> c2 =
|
|
SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<CustomAllocator>(
|
|
new CustomAllocator()), info);
|
|
char* context = (char*) c2->accessTopRasterHandle();
|
|
SkDebugf("context = %.4s\n", context);
|
|
|
|
}
|
|
#StdOut
|
|
context = skia
|
|
##
|
|
#ToDo skstd::make_unique could not be used because def is private -- note to fix in c++14? ##
|
|
##
|
|
|
|
#SeeAlso SkRasterHandleAllocator
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
#Subtopic Pixels
|
|
#Line # read and write pixel values ##
|
|
##
|
|
|
|
#Method bool peekPixels(SkPixmap* pixmap)
|
|
#In Pixels
|
|
#Line # returns if Canvas has direct access to its pixels ##
|
|
Returns true if Canvas has direct access to its pixels.
|
|
|
|
Pixels are readable when Device is raster. Pixels are not readable when Canvas
|
|
is returned from GPU_Surface, returned by SkDocument::beginPage, returned by
|
|
SkPictureRecorder::beginRecording, or Canvas is the base of a utility class
|
|
like SkDebugCanvas.
|
|
|
|
pixmap is valid only while Canvas is in scope and unchanged. Any
|
|
Canvas or Surface call may invalidate the pixmap values.
|
|
|
|
#Param pixmap storage for pixel state if pixels are readable; otherwise, ignored ##
|
|
|
|
#Return true if Canvas has direct access to pixels ##
|
|
|
|
#Example
|
|
SkPixmap pixmap;
|
|
if (canvas->peekPixels(&pixmap)) {
|
|
SkDebugf("width=%d height=%d\n", pixmap.bounds().width(), pixmap.bounds().height());
|
|
}
|
|
#StdOut
|
|
width=256 height=256
|
|
##
|
|
##
|
|
|
|
#SeeAlso readPixels SkBitmap::peekPixels SkImage::peekPixels SkSurface::peekPixels
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
|
|
int srcX, int srcY)
|
|
#In Pixels
|
|
#Line # copies and converts rectangle of pixels from Canvas ##
|
|
|
|
Copies Rect of pixels from Canvas into dstPixels. Matrix and Clip are
|
|
ignored.
|
|
|
|
Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
|
|
Destination Rect 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 Device is raster, or backed by a GPU.
|
|
Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
|
|
returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
|
|
class like SkDebugCanvas.
|
|
|
|
The destination pixel storage must be allocated by the caller.
|
|
|
|
Pixel values are converted only if Color_Type and Alpha_Type
|
|
do not match. Only pixels within both source and destination rectangles
|
|
are copied. dstPixels contents outside Rect intersection are unchanged.
|
|
|
|
Pass negative values for srcX or srcY to offset pixels across or down destination.
|
|
|
|
Does not copy, and returns false if:
|
|
|
|
#List
|
|
# Source and destination rectangles do not intersect. ##
|
|
# Canvas pixels could not be converted to dstInfo.colorType() or dstInfo.alphaType(). ##
|
|
# Canvas pixels are not readable; for instance, Canvas is document-based. ##
|
|
# dstRowBytes is too small to contain one row of pixels. ##
|
|
##
|
|
|
|
#Param dstInfo width, height, Color_Type, and Alpha_Type 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 ##
|
|
|
|
#Example
|
|
#Width 64
|
|
#Height 64
|
|
#Description
|
|
A black circle drawn on a blue background provides an image to copy.
|
|
readPixels copies one quarter of the canvas into each of the four corners.
|
|
The copied quarter circles overdraw the original circle.
|
|
##
|
|
canvas->clear(SK_ColorBLUE);
|
|
SkPaint paint;
|
|
canvas->drawCircle(32, 32, 28, paint);
|
|
SkImageInfo info = SkImageInfo::Make(64, 64, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
|
|
sk_sp<SkData> data(SkData::MakeUninitialized(info.minRowBytes() * info.height()));
|
|
sk_bzero(data->writable_data(), info.minRowBytes() * info.height());
|
|
for (int x : { 32, -32 } ) {
|
|
for (int y : { 32, -32 } ) {
|
|
canvas->readPixels(info, data->writable_data(), info.minRowBytes(), x, y);
|
|
}
|
|
}
|
|
sk_sp<SkImage> image = SkImage::MakeRasterData(info, data, info.minRowBytes());
|
|
canvas->drawImage(image, 0, 0);
|
|
##
|
|
|
|
#Example
|
|
#Description
|
|
Canvas returned by Raster_Surface has Premultiplied pixel values.
|
|
clear() takes Unpremultiplied input with Color_Alpha equal 0x80
|
|
and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
|
|
to generate Premultiplied value 0x802B5580. readPixels converts pixel back
|
|
to Unpremultiplied value 0x8056A9FF, introducing error.
|
|
##
|
|
canvas->clear(0x8055aaff);
|
|
for (SkAlphaType alphaType : { kPremul_SkAlphaType, kUnpremul_SkAlphaType } ) {
|
|
uint32_t pixel = 0;
|
|
SkImageInfo info = SkImageInfo::Make(1, 1, kBGRA_8888_SkColorType, alphaType);
|
|
if (canvas->readPixels(info, &pixel, 4, 0, 0)) {
|
|
SkDebugf("pixel = %08x\n", pixel);
|
|
}
|
|
}
|
|
|
|
#StdOut
|
|
pixel = 802b5580
|
|
pixel = 8056a9ff
|
|
##
|
|
##
|
|
|
|
#SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method bool readPixels(const SkPixmap& pixmap, int srcX, int srcY)
|
|
|
|
Copies Rect of pixels from Canvas into pixmap. Matrix and Clip are
|
|
ignored.
|
|
|
|
Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
|
|
Destination Rect 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 Device is raster, or backed by a GPU.
|
|
Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
|
|
returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
|
|
class like SkDebugCanvas.
|
|
|
|
Caller must allocate pixel storage in pixmap if needed.
|
|
|
|
Pixel values are converted only if Color_Type and Alpha_Type
|
|
do not match. Only pixels within both source and destination Rects
|
|
are copied. pixmap pixels contents outside Rect intersection are unchanged.
|
|
|
|
Pass negative values for srcX or srcY to offset pixels across or down pixmap.
|
|
|
|
Does not copy, and returns false if:
|
|
|
|
#List
|
|
# Source and destination rectangles do not intersect. ##
|
|
# Canvas pixels could not be converted to pixmap.colorType() or pixmap.alphaType(). ##
|
|
# Canvas pixels are not readable; for instance, Canvas is document-based. ##
|
|
# Pixmap pixels could not be allocated. ##
|
|
# pixmap.rowBytes() is too small to contain one row of pixels. ##
|
|
##
|
|
|
|
#Param pixmap storage for pixels copied from Canvas ##
|
|
#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
|
|
#Description
|
|
clear() takes Unpremultiplied input with Color_Alpha equal 0x80
|
|
and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
|
|
to generate Premultiplied value 0x802B5580.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
canvas->clear(0x8055aaff);
|
|
uint32_t pixels[1] = { 0 };
|
|
SkPixmap pixmap(SkImageInfo::MakeN32Premul(1, 1), pixels, 4);
|
|
canvas->readPixels(pixmap, 0, 0);
|
|
SkDebugf("pixel = %08x\n", pixels[0]);
|
|
}
|
|
#StdOut
|
|
pixel = 802b5580
|
|
##
|
|
##
|
|
|
|
#SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method bool readPixels(const SkBitmap& bitmap, int srcX, int srcY)
|
|
|
|
Copies Rect of pixels from Canvas into bitmap. Matrix and Clip are
|
|
ignored.
|
|
|
|
Source Rect corners are (srcX, srcY) and (imageInfo().width(), imageInfo().height()).
|
|
Destination Rect 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 Device is raster, or backed by a GPU.
|
|
Pixels are not readable when SkCanvas is returned by SkDocument::beginPage,
|
|
returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
|
|
class like SkDebugCanvas.
|
|
|
|
Caller must allocate pixel storage in bitmap if needed.
|
|
|
|
Bitmap values are converted only if Color_Type and Alpha_Type
|
|
do not match. Only pixels within both source and destination rectangles
|
|
are copied. Bitmap pixels outside Rect intersection are unchanged.
|
|
|
|
Pass negative values for srcX or srcY to offset pixels across or down bitmap.
|
|
|
|
Does not copy, and returns false if:
|
|
|
|
#List
|
|
# Source and destination rectangles do not intersect. ##
|
|
# Canvas pixels could not be converted to bitmap.colorType() or bitmap.alphaType(). ##
|
|
# Canvas pixels are not readable; for instance, Canvas 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 Canvas ##
|
|
#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
|
|
#Description
|
|
clear() takes Unpremultiplied input with Color_Alpha equal 0x80
|
|
and RGB equal 0x55, 0xAA, 0xFF. RGB is multiplied by Color_Alpha
|
|
to generate Premultiplied value 0x802B5580.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
canvas->clear(0x8055aaff);
|
|
SkBitmap bitmap;
|
|
bitmap.allocPixels(SkImageInfo::MakeN32Premul(1, 1));
|
|
canvas->readPixels(bitmap, 0, 0);
|
|
SkDebugf("pixel = %08x\n", bitmap.getAddr32(0, 0)[0]);
|
|
}
|
|
#StdOut
|
|
pixel = 802b5580
|
|
##
|
|
##
|
|
|
|
#SeeAlso peekPixels writePixels drawBitmap drawImage SkBitmap::readPixels SkPixmap::readPixels SkImage::readPixels SkSurface::readPixels
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method bool writePixels(const SkImageInfo& info, const void* pixels, size_t rowBytes, int x, int y)
|
|
#In Pixels
|
|
#Line # copies and converts rectangle of pixels to Canvas ##
|
|
Copies Rect from pixels to Canvas. Matrix and Clip are ignored.
|
|
Source Rect corners are (0, 0) and (info.width(), info.height()).
|
|
Destination Rect 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 Device is raster, or backed by a GPU.
|
|
Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
|
|
returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
|
|
class like SkDebugCanvas.
|
|
|
|
Pixel values are converted only if Color_Type and Alpha_Type
|
|
do not match. Only pixels within both source and destination rectangles
|
|
are copied. Canvas pixels outside Rect intersection are unchanged.
|
|
|
|
Pass negative values for x or y to offset pixels to the left or
|
|
above Canvas pixels.
|
|
|
|
Does not copy, and returns false if:
|
|
|
|
#List
|
|
# Source and destination rectangles do not intersect. ##
|
|
# pixels could not be converted to Canvas imageInfo().colorType() or
|
|
imageInfo().alphaType(). ##
|
|
# Canvas pixels are not writable; for instance, Canvas is document-based. ##
|
|
# rowBytes is too small to contain one row of pixels. ##
|
|
##
|
|
|
|
#Param info width, height, Color_Type, and Alpha_Type 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 Canvas writable pixels on x-axis; may be negative ##
|
|
#Param y offset into Canvas writable pixels on y-axis; may be negative ##
|
|
|
|
#Return true if pixels were written to Canvas ##
|
|
|
|
#Example
|
|
SkImageInfo imageInfo = SkImageInfo::MakeN32(256, 1, kPremul_SkAlphaType);
|
|
for (int y = 0; y < 256; ++y) {
|
|
uint32_t pixels[256];
|
|
for (int x = 0; x < 256; ++x) {
|
|
pixels[x] = SkColorSetARGB(x, x + y, x, x - y);
|
|
}
|
|
canvas->writePixels(imageInfo, &pixels, sizeof(pixels), 0, y);
|
|
}
|
|
##
|
|
|
|
#SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method bool writePixels(const SkBitmap& bitmap, int x, int y)
|
|
|
|
Copies Rect from pixels to Canvas. Matrix and Clip are ignored.
|
|
Source Rect corners are (0, 0) and (bitmap.width(), bitmap.height()).
|
|
|
|
Destination Rect 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 Device is raster, or backed by a GPU.
|
|
Pixels are not writable when SkCanvas is returned by SkDocument::beginPage,
|
|
returned by SkPictureRecorder::beginRecording, or Canvas is the base of a utility
|
|
class like SkDebugCanvas.
|
|
|
|
Pixel values are converted only if Color_Type and Alpha_Type
|
|
do not match. Only pixels within both source and destination rectangles
|
|
are copied. Canvas pixels outside Rect intersection are unchanged.
|
|
|
|
Pass negative values for x or y to offset pixels to the left or
|
|
above Canvas pixels.
|
|
|
|
Does not copy, and returns false if:
|
|
|
|
#List
|
|
# Source and destination rectangles do not intersect. ##
|
|
# bitmap does not have allocated pixels. ##
|
|
# bitmap pixels could not be converted to Canvas imageInfo().colorType() or
|
|
imageInfo().alphaType(). ##
|
|
# Canvas pixels are not writable; for instance, Canvas is document based. ##
|
|
# bitmap pixels are inaccessible; for instance, bitmap wraps a texture. ##
|
|
##
|
|
|
|
#Param bitmap contains pixels copied to Canvas ##
|
|
#Param x offset into Canvas writable pixels in x; may be negative ##
|
|
#Param y offset into Canvas writable pixels in y; may be negative ##
|
|
|
|
#Return true if pixels were written to Canvas ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkImageInfo imageInfo = SkImageInfo::MakeN32Premul(2, 2);
|
|
SkBitmap bitmap;
|
|
bitmap.setInfo(imageInfo);
|
|
uint32_t pixels[4];
|
|
bitmap.setPixels(pixels);
|
|
for (int y = 0; y < 256; y += 2) {
|
|
for (int x = 0; x < 256; x += 2) {
|
|
pixels[0] = SkColorSetRGB(x, y, x | y);
|
|
pixels[1] = SkColorSetRGB(x ^ y, y, x);
|
|
pixels[2] = SkColorSetRGB(x, x & y, y);
|
|
pixels[3] = SkColorSetRGB(~x, ~y, x);
|
|
canvas->writePixels(bitmap, x, y);
|
|
}
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso readPixels drawBitmap drawImage SkBitmap::writePixels
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
#Subtopic State_Stack
|
|
#Line # stack of state for hierarchical drawing ##
|
|
|
|
Canvas maintains a stack of state that allows hierarchical drawing, commonly used
|
|
to implement windows and views. The initial state has an identity matrix and and
|
|
an infinite clip. Even with a wide-open clip, drawing is constrained by the
|
|
bounds of the Canvas Surface or Device.
|
|
|
|
Canvas savable state consists of Clip and Matrix.
|
|
Clip describes the area that may be drawn to.
|
|
Matrix transforms the geometry.
|
|
|
|
save(), saveLayer, saveLayerPreserveLCDTextRequests, and saveLayerAlpha
|
|
save state and return the depth of the stack.
|
|
|
|
restore(), restoreToCount, and ~SkCanvas() revert state to its value when saved.
|
|
|
|
Each state on the stack intersects Clip with the previous Clip,
|
|
and concatenates Matrix with the previous Matrix.
|
|
The intersected Clip makes the drawing area the same or smaller;
|
|
the concatenated Matrix may move the origin and potentially scale or rotate
|
|
the coordinate space.
|
|
|
|
Canvas does not require balancing the state stack but it is a good idea
|
|
to do so. Calling save() without restore() will eventually cause Skia to fail;
|
|
mismatched save() and restore() create hard to find bugs.
|
|
|
|
It is not possible to use state to draw outside of the clip defined by the
|
|
previous state.
|
|
|
|
#Example
|
|
#Description
|
|
Draw to ever smaller clips; then restore drawing to full canvas.
|
|
Note that the second clipRect is not permitted to enlarge Clip.
|
|
##
|
|
#Height 160
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
canvas->save(); // records stack depth to restore
|
|
canvas->clipRect(SkRect::MakeWH(100, 100)); // constrains drawing to clip
|
|
canvas->clear(SK_ColorRED); // draws to limit of clip
|
|
canvas->save(); // records stack depth to restore
|
|
canvas->clipRect(SkRect::MakeWH(50, 150)); // Rect below 100 is ignored
|
|
canvas->clear(SK_ColorBLUE); // draws to smaller clip
|
|
canvas->restore(); // enlarges clip
|
|
canvas->drawLine(20, 20, 150, 150, paint); // line below 100 is not drawn
|
|
canvas->restore(); // enlarges clip
|
|
canvas->drawLine(150, 20, 50, 120, paint); // line below 100 is drawn
|
|
}
|
|
##
|
|
|
|
Each Clip uses the current Matrix for its coordinates.
|
|
|
|
#Example
|
|
#Description
|
|
While clipRect is given the same rectangle twice, Matrix makes the second
|
|
clipRect draw at half the size of the first.
|
|
##
|
|
#Height 128
|
|
void draw(SkCanvas* canvas) {
|
|
canvas->clipRect(SkRect::MakeWH(100, 100));
|
|
canvas->clear(SK_ColorRED);
|
|
canvas->scale(.5, .5);
|
|
canvas->clipRect(SkRect::MakeWH(100, 100));
|
|
canvas->clear(SK_ColorBLUE);
|
|
}
|
|
##
|
|
|
|
#SeeAlso save() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restore() restoreToCount
|
|
|
|
#Method int save()
|
|
|
|
#In State_Stack
|
|
#Line # saves Clip and Matrix on stack ##
|
|
Saves Matrix and Clip.
|
|
Calling restore() discards changes to Matrix and Clip,
|
|
restoring the Matrix and Clip to their state when save() was called.
|
|
|
|
Matrix may be changed by translate(), scale(), rotate(), skew(), concat(), setMatrix,
|
|
and resetMatrix. Clip may be changed by clipRect, clipRRect, clipPath, clipRegion.
|
|
|
|
Saved Canvas 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
|
|
#Description
|
|
The black square is translated 50 pixels down and to the right.
|
|
Restoring Canvas state removes translate() from Canvas stack;
|
|
the red square is not translated, and is drawn at the origin.
|
|
##
|
|
#Height 100
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
SkRect rect = { 0, 0, 25, 25 };
|
|
canvas->drawRect(rect, paint);
|
|
canvas->save();
|
|
canvas->translate(50, 50);
|
|
canvas->drawRect(rect, paint);
|
|
canvas->restore();
|
|
paint.setColor(SK_ColorRED);
|
|
canvas->drawRect(rect, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restore() restoreToCount
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void restore()
|
|
|
|
#In State_Stack
|
|
#Line # restores changes to Clip and Matrix, pops save stack ##
|
|
Removes changes to Matrix and Clip since Canvas state was
|
|
last saved. The state is removed from the stack.
|
|
|
|
Does nothing if the stack is empty.
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkCanvas simple;
|
|
SkDebugf("depth = %d\n", simple.getSaveCount());
|
|
simple.restore();
|
|
SkDebugf("depth = %d\n", simple.getSaveCount());
|
|
}
|
|
##
|
|
|
|
#SeeAlso save() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha restoreToCount
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method int getSaveCount() const
|
|
|
|
#In State_Stack
|
|
#Line # returns depth of stack containing Clip and Matrix ##
|
|
Returns the number of saved states, each containing: Matrix 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
|
|
void draw(SkCanvas* canvas) {
|
|
SkCanvas simple;
|
|
SkDebugf("depth = %d\n", simple.getSaveCount());
|
|
simple.save();
|
|
SkDebugf("depth = %d\n", simple.getSaveCount());
|
|
simple.restore();
|
|
SkDebugf("depth = %d\n", simple.getSaveCount());
|
|
}
|
|
#StdOut
|
|
depth = 1
|
|
depth = 2
|
|
depth = 1
|
|
##
|
|
##
|
|
|
|
#SeeAlso save() restore() restoreToCount
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void restoreToCount(int saveCount)
|
|
|
|
#In State_Stack
|
|
#Line # restores changes to Clip and Matrix to given depth ##
|
|
Restores state to Matrix 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
|
|
void draw(SkCanvas* canvas) {
|
|
SkDebugf("depth = %d\n", canvas->getSaveCount());
|
|
canvas->save();
|
|
canvas->save();
|
|
SkDebugf("depth = %d\n", canvas->getSaveCount());
|
|
canvas->restoreToCount(0);
|
|
SkDebugf("depth = %d\n", canvas->getSaveCount());
|
|
}
|
|
#StdOut
|
|
depth = 1
|
|
depth = 3
|
|
depth = 1
|
|
##
|
|
##
|
|
|
|
#SeeAlso restore() getSaveCount save()
|
|
|
|
##
|
|
|
|
#Subtopic State_Stack ##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Subtopic Layer
|
|
#Substitute layer
|
|
#Alias Layers
|
|
#Substitute layers
|
|
##
|
|
#Line # temporary Bitmap to draw into ##
|
|
|
|
Layer allocates a temporary Bitmap to draw into. When the drawing is
|
|
complete, the Bitmap is drawn into the Canvas.
|
|
|
|
Layer is saved in a stack along with other saved state. When state with a Layer
|
|
is restored, the Bitmap is drawn into the previous Layer.
|
|
|
|
Layer may be initialized with the contents of the previous Layer. When Layer is
|
|
restored, its Bitmap can be modified by Paint passed to Layer to apply
|
|
Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode.
|
|
|
|
#Method int saveLayer(const SkRect* bounds, const SkPaint* paint)
|
|
|
|
#In Layer
|
|
#Line # saves Clip and Matrix on stack; creates Layer ##
|
|
Saves Matrix and Clip, and allocates a Bitmap for subsequent drawing.
|
|
Calling restore() discards changes to Matrix and Clip, and draws the Bitmap.
|
|
|
|
Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
|
|
setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
|
|
clipPath, clipRegion.
|
|
|
|
Rect bounds suggests but does not define the Bitmap size. To clip drawing to
|
|
a specific rectangle, use clipRect.
|
|
|
|
Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and
|
|
Blend_Mode 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
|
|
#Description
|
|
Rectangles are blurred by Image_Filter when restore() draws Layer to main
|
|
Canvas.
|
|
##
|
|
#Height 128
|
|
#Function
|
|
###$
|
|
#include "SkBlurImageFilter.h"
|
|
$$$#
|
|
##
|
|
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint, blur;
|
|
blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr));
|
|
canvas->saveLayer(nullptr, &blur);
|
|
SkRect rect = { 25, 25, 50, 50};
|
|
canvas->drawRect(rect, paint);
|
|
canvas->translate(50, 50);
|
|
paint.setColor(SK_ColorRED);
|
|
canvas->drawRect(rect, paint);
|
|
canvas->restore();
|
|
}
|
|
##
|
|
|
|
#SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha SaveLayerRec
|
|
|
|
##
|
|
|
|
#Method int saveLayer(const SkRect& bounds, const SkPaint* paint)
|
|
|
|
#In Layer
|
|
Saves Matrix and Clip, and allocates a Bitmap for subsequent drawing.
|
|
Calling restore() discards changes to Matrix and Clip, and draws the Bitmap.
|
|
|
|
Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
|
|
setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
|
|
clipPath, clipRegion.
|
|
|
|
Rect bounds suggests but does not define the Layer size. To clip drawing to
|
|
a specific rectangle, use clipRect.
|
|
|
|
Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and
|
|
Blend_Mode 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 ##
|
|
|
|
#Example
|
|
#Description
|
|
Rectangles are blurred by Image_Filter when restore() draws Layer to main Canvas.
|
|
The red rectangle is clipped; it does not fully fit on Layer.
|
|
Image_Filter blurs past edge of Layer so red rectangle is blurred on all sides.
|
|
##
|
|
#Height 128
|
|
#Function
|
|
###$
|
|
#include "SkBlurImageFilter.h"
|
|
$$$#
|
|
##
|
|
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint, blur;
|
|
blur.setImageFilter(SkBlurImageFilter::Make(3, 3, nullptr));
|
|
canvas->saveLayer(SkRect::MakeWH(90, 90), &blur);
|
|
SkRect rect = { 25, 25, 50, 50};
|
|
canvas->drawRect(rect, paint);
|
|
canvas->translate(50, 50);
|
|
paint.setColor(SK_ColorRED);
|
|
canvas->drawRect(rect, paint);
|
|
canvas->restore();
|
|
}
|
|
##
|
|
|
|
#SeeAlso save() restore() saveLayerPreserveLCDTextRequests saveLayerAlpha SaveLayerRec
|
|
|
|
##
|
|
|
|
#Method int saveLayerPreserveLCDTextRequests(const SkRect* bounds, const SkPaint* paint)
|
|
|
|
#In Layer
|
|
#Line # saves Clip and Matrix on stack; creates Layer for LCD text ##
|
|
Saves Matrix and Clip, and allocates a Bitmap for subsequent drawing.
|
|
LCD_Text is preserved when the Layer is drawn to the prior Layer.
|
|
|
|
Calling restore() discards changes to Matrix and Clip, and draws Layer.
|
|
|
|
Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
|
|
setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
|
|
clipPath, clipRegion.
|
|
|
|
Rect bounds suggests but does not define the Layer size. To clip drawing to
|
|
a specific rectangle, use clipRect.
|
|
|
|
Optional Paint paint applies Color_Alpha, Color_Filter, Image_Filter, and
|
|
Blend_Mode when restore() is called.
|
|
|
|
Call restoreToCount with returned value to restore this and subsequent saves.
|
|
|
|
Draw text on an opaque background so that LCD_Text blends correctly with the
|
|
prior Layer. LCD_Text drawn on a background with transparency may result in
|
|
incorrect blending.
|
|
|
|
#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 ##
|
|
|
|
#Example
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setLCDRenderText(true);
|
|
paint.setTextSize(20);
|
|
for (auto preserve : { false, true } ) {
|
|
preserve ? canvas->saveLayerPreserveLCDTextRequests(nullptr, nullptr)
|
|
: canvas->saveLayer(nullptr, nullptr);
|
|
SkPaint p;
|
|
p.setColor(SK_ColorWHITE);
|
|
// Comment out the next line to draw on a non-opaque background.
|
|
canvas->drawRect(SkRect::MakeLTRB(25, 40, 200, 70), p);
|
|
canvas->drawString("Hamburgefons", 30, 60, paint);
|
|
|
|
p.setColor(0xFFCCCCCC);
|
|
canvas->drawRect(SkRect::MakeLTRB(25, 70, 200, 100), p);
|
|
canvas->drawString("Hamburgefons", 30, 90, paint);
|
|
|
|
canvas->restore();
|
|
canvas->translate(0, 80);
|
|
}
|
|
##
|
|
|
|
#SeeAlso save() restore() saveLayer saveLayerAlpha SaveLayerRec
|
|
|
|
##
|
|
|
|
#Method int saveLayerAlpha(const SkRect* bounds, U8CPU alpha)
|
|
|
|
#In Layer
|
|
#Line # saves Clip and Matrix on stack; creates Layer; sets opacity ##
|
|
Saves Matrix and Clip, and allocates Bitmap for subsequent drawing.
|
|
|
|
Calling restore() discards changes to Matrix and Clip,
|
|
and blends Layer with alpha opacity onto prior Layer.
|
|
|
|
Matrix may be changed by translate(), scale(), rotate(), skew(), concat(),
|
|
setMatrix, and resetMatrix. Clip may be changed by clipRect, clipRRect,
|
|
clipPath, clipRegion.
|
|
|
|
Rect bounds suggests but does not define Layer size. To clip drawing to
|
|
a specific rectangle, use clipRect.
|
|
|
|
alpha of zero is fully transparent, 255 is fully opaque.
|
|
|
|
Call restoreToCount with returned value to restore this and subsequent saves.
|
|
|
|
#Param bounds hint to limit the size of Layer; may be nullptr ##
|
|
#Param alpha opacity of Layer ##
|
|
|
|
#Return depth of saved stack ##
|
|
|
|
#Example
|
|
SkPaint paint;
|
|
paint.setColor(SK_ColorRED);
|
|
canvas->drawCircle(50, 50, 50, paint);
|
|
canvas->saveLayerAlpha(nullptr, 128);
|
|
paint.setColor(SK_ColorBLUE);
|
|
canvas->drawCircle(100, 50, 50, paint);
|
|
paint.setColor(SK_ColorGREEN);
|
|
paint.setAlpha(128);
|
|
canvas->drawCircle(75, 90, 50, paint);
|
|
canvas->restore();
|
|
##
|
|
|
|
#SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests SaveLayerRec
|
|
|
|
##
|
|
|
|
#Enum SaveLayerFlagsSet
|
|
#Line # sets SaveLayerRec options ##
|
|
#Code
|
|
#Populate
|
|
##
|
|
|
|
|
|
#Typedef uint32_t SaveLayerFlags
|
|
#Line # options for SaveLayerRec ##
|
|
##
|
|
|
|
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.
|
|
|
|
#Const kPreserveLCDText_SaveLayerFlag 2
|
|
#Line # creates Layer for LCD text ##
|
|
Creates Layer for LCD text. Flag is ignored if Layer Paint contains
|
|
Image_Filter or Color_Filter.
|
|
##
|
|
|
|
#Const kInitWithPrevious_SaveLayerFlag 4
|
|
#Line # initializes with previous contents ##
|
|
Initializes Layer with the contents of the previous Layer.
|
|
##
|
|
|
|
#Const kMaskAgainstCoverage_EXPERIMENTAL_DONT_USE_SaveLayerFlag 8
|
|
#Experimental do not use
|
|
##
|
|
|
|
#Const kDontClipToLayer_Legacy_SaveLayerFlag 0x80000000
|
|
#Deprecated soon
|
|
##
|
|
|
|
#Example
|
|
#Height 160
|
|
#Description
|
|
Canvas Layer captures red and blue circles scaled up by four.
|
|
scalePaint blends Layer back with transparency.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint redPaint, bluePaint, scalePaint;
|
|
redPaint.setColor(SK_ColorRED);
|
|
canvas->drawCircle(21, 21, 8, redPaint);
|
|
bluePaint.setColor(SK_ColorBLUE);
|
|
canvas->drawCircle(31, 21, 8, bluePaint);
|
|
SkMatrix matrix;
|
|
matrix.setScale(4, 4);
|
|
scalePaint.setAlpha(0x40);
|
|
scalePaint.setImageFilter(
|
|
SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
|
|
SkCanvas::SaveLayerRec saveLayerRec(nullptr, &scalePaint,
|
|
SkCanvas::kInitWithPrevious_SaveLayerFlag);
|
|
canvas->saveLayer(saveLayerRec);
|
|
canvas->restore();
|
|
}
|
|
##
|
|
|
|
#SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha SaveLayerRec
|
|
|
|
#Enum ##
|
|
|
|
#Subtopic SaveLayerRec
|
|
#Line # contains the state used to create the Layer ##
|
|
|
|
#Struct SaveLayerRec
|
|
#Line # contains the state used to create the Layer ##
|
|
|
|
#Code
|
|
#Populate
|
|
##
|
|
|
|
SaveLayerRec contains the state used to create the Layer.
|
|
|
|
#Member const SkRect* fBounds
|
|
#Line # hints at Layer size limit ##
|
|
fBounds is used as a hint to limit the size of Layer; may be nullptr.
|
|
fBounds suggests but does not define Layer size. To clip drawing to
|
|
a specific rectangle, use clipRect.
|
|
##
|
|
|
|
#Member const SkPaint* fPaint
|
|
#Line # modifies overlay ##
|
|
fPaint modifies how Layer overlays the prior Layer; may be nullptr.
|
|
Color_Alpha, Blend_Mode, Color_Filter, Draw_Looper, Image_Filter, and
|
|
Mask_Filter affect Layer draw.
|
|
##
|
|
|
|
#Member const SkImageFilter* fBackdrop
|
|
#Line # applies Image_Filter to prior Layer ##
|
|
fBackdrop applies Image_Filter to the prior Layer when copying to the Layer;
|
|
may be nullptr. Use kInitWithPrevious_SaveLayerFlag to copy the
|
|
prior Layer without an Image_Filter.
|
|
##
|
|
|
|
#Member const SkImage* fClipMask
|
|
#Line # clips Layer with Mask_Alpha ##
|
|
restore() clips Layer by the Color_Alpha channel of fClipMask when
|
|
Layer is copied to Device. fClipMask may be nullptr. .
|
|
##
|
|
|
|
#Member const SkMatrix* fClipMatrix
|
|
#Line # transforms Mask_Alpha used to clip ##
|
|
fClipMatrix transforms fClipMask before it clips Layer. If
|
|
fClipMask describes a translucent gradient, it may be scaled and rotated
|
|
without introducing artifacts. fClipMatrix may be nullptr.
|
|
##
|
|
|
|
#Member SaveLayerFlags fSaveLayerFlags
|
|
#Line # preserves LCD Text, creates with prior Layer contents ##
|
|
fSaveLayerFlags are used to create Layer without transparency,
|
|
create Layer for LCD text, and to create Layer with the
|
|
contents of the previous Layer.
|
|
##
|
|
|
|
#Example
|
|
#Height 160
|
|
#Description
|
|
Canvas Layer captures a red Anti_Aliased circle and a blue Aliased circle scaled
|
|
up by four. After drawing another red circle without scaling on top, the Layer is
|
|
transferred to the main canvas.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint redPaint, bluePaint;
|
|
redPaint.setAntiAlias(true);
|
|
redPaint.setColor(SK_ColorRED);
|
|
canvas->drawCircle(21, 21, 8, redPaint);
|
|
bluePaint.setColor(SK_ColorBLUE);
|
|
canvas->drawCircle(31, 21, 8, bluePaint);
|
|
SkMatrix matrix;
|
|
matrix.setScale(4, 4);
|
|
auto scaler = SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr);
|
|
SkCanvas::SaveLayerRec saveLayerRec(nullptr, nullptr, scaler.get(), 0);
|
|
canvas->saveLayer(saveLayerRec);
|
|
canvas->drawCircle(125, 85, 8, redPaint);
|
|
canvas->restore();
|
|
}
|
|
##
|
|
|
|
#Subtopic Constructors
|
|
##
|
|
|
|
#Method SaveLayerRec()
|
|
#Line # constructs SaveLayerRec ##
|
|
Sets fBounds, fPaint, and fBackdrop to nullptr. Clears fSaveLayerFlags.
|
|
|
|
#Return empty SaveLayerRec ##
|
|
|
|
#Example
|
|
SkCanvas::SaveLayerRec rec1;
|
|
rec1.fSaveLayerFlags = SkCanvas::kPreserveLCDText_SaveLayerFlag;
|
|
SkCanvas::SaveLayerRec rec2(nullptr, nullptr, SkCanvas::kPreserveLCDText_SaveLayerFlag);
|
|
SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
|
|
&& rec1.fPaint == rec2.fPaint
|
|
&& rec1.fBackdrop == rec2.fBackdrop
|
|
&& rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
|
|
#StdOut
|
|
rec1 == rec2
|
|
##
|
|
##
|
|
|
|
#SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
|
|
|
|
##
|
|
|
|
#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, SaveLayerFlags saveLayerFlags = 0)
|
|
|
|
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 backdrop ##
|
|
|
|
#Example
|
|
SkCanvas::SaveLayerRec rec1;
|
|
SkCanvas::SaveLayerRec rec2(nullptr, nullptr);
|
|
SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
|
|
&& rec1.fPaint == rec2.fPaint
|
|
&& rec1.fBackdrop == rec2.fBackdrop
|
|
&& rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
|
|
#StdOut
|
|
rec1 == rec2
|
|
##
|
|
##
|
|
|
|
#SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
|
|
|
|
##
|
|
|
|
#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
|
|
SaveLayerFlags saveLayerFlags)
|
|
|
|
Sets fBounds, fPaint, fBackdrop, and fSaveLayerFlags.
|
|
|
|
#Param bounds Layer dimensions; may be nullptr ##
|
|
#Param paint applied to Layer when overlaying prior Layer;
|
|
may be nullptr
|
|
##
|
|
#Param backdrop prior Layer copied with Image_Filter; may be nullptr
|
|
##
|
|
#Param saveLayerFlags SaveLayerRec options to modify Layer ##
|
|
|
|
#Return SaveLayerRec fully specified ##
|
|
|
|
#Example
|
|
SkCanvas::SaveLayerRec rec1;
|
|
SkCanvas::SaveLayerRec rec2(nullptr, nullptr, nullptr, 0);
|
|
SkDebugf("rec1 %c= rec2\n", rec1.fBounds == rec2.fBounds
|
|
&& rec1.fPaint == rec2.fPaint
|
|
&& rec1.fBackdrop == rec2.fBackdrop
|
|
&& rec1.fSaveLayerFlags == rec2.fSaveLayerFlags ? '=' : '!');
|
|
#StdOut
|
|
rec1 == rec2
|
|
##
|
|
##
|
|
|
|
#SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
|
|
|
|
##
|
|
|
|
#Method SaveLayerRec(const SkRect* bounds, const SkPaint* paint, const SkImageFilter* backdrop,
|
|
const SkImage* clipMask, const SkMatrix* clipMatrix,
|
|
SaveLayerFlags saveLayerFlags)
|
|
|
|
#Experimental not ready
|
|
|
|
Sets fBounds, fPaint, fBackdrop, fClipMask, fClipMatrix, and fSaveLayerFlags.
|
|
clipMatrix uses Color_Alpha channel of image, transformed by clipMatrix, to clip
|
|
Layer when drawn to Canvas.
|
|
|
|
Implementation is not complete; has no effect if Device is GPU-backed.
|
|
|
|
#Param bounds Layer dimensions; may be nullptr ##
|
|
#Param paint graphics state applied to Layer when overlaying prior
|
|
Layer; may be nullptr
|
|
##
|
|
#Param backdrop prior Layer copied with Image_Filter;
|
|
may be nullptr
|
|
##
|
|
#Param clipMask clip applied to Layer; may be nullptr ##
|
|
#Param clipMatrix matrix applied to clipMask; may be nullptr to use
|
|
identity matrix
|
|
##
|
|
#Param saveLayerFlags SaveLayerRec options to modify Layer ##
|
|
|
|
#Return SaveLayerRec fully specified ##
|
|
|
|
#SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
|
|
|
|
##
|
|
|
|
#Struct ##
|
|
|
|
#Subtopic ##
|
|
|
|
#Method int saveLayer(const SaveLayerRec& layerRec)
|
|
|
|
#In Layer
|
|
Saves Matrix and Clip, and allocates Bitmap for subsequent drawing.
|
|
|
|
Calling restore() discards changes to Matrix and Clip,
|
|
and blends Bitmap with Color_Alpha opacity onto the prior Layer.
|
|
|
|
Matrix 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 ##
|
|
|
|
#Example
|
|
#Description
|
|
The example draws an image, and saves it into a Layer with kInitWithPrevious_SaveLayerFlag.
|
|
Next it punches a hole in Layer and restore with SkBlendMode::kPlus.
|
|
Where Layer was cleared, the original image will draw unchanged.
|
|
Outside of the circle the mandrill is brightened.
|
|
##
|
|
#Image 3
|
|
// sk_sp<SkImage> image = GetResourceAsImage("images/mandrill_256.png");
|
|
canvas->drawImage(image, 0, 0, nullptr);
|
|
SkCanvas::SaveLayerRec rec;
|
|
SkPaint paint;
|
|
paint.setBlendMode(SkBlendMode::kPlus);
|
|
rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
|
|
rec.fPaint = &paint;
|
|
canvas->saveLayer(rec);
|
|
paint.setBlendMode(SkBlendMode::kClear);
|
|
canvas->drawCircle(128, 128, 96, paint);
|
|
canvas->restore();
|
|
##
|
|
|
|
#ToDo above example needs to replace GetResourceAsImage with way to select image in fiddle ##
|
|
|
|
#SeeAlso save() restore() saveLayer saveLayerPreserveLCDTextRequests saveLayerAlpha
|
|
|
|
##
|
|
|
|
#Subtopic Layer ##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
#Subtopic Matrix
|
|
#Line # coordinate transformation ##
|
|
|
|
#Method void translate(SkScalar dx, SkScalar dy)
|
|
|
|
#In Matrix
|
|
#Line # translates Matrix ##
|
|
Translates Matrix by dx along the x-axis and dy along the y-axis.
|
|
|
|
Mathematically, replaces Matrix with a translation matrix
|
|
Premultiplied with Matrix.
|
|
|
|
This has the effect of moving the drawing by (dx, dy) before transforming
|
|
the result with Matrix.
|
|
|
|
#Param dx distance to translate in x ##
|
|
#Param dy distance to translate in y ##
|
|
|
|
#Example
|
|
#Height 128
|
|
#Description
|
|
scale() followed by translate() produces different results from translate() followed
|
|
by scale().
|
|
|
|
The blue stroke follows translate of (50, 50); a black
|
|
fill follows scale of (2, 1/2.f). After restoring the clip, which resets
|
|
Matrix, a red frame follows the same scale of (2, 1/2.f); a gray fill
|
|
follows translate of (50, 50).
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint filledPaint;
|
|
SkPaint outlinePaint;
|
|
outlinePaint.setStyle(SkPaint::kStroke_Style);
|
|
outlinePaint.setColor(SK_ColorBLUE);
|
|
canvas->save();
|
|
canvas->translate(50, 50);
|
|
canvas->drawCircle(28, 28, 15, outlinePaint); // blue center: (50+28, 50+28)
|
|
canvas->scale(2, 1/2.f);
|
|
canvas->drawCircle(28, 28, 15, filledPaint); // black center: (50+(28*2), 50+(28/2))
|
|
canvas->restore();
|
|
filledPaint.setColor(SK_ColorGRAY);
|
|
outlinePaint.setColor(SK_ColorRED);
|
|
canvas->scale(2, 1/2.f);
|
|
canvas->drawCircle(28, 28, 15, outlinePaint); // red center: (28*2, 28/2)
|
|
canvas->translate(50, 50);
|
|
canvas->drawCircle(28, 28, 15, filledPaint); // gray center: ((50+28)*2, (50+28)/2)
|
|
}
|
|
##
|
|
|
|
#SeeAlso concat() scale() skew() rotate() setMatrix
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void scale(SkScalar sx, SkScalar sy)
|
|
|
|
#In Matrix
|
|
#Line # scales Matrix ##
|
|
Scales Matrix by sx on the x-axis and sy on the y-axis.
|
|
|
|
Mathematically, replaces Matrix with a scale matrix
|
|
Premultiplied with Matrix.
|
|
|
|
This has the effect of scaling the drawing by (sx, sy) before transforming
|
|
the result with Matrix.
|
|
|
|
#Param sx amount to scale in x ##
|
|
#Param sy amount to scale in y ##
|
|
|
|
#Example
|
|
#Height 160
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
SkRect rect = { 10, 20, 60, 120 };
|
|
canvas->translate(20, 20);
|
|
canvas->drawRect(rect, paint);
|
|
canvas->scale(2, .5f);
|
|
paint.setColor(SK_ColorGRAY);
|
|
canvas->drawRect(rect, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso concat() translate() skew() rotate() setMatrix
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void rotate(SkScalar degrees)
|
|
|
|
#In Matrix
|
|
#Line # rotates Matrix ##
|
|
Rotates Matrix by degrees. Positive degrees rotates clockwise.
|
|
|
|
Mathematically, replaces Matrix with a rotation matrix
|
|
Premultiplied with Matrix.
|
|
|
|
This has the effect of rotating the drawing by degrees before transforming
|
|
the result with Matrix.
|
|
|
|
#Param degrees amount to rotate, in degrees ##
|
|
|
|
#Example
|
|
#Description
|
|
Draw clock hands at time 5:10. The hour hand and minute hand point up and
|
|
are rotated clockwise.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
canvas->translate(128, 128);
|
|
canvas->drawCircle(0, 0, 60, paint);
|
|
canvas->save();
|
|
canvas->rotate(10 * 360 / 60); // 10 minutes of 60 scaled to 360 degrees
|
|
canvas->drawLine(0, 0, 0, -50, paint);
|
|
canvas->restore();
|
|
canvas->rotate((5 + 10.f/60) * 360 / 12); // 5 and 10/60 hours of 12 scaled to 360 degrees
|
|
canvas->drawLine(0, 0, 0, -30, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso concat() translate() skew() scale() setMatrix
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void rotate(SkScalar degrees, SkScalar px, SkScalar py)
|
|
|
|
#In Matrix
|
|
Rotates Matrix 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 Matrix with the resulting matrix
|
|
Premultiplied with Matrix.
|
|
|
|
This has the effect of rotating the drawing about a given point before
|
|
transforming the result with Matrix.
|
|
|
|
#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
|
|
#Height 192
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setTextSize(96);
|
|
canvas->drawString("A1", 130, 100, paint);
|
|
canvas->rotate(180, 130, 100);
|
|
canvas->drawString("A1", 130, 100, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso concat() translate() skew() scale() setMatrix
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void skew(SkScalar sx, SkScalar sy)
|
|
|
|
#In Matrix
|
|
#Line # skews Matrix ##
|
|
Skews Matrix 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 Matrix with a skew matrix Premultiplied with Matrix.
|
|
|
|
This has the effect of skewing the drawing by (sx, sy) before transforming
|
|
the result with Matrix.
|
|
|
|
#Param sx amount to skew on x-axis ##
|
|
#Param sy amount to skew on y-axis ##
|
|
|
|
#Example
|
|
#Description
|
|
Black text mimics an oblique text style by using a negative skew on x-axis
|
|
that shifts the geometry to the right as the y-axis values decrease.
|
|
Red text uses a positive skew on y-axis to shift the geometry down
|
|
as the x-axis values increase.
|
|
Blue text combines sx and sy skew to rotate and scale.
|
|
##
|
|
SkPaint paint;
|
|
paint.setTextSize(128);
|
|
canvas->translate(30, 130);
|
|
canvas->save();
|
|
canvas->skew(-.5, 0);
|
|
canvas->drawString("A1", 0, 0, paint);
|
|
canvas->restore();
|
|
canvas->save();
|
|
canvas->skew(0, .5);
|
|
paint.setColor(SK_ColorRED);
|
|
canvas->drawString("A1", 0, 0, paint);
|
|
canvas->restore();
|
|
canvas->skew(-.5, .5);
|
|
paint.setColor(SK_ColorBLUE);
|
|
canvas->drawString("A1", 0, 0, paint);
|
|
##
|
|
|
|
#SeeAlso concat() translate() rotate() scale() setMatrix
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void concat(const SkMatrix& matrix)
|
|
|
|
#In Matrix
|
|
#Line # multiplies Matrix by Matrix ##
|
|
Replaces Matrix with matrix Premultiplied with existing Matrix.
|
|
|
|
This has the effect of transforming the drawn geometry by matrix, before
|
|
transforming the result with existing Matrix.
|
|
|
|
#Param matrix matrix to Premultiply with existing Matrix ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setTextSize(80);
|
|
paint.setTextScaleX(.3);
|
|
SkMatrix matrix;
|
|
SkRect rect[2] = {{ 10, 20, 90, 110 }, { 40, 130, 140, 180 }};
|
|
matrix.setRectToRect(rect[0], rect[1], SkMatrix::kFill_ScaleToFit);
|
|
canvas->drawRect(rect[0], paint);
|
|
canvas->drawRect(rect[1], paint);
|
|
paint.setColor(SK_ColorWHITE);
|
|
canvas->drawString("Here", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
|
|
canvas->concat(matrix);
|
|
canvas->drawString("There", rect[0].fLeft + 10, rect[0].fBottom - 10, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso translate() rotate() scale() skew() setMatrix
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void setMatrix(const SkMatrix& matrix)
|
|
|
|
#In Matrix
|
|
#Line # sets Matrix ##
|
|
Replaces Matrix with matrix.
|
|
Unlike concat(), any prior matrix state is overwritten.
|
|
|
|
#Param matrix matrix to copy, replacing existing Matrix ##
|
|
|
|
#Example
|
|
#Height 128
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
canvas->scale(4, 6);
|
|
canvas->drawString("truth", 2, 10, paint);
|
|
SkMatrix matrix;
|
|
matrix.setScale(2.8f, 6);
|
|
canvas->setMatrix(matrix);
|
|
canvas->drawString("consequences", 2, 20, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso resetMatrix concat() translate() rotate() scale() skew()
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void resetMatrix()
|
|
|
|
#In Matrix
|
|
#Line # resets Matrix to identity ##
|
|
Sets Matrix to the identity matrix.
|
|
Any prior matrix state is overwritten.
|
|
|
|
#Example
|
|
#Height 128
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
canvas->scale(4, 6);
|
|
canvas->drawString("truth", 2, 10, paint);
|
|
canvas->resetMatrix();
|
|
canvas->scale(2.8f, 6);
|
|
canvas->drawString("consequences", 2, 20, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso setMatrix concat() translate() rotate() scale() skew()
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method const SkMatrix& getTotalMatrix() const
|
|
|
|
#In Matrix
|
|
#Line # returns Matrix ##
|
|
Returns Matrix.
|
|
This does not account for translation by Device or Surface.
|
|
|
|
#Return Matrix in Canvas ##
|
|
|
|
#Example
|
|
SkDebugf("isIdentity %s\n", canvas->getTotalMatrix().isIdentity() ? "true" : "false");
|
|
#StdOut
|
|
isIdentity true
|
|
##
|
|
##
|
|
|
|
#SeeAlso setMatrix resetMatrix concat()
|
|
|
|
##
|
|
|
|
#Subtopic Matrix ##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
#Subtopic Clip
|
|
#Line # stack of clipping Paths ##
|
|
|
|
Clip is built from a stack of clipping paths. Each Path in the
|
|
stack can be constructed from one or more Path_Contour elements. The
|
|
Path_Contour may be composed of any number of Path_Verb segments. Each
|
|
Path_Contour forms a closed area; Path_Fill_Type defines the area enclosed
|
|
by Path_Contour.
|
|
|
|
Clip stack of Path elements successfully restrict the Path area. Each
|
|
Path is transformed by Matrix, then intersected with or subtracted from the
|
|
prior Clip to form the replacement Clip. Use SkClipOp::kDifference
|
|
to subtract Path from Clip; use SkClipOp::kIntersect to intersect Path
|
|
with Clip.
|
|
|
|
A clipping Path may be Anti_Aliased; if Path, after transformation, is
|
|
composed of horizontal and vertical lines, clearing Anti_Alias allows whole pixels
|
|
to either be inside or outside the clip. The fastest drawing has a Aliased,
|
|
rectangular clip.
|
|
|
|
If clipping Path has Anti_Alias set, clip may partially clip a pixel, requiring
|
|
that drawing blend partially with the destination along the edge. A rotated
|
|
rectangular Anti_Aliased clip looks smoother but draws slower.
|
|
|
|
Clip can combine with Rect and Round_Rect primitives; like
|
|
Path, these are transformed by Matrix before they are combined with Clip.
|
|
|
|
Clip can combine with Region. Region is assumed to be in Device coordinates
|
|
and is unaffected by Matrix.
|
|
|
|
#Example
|
|
#Height 90
|
|
#Description
|
|
Draw a red circle with an Aliased clip and an Anti_Aliased clip.
|
|
Use an image filter to zoom into the pixels drawn.
|
|
The edge of the Aliased clip fully draws pixels in the red circle.
|
|
The edge of the Anti_Aliased clip partially draws pixels in the red circle.
|
|
##
|
|
SkPaint redPaint, scalePaint;
|
|
redPaint.setAntiAlias(true);
|
|
redPaint.setColor(SK_ColorRED);
|
|
canvas->save();
|
|
for (bool antialias : { false, true } ) {
|
|
canvas->save();
|
|
canvas->clipRect(SkRect::MakeWH(19.5f, 11.5f), antialias);
|
|
canvas->drawCircle(17, 11, 8, redPaint);
|
|
canvas->restore();
|
|
canvas->translate(16, 0);
|
|
}
|
|
canvas->restore();
|
|
SkMatrix matrix;
|
|
matrix.setScale(6, 6);
|
|
scalePaint.setImageFilter(
|
|
SkImageFilter::MakeMatrixFilter(matrix, kNone_SkFilterQuality, nullptr));
|
|
SkCanvas::SaveLayerRec saveLayerRec(
|
|
nullptr, &scalePaint, SkCanvas::kInitWithPrevious_SaveLayerFlag);
|
|
canvas->saveLayer(saveLayerRec);
|
|
canvas->restore();
|
|
##
|
|
|
|
#Method void clipRect(const SkRect& rect, SkClipOp op, bool doAntiAlias)
|
|
|
|
#In Clip
|
|
#Line # combines Clip with Rect ##
|
|
Replaces Clip with the intersection or difference of Clip and rect,
|
|
with an Aliased or Anti_Aliased clip edge. rect is transformed by Matrix
|
|
before it is combined with Clip.
|
|
|
|
#Param rect Rect to combine with Clip ##
|
|
#Param op Clip_Op to apply to Clip ##
|
|
#Param doAntiAlias true if Clip is to be Anti_Aliased ##
|
|
|
|
#Example
|
|
#Height 128
|
|
void draw(SkCanvas* canvas) {
|
|
canvas->rotate(10);
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
for (auto alias: { false, true } ) {
|
|
canvas->save();
|
|
canvas->clipRect(SkRect::MakeWH(90, 80), SkClipOp::kIntersect, alias);
|
|
canvas->drawCircle(100, 60, 60, paint);
|
|
canvas->restore();
|
|
canvas->translate(80, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso clipRRect clipPath clipRegion
|
|
|
|
##
|
|
|
|
#Method void clipRect(const SkRect& rect, SkClipOp op)
|
|
|
|
#In Clip
|
|
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 Matrix before it is combined with Clip.
|
|
|
|
#Param rect Rect to combine with Clip ##
|
|
#Param op Clip_Op to apply to Clip ##
|
|
|
|
#Example
|
|
#Height 192
|
|
#Width 280
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
for (SkClipOp op: { SkClipOp::kIntersect, SkClipOp::kDifference } ) {
|
|
canvas->save();
|
|
canvas->clipRect(SkRect::MakeWH(90, 120), op, false);
|
|
canvas->drawCircle(100, 100, 60, paint);
|
|
canvas->restore();
|
|
canvas->translate(80, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso clipRRect clipPath clipRegion
|
|
|
|
##
|
|
|
|
#Method void clipRect(const SkRect& rect, bool doAntiAlias = false)
|
|
|
|
#In Clip
|
|
Replaces Clip with the intersection of Clip and rect.
|
|
Resulting Clip is Aliased; pixels are fully contained by the clip.
|
|
rect is transformed by Matrix
|
|
before it is combined with Clip.
|
|
|
|
#Param rect Rect to combine with Clip ##
|
|
#Param doAntiAlias true if Clip is to be Anti_Aliased ##
|
|
|
|
#Example
|
|
#Height 133
|
|
#Description
|
|
A circle drawn in pieces looks uniform when drawn Aliased.
|
|
The same circle pieces blend with pixels more than once when Anti_Aliased,
|
|
visible as a thin pair of lines through the right circle.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
canvas->clear(SK_ColorWHITE);
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(0x8055aaff);
|
|
SkRect clipRect = { 0, 0, 87.4f, 87.4f };
|
|
for (auto alias: { false, true } ) {
|
|
canvas->save();
|
|
canvas->clipRect(clipRect, SkClipOp::kIntersect, alias);
|
|
canvas->drawCircle(67, 67, 60, paint);
|
|
canvas->restore();
|
|
canvas->save();
|
|
canvas->clipRect(clipRect, SkClipOp::kDifference, alias);
|
|
canvas->drawCircle(67, 67, 60, paint);
|
|
canvas->restore();
|
|
canvas->translate(120, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso clipRRect clipPath clipRegion
|
|
|
|
##
|
|
|
|
#Method void androidFramework_setDeviceClipRestriction(const SkIRect& rect)
|
|
|
|
#In Clip
|
|
#Line # exists for use by Android framework ##
|
|
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.
|
|
|
|
#Private
|
|
This private API is for use by Android framework only.
|
|
##
|
|
|
|
#Param rect maximum allowed clip in device coordinates
|
|
#Param ##
|
|
|
|
##
|
|
|
|
#Method void clipRRect(const SkRRect& rrect, SkClipOp op, bool doAntiAlias)
|
|
|
|
#In Clip
|
|
#Line # combines Clip with Round_Rect ##
|
|
Replaces Clip with the intersection or difference of Clip and rrect,
|
|
with an Aliased or Anti_Aliased clip edge.
|
|
rrect is transformed by Matrix
|
|
before it is combined with Clip.
|
|
|
|
#Param rrect Round_Rect to combine with Clip ##
|
|
#Param op Clip_Op to apply to Clip ##
|
|
#Param doAntiAlias true if Clip is to be Anti_Aliased ##
|
|
|
|
#Example
|
|
#Height 128
|
|
void draw(SkCanvas* canvas) {
|
|
canvas->clear(SK_ColorWHITE);
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(0x8055aaff);
|
|
SkRRect oval;
|
|
oval.setOval({10, 20, 90, 100});
|
|
canvas->clipRRect(oval, SkClipOp::kIntersect, true);
|
|
canvas->drawCircle(70, 100, 60, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso clipRect clipPath clipRegion
|
|
|
|
##
|
|
|
|
#Method void clipRRect(const SkRRect& rrect, SkClipOp op)
|
|
|
|
#In Clip
|
|
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 Matrix before it is combined with Clip.
|
|
|
|
#Param rrect Round_Rect to combine with Clip ##
|
|
#Param op Clip_Op to apply to Clip ##
|
|
|
|
#Example
|
|
#Height 128
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setColor(0x8055aaff);
|
|
auto oval = SkRRect::MakeOval({10, 20, 90, 100});
|
|
canvas->clipRRect(oval, SkClipOp::kIntersect);
|
|
canvas->drawCircle(70, 100, 60, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso clipRect clipPath clipRegion
|
|
|
|
##
|
|
|
|
#Method void clipRRect(const SkRRect& rrect, bool doAntiAlias = false)
|
|
|
|
#In Clip
|
|
Replaces Clip with the intersection of Clip and rrect,
|
|
with an Aliased or Anti_Aliased clip edge.
|
|
rrect is transformed by Matrix before it is combined with Clip.
|
|
|
|
#Param rrect Round_Rect to combine with Clip ##
|
|
#Param doAntiAlias true if Clip is to be Anti_Aliased ##
|
|
|
|
#Example
|
|
#Height 128
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
auto oval = SkRRect::MakeRectXY({10, 20, 90, 100}, 9, 13);
|
|
canvas->clipRRect(oval, true);
|
|
canvas->drawCircle(70, 100, 60, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso clipRect clipPath clipRegion
|
|
|
|
##
|
|
|
|
#Method void clipPath(const SkPath& path, SkClipOp op, bool doAntiAlias)
|
|
|
|
#In Clip
|
|
#Line # combines Clip with Path ##
|
|
Replaces Clip with the intersection or difference of Clip and path,
|
|
with an Aliased or Anti_Aliased clip edge. Path_Fill_Type 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 Matrix before it is combined with Clip.
|
|
|
|
#Param path Path to combine with Clip ##
|
|
#Param op Clip_Op to apply to Clip ##
|
|
#Param doAntiAlias true if Clip is to be Anti_Aliased ##
|
|
|
|
#Example
|
|
#Description
|
|
Top figure uses SkPath::kInverseWinding_FillType and SkClipOp::kDifference;
|
|
area outside clip is subtracted from circle.
|
|
|
|
Bottom figure uses SkPath::kWinding_FillType and SkClipOp::kIntersect;
|
|
area inside clip is intersected with circle.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
SkPath path;
|
|
path.addRect({20, 30, 100, 110});
|
|
path.setFillType(SkPath::kInverseWinding_FillType);
|
|
canvas->save();
|
|
canvas->clipPath(path, SkClipOp::kDifference, false);
|
|
canvas->drawCircle(70, 100, 60, paint);
|
|
canvas->restore();
|
|
canvas->translate(100, 100);
|
|
path.setFillType(SkPath::kWinding_FillType);
|
|
canvas->clipPath(path, SkClipOp::kIntersect, false);
|
|
canvas->drawCircle(70, 100, 60, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso clipRect clipRRect clipRegion
|
|
|
|
##
|
|
|
|
#Method void clipPath(const SkPath& path, SkClipOp op)
|
|
|
|
#In Clip
|
|
Replaces Clip with the intersection or difference of Clip and path.
|
|
Resulting Clip is Aliased; pixels are fully contained by the clip.
|
|
Path_Fill_Type 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 Matrix
|
|
before it is combined with Clip.
|
|
|
|
#Param path Path to combine with Clip ##
|
|
#Param op Clip_Op to apply to Clip ##
|
|
|
|
#Example
|
|
#Description
|
|
Overlapping Rects form a clip. When clip Path_Fill_Type is set to
|
|
SkPath::kWinding_FillType, the overlap is included. Set to
|
|
SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
SkPath path;
|
|
path.addRect({20, 15, 100, 95});
|
|
path.addRect({50, 65, 130, 135});
|
|
path.setFillType(SkPath::kWinding_FillType);
|
|
canvas->save();
|
|
canvas->clipPath(path, SkClipOp::kIntersect);
|
|
canvas->drawCircle(70, 85, 60, paint);
|
|
canvas->restore();
|
|
canvas->translate(100, 100);
|
|
path.setFillType(SkPath::kEvenOdd_FillType);
|
|
canvas->clipPath(path, SkClipOp::kIntersect);
|
|
canvas->drawCircle(70, 85, 60, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso clipRect clipRRect clipRegion
|
|
|
|
##
|
|
|
|
#Method void clipPath(const SkPath& path, bool doAntiAlias = false)
|
|
|
|
#In Clip
|
|
Replaces Clip with the intersection of Clip and path.
|
|
Resulting Clip is Aliased; pixels are fully contained by the clip.
|
|
Path_Fill_Type 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 Matrix before it is combined with Clip.
|
|
|
|
#Param path Path to combine with Clip ##
|
|
#Param doAntiAlias true if Clip is to be Anti_Aliased ##
|
|
|
|
#Example
|
|
#Height 212
|
|
#Description
|
|
Clip loops over itself covering its center twice. When clip Path_Fill_Type
|
|
is set to SkPath::kWinding_FillType, the overlap is included. Set to
|
|
SkPath::kEvenOdd_FillType, the overlap is excluded and forms a hole.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
SkPath path;
|
|
SkPoint poly[] = {{20, 20}, { 80, 20}, { 80, 80}, {40, 80},
|
|
{40, 40}, {100, 40}, {100, 100}, {20, 100}};
|
|
path.addPoly(poly, SK_ARRAY_COUNT(poly), true);
|
|
path.setFillType(SkPath::kWinding_FillType);
|
|
canvas->save();
|
|
canvas->clipPath(path, SkClipOp::kIntersect);
|
|
canvas->drawCircle(50, 50, 45, paint);
|
|
canvas->restore();
|
|
canvas->translate(100, 100);
|
|
path.setFillType(SkPath::kEvenOdd_FillType);
|
|
canvas->clipPath(path, SkClipOp::kIntersect);
|
|
canvas->drawCircle(50, 50, 45, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso clipRect clipRRect clipRegion
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void setAllowSimplifyClip(bool allow)
|
|
|
|
#In Clip
|
|
#Experimental testing
|
|
|
|
Set to simplify clip stack using PathOps.
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void clipRegion(const SkRegion& deviceRgn, SkClipOp op = SkClipOp::kIntersect)
|
|
|
|
#In Clip
|
|
#Line # combines Clip with Region ##
|
|
Replaces Clip with the intersection or difference of Clip and Region deviceRgn.
|
|
Resulting Clip is Aliased; pixels are fully contained by the clip.
|
|
deviceRgn is unaffected by Matrix.
|
|
|
|
#Param deviceRgn Region to combine with Clip ##
|
|
#Param op Clip_Op to apply to Clip ##
|
|
|
|
#Example
|
|
#Description
|
|
region is unaffected by canvas rotation; iRect is affected by canvas rotation.
|
|
Both clips are Aliased; this is not noticeable on Region clip because it
|
|
aligns to pixel boundaries.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
SkIRect iRect = {30, 40, 120, 130 };
|
|
SkRegion region(iRect);
|
|
canvas->rotate(10);
|
|
canvas->save();
|
|
canvas->clipRegion(region, SkClipOp::kIntersect);
|
|
canvas->drawCircle(50, 50, 45, paint);
|
|
canvas->restore();
|
|
canvas->translate(100, 100);
|
|
canvas->clipRect(SkRect::Make(iRect), SkClipOp::kIntersect);
|
|
canvas->drawCircle(50, 50, 45, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso clipRect clipRRect clipPath
|
|
|
|
##
|
|
|
|
#Method bool quickReject(const SkRect& rect) const
|
|
|
|
#In Clip
|
|
#Line # returns if Rect is outside Clip ##
|
|
Returns true if Rect rect, transformed by Matrix, 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 Rect to compare with Clip ##
|
|
|
|
#Return true if rect, transformed by Matrix, does not intersect Clip ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkRect testRect = {30, 30, 120, 129 };
|
|
SkRect clipRect = {30, 130, 120, 230 };
|
|
canvas->save();
|
|
canvas->clipRect(clipRect);
|
|
SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
|
|
canvas->restore();
|
|
canvas->rotate(10);
|
|
canvas->clipRect(clipRect);
|
|
SkDebugf("quickReject %s\n", canvas->quickReject(testRect) ? "true" : "false");
|
|
}
|
|
#StdOut
|
|
quickReject true
|
|
quickReject false
|
|
##
|
|
##
|
|
|
|
#SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing
|
|
|
|
##
|
|
|
|
#Method bool quickReject(const SkPath& path) const
|
|
|
|
#In Clip
|
|
Returns true if path, transformed by Matrix, 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 Path to compare with Clip ##
|
|
|
|
#Return true if path, transformed by Matrix, does not intersect Clip ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPoint testPoints[] = {{30, 30}, {120, 30}, {120, 129} };
|
|
SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
|
|
SkPath testPath, clipPath;
|
|
testPath.addPoly(testPoints, SK_ARRAY_COUNT(testPoints), true);
|
|
clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
|
|
canvas->save();
|
|
canvas->clipPath(clipPath);
|
|
SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
|
|
canvas->restore();
|
|
canvas->rotate(10);
|
|
canvas->clipPath(clipPath);
|
|
SkDebugf("quickReject %s\n", canvas->quickReject(testPath) ? "true" : "false");
|
|
#StdOut
|
|
quickReject true
|
|
quickReject false
|
|
##
|
|
}
|
|
##
|
|
|
|
#SeeAlso getLocalClipBounds getTotalMatrix SkBitmap::drawsNothing
|
|
|
|
##
|
|
|
|
#Method SkRect getLocalClipBounds() const
|
|
|
|
#In Clip
|
|
#Line # returns Clip bounds in source coordinates ##
|
|
Returns bounds of Clip, transformed by inverse of Matrix. If Clip is empty,
|
|
return SkRect::MakeEmpty, where all Rect sides equal zero.
|
|
|
|
Rect returned is outset by one to account for partial pixel coverage if Clip
|
|
is Anti_Aliased.
|
|
|
|
#Return bounds of Clip in local coordinates ##
|
|
|
|
#Example
|
|
#Description
|
|
Initial bounds is device bounds outset by 1 on all sides.
|
|
Clipped bounds is clipPath bounds outset by 1 on all sides.
|
|
Scaling the canvas by two on both axes scales the local bounds by 1/2
|
|
on both axes.
|
|
##
|
|
SkCanvas local(256, 256);
|
|
canvas = &local;
|
|
SkRect bounds = canvas->getLocalClipBounds();
|
|
SkDebugf("left:%g top:%g right:%g bottom:%g\n",
|
|
bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
|
|
SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
|
|
SkPath clipPath;
|
|
clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
|
|
canvas->clipPath(clipPath);
|
|
bounds = canvas->getLocalClipBounds();
|
|
SkDebugf("left:%g top:%g right:%g bottom:%g\n",
|
|
bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
|
|
canvas->scale(2, 2);
|
|
bounds = canvas->getLocalClipBounds();
|
|
SkDebugf("left:%g top:%g right:%g bottom:%g\n",
|
|
bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
|
|
#StdOut
|
|
left:-1 top:-1 right:257 bottom:257
|
|
left:29 top:129 right:121 bottom:231
|
|
left:14.5 top:64.5 right:60.5 bottom:115.5
|
|
##
|
|
##
|
|
|
|
# local canvas in example works around bug in fiddle ##
|
|
#Bug 6524
|
|
#SeeAlso getDeviceClipBounds getBaseLayerSize quickReject
|
|
|
|
##
|
|
|
|
#Method bool getLocalClipBounds(SkRect* bounds) const
|
|
|
|
#In Clip
|
|
Returns bounds of Clip, transformed by inverse of Matrix. If Clip is empty,
|
|
return false, and set bounds to SkRect::MakeEmpty, where all Rect sides equal zero.
|
|
|
|
bounds is outset by one to account for partial pixel coverage if Clip
|
|
is Anti_Aliased.
|
|
|
|
#Param bounds Rect of Clip in local coordinates ##
|
|
|
|
#Return true if Clip bounds is not empty ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkCanvas local(256, 256);
|
|
canvas = &local;
|
|
SkRect bounds;
|
|
SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
|
|
? "false" : "true");
|
|
SkPath path;
|
|
canvas->clipPath(path);
|
|
SkDebugf("local bounds empty = %s\n", canvas->getLocalClipBounds(&bounds)
|
|
? "false" : "true");
|
|
}
|
|
#StdOut
|
|
local bounds empty = false
|
|
local bounds empty = true
|
|
##
|
|
##
|
|
|
|
# local canvas in example works around bug in fiddle ##
|
|
#Bug 6524
|
|
#SeeAlso getDeviceClipBounds getBaseLayerSize quickReject
|
|
|
|
##
|
|
|
|
#Method SkIRect getDeviceClipBounds() const
|
|
|
|
#In Clip
|
|
#Line # returns IRect bounds of Clip ##
|
|
Returns IRect bounds of Clip, unaffected by Matrix. If Clip is empty,
|
|
return SkRect::MakeEmpty, where all Rect sides equal zero.
|
|
|
|
Unlike getLocalClipBounds, returned IRect is not outset.
|
|
|
|
#Return bounds of Clip in Device coordinates ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
#Description
|
|
Initial bounds is device bounds, not outset.
|
|
Clipped bounds is clipPath bounds, not outset.
|
|
Scaling the canvas by 1/2 on both axes scales the device bounds by 1/2
|
|
on both axes.
|
|
##
|
|
SkCanvas device(256, 256);
|
|
canvas = &device;
|
|
SkIRect bounds = canvas->getDeviceClipBounds();
|
|
SkDebugf("left:%d top:%d right:%d bottom:%d\n",
|
|
bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
|
|
SkPoint clipPoints[] = {{30, 130}, {120, 130}, {120, 230} };
|
|
SkPath clipPath;
|
|
clipPath.addPoly(clipPoints, SK_ARRAY_COUNT(clipPoints), true);
|
|
canvas->save();
|
|
canvas->clipPath(clipPath);
|
|
bounds = canvas->getDeviceClipBounds();
|
|
SkDebugf("left:%d top:%d right:%d bottom:%d\n",
|
|
bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
|
|
canvas->restore();
|
|
canvas->scale(1.f/2, 1.f/2);
|
|
canvas->clipPath(clipPath);
|
|
bounds = canvas->getDeviceClipBounds();
|
|
SkDebugf("left:%d top:%d right:%d bottom:%d\n",
|
|
bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
|
|
#StdOut
|
|
left:0 top:0 right:256 bottom:256
|
|
left:30 top:130 right:120 bottom:230
|
|
left:15 top:65 right:60 bottom:115
|
|
##
|
|
}
|
|
##
|
|
|
|
#ToDo some confusion on why with an identity Matrix local and device are different ##
|
|
#SeeAlso getLocalClipBounds getBaseLayerSize quickReject
|
|
|
|
# device canvas in example works around bug in fiddle ##
|
|
#Bug 6524
|
|
|
|
##
|
|
|
|
#Method bool getDeviceClipBounds(SkIRect* bounds) const
|
|
|
|
#In Clip
|
|
Returns IRect bounds of Clip, unaffected by Matrix. If Clip is empty,
|
|
return false, and set bounds to SkRect::MakeEmpty, where all Rect sides equal zero.
|
|
|
|
Unlike getLocalClipBounds, bounds is not outset.
|
|
|
|
#Param bounds Rect of Clip in device coordinates ##
|
|
|
|
#Return true if Clip bounds is not empty ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkIRect bounds;
|
|
SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
|
|
? "false" : "true");
|
|
SkPath path;
|
|
canvas->clipPath(path);
|
|
SkDebugf("device bounds empty = %s\n", canvas->getDeviceClipBounds(&bounds)
|
|
? "false" : "true");
|
|
}
|
|
#StdOut
|
|
device bounds empty = false
|
|
device bounds empty = true
|
|
##
|
|
##
|
|
|
|
#SeeAlso getLocalClipBounds getBaseLayerSize quickReject
|
|
|
|
##
|
|
|
|
#Subtopic Clip ##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
#Subtopic Draw
|
|
#Line # draws into Canvas ##
|
|
##
|
|
|
|
#Method void drawColor(SkColor color, SkBlendMode mode = SkBlendMode::kSrcOver)
|
|
#In Draw
|
|
#Line # fills Clip with Color and Blend_Mode ##
|
|
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
|
|
canvas->drawColor(SK_ColorRED);
|
|
canvas->clipRect(SkRect::MakeWH(150, 150));
|
|
canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00), SkBlendMode::kPlus);
|
|
canvas->clipRect(SkRect::MakeWH(75, 75));
|
|
canvas->drawColor(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF), SkBlendMode::kPlus);
|
|
##
|
|
|
|
#SeeAlso clear SkBitmap::erase drawPaint
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void clear(SkColor color)
|
|
#In Draw
|
|
#Line # fills Clip with Color ##
|
|
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 ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
canvas->save();
|
|
canvas->clipRect(SkRect::MakeWH(256, 128));
|
|
canvas->clear(SkColorSetARGB(0x80, 0xFF, 0x00, 0x00));
|
|
canvas->restore();
|
|
canvas->save();
|
|
canvas->clipRect(SkRect::MakeWH(150, 192));
|
|
canvas->clear(SkColorSetARGB(0x80, 0x00, 0xFF, 0x00));
|
|
canvas->restore();
|
|
canvas->clipRect(SkRect::MakeWH(75, 256));
|
|
canvas->clear(SkColorSetARGB(0x80, 0x00, 0x00, 0xFF));
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawColor SkBitmap::erase drawPaint
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void discard()
|
|
#In Utility
|
|
#Line # makes Canvas contents undefined ##
|
|
Makes Canvas contents undefined. Subsequent calls that read Canvas pixels,
|
|
such as drawing with SkBlendMode, return undefined results. discard() does
|
|
not change Clip or Matrix.
|
|
|
|
discard() may do nothing, depending on the implementation of Surface or Device
|
|
that created Canvas.
|
|
|
|
discard() allows optimized performance on subsequent draws by removing
|
|
cached data associated with Surface or Device.
|
|
It is not necessary to call discard() once done with Canvas;
|
|
any cached data is deleted when owning Surface or Device is deleted.
|
|
|
|
#ToDo example? not sure how to make this meaningful w/o more implementation detail ##
|
|
#SeeAlso flush() SkSurface::prepareForExternalIO GrContext::abandonContext
|
|
|
|
#NoExample
|
|
##
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawPaint(const SkPaint& paint)
|
|
#In Draw
|
|
#Line # fills Clip with Paint ##
|
|
Fills Clip with Paint paint. Paint components Mask_Filter, Shader,
|
|
Color_Filter, Image_Filter, and Blend_Mode affect drawing;
|
|
Path_Effect in paint is ignored.
|
|
|
|
# can Path_Effect in paint ever alter drawPaint?
|
|
|
|
#Param paint graphics state used to fill Canvas ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
|
|
SkScalar pos[] = { 0, SK_Scalar1/2, SK_Scalar1 };
|
|
SkPaint paint;
|
|
paint.setShader(SkGradientShader::MakeSweep(256, 256, colors, pos, SK_ARRAY_COUNT(colors)));
|
|
canvas->drawPaint(paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso clear drawColor SkBitmap::erase
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Enum PointMode
|
|
#Line # sets drawPoints options ##
|
|
|
|
#Code
|
|
#Populate
|
|
##
|
|
|
|
Selects if an array of points are drawn as discrete points, as lines, or as
|
|
an open polygon.
|
|
|
|
#Const kPoints_PointMode 0
|
|
#Line # draw each point separately ##
|
|
##
|
|
|
|
#Const kLines_PointMode 1
|
|
#Line # draw each pair of points as a line segment ##
|
|
##
|
|
|
|
#Const kPolygon_PointMode 2
|
|
#Line # draw the array of points as a open polygon ##
|
|
##
|
|
|
|
#Example
|
|
#Description
|
|
The upper left corner shows three squares when drawn as points.
|
|
The upper right corner shows one line; when drawn as lines, two points are required per line.
|
|
The lower right corner shows two lines; when draw as polygon, no miter is drawn at the corner.
|
|
The lower left corner shows two lines with a miter when path contains polygon.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
paint.setStrokeWidth(10);
|
|
SkPoint points[] = {{64, 32}, {96, 96}, {32, 96}};
|
|
canvas->drawPoints(SkCanvas::kPoints_PointMode, 3, points, paint);
|
|
canvas->translate(128, 0);
|
|
canvas->drawPoints(SkCanvas::kLines_PointMode, 3, points, paint);
|
|
canvas->translate(0, 128);
|
|
canvas->drawPoints(SkCanvas::kPolygon_PointMode, 3, points, paint);
|
|
SkPath path;
|
|
path.addPoly(points, 3, false);
|
|
canvas->translate(-128, 0);
|
|
canvas->drawPath(path, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawLine drawPoint drawPath
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawPoints(PointMode mode, size_t count, const SkPoint pts[], const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws array as points, lines, polygon ##
|
|
Draws pts using Clip, Matrix and Paint 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
|
|
Paint_Stroke_Cap. If paint is set to SkPaint::kRound_Cap, each point draws a
|
|
circle of diameter Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap
|
|
or SkPaint::kButt_Cap, each point draws a square of width and height
|
|
Paint_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 Paint_Stroke_Cap and Paint_Stroke_Width.
|
|
Paint_Style is ignored, as if were set to SkPaint::kStroke_Style.
|
|
|
|
Always draws each element one at a time; is not affected by
|
|
Paint_Stroke_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
|
|
#Height 200
|
|
#Description
|
|
#List
|
|
# The first column draws points. ##
|
|
# The second column draws points as lines. ##
|
|
# The third column draws points as a polygon. ##
|
|
# The fourth column draws points as a polygonal path. ##
|
|
# The first row uses a round cap and round join. ##
|
|
# The second row uses a square cap and a miter join. ##
|
|
# The third row uses a butt cap and a bevel join. ##
|
|
##
|
|
The transparent color makes multiple line draws visible;
|
|
the path is drawn all at once.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
paint.setStrokeWidth(10);
|
|
paint.setColor(0x80349a45);
|
|
const SkPoint points[] = {{32, 16}, {48, 48}, {16, 32}};
|
|
const SkPaint::Join join[] = { SkPaint::kRound_Join,
|
|
SkPaint::kMiter_Join,
|
|
SkPaint::kBevel_Join };
|
|
int joinIndex = 0;
|
|
SkPath path;
|
|
path.addPoly(points, 3, false);
|
|
for (const auto cap : { SkPaint::kRound_Cap, SkPaint::kSquare_Cap, SkPaint::kButt_Cap } ) {
|
|
paint.setStrokeCap(cap);
|
|
paint.setStrokeJoin(join[joinIndex++]);
|
|
for (const auto mode : { SkCanvas::kPoints_PointMode,
|
|
SkCanvas::kLines_PointMode,
|
|
SkCanvas::kPolygon_PointMode } ) {
|
|
canvas->drawPoints(mode, 3, points, paint);
|
|
canvas->translate(64, 0);
|
|
}
|
|
canvas->drawPath(path, paint);
|
|
canvas->translate(-192, 64);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawLine drawPoint drawPath
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawPoint(SkScalar x, SkScalar y, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws point at (x, y) position ##
|
|
Draws point at (x, y) using Clip, Matrix and Paint paint.
|
|
|
|
The shape of point drawn depends on paint Paint_Stroke_Cap.
|
|
If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
|
|
Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
|
|
draw a square of width and height Paint_Stroke_Width.
|
|
Paint_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
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(0x80349a45);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
paint.setStrokeWidth(100);
|
|
paint.setStrokeCap(SkPaint::kRound_Cap);
|
|
canvas->scale(1, 1.2f);
|
|
canvas->drawPoint(64, 96, paint);
|
|
canvas->scale(.6f, .8f);
|
|
paint.setColor(SK_ColorWHITE);
|
|
canvas->drawPoint(106, 120, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawPoints drawCircle drawRect drawLine drawPath
|
|
|
|
##
|
|
|
|
#Method void drawPoint(SkPoint p, const SkPaint& paint)
|
|
|
|
Draws point p using Clip, Matrix and Paint paint.
|
|
|
|
The shape of point drawn depends on paint Paint_Stroke_Cap.
|
|
If paint is set to SkPaint::kRound_Cap, draw a circle of diameter
|
|
Paint_Stroke_Width. If paint is set to SkPaint::kSquare_Cap or SkPaint::kButt_Cap,
|
|
draw a square of width and height Paint_Stroke_Width.
|
|
Paint_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 ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(0x80349a45);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
paint.setStrokeWidth(100);
|
|
paint.setStrokeCap(SkPaint::kSquare_Cap);
|
|
canvas->scale(1, 1.2f);
|
|
canvas->drawPoint({64, 96}, paint);
|
|
canvas->scale(.6f, .8f);
|
|
paint.setColor(SK_ColorWHITE);
|
|
canvas->drawPoint(106, 120, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawPoints drawCircle drawRect drawLine drawPath
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawLine(SkScalar x0, SkScalar y0, SkScalar x1, SkScalar y1, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws line segment between two points ##
|
|
Draws line segment from (x0, y0) to (x1, y1) using Clip, Matrix, and Paint paint.
|
|
In paint: Paint_Stroke_Width describes the line thickness;
|
|
Paint_Stroke_Cap draws the end rounded or square;
|
|
Paint_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
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(0xFF9a67be);
|
|
paint.setStrokeWidth(20);
|
|
canvas->skew(1, 0);
|
|
canvas->drawLine(32, 96, 32, 160, paint);
|
|
canvas->skew(-2, 0);
|
|
canvas->drawLine(288, 96, 288, 160, paint);
|
|
##
|
|
|
|
#SeeAlso drawPoint drawCircle drawRect drawPath
|
|
|
|
##
|
|
|
|
#Method void drawLine(SkPoint p0, SkPoint p1, const SkPaint& paint)
|
|
|
|
Draws line segment from p0 to p1 using Clip, Matrix, and Paint paint.
|
|
In paint: Paint_Stroke_Width describes the line thickness;
|
|
Paint_Stroke_Cap draws the end rounded or square;
|
|
Paint_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 ##
|
|
|
|
#Example
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(0xFF9a67be);
|
|
paint.setStrokeWidth(20);
|
|
canvas->skew(1, 0);
|
|
canvas->drawLine({32, 96}, {32, 160}, paint);
|
|
canvas->skew(-2, 0);
|
|
canvas->drawLine({288, 96}, {288, 160}, paint);
|
|
##
|
|
|
|
#SeeAlso drawPoint drawCircle drawRect drawPath
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawRect(const SkRect& rect, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws Rect using Clip, Matrix, and Paint ##
|
|
Draws Rect rect using Clip, Matrix, and Paint paint.
|
|
In paint: Paint_Style determines if rectangle is stroked or filled;
|
|
if stroked, Paint_Stroke_Width describes the line thickness, and
|
|
Paint_Stroke_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
|
|
void draw(SkCanvas* canvas) {
|
|
SkPoint rectPts[] = { {64, 48}, {192, 160} };
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
paint.setStrokeWidth(20);
|
|
paint.setStrokeJoin(SkPaint::kRound_Join);
|
|
SkMatrix rotator;
|
|
rotator.setRotate(30, 128, 128);
|
|
for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
|
|
paint.setColor(color);
|
|
SkRect rect;
|
|
rect.set(rectPts[0], rectPts[1]);
|
|
canvas->drawRect(rect, paint);
|
|
rotator.mapPoints(rectPts, 2);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawIRect drawRRect drawRoundRect drawRegion drawPath drawLine
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawIRect(const SkIRect& rect, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws IRect using Clip, Matrix, and Paint ##
|
|
Draws IRect rect using Clip, Matrix, and Paint paint.
|
|
In paint: Paint_Style determines if rectangle is stroked or filled;
|
|
if stroked, Paint_Stroke_Width describes the line thickness, and
|
|
Paint_Stroke_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
|
|
SkIRect rect = { 64, 48, 192, 160 };
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
paint.setStrokeWidth(20);
|
|
paint.setStrokeJoin(SkPaint::kRound_Join);
|
|
for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorMAGENTA } ) {
|
|
paint.setColor(color);
|
|
canvas->drawIRect(rect, paint);
|
|
canvas->rotate(30, 128, 128);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawRect drawRRect drawRoundRect drawRegion drawPath drawLine
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawRegion(const SkRegion& region, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws Region using Clip, Matrix, and Paint ##
|
|
Draws Region region using Clip, Matrix, and Paint paint.
|
|
In paint: Paint_Style determines if rectangle is stroked or filled;
|
|
if stroked, Paint_Stroke_Width describes the line thickness, and
|
|
Paint_Stroke_Join draws the corners rounded or square.
|
|
|
|
#Param region region to draw ##
|
|
#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkRegion region;
|
|
region.op( 10, 10, 50, 50, SkRegion::kUnion_Op);
|
|
region.op( 10, 50, 90, 90, SkRegion::kUnion_Op);
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
paint.setStrokeWidth(20);
|
|
paint.setStrokeJoin(SkPaint::kRound_Join);
|
|
canvas->drawRegion(region, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawRect drawIRect drawPath
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawOval(const SkRect& oval, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws Oval using Clip, Matrix, and Paint ##
|
|
Draws Oval oval using Clip, Matrix, and Paint.
|
|
In paint: Paint_Style determines if Oval is stroked or filled;
|
|
if stroked, Paint_Stroke_Width describes the line thickness.
|
|
|
|
#Param oval Rect bounds of Oval ##
|
|
#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
canvas->clear(0xFF3f5f9f);
|
|
SkColor kColor1 = SkColorSetARGB(0xff, 0xff, 0x7f, 0);
|
|
SkColor g1Colors[] = { kColor1, SkColorSetA(kColor1, 0x20) };
|
|
SkPoint g1Points[] = { { 0, 0 }, { 0, 100 } };
|
|
SkScalar pos[] = { 0.2f, 1.0f };
|
|
SkRect bounds = SkRect::MakeWH(80, 70);
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setShader(SkGradientShader::MakeLinear(g1Points, g1Colors, pos, SK_ARRAY_COUNT(g1Colors),
|
|
SkShader::kClamp_TileMode));
|
|
canvas->drawOval(bounds , paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawCircle drawPoint drawPath drawRRect drawRoundRect
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawRRect(const SkRRect& rrect, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws Round_Rect using Clip, Matrix, and Paint ##
|
|
Draws Round_Rect rrect using Clip, Matrix, and Paint paint.
|
|
In paint: Paint_Style determines if rrect is stroked or filled;
|
|
if stroked, Paint_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 Round_Rect with up to eight corner radii to draw ##
|
|
#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
SkRect outer = {30, 40, 210, 220};
|
|
SkRect radii = {30, 50, 70, 90 };
|
|
SkRRect rRect;
|
|
rRect.setNinePatch(outer, radii.fLeft, radii.fTop, radii.fRight, radii.fBottom);
|
|
canvas->drawRRect(rRect, paint);
|
|
paint.setColor(SK_ColorWHITE);
|
|
canvas->drawLine(outer.fLeft + radii.fLeft, outer.fTop,
|
|
outer.fLeft + radii.fLeft, outer.fBottom, paint);
|
|
canvas->drawLine(outer.fRight - radii.fRight, outer.fTop,
|
|
outer.fRight - radii.fRight, outer.fBottom, paint);
|
|
canvas->drawLine(outer.fLeft, outer.fTop + radii.fTop,
|
|
outer.fRight, outer.fTop + radii.fTop, paint);
|
|
canvas->drawLine(outer.fLeft, outer.fBottom - radii.fBottom,
|
|
outer.fRight, outer.fBottom - radii.fBottom, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawRect drawRoundRect drawDRRect drawCircle drawOval drawPath
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawDRRect(const SkRRect& outer, const SkRRect& inner, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws double Round_Rect stroked or filled ##
|
|
Draws Round_Rect outer and inner
|
|
using Clip, Matrix, and Paint paint.
|
|
outer must contain inner or the drawing is undefined.
|
|
In paint: Paint_Style determines if Round_Rect is stroked or filled;
|
|
if stroked, Paint_Stroke_Width describes the line thickness.
|
|
If stroked and Round_Rect corner has zero length radii, Paint_Stroke_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
|
|
Path built with identical data as fast.
|
|
|
|
#Param outer Round_Rect outer bounds to draw ##
|
|
#Param inner Round_Rect inner bounds to draw ##
|
|
#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
|
|
SkRRect inner = SkRRect::MakeOval({60, 70, 170, 160});
|
|
SkPaint paint;
|
|
canvas->drawDRRect(outer, inner, paint);
|
|
}
|
|
##
|
|
|
|
#Example
|
|
#Description
|
|
Outer Rect has no corner radii, but stroke join is rounded.
|
|
Inner Round_Rect has corner radii; outset stroke increases radii of corners.
|
|
Stroke join does not affect inner Round_Rect since it has no sharp corners.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkRRect outer = SkRRect::MakeRect({20, 40, 210, 200});
|
|
SkRRect inner = SkRRect::MakeRectXY({60, 70, 170, 160}, 10, 10);
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
paint.setStrokeWidth(20);
|
|
paint.setStrokeJoin(SkPaint::kRound_Join);
|
|
canvas->drawDRRect(outer, inner, paint);
|
|
paint.setStrokeWidth(1);
|
|
paint.setColor(SK_ColorWHITE);
|
|
canvas->drawDRRect(outer, inner, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawRect drawRoundRect drawRRect drawCircle drawOval drawPath
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws Circle using Clip, Matrix, and Paint ##
|
|
Draws Circle at (cx, cy) with radius using Clip, Matrix, and Paint paint.
|
|
If radius is zero or less, nothing is drawn.
|
|
In paint: Paint_Style determines if Circle is stroked or filled;
|
|
if stroked, Paint_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 Paint stroke or fill, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
canvas->drawCircle(128, 128, 90, paint);
|
|
paint.setColor(SK_ColorWHITE);
|
|
canvas->drawCircle(86, 86, 20, paint);
|
|
canvas->drawCircle(160, 76, 20, paint);
|
|
canvas->drawCircle(140, 150, 35, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine
|
|
|
|
##
|
|
|
|
#Method void drawCircle(SkPoint center, SkScalar radius, const SkPaint& paint)
|
|
|
|
Draws Circle at center with radius using Clip, Matrix, and Paint paint.
|
|
If radius is zero or less, nothing is drawn.
|
|
In paint: Paint_Style determines if Circle is stroked or filled;
|
|
if stroked, Paint_Stroke_Width describes the line thickness.
|
|
|
|
#Param center Circle center ##
|
|
#Param radius half the diameter of Circle ##
|
|
#Param paint Paint stroke or fill, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
canvas->drawCircle(128, 128, 90, paint);
|
|
paint.setColor(SK_ColorWHITE);
|
|
canvas->drawCircle({86, 86}, 20, paint);
|
|
canvas->drawCircle({160, 76}, 20, paint);
|
|
canvas->drawCircle({140, 150}, 35, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawOval drawRRect drawRoundRect drawPath drawArc drawPoint drawLine
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawArc(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle,
|
|
bool useCenter, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws Arc using Clip, Matrix, and Paint ##
|
|
|
|
Draws Arc using Clip, Matrix, and Paint 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 Rect oval is empty or sweepAngle is zero, nothing is drawn.
|
|
|
|
#Param oval Rect 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 Paint stroke or fill, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
SkRect oval = { 4, 4, 60, 60};
|
|
for (auto useCenter : { false, true } ) {
|
|
for (auto style : { SkPaint::kFill_Style, SkPaint::kStroke_Style } ) {
|
|
paint.setStyle(style);
|
|
for (auto degrees : { 45, 90, 180, 360} ) {
|
|
canvas->drawArc(oval, 0, degrees , useCenter, paint);
|
|
canvas->translate(64, 0);
|
|
}
|
|
canvas->translate(-256, 64);
|
|
}
|
|
}
|
|
}
|
|
##
|
|
|
|
#Example
|
|
#Height 64
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
paint.setStrokeWidth(4);
|
|
SkRect oval = { 4, 4, 60, 60};
|
|
float intervals[] = { 5, 5 };
|
|
paint.setPathEffect(SkDashPathEffect::Make(intervals, 2, 2.5f));
|
|
for (auto degrees : { 270, 360, 540, 720 } ) {
|
|
canvas->drawArc(oval, 0, degrees, false, paint);
|
|
canvas->translate(64, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso SkPath::arcTo drawCircle drawOval drawPath
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws Round_Rect using Clip, Matrix, and Paint ##
|
|
Draws Round_Rect bounded by Rect rect, with corner radii (rx, ry) using Clip,
|
|
Matrix, and Paint paint.
|
|
|
|
In paint: Paint_Style determines if Round_Rect is stroked or filled;
|
|
if stroked, Paint_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, Round_Rect is drawn as Rect and if stroked is affected by
|
|
Paint_Stroke_Join.
|
|
|
|
#Param rect Rect bounds of Round_Rect 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
|
|
#Description
|
|
Top row has a zero radius a generates a rectangle.
|
|
Second row radii sum to less than sides.
|
|
Third row radii sum equals sides.
|
|
Fourth row radii sum exceeds sides; radii are scaled to fit.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkVector radii[] = { {0, 20}, {10, 10}, {10, 20}, {10, 40} };
|
|
SkPaint paint;
|
|
paint.setStrokeWidth(15);
|
|
paint.setStrokeJoin(SkPaint::kRound_Join);
|
|
paint.setAntiAlias(true);
|
|
for (auto style : { SkPaint::kStroke_Style, SkPaint::kFill_Style } ) {
|
|
paint.setStyle(style );
|
|
for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) {
|
|
canvas->drawRoundRect({10, 10, 60, 40}, radii[i].fX, radii[i].fY, paint);
|
|
canvas->translate(0, 60);
|
|
}
|
|
canvas->translate(80, -240);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso DrawRRect drawRect drawDRRect drawPath drawCircle drawOval drawPoint
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawPath(const SkPath& path, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws Path using Clip, Matrix, and Paint ##
|
|
Draws Path path using Clip, Matrix, and Paint paint.
|
|
Path contains an array of Path_Contour, each of which may be open or closed.
|
|
|
|
In paint: Paint_Style determines if Round_Rect is stroked or filled:
|
|
if filled, Path_Fill_Type determines whether Path_Contour describes inside or
|
|
outside of fill; if stroked, Paint_Stroke_Width describes the line thickness,
|
|
Paint_Stroke_Cap describes line ends, and Paint_Stroke_Join describes how
|
|
corners are drawn.
|
|
|
|
#Param path Path to draw ##
|
|
#Param paint stroke, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
#Description
|
|
Top rows draw stroked path with combinations of joins and caps. The open contour
|
|
is affected by caps; the closed contour is affected by joins.
|
|
Bottom row draws fill the same for open and closed contour.
|
|
First bottom column shows winding fills overlap.
|
|
Second bottom column shows even odd fills exclude overlap.
|
|
Third bottom column shows inverse winding fills area outside both contours.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPath path;
|
|
path.moveTo(20, 20);
|
|
path.quadTo(60, 20, 60, 60);
|
|
path.close();
|
|
path.moveTo(60, 20);
|
|
path.quadTo(60, 60, 20, 60);
|
|
SkPaint paint;
|
|
paint.setStrokeWidth(10);
|
|
paint.setAntiAlias(true);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
for (auto join: { SkPaint::kBevel_Join, SkPaint::kRound_Join, SkPaint::kMiter_Join } ) {
|
|
paint.setStrokeJoin(join);
|
|
for (auto cap: { SkPaint::kButt_Cap, SkPaint::kSquare_Cap, SkPaint::kRound_Cap } ) {
|
|
paint.setStrokeCap(cap);
|
|
canvas->drawPath(path, paint);
|
|
canvas->translate(80, 0);
|
|
}
|
|
canvas->translate(-240, 60);
|
|
}
|
|
paint.setStyle(SkPaint::kFill_Style);
|
|
for (auto fill : { SkPath::kWinding_FillType,
|
|
SkPath::kEvenOdd_FillType,
|
|
SkPath::kInverseWinding_FillType } ) {
|
|
path.setFillType(fill);
|
|
canvas->save();
|
|
canvas->clipRect({0, 10, 80, 70});
|
|
canvas->drawPath(path, paint);
|
|
canvas->restore();
|
|
canvas->translate(80, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso SkPath drawLine drawArc drawRect drawPoints
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
#Subtopic Draw_Image
|
|
#Line # draws Image to Canvas ##
|
|
|
|
drawImage, drawImageRect, and drawImageNine can be called with a bare pointer or
|
|
a smart pointer as a convenience. The pairs of calls are otherwise identical.
|
|
|
|
#Method void drawImage(const SkImage* image, SkScalar left, SkScalar top, const SkPaint* paint = nullptr)
|
|
#In Draw_Image
|
|
#In Draw
|
|
#Line # draws Image at (x, y) position ##
|
|
Draws Image image, with its top-left corner at (left, top),
|
|
using Clip, Matrix, and optional Paint paint.
|
|
|
|
If paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter, Blend_Mode,
|
|
and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from image bounds. If generated
|
|
mask extends beyond image bounds, replicate image edge colors, just as Shader
|
|
made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the
|
|
image edge color when it samples outside of its bounds.
|
|
|
|
#Param image uncompressed rectangular map of pixels ##
|
|
#Param left left side of image ##
|
|
#Param top top side of image ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
|
|
#Example
|
|
#Height 64
|
|
#Image 4
|
|
void draw(SkCanvas* canvas) {
|
|
// sk_sp<SkImage> image;
|
|
SkImage* imagePtr = image.get();
|
|
canvas->drawImage(imagePtr, 0, 0);
|
|
SkPaint paint;
|
|
canvas->drawImage(imagePtr, 80, 0, &paint);
|
|
paint.setAlpha(0x80);
|
|
canvas->drawImage(imagePtr, 160, 0, &paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawImage(const sk_sp<SkImage>& image, SkScalar left, SkScalar top,
|
|
const SkPaint* paint = nullptr)
|
|
|
|
Draws Image image, with its top-left corner at (left, top),
|
|
using Clip, Matrix, and optional Paint paint.
|
|
|
|
If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
|
|
Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from image bounds. If generated
|
|
mask extends beyond image bounds, replicate image edge colors, just as Shader
|
|
made from SkImage::makeShader with SkShader::kClamp_TileMode set replicates the
|
|
image edge color when it samples outside of its bounds.
|
|
|
|
#Param image uncompressed rectangular map of pixels ##
|
|
#Param left left side of image ##
|
|
#Param top pop side of image ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
|
|
#Example
|
|
#Height 64
|
|
#Image 4
|
|
void draw(SkCanvas* canvas) {
|
|
// sk_sp<SkImage> image;
|
|
canvas->drawImage(image, 0, 0);
|
|
SkPaint paint;
|
|
canvas->drawImage(image, 80, 0, &paint);
|
|
paint.setAlpha(0x80);
|
|
canvas->drawImage(image, 160, 0, &paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawBitmap drawImageLattice drawImageNine drawImageRect SkPaint::setImageFilter
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Enum SrcRectConstraint
|
|
#Line # sets drawImageRect options ##
|
|
|
|
#Code
|
|
#Populate
|
|
##
|
|
|
|
SrcRectConstraint controls the behavior at the edge of source Rect,
|
|
provided to drawImageRect, trading off speed for precision.
|
|
|
|
Image_Filter in Paint may sample multiple pixels in the image. Source Rect
|
|
restricts the bounds of pixels that may be read. Image_Filter may slow down if
|
|
it cannot read outside the bounds, when sampling near the edge of source Rect.
|
|
SrcRectConstraint specifies whether an Image_Filter is allowed to read pixels
|
|
outside source Rect.
|
|
|
|
#Const kStrict_SrcRectConstraint 0
|
|
#Line # sample only inside bounds; slower ##
|
|
Requires Image_Filter to respect source Rect,
|
|
sampling only inside of its bounds, possibly with a performance penalty.
|
|
##
|
|
|
|
#Const kFast_SrcRectConstraint 1
|
|
#Line # sample outside bounds; faster ##
|
|
Permits Image_Filter to sample outside of source Rect
|
|
by half the width of Image_Filter, permitting it to run faster but with
|
|
error at the image edges.
|
|
##
|
|
|
|
#Example
|
|
#Height 64
|
|
#Description
|
|
redBorder contains a black and white checkerboard bordered by red.
|
|
redBorder is drawn scaled by 16 on the left.
|
|
The middle and right bitmaps are filtered checkerboards.
|
|
Drawing the checkerboard with kStrict_SrcRectConstraint shows only a blur of black and white.
|
|
Drawing the checkerboard with kFast_SrcRectConstraint allows red to bleed in the corners.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkBitmap redBorder;
|
|
redBorder.allocPixels(SkImageInfo::MakeN32Premul(4, 4));
|
|
SkCanvas checkRed(redBorder);
|
|
checkRed.clear(SK_ColorRED);
|
|
uint32_t checkers[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
|
|
{ SK_ColorWHITE, SK_ColorBLACK } };
|
|
checkRed.writePixels(
|
|
SkImageInfo::MakeN32Premul(2, 2), (void*) checkers, sizeof(checkers[0]), 1, 1);
|
|
canvas->scale(16, 16);
|
|
canvas->drawBitmap(redBorder, 0, 0, nullptr);
|
|
canvas->resetMatrix();
|
|
sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
|
|
SkPaint lowPaint;
|
|
lowPaint.setFilterQuality(kLow_SkFilterQuality);
|
|
for (auto constraint : { SkCanvas::kStrict_SrcRectConstraint,
|
|
SkCanvas::kFast_SrcRectConstraint } ) {
|
|
canvas->translate(80, 0);
|
|
canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
|
|
SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawImageRect drawImage SkPaint::setImageFilter
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawImageRect(const SkImage* image, const SkRect& src, const SkRect& dst,
|
|
const SkPaint* paint,
|
|
SrcRectConstraint constraint = kStrict_SrcRectConstraint)
|
|
#In Draw_Image
|
|
#In Draw
|
|
#Line # draws Image, source Rect to destination Rect ##
|
|
|
|
Draws Rect src of Image image, scaled and translated to fill Rect dst.
|
|
Additionally transform draw using Clip, Matrix, and optional Paint paint.
|
|
|
|
If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
|
|
Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from image bounds.
|
|
|
|
If generated mask extends beyond image bounds, replicate image edge colors, just
|
|
as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
|
|
replicates the image edge color when it samples outside of its bounds.
|
|
|
|
constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
|
|
sample within src; set to kFast_SrcRectConstraint allows sampling outside to
|
|
improve performance.
|
|
|
|
#Param image Image containing pixels, dimensions, and format ##
|
|
#Param src source Rect of image to draw from ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
#Param constraint filter strictly within src or draw faster ##
|
|
|
|
#Example
|
|
#Height 64
|
|
#Description
|
|
The left bitmap draws with Paint default kNone_SkFilterQuality, and stays within
|
|
its bounds; there is no bleeding with kFast_SrcRectConstraint.
|
|
the middle and right bitmaps draw with kLow_SkFilterQuality; with
|
|
kStrict_SrcRectConstraint, the filter remains within the checkerboard, and
|
|
with kFast_SrcRectConstraint red bleeds on the edges.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
uint32_t pixels[][4] = {
|
|
{ 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 },
|
|
{ 0xFFFF0000, 0xFF000000, 0xFFFFFFFF, 0xFFFF0000 },
|
|
{ 0xFFFF0000, 0xFFFFFFFF, 0xFF000000, 0xFFFF0000 },
|
|
{ 0xFFFF0000, 0xFFFF0000, 0xFFFF0000, 0xFFFF0000 } };
|
|
SkBitmap redBorder;
|
|
redBorder.installPixels(SkImageInfo::MakeN32Premul(4, 4),
|
|
(void*) pixels, sizeof(pixels[0]));
|
|
sk_sp<SkImage> image = SkImage::MakeFromBitmap(redBorder);
|
|
SkPaint lowPaint;
|
|
for (auto constraint : {
|
|
SkCanvas::kFast_SrcRectConstraint,
|
|
SkCanvas::kStrict_SrcRectConstraint,
|
|
SkCanvas::kFast_SrcRectConstraint } ) {
|
|
canvas->drawImageRect(image.get(), SkRect::MakeLTRB(1, 1, 3, 3),
|
|
SkRect::MakeLTRB(16, 16, 48, 48), &lowPaint, constraint);
|
|
lowPaint.setFilterQuality(kLow_SkFilterQuality);
|
|
canvas->translate(80, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawImageRect(const SkImage* image, const SkIRect& isrc, const SkRect& dst,
|
|
const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
|
|
#In Draw_Image
|
|
#In Draw
|
|
|
|
Draws IRect isrc of Image image, scaled and translated to fill Rect dst.
|
|
Note that isrc is on integer pixel boundaries; dst may include fractional
|
|
boundaries. Additionally transform draw using Clip, Matrix, and optional Paint
|
|
paint.
|
|
|
|
If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
|
|
Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from image bounds.
|
|
|
|
If generated mask extends beyond image bounds, replicate image edge colors, just
|
|
as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
|
|
replicates the image edge color when it samples outside of its bounds.
|
|
|
|
constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
|
|
sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to
|
|
improve performance.
|
|
|
|
#Param image Image containing pixels, dimensions, and format ##
|
|
#Param isrc source IRect of image to draw from ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
#Param constraint filter strictly within isrc or draw faster ##
|
|
|
|
#Example
|
|
#Image 4
|
|
void draw(SkCanvas* canvas) {
|
|
// sk_sp<SkImage> image;
|
|
for (auto i : { 1, 2, 4, 8 } ) {
|
|
canvas->drawImageRect(image.get(), SkIRect::MakeLTRB(0, 0, 100, 100),
|
|
SkRect::MakeXYWH(i * 20, i * 20, i * 20, i * 20), nullptr);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawImageRect(const SkImage* image, const SkRect& dst, const SkPaint* paint,
|
|
SrcRectConstraint constraint = kStrict_SrcRectConstraint)
|
|
#In Draw_Image
|
|
#In Draw
|
|
|
|
Draws Image image, scaled and translated to fill Rect dst, using Clip, Matrix,
|
|
and optional Paint paint.
|
|
|
|
If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
|
|
Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from image bounds.
|
|
|
|
If generated mask extends beyond image bounds, replicate image edge colors, just
|
|
as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
|
|
replicates the image edge color when it samples outside of its bounds.
|
|
|
|
constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
|
|
sample within image; set to kFast_SrcRectConstraint allows sampling outside to
|
|
improve performance.
|
|
|
|
#Param image Image containing pixels, dimensions, and format ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
#Param constraint filter strictly within image or draw faster ##
|
|
|
|
#Example
|
|
#Image 4
|
|
void draw(SkCanvas* canvas) {
|
|
// sk_sp<SkImage> image;
|
|
for (auto i : { 20, 40, 80, 160 } ) {
|
|
canvas->drawImageRect(image.get(), SkRect::MakeXYWH(i, i, i, i), nullptr);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& src, const SkRect& dst,
|
|
const SkPaint* paint,
|
|
SrcRectConstraint constraint = kStrict_SrcRectConstraint)
|
|
#In Draw_Image
|
|
#In Draw
|
|
Draws Rect src of Image image, scaled and translated to fill Rect dst.
|
|
Additionally transform draw using Clip, Matrix, and optional Paint paint.
|
|
|
|
If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
|
|
Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from image bounds.
|
|
|
|
If generated mask extends beyond image bounds, replicate image edge colors, just
|
|
as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
|
|
replicates the image edge color when it samples outside of its bounds.
|
|
|
|
constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
|
|
sample within src; set to kFast_SrcRectConstraint allows sampling outside to
|
|
improve performance.
|
|
|
|
#Param image Image containing pixels, dimensions, and format ##
|
|
#Param src source Rect of image to draw from ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
#Param constraint filter strictly within src or draw faster ##
|
|
|
|
#Example
|
|
#Height 64
|
|
#Description
|
|
Canvas scales and translates; transformation from src to dst also scales.
|
|
The two matrices are concatenated to create the final transformation.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
uint32_t pixels[][2] = { { SK_ColorBLACK, SK_ColorWHITE },
|
|
{ SK_ColorWHITE, SK_ColorBLACK } };
|
|
SkBitmap bitmap;
|
|
bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
|
|
(void*) pixels, sizeof(pixels[0]));
|
|
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
|
|
SkPaint paint;
|
|
canvas->scale(4, 4);
|
|
for (auto alpha : { 50, 100, 150, 255 } ) {
|
|
paint.setAlpha(alpha);
|
|
canvas->drawImageRect(image, SkRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
|
|
canvas->translate(8, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawImageRect(const sk_sp<SkImage>& image, const SkIRect& isrc, const SkRect& dst,
|
|
const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
|
|
#In Draw_Image
|
|
#In Draw
|
|
Draws IRect isrc of Image image, scaled and translated to fill Rect dst.
|
|
isrc is on integer pixel boundaries; dst may include fractional boundaries.
|
|
Additionally transform draw using Clip, Matrix, and optional Paint paint.
|
|
|
|
If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
|
|
Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from image bounds.
|
|
|
|
If generated mask extends beyond image bounds, replicate image edge colors, just
|
|
as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
|
|
replicates the image edge color when it samples outside of its bounds.
|
|
|
|
constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
|
|
sample within image; set to kFast_SrcRectConstraint allows sampling outside to
|
|
improve performance.
|
|
|
|
#Param image Image containing pixels, dimensions, and format ##
|
|
#Param isrc source IRect of image to draw from ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
#Param constraint filter strictly within image or draw faster ##
|
|
|
|
#Example
|
|
#Height 64
|
|
void draw(SkCanvas* canvas) {
|
|
uint32_t pixels[][2] = { { 0x00000000, 0x55555555},
|
|
{ 0xAAAAAAAA, 0xFFFFFFFF} };
|
|
SkBitmap bitmap;
|
|
bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
|
|
(void*) pixels, sizeof(pixels[0]));
|
|
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
|
|
SkPaint paint;
|
|
canvas->scale(4, 4);
|
|
for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
|
|
paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
|
|
canvas->drawImageRect(image, SkIRect::MakeWH(2, 2), SkRect::MakeWH(8, 8), &paint);
|
|
canvas->translate(8, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawImageRect(const sk_sp<SkImage>& image, const SkRect& dst, const SkPaint* paint,
|
|
SrcRectConstraint constraint = kStrict_SrcRectConstraint)
|
|
#In Draw_Image
|
|
#In Draw
|
|
Draws Image image, scaled and translated to fill Rect dst,
|
|
using Clip, Matrix, and optional Paint paint.
|
|
|
|
If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
|
|
Blend_Mode, and Draw_Looper. If image is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from image bounds.
|
|
|
|
If generated mask extends beyond image bounds, replicate image edge colors, just
|
|
as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
|
|
replicates the image edge color when it samples outside of its bounds.
|
|
|
|
constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
|
|
sample within image; set to kFast_SrcRectConstraint allows sampling outside to
|
|
improve performance.
|
|
|
|
#Param image Image containing pixels, dimensions, and format ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
#Param constraint filter strictly within image or draw faster ##
|
|
|
|
#Example
|
|
#Height 64
|
|
void draw(SkCanvas* canvas) {
|
|
uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
|
|
{ 0xAAAA0000, 0xFFFF0000} };
|
|
SkBitmap bitmap;
|
|
bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
|
|
(void*) pixels, sizeof(pixels[0]));
|
|
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
|
|
SkPaint paint;
|
|
canvas->scale(4, 4);
|
|
for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
|
|
paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
|
|
canvas->drawImageRect(image, SkRect::MakeWH(8, 8), &paint);
|
|
canvas->translate(8, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso SrcRectConstraint drawImage drawImageLattice drawImageNine
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
|
|
const SkPaint* paint = nullptr)
|
|
#In Draw_Image
|
|
#In Draw
|
|
#Line # draws Nine_Patch Image ##
|
|
|
|
Draws Image image stretched proportionally to fit into Rect dst.
|
|
IRect 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, Matrix, and optional Paint paint.
|
|
|
|
#paint_as_used_by_draw_lattice_or_draw_nine(image)#
|
|
|
|
If generated mask extends beyond image bounds, replicate image edge colors, just
|
|
as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
|
|
replicates the image edge color when it samples outside of its bounds.
|
|
|
|
#Param image Image containing pixels, dimensions, and format ##
|
|
#Param center IRect edge of image corners and sides ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
|
|
#Example
|
|
#Height 128
|
|
#Description
|
|
The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
|
|
The second image equals the size of center; only corners are drawn without scaling.
|
|
The remaining images are larger than center. All corners draw without scaling.
|
|
The sides and center are scaled if needed to take up the remaining space.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkIRect center = { 20, 10, 50, 40 };
|
|
SkBitmap bitmap;
|
|
bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
|
|
SkCanvas bitCanvas(bitmap);
|
|
SkPaint paint;
|
|
SkColor gray = 0xFF000000;
|
|
int left = 0;
|
|
for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
|
|
int top = 0;
|
|
for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
|
|
paint.setColor(gray);
|
|
bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
|
|
gray += 0x001f1f1f;
|
|
top = bottom;
|
|
}
|
|
left = right;
|
|
}
|
|
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
|
|
SkImage* imagePtr = image.get();
|
|
for (auto dest: { 20, 30, 40, 60, 90 } ) {
|
|
canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
|
|
canvas->translate(dest + 4, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawImageNine(const sk_sp<SkImage>& image, const SkIRect& center, const SkRect& dst,
|
|
const SkPaint* paint = nullptr)
|
|
#In Draw_Image
|
|
#In Draw
|
|
Draws Image image stretched proportionally to fit into Rect dst.
|
|
IRect center divides the image into nine sections: four sides, four corners, and
|
|
the center. Corners are not scaled, 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, Matrix, and optional Paint paint.
|
|
|
|
#paint_as_used_by_draw_lattice_or_draw_nine(image)#
|
|
|
|
If generated mask extends beyond image bounds, replicate image edge colors, just
|
|
as Shader made from SkImage::makeShader with SkShader::kClamp_TileMode set
|
|
replicates the image edge color when it samples outside of its bounds.
|
|
|
|
#Param image Image containing pixels, dimensions, and format ##
|
|
#Param center IRect edge of image corners and sides ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
|
|
#Example
|
|
#Height 128
|
|
#Description
|
|
The two leftmost images has four corners and sides to the left and right of center.
|
|
The leftmost image scales the width of corners proportionately to fit.
|
|
The third and fourth image corners are not scaled; the sides and center are scaled to
|
|
fill the remaining space.
|
|
The rightmost image has four corners scaled vertically to fit, and uses sides above
|
|
and below center to fill the remaining space.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkIRect center = { 20, 10, 50, 40 };
|
|
SkBitmap bitmap;
|
|
bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
|
|
SkCanvas bitCanvas(bitmap);
|
|
SkPaint paint;
|
|
SkColor gray = 0xFF000000;
|
|
int left = 0;
|
|
for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
|
|
int top = 0;
|
|
for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
|
|
paint.setColor(gray);
|
|
bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
|
|
gray += 0x001f1f1f;
|
|
top = bottom;
|
|
}
|
|
left = right;
|
|
}
|
|
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
|
|
for (auto dest: { 20, 30, 40, 60, 90 } ) {
|
|
canvas->drawImageNine(image, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
|
|
canvas->translate(dest + 4, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawImage drawBitmapNine drawImageLattice drawImageRect
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar top,
|
|
const SkPaint* paint = nullptr)
|
|
#In Draw_Image
|
|
#In Draw
|
|
#Line # draws Bitmap at (x, y) position ##
|
|
|
|
Draws Bitmap bitmap, with its top-left corner at (left, top),
|
|
using Clip, Matrix, and optional Paint paint.
|
|
|
|
If Paint paint is not nullptr, apply Color_Filter, Color_Alpha, Image_Filter,
|
|
Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from bitmap bounds.
|
|
|
|
If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
|
|
just as Shader made from SkShader::MakeBitmapShader with
|
|
SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
|
|
outside of its bounds.
|
|
|
|
#Param bitmap Bitmap containing pixels, dimensions, and format ##
|
|
#Param left left side of bitmap ##
|
|
#Param top top side of bitmap ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
|
|
#Example
|
|
#Height 64
|
|
void draw(SkCanvas* canvas) {
|
|
uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
|
|
{ 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
|
|
{ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
|
|
{ 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
|
|
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
{ 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
|
|
{ 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00},
|
|
{ 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF} };
|
|
SkBitmap bitmap;
|
|
bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
|
|
(void*) pixels, sizeof(pixels[0]));
|
|
SkPaint paint;
|
|
canvas->scale(4, 4);
|
|
for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
|
|
paint.setColor(color);
|
|
canvas->drawBitmap(bitmap, 0, 0, &paint);
|
|
canvas->translate(12, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawImage drawBitmapLattice drawBitmapNine drawBitmapRect SkBitmap::readPixels SkBitmap::writePixels
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& src, const SkRect& dst,
|
|
const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
|
|
#In Draw_Image
|
|
#In Draw
|
|
#Line # draws Bitmap, source Rect to destination Rect ##
|
|
|
|
Draws Rect src of Bitmap bitmap, scaled and translated to fill Rect dst.
|
|
Additionally transform draw using Clip, Matrix, and optional Paint paint.
|
|
|
|
If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
|
|
Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from bitmap bounds.
|
|
|
|
If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
|
|
just as Shader made from SkShader::MakeBitmapShader with
|
|
SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
|
|
outside of its bounds.
|
|
|
|
constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
|
|
sample within src; set to kFast_SrcRectConstraint allows sampling outside to
|
|
improve performance.
|
|
|
|
#Param bitmap Bitmap containing pixels, dimensions, and format ##
|
|
#Param src source Rect of image to draw from ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
#Param constraint filter strictly within src or draw faster ##
|
|
|
|
#Example
|
|
#Height 64
|
|
void draw(SkCanvas* canvas) {
|
|
uint8_t pixels[][8] = { { 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00},
|
|
{ 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
|
|
{ 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00},
|
|
{ 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF},
|
|
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
|
{ 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00},
|
|
{ 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
|
|
{ 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00} };
|
|
SkBitmap bitmap;
|
|
bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
|
|
(void*) pixels, sizeof(pixels[0]));
|
|
SkPaint paint;
|
|
paint.setMaskFilter(SkMaskFilter::MakeBlur(kSolid_SkBlurStyle, 6));
|
|
for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00} ) {
|
|
paint.setColor(color);
|
|
canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
|
|
canvas->translate(48, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawBitmapRect(const SkBitmap& bitmap, const SkIRect& isrc, const SkRect& dst,
|
|
const SkPaint* paint, SrcRectConstraint constraint = kStrict_SrcRectConstraint)
|
|
#In Draw_Image
|
|
#In Draw
|
|
Draws IRect isrc of Bitmap bitmap, scaled and translated to fill Rect dst.
|
|
isrc is on integer pixel boundaries; dst may include fractional boundaries.
|
|
Additionally transform draw using Clip, Matrix, and optional Paint paint.
|
|
|
|
If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
|
|
Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from bitmap bounds.
|
|
|
|
If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
|
|
just as Shader made from SkShader::MakeBitmapShader with
|
|
SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
|
|
outside of its bounds.
|
|
|
|
constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
|
|
sample within isrc; set to kFast_SrcRectConstraint allows sampling outside to
|
|
improve performance.
|
|
|
|
#Param bitmap Bitmap containing pixels, dimensions, and format ##
|
|
#Param isrc source IRect of image to draw from ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
#Param constraint sample strictly within isrc, or draw faster ##
|
|
|
|
#Example
|
|
#Height 64
|
|
void draw(SkCanvas* canvas) {
|
|
uint8_t pixels[][8] = { { 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00},
|
|
{ 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
|
|
{ 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
|
|
{ 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF},
|
|
{ 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF},
|
|
{ 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF},
|
|
{ 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00},
|
|
{ 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00} };
|
|
SkBitmap bitmap;
|
|
bitmap.installPixels(SkImageInfo::MakeA8(8, 8),
|
|
(void*) pixels, sizeof(pixels[0]));
|
|
SkPaint paint;
|
|
paint.setFilterQuality(kHigh_SkFilterQuality);
|
|
for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xFF007F00, 0xFF7f007f} ) {
|
|
paint.setColor(color);
|
|
canvas->drawBitmapRect(bitmap, SkIRect::MakeWH(8, 8), SkRect::MakeWH(32, 32), &paint);
|
|
canvas->translate(48.25f, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawBitmapRect(const SkBitmap& bitmap, const SkRect& dst, const SkPaint* paint,
|
|
SrcRectConstraint constraint = kStrict_SrcRectConstraint)
|
|
#In Draw_Image
|
|
#In Draw
|
|
Draws Bitmap bitmap, scaled and translated to fill Rect dst.
|
|
bitmap bounds is on integer pixel boundaries; dst may include fractional boundaries.
|
|
Additionally transform draw using Clip, Matrix, and optional Paint paint.
|
|
|
|
If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
|
|
Blend_Mode, and Draw_Looper. If bitmap is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from bitmap bounds.
|
|
|
|
If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
|
|
just as Shader made from SkShader::MakeBitmapShader with
|
|
SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
|
|
outside of its bounds.
|
|
|
|
constraint set to kStrict_SrcRectConstraint limits Paint Filter_Quality to
|
|
sample within bitmap; set to kFast_SrcRectConstraint allows sampling outside to
|
|
improve performance.
|
|
|
|
#Param bitmap Bitmap containing pixels, dimensions, and format ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
#Param constraint filter strictly within bitmap or draw faster ##
|
|
|
|
#Example
|
|
#Height 64
|
|
void draw(SkCanvas* canvas) {
|
|
uint32_t pixels[][2] = { { 0x00000000, 0x55550000},
|
|
{ 0xAAAA0000, 0xFFFF0000} };
|
|
SkBitmap bitmap;
|
|
bitmap.installPixels(SkImageInfo::MakeN32Premul(2, 2),
|
|
(void*) pixels, sizeof(pixels[0]));
|
|
SkPaint paint;
|
|
canvas->scale(4, 4);
|
|
for (auto color : { SK_ColorRED, SK_ColorBLUE, SK_ColorGREEN } ) {
|
|
paint.setColorFilter(SkColorFilter::MakeModeFilter(color, SkBlendMode::kPlus));
|
|
canvas->drawBitmapRect(bitmap, SkRect::MakeWH(8, 8), &paint);
|
|
canvas->translate(8, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawImageRect drawBitmap drawBitmapLattice drawBitmapNine
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#PhraseDef paint_as_used_by_draw_lattice_or_draw_nine(bitmap_or_image)
|
|
If Paint paint is supplied, apply Color_Filter, Color_Alpha, Image_Filter,
|
|
Blend_Mode, and Draw_Looper. If #bitmap_or_image# is kAlpha_8_SkColorType, apply Shader.
|
|
If paint contains Mask_Filter, generate mask from #bitmap_or_image# bounds. If paint
|
|
Filter_Quality set to kNone_SkFilterQuality, disable pixel filtering. For all
|
|
other values of paint Filter_Quality, use kLow_SkFilterQuality to filter pixels.
|
|
Any SkMaskFilter on paint is ignored as is paint Anti_Aliasing state.
|
|
##
|
|
|
|
#Method void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst,
|
|
const SkPaint* paint = nullptr)
|
|
#In Draw_Image
|
|
#In Draw
|
|
#Line # draws Nine_Patch Bitmap ##
|
|
|
|
Draws Bitmap bitmap stretched proportionally to fit into Rect dst.
|
|
IRect center divides the bitmap into nine sections: four sides, four corners,
|
|
and the center. Corners are not scaled, 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, Matrix, and optional Paint paint.
|
|
|
|
#paint_as_used_by_draw_lattice_or_draw_nine(bitmap)#
|
|
|
|
If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
|
|
just as Shader made from SkShader::MakeBitmapShader with
|
|
SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
|
|
outside of its bounds.
|
|
|
|
#Param bitmap Bitmap containing pixels, dimensions, and format ##
|
|
#Param center IRect edge of image corners and sides ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
|
|
#Example
|
|
#Height 128
|
|
#Description
|
|
The two leftmost bitmap draws has four corners and sides to the left and right of center.
|
|
The leftmost bitmap draw scales the width of corners proportionately to fit.
|
|
The third and fourth draw corners are not scaled; the sides and center are scaled to
|
|
fill the remaining space.
|
|
The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
|
|
and below center to fill the remaining space.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkIRect center = { 20, 10, 50, 40 };
|
|
SkBitmap bitmap;
|
|
bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
|
|
SkCanvas bitCanvas(bitmap);
|
|
SkPaint paint;
|
|
SkColor gray = 0xFF000000;
|
|
int left = 0;
|
|
for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
|
|
int top = 0;
|
|
for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
|
|
paint.setColor(gray);
|
|
bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
|
|
gray += 0x001f1f1f;
|
|
top = bottom;
|
|
}
|
|
left = right;
|
|
}
|
|
for (auto dest: { 20, 30, 40, 60, 90 } ) {
|
|
canvas->drawBitmapNine(bitmap, center, SkRect::MakeWH(dest, 110 - dest), nullptr);
|
|
canvas->translate(dest + 4, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawImageNine drawBitmap drawBitmapLattice drawBitmapRect
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
#Subtopic Lattice
|
|
#Line # divides Bitmap or Image into a rectangular grid ##
|
|
|
|
#Struct Lattice
|
|
#Line # divides Bitmap or Image into a rectangular grid ##
|
|
|
|
#Code
|
|
#Populate
|
|
##
|
|
|
|
Lattice divides Bitmap or Image 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.
|
|
|
|
#Enum RectType
|
|
#Line # optional setting per rectangular grid entry ##
|
|
#Code
|
|
#Populate
|
|
##
|
|
|
|
Optional setting per rectangular grid entry to make it transparent,
|
|
or to fill the grid entry with a color.
|
|
|
|
#Const kDefault 0
|
|
#Line # draws Bitmap into lattice rectangle ##
|
|
##
|
|
|
|
#Const kTransparent 1
|
|
#Line # skips lattice rectangle by making it transparent ##
|
|
##
|
|
|
|
#Const kFixedColor 2
|
|
#Line # draws one of fColors into lattice rectangle ##
|
|
##
|
|
##
|
|
|
|
#Subtopic Members
|
|
##
|
|
|
|
#Member const int* fXDivs
|
|
#Line # x-axis values dividing bitmap ##
|
|
Array of x-axis values that divide the bitmap vertically.
|
|
Array entries must be unique, increasing, greater than or equal to
|
|
fBounds left edge, and less than fBounds right edge.
|
|
Set the first element to fBounds left to collapse the left column of
|
|
fixed grid entries.
|
|
##
|
|
|
|
#Member const int* fYDivs
|
|
#Line # y-axis values dividing bitmap ##
|
|
Array of y-axis values that divide the bitmap horizontally.
|
|
Array entries must be unique, increasing, greater than or equal to
|
|
fBounds top edge, and less than fBounds bottom edge.
|
|
Set the first element to fBounds top to collapse the top row of fixed
|
|
grid entries.
|
|
##
|
|
|
|
#Member const RectType* fRectTypes
|
|
#Line # array of fill types ##
|
|
Optional array of fill types, one per rectangular grid entry:
|
|
array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
|
|
|
|
Each RectType is one of: kDefault, kTransparent, kFixedColor.
|
|
|
|
Array entries correspond to the rectangular grid entries, ascending
|
|
left to right and then top to bottom.
|
|
##
|
|
|
|
#Member int fXCount
|
|
#Line # number of x-coordinates ##
|
|
Number of entries in fXDivs array; one less than the number of
|
|
horizontal divisions.
|
|
##
|
|
|
|
#Member int fYCount
|
|
#Line # number of y-coordinates ##
|
|
Number of entries in fYDivs array; one less than the number of vertical
|
|
divisions.
|
|
##
|
|
|
|
#Member const SkIRect* fBounds
|
|
#Line # source bounds to draw from ##
|
|
Optional subset IRect source to draw from.
|
|
If nullptr, source bounds is dimensions of Bitmap or Image.
|
|
##
|
|
|
|
#Member const SkColor* fColors
|
|
#Line # array of colors ##
|
|
Optional array of colors, one per rectangular grid entry.
|
|
Array length must be #Formula # (fXCount + 1) * (fYCount + 1) ##.
|
|
|
|
Array entries correspond to the rectangular grid entries, ascending
|
|
left to right, then top to bottom.
|
|
##
|
|
|
|
#Struct Lattice ##
|
|
|
|
#Method void drawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst,
|
|
const SkPaint* paint = nullptr)
|
|
#In Draw_Image
|
|
#In Draw
|
|
#Line # draws proportionally stretched Bitmap ##
|
|
|
|
Draws Bitmap bitmap stretched proportionally to fit into Rect dst.
|
|
|
|
Lattice lattice divides bitmap into a rectangular grid.
|
|
Each intersection of an even-numbered row and column is fixed; like the corners
|
|
of drawBitmapNine, 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, Matrix, and optional Paint paint.
|
|
|
|
#paint_as_used_by_draw_lattice_or_draw_nine(bitmap)#
|
|
|
|
If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
|
|
just as Shader made from SkShader::MakeBitmapShader with
|
|
SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
|
|
outside of its bounds.
|
|
|
|
#Param bitmap Bitmap containing pixels, dimensions, and format ##
|
|
#Param lattice division of bitmap into fixed and variable rectangles ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
|
|
#Example
|
|
#Height 128
|
|
#Description
|
|
The two leftmost bitmap draws has four corners and sides to the left and right of center.
|
|
The leftmost bitmap draw scales the width of corners proportionately to fit.
|
|
The third and fourth draw corners are not scaled; the sides are scaled to
|
|
fill the remaining space; the center is transparent.
|
|
The rightmost bitmap draw has four corners scaled vertically to fit, and uses sides above
|
|
and below center to fill the remaining space.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkIRect center = { 20, 10, 50, 40 };
|
|
SkBitmap bitmap;
|
|
bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
|
|
SkCanvas bitCanvas(bitmap);
|
|
SkPaint paint;
|
|
SkColor gray = 0xFF000000;
|
|
int left = 0;
|
|
for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
|
|
int top = 0;
|
|
for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
|
|
paint.setColor(gray);
|
|
bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
|
|
gray += 0x001f1f1f;
|
|
top = bottom;
|
|
}
|
|
left = right;
|
|
}
|
|
const int xDivs[] = { center.fLeft, center.fRight };
|
|
const int yDivs[] = { center.fTop, center.fBottom };
|
|
SkCanvas::Lattice::RectType fillTypes[3][3];
|
|
memset(fillTypes, 0, sizeof(fillTypes));
|
|
fillTypes[1][1] = SkCanvas::Lattice::kTransparent;
|
|
SkColor dummy[9]; // temporary pending bug fix
|
|
SkCanvas::Lattice lattice = { xDivs, yDivs, fillTypes[0], SK_ARRAY_COUNT(xDivs),
|
|
SK_ARRAY_COUNT(yDivs), nullptr, dummy };
|
|
for (auto dest: { 20, 30, 40, 60, 90 } ) {
|
|
canvas->drawBitmapLattice(bitmap, lattice, SkRect::MakeWH(dest, 110 - dest), nullptr);
|
|
canvas->translate(dest + 4, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawImageLattice drawBitmap drawBitmapNine Lattice
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawImageLattice(const SkImage* image, const Lattice& lattice, const SkRect& dst,
|
|
const SkPaint* paint = nullptr)
|
|
#In Draw_Image
|
|
#In Draw
|
|
#Line # draws proportionally stretched Image ##
|
|
|
|
Draws Image image stretched proportionally to fit into Rect dst.
|
|
|
|
Lattice lattice divides image into a rectangular grid.
|
|
Each intersection of an even-numbered row and column is fixed; like the corners
|
|
of drawBitmapNine, 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, Matrix, and optional Paint paint.
|
|
|
|
#paint_as_used_by_draw_lattice_or_draw_nine(image)#
|
|
|
|
If generated mask extends beyond bitmap bounds, replicate bitmap edge colors,
|
|
just as Shader made from SkShader::MakeBitmapShader with
|
|
SkShader::kClamp_TileMode set replicates the bitmap edge color when it samples
|
|
outside of its bounds.
|
|
|
|
#Param image Image containing pixels, dimensions, and format ##
|
|
#Param lattice division of bitmap into fixed and variable rectangles ##
|
|
#Param dst destination Rect of image to draw to ##
|
|
#Param paint Paint containing Blend_Mode, Color_Filter, Image_Filter,
|
|
and so on; or nullptr
|
|
##
|
|
|
|
#Example
|
|
#Height 128
|
|
#Description
|
|
The leftmost image is smaller than center; only corners are drawn, all scaled to fit.
|
|
The second image equals the size of center; only corners are drawn without scaling.
|
|
The remaining images are larger than center. All corners draw without scaling. The sides
|
|
are scaled if needed to take up the remaining space; the center is transparent.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkIRect center = { 20, 10, 50, 40 };
|
|
SkBitmap bitmap;
|
|
bitmap.allocPixels(SkImageInfo::MakeN32Premul(60, 60));
|
|
SkCanvas bitCanvas(bitmap);
|
|
SkPaint paint;
|
|
SkColor gray = 0xFF000000;
|
|
int left = 0;
|
|
for (auto right: { center.fLeft, center.fRight, bitmap.width() } ) {
|
|
int top = 0;
|
|
for (auto bottom: { center.fTop, center.fBottom, bitmap.height() } ) {
|
|
paint.setColor(gray);
|
|
bitCanvas.drawIRect(SkIRect::MakeLTRB(left, top, right, bottom), paint);
|
|
gray += 0x001f1f1f;
|
|
top = bottom;
|
|
}
|
|
left = right;
|
|
}
|
|
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
|
|
SkImage* imagePtr = image.get();
|
|
for (auto dest: { 20, 30, 40, 60, 90 } ) {
|
|
canvas->drawImageNine(imagePtr, center, SkRect::MakeWH(dest, dest), nullptr);
|
|
canvas->translate(dest + 4, 0);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawBitmapLattice drawImage drawImageNine Lattice
|
|
|
|
##
|
|
|
|
#Subtopic Lattice ##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Enum QuadAAFlags
|
|
#Line # don't use this ##
|
|
#Code
|
|
#Populate
|
|
##
|
|
|
|
#Private
|
|
##
|
|
|
|
#Const kLeft_QuadAAFlag 1
|
|
#Line # antialias the left edge ##
|
|
##
|
|
|
|
#Const kTop_QuadAAFlag 2
|
|
#Line # antialias the top edge ##
|
|
##
|
|
|
|
#Const kRight_QuadAAFlag 4
|
|
#Line # antialias the right edge ##
|
|
##
|
|
|
|
#Const kBottom_QuadAAFlag 8
|
|
#Line # antialias the bottom edge ##
|
|
##
|
|
|
|
#Const kNone_QuadAAFlags 0
|
|
#Line # antialias none of the edges ##
|
|
##
|
|
|
|
#Const kAll_QuadAAFlags 15
|
|
#Line # antialias all of the edges ##
|
|
##
|
|
|
|
#NoExample
|
|
##
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Struct ImageSetEntry
|
|
#Line # don't use this ##
|
|
#Private
|
|
##
|
|
|
|
#Member SkImage* fImage
|
|
#Line # image to draw ##
|
|
##
|
|
|
|
#Member SkRect fSrcRect
|
|
#Line # image src rectangle ##
|
|
##
|
|
|
|
#Member SkRect fDstRect
|
|
#Line # local space rectangle ##
|
|
##
|
|
|
|
#Member unsigned fAAFlags
|
|
#Line # antialiasing flags ##
|
|
##
|
|
|
|
#NoExample
|
|
##
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void experimental_DrawImageSetV0(const ImageSetEntry imageSet[], int cnt, float alpha,
|
|
SkFilterQuality quality, SkBlendMode mode);
|
|
#Private
|
|
##
|
|
#In Draw_Image
|
|
#In Draw
|
|
#Line # draws a set a of images (don't call this) ##
|
|
|
|
Draws a set of images. Do not use this method.
|
|
|
|
#Param imageSet images ##
|
|
#Param cnt number of images ##
|
|
#Param alpha alpha ##
|
|
#Param quality filter quality ##
|
|
#Param mode blend mode ##
|
|
|
|
#NoExample
|
|
##
|
|
|
|
##
|
|
|
|
#Subtopic Draw_Image ##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
#Subtopic Draw_Text
|
|
#Line # draws text into Canvas ##
|
|
##
|
|
|
|
#Method void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
|
|
const SkPaint& paint)
|
|
#In Draw_Text
|
|
#In Draw
|
|
#Line # draws text at (x, y), using font advance ##
|
|
|
|
Draws text, with origin at (x, y), using Clip, Matrix, and Paint paint.
|
|
|
|
text meaning depends on Paint_Text_Encoding; by default, text is encoded as
|
|
UTF-8.
|
|
|
|
x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default
|
|
text draws left to right, positioning the first glyph left side bearing at x
|
|
and its baseline at y. Text size is affected by Matrix and Paint_Text_Size.
|
|
|
|
All elements of paint: Path_Effect, Mask_Filter, Shader,
|
|
Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
|
|
filled 12 point black Glyphs.
|
|
|
|
#Param text character code points or Glyphs drawn ##
|
|
#Param byteLength byte length of text array ##
|
|
#Param x start of text on x-axis ##
|
|
#Param y start of text on y-axis ##
|
|
#Param paint text size, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
#Height 200
|
|
#Description
|
|
The same text is drawn varying Paint_Text_Size and varying
|
|
Matrix.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
float textSizes[] = { 12, 18, 24, 36 };
|
|
for (auto size: textSizes ) {
|
|
paint.setTextSize(size);
|
|
canvas->drawText("Aa", 2, 10, 20, paint);
|
|
canvas->translate(0, size * 2);
|
|
}
|
|
paint.reset();
|
|
paint.setAntiAlias(true);
|
|
float yPos = 20;
|
|
for (auto size: textSizes ) {
|
|
float scale = size / 12.f;
|
|
canvas->resetMatrix();
|
|
canvas->translate(100, 0);
|
|
canvas->scale(scale, scale);
|
|
canvas->drawText("Aa", 2, 10 / scale, yPos / scale, paint);
|
|
yPos += size * 2;
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawString drawPosText drawPosTextH drawTextBlob drawTextRSXform
|
|
|
|
##
|
|
|
|
#Method void drawString(const char* string, SkScalar x, SkScalar y, const SkPaint& paint)
|
|
#In Draw_Text
|
|
#In Draw
|
|
#Line # draws null terminated string at (x, y) using font advance ##
|
|
Draws null terminated string, with origin at (x, y), using Clip, Matrix, and
|
|
Paint paint.
|
|
|
|
string meaning depends on Paint_Text_Encoding; by default, strings are encoded
|
|
as UTF-8. Other values of Paint_Text_Encoding are unlikely to produce the desired
|
|
results, since zero bytes may be embedded in the string.
|
|
|
|
x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default
|
|
string draws left to right, positioning the first glyph left side bearing at x
|
|
and its baseline at y. Text size is affected by Matrix and Paint_Text_Size.
|
|
|
|
All elements of paint: Path_Effect, Mask_Filter, Shader,
|
|
Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
|
|
filled 12 point black Glyphs.
|
|
|
|
#Param string character code points or Glyphs 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 paint text size, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
#Height 48
|
|
SkPaint paint;
|
|
canvas->drawString("a small hello", 20, 20, paint);
|
|
##
|
|
|
|
#SeeAlso drawText drawPosText drawPosTextH drawTextBlob drawTextRSXform
|
|
|
|
##
|
|
|
|
#Method void drawString(const SkString& string, SkScalar x, SkScalar y, const SkPaint& paint)
|
|
|
|
Draws null terminated string, with origin at (x, y), using Clip, Matrix, and
|
|
Paint paint.
|
|
|
|
string meaning depends on Paint_Text_Encoding; by default, strings are encoded
|
|
as UTF-8. Other values of Paint_Text_Encoding are unlikely to produce the desired
|
|
results, since zero bytes may be embedded in the string.
|
|
|
|
x and y meaning depends on Paint_Text_Align and Paint_Vertical_Text; by default
|
|
string draws left to right, positioning the first glyph left side bearing at x
|
|
and its baseline at y. Text size is affected by Matrix and Paint_Text_Size.
|
|
|
|
All elements of paint: Path_Effect, Mask_Filter, Shader,
|
|
Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
|
|
filled 12 point black Glyphs.
|
|
|
|
#Param string character code points or Glyphs 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 paint text size, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
SkPaint paint;
|
|
SkString string("a small hello");
|
|
canvas->drawString(string, 20, 20, paint);
|
|
##
|
|
|
|
#SeeAlso drawText drawPosText drawPosTextH drawTextBlob drawTextRSXform
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawPosText(const void* text, size_t byteLength, const SkPoint pos[],
|
|
const SkPaint& paint)
|
|
#In Draw_Text
|
|
#In Draw
|
|
#Line # draws text at array of (x, y) positions ##
|
|
|
|
Draws each glyph in text with the origin in pos array, using Clip, Matrix, and
|
|
Paint paint. The number of entries in pos array must match the number of Glyphs
|
|
described by byteLength of text.
|
|
|
|
text meaning depends on Paint_Text_Encoding; by default, text is encoded as
|
|
UTF-8. pos elements meaning depends on Paint_Vertical_Text; by default
|
|
glyph left side bearing and baseline are relative to Point in pos array.
|
|
Text size is affected by Matrix and Paint_Text_Size.
|
|
|
|
All elements of paint: Path_Effect, Mask_Filter, Shader,
|
|
Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
|
|
filled 12 point black Glyphs.
|
|
|
|
Layout engines such as Harfbuzz typically position each glyph
|
|
rather than using the font advance widths.
|
|
|
|
#Param text character code points or Glyphs drawn ##
|
|
#Param byteLength byte length of text array ##
|
|
#Param pos array of glyph origins ##
|
|
#Param paint text size, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
#Height 120
|
|
void draw(SkCanvas* canvas) {
|
|
const char hello[] = "HeLLo!";
|
|
const SkPoint pos[] = { {40, 100}, {82, 95}, {115, 110}, {130, 95}, {145, 85},
|
|
{172, 100} };
|
|
SkPaint paint;
|
|
paint.setTextSize(60);
|
|
canvas->drawPosText(hello, strlen(hello), pos, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawText drawPosTextH drawTextBlob drawTextRSXform
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
|
|
const SkPaint& paint)
|
|
#In Draw_Text
|
|
#In Draw
|
|
#Line # draws text at x positions with common baseline ##
|
|
|
|
Draws each glyph in text with its (x, y) origin composed from xpos array and
|
|
constY, using Clip, Matrix, and Paint paint. The number of entries in xpos array
|
|
must match the number of Glyphs described by byteLength of text.
|
|
|
|
text meaning depends on Paint_Text_Encoding; by default, text is encoded as
|
|
UTF-8. xpos elements meaning depends on Paint_Vertical_Text;
|
|
by default each glyph left side bearing is positioned at an xpos element and
|
|
its baseline is positioned at constY. Text size is affected by Matrix and
|
|
Paint_Text_Size.
|
|
|
|
All elements of paint: Path_Effect, Mask_Filter, Shader,
|
|
Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
|
|
filled 12 point black Glyphs.
|
|
|
|
Layout engines such as Harfbuzz typically position each glyph
|
|
rather than using the font advance widths if all Glyphs share the same
|
|
baseline.
|
|
|
|
#Param text character code points or Glyphs drawn ##
|
|
#Param byteLength byte length of text array ##
|
|
#Param xpos array of x-axis positions, used to position each glyph ##
|
|
#Param constY shared y-axis value for all of x-axis positions ##
|
|
#Param paint text size, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
#Height 40
|
|
void draw(SkCanvas* canvas) {
|
|
SkScalar xpos[] = { 20, 40, 80, 160 };
|
|
SkPaint paint;
|
|
canvas->drawPosTextH("XXXX", 4, xpos, 20, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawText drawPosText drawTextBlob drawTextRSXform
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
|
|
const SkRect* cullRect, const SkPaint& paint)
|
|
#In Draw_Text
|
|
#In Draw
|
|
#Line # draws text with array of RSXform ##
|
|
|
|
Draws text, transforming each glyph by the corresponding SkRSXform,
|
|
using Clip, Matrix, and Paint paint.
|
|
|
|
RSXform xform array specifies a separate square scale, rotation, and translation
|
|
for each glyph. xform does not affect paint Shader.
|
|
|
|
Optional Rect cullRect is a conservative bounds of text, taking into account
|
|
RSXform and paint. If cullRect is outside of Clip, canvas can skip drawing.
|
|
|
|
All elements of paint: Path_Effect, Mask_Filter, Shader,
|
|
Color_Filter, Image_Filter, and Draw_Looper; apply to text. By default, draws
|
|
filled 12 point black Glyphs.
|
|
|
|
#Param text character code points or Glyphs drawn ##
|
|
#Param byteLength byte length of text array ##
|
|
#Param xform RSXform rotates, scales, and translates each glyph individually ##
|
|
#Param cullRect Rect bounds of text for efficient clipping; or nullptr ##
|
|
#Param paint text size, blend, color, and so on, used to draw ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
const int iterations = 26;
|
|
SkRSXform transforms[iterations];
|
|
char alphabet[iterations];
|
|
SkScalar angle = 0;
|
|
SkScalar scale = 1;
|
|
for (size_t i = 0; i < SK_ARRAY_COUNT(transforms); ++i) {
|
|
const SkScalar s = SkScalarSin(angle) * scale;
|
|
const SkScalar c = SkScalarCos(angle) * scale;
|
|
transforms[i] = SkRSXform::Make(-c, -s, -s * 16, c * 16);
|
|
angle += .45;
|
|
scale += .2;
|
|
alphabet[i] = 'A' + i;
|
|
}
|
|
SkPaint paint;
|
|
paint.setTextAlign(SkPaint::kCenter_Align);
|
|
canvas->translate(110, 138);
|
|
canvas->drawTextRSXform(alphabet, sizeof(alphabet), transforms, nullptr, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawText drawPosText drawTextBlob
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
|
|
#In Draw_Text
|
|
#In Draw
|
|
#Line # draws text with arrays of positions and Paint ##
|
|
Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
|
|
|
|
blob contains Glyphs, their positions, and paint attributes specific to text:
|
|
#paint_font_metrics#.
|
|
|
|
Paint_Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding.
|
|
|
|
Elements of paint: Anti_Alias, Blend_Mode, Color including Color_Alpha,
|
|
Color_Filter, Paint_Dither, Draw_Looper, Mask_Filter, Path_Effect, Shader, and
|
|
Paint_Style; apply to blob. If Paint contains SkPaint::kStroke_Style:
|
|
Paint_Miter_Limit, Paint_Stroke_Cap, Paint_Stroke_Join, and Paint_Stroke_Width;
|
|
apply to Path 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
|
|
#Height 120
|
|
void draw(SkCanvas* canvas) {
|
|
SkTextBlobBuilder textBlobBuilder;
|
|
const char bunny[] = "/(^x^)\\";
|
|
const int len = sizeof(bunny) - 1;
|
|
uint16_t glyphs[len];
|
|
SkPaint paint;
|
|
paint.textToGlyphs(bunny, len, glyphs);
|
|
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
|
int runs[] = { 3, 1, 3 };
|
|
SkPoint textPos = { 20, 100 };
|
|
int glyphIndex = 0;
|
|
for (auto runLen : runs) {
|
|
paint.setTextSize(1 == runLen ? 20 : 50);
|
|
const SkTextBlobBuilder::RunBuffer& run =
|
|
textBlobBuilder.allocRun(paint, runLen, textPos.fX, textPos.fY);
|
|
memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
|
|
textPos.fX += paint.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen, nullptr);
|
|
glyphIndex += runLen;
|
|
}
|
|
sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
|
|
paint.reset();
|
|
canvas->drawTextBlob(blob.get(), 0, 0, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawText drawPosText drawPosTextH
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawTextBlob(const sk_sp<SkTextBlob>& blob, SkScalar x, SkScalar y, const SkPaint& paint)
|
|
|
|
Draws Text_Blob blob at (x, y), using Clip, Matrix, and Paint paint.
|
|
|
|
blob contains Glyphs, their positions, and paint attributes specific to text:
|
|
#paint_font_metrics#.
|
|
|
|
Paint_Text_Encoding must be set to SkPaint::kGlyphID_TextEncoding.
|
|
|
|
Elements of paint: Path_Effect, Mask_Filter, Shader, Color_Filter,
|
|
Image_Filter, and Draw_Looper; 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 ##
|
|
|
|
#Example
|
|
#Height 120
|
|
#Description
|
|
Paint attributes unrelated to text, like color, have no effect on paint in allocated Text_Blob.
|
|
Paint attributes related to text, like text size, have no effect on paint passed to drawTextBlob.
|
|
##
|
|
void draw(SkCanvas* canvas) {
|
|
SkTextBlobBuilder textBlobBuilder;
|
|
SkPaint paint;
|
|
paint.setTextSize(50);
|
|
paint.setColor(SK_ColorRED);
|
|
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
|
const SkTextBlobBuilder::RunBuffer& run =
|
|
textBlobBuilder.allocRun(paint, 1, 20, 100);
|
|
run.glyphs[0] = 20;
|
|
sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
|
|
paint.setTextSize(10);
|
|
paint.setColor(SK_ColorBLUE);
|
|
canvas->drawTextBlob(blob.get(), 0, 0, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawText drawPosText drawPosTextH
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawPicture(const SkPicture* picture)
|
|
#In Draw
|
|
#Line # draws Picture using Clip and Matrix ##
|
|
Draws Picture picture, using Clip and Matrix.
|
|
Clip and Matrix are unchanged by picture contents, as if
|
|
save() was called before and restore() was called after drawPicture.
|
|
|
|
Picture records a series of draw commands for later playback.
|
|
|
|
#Param picture recorded drawing commands to play ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPictureRecorder recorder;
|
|
SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
|
|
for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
|
|
SkPaint paint;
|
|
paint.setColor(color);
|
|
recordingCanvas->drawRect({10, 10, 30, 40}, paint);
|
|
recordingCanvas->translate(10, 10);
|
|
recordingCanvas->scale(1.2f, 1.4f);
|
|
}
|
|
sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
|
|
canvas->drawPicture(playback);
|
|
canvas->scale(2, 2);
|
|
canvas->translate(50, 0);
|
|
canvas->drawPicture(playback);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawDrawable SkPicture SkPicture::playback
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawPicture(const sk_sp<SkPicture>& picture)
|
|
|
|
Draws Picture picture, using Clip and Matrix.
|
|
Clip and Matrix are unchanged by picture contents, as if
|
|
save() was called before and restore() was called after drawPicture.
|
|
|
|
Picture records a series of draw commands for later playback.
|
|
|
|
#Param picture recorded drawing commands to play ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPictureRecorder recorder;
|
|
SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
|
|
for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
|
|
SkPaint paint;
|
|
paint.setColor(color);
|
|
recordingCanvas->drawRect({10, 10, 30, 40}, paint);
|
|
recordingCanvas->translate(10, 10);
|
|
recordingCanvas->scale(1.2f, 1.4f);
|
|
}
|
|
sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
|
|
canvas->drawPicture(playback);
|
|
canvas->scale(2, 2);
|
|
canvas->translate(50, 0);
|
|
canvas->drawPicture(playback);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawDrawable SkPicture SkPicture::playback
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint)
|
|
|
|
Draws Picture picture, using Clip and Matrix; transforming picture with
|
|
Matrix matrix, if provided; and use Paint paint Color_Alpha, Color_Filter,
|
|
Image_Filter, and Blend_Mode, if provided.
|
|
|
|
matrix transformation is equivalent to: save(), concat(), drawPicture, restore().
|
|
paint use is equivalent to: saveLayer, drawPicture, restore().
|
|
|
|
#Param picture recorded drawing commands to play ##
|
|
#Param matrix Matrix to rotate, scale, translate, and so on; may be nullptr ##
|
|
#Param paint Paint to apply transparency, filtering, and so on; may be nullptr ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
SkPictureRecorder recorder;
|
|
SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
|
|
for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
|
|
paint.setColor(color);
|
|
recordingCanvas->drawRect({10, 10, 30, 40}, paint);
|
|
recordingCanvas->translate(10, 10);
|
|
recordingCanvas->scale(1.2f, 1.4f);
|
|
}
|
|
sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
|
|
const SkPicture* playbackPtr = playback.get();
|
|
SkMatrix matrix;
|
|
matrix.reset();
|
|
for (auto alpha : { 70, 140, 210 } ) {
|
|
paint.setAlpha(alpha);
|
|
canvas->drawPicture(playbackPtr, &matrix, &paint);
|
|
matrix.preTranslate(70, 70);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawDrawable SkPicture SkPicture::playback
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawPicture(const sk_sp<SkPicture>& picture, const SkMatrix* matrix, const SkPaint* paint)
|
|
|
|
Draws Picture picture, using Clip and Matrix; transforming picture with
|
|
Matrix matrix, if provided; and use Paint paint Color_Alpha, Color_Filter,
|
|
Image_Filter, and Blend_Mode, if provided.
|
|
|
|
matrix transformation is equivalent to: save(), concat(), drawPicture, restore().
|
|
paint use is equivalent to: saveLayer, drawPicture, restore().
|
|
|
|
#Param picture recorded drawing commands to play ##
|
|
#Param matrix Matrix to rotate, scale, translate, and so on; may be nullptr ##
|
|
#Param paint Paint to apply transparency, filtering, and so on; may be nullptr ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
SkPictureRecorder recorder;
|
|
SkCanvas* recordingCanvas = recorder.beginRecording(50, 50);
|
|
for (auto color : { SK_ColorRED, SK_ColorBLUE, 0xff007f00 } ) {
|
|
paint.setColor(color);
|
|
recordingCanvas->drawRect({10, 10, 30, 40}, paint);
|
|
recordingCanvas->translate(10, 10);
|
|
recordingCanvas->scale(1.2f, 1.4f);
|
|
}
|
|
sk_sp<SkPicture> playback = recorder.finishRecordingAsPicture();
|
|
SkMatrix matrix;
|
|
matrix.reset();
|
|
for (auto alpha : { 70, 140, 210 } ) {
|
|
paint.setAlpha(alpha);
|
|
canvas->drawPicture(playback, &matrix, &paint);
|
|
matrix.preTranslate(70, 70);
|
|
}
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawDrawable SkPicture SkPicture::playback
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws Vertices, a triangle mesh ##
|
|
Draws Vertices vertices, a triangle mesh, using Clip and Matrix.
|
|
If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint
|
|
contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
|
|
|
|
#Param vertices triangle mesh to draw ##
|
|
#Param mode combines Vertices_Colors with Shader, if both are present ##
|
|
#Param paint specifies the Shader, used as Vertices texture; may be nullptr ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
|
|
SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
|
|
auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
|
|
SK_ARRAY_COUNT(points), points, nullptr, colors);
|
|
canvas->drawVertices(vertices.get(), SkBlendMode::kSrc, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawPatch drawPicture
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawVertices(const sk_sp<SkVertices>& vertices, SkBlendMode mode, const SkPaint& paint)
|
|
|
|
Draws Vertices vertices, a triangle mesh, using Clip and Matrix.
|
|
If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint
|
|
contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
|
|
|
|
#Param vertices triangle mesh to draw ##
|
|
#Param mode combines Vertices_Colors with Shader, if both are present ##
|
|
#Param paint specifies the Shader, used as Vertices texture, may be nullptr ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
|
|
SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
|
|
SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
|
|
paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
|
|
SkShader::kClamp_TileMode));
|
|
auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
|
|
SK_ARRAY_COUNT(points), points, texs, colors);
|
|
canvas->drawVertices(vertices, SkBlendMode::kDarken, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawPatch drawPicture
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawVertices(const SkVertices* vertices, const SkVertices::Bone bones[],
|
|
int boneCount, SkBlendMode mode, const SkPaint& paint)
|
|
|
|
Draws Vertices vertices, a triangle mesh, using Clip and Matrix. Bone data is used to
|
|
deform vertices with bone weights.
|
|
If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint
|
|
contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
|
|
The first element of bones should be an object to world space transformation matrix that
|
|
will be applied before performing mesh deformations. If no such transformation is needed,
|
|
it should be the identity matrix.
|
|
boneCount must be at most 80, and thus the size of bones should be at most 80.
|
|
|
|
#Param vertices triangle mesh to draw ##
|
|
#Param bones bone matrix data ##
|
|
#Param boneCount number of bone matrices ##
|
|
#Param mode combines Vertices_Colors with Shader, if both are present ##
|
|
#Param paint specifies the Shader, used as Vertices texture, may be nullptr ##
|
|
|
|
#NoExample
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
|
|
SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
|
|
SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
|
|
SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 },
|
|
{ 1, 0, 0, 0 },
|
|
{ 2, 0, 0, 0 },
|
|
{ 3, 0, 0, 0 } };
|
|
SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f },
|
|
{ 1.0f, 0.0f, 0.0f, 0.0f },
|
|
{ 1.0f, 0.0f, 0.0f, 0.0f },
|
|
{ 1.0f, 0.0f, 0.0f, 0.0f } };
|
|
SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},
|
|
{{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }},
|
|
{{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }},
|
|
{{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} };
|
|
paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
|
|
SkShader::kClamp_TileMode));
|
|
auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
|
|
SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights);
|
|
canvas->drawVertices(vertices.get(), bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawPatch drawPicture
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawVertices(const sk_sp<SkVertices>& vertices, const SkVertices::Bone bones[],
|
|
int boneCount, SkBlendMode mode, const SkPaint& paint)
|
|
|
|
Draws Vertices vertices, a triangle mesh, using Clip and Matrix. Bone data is used to
|
|
deform vertices with bone weights.
|
|
If Vertices_Texs and Vertices_Colors are defined in vertices, and Paint paint
|
|
contains Shader, Blend_Mode mode combines Vertices_Colors with Shader.
|
|
The first element of bones should be an object to world space transformation matrix that
|
|
will be applied before performing mesh deformations. If no such transformation is needed,
|
|
it should be the identity matrix.
|
|
boneCount must be at most 80, and thus the size of bones should be at most 80.
|
|
|
|
#Param vertices triangle mesh to draw ##
|
|
#Param bones bone matrix data ##
|
|
#Param boneCount number of bone matrices ##
|
|
#Param mode combines Vertices_Colors with Shader, if both are present ##
|
|
#Param paint specifies the Shader, used as Vertices texture, may be nullptr ##
|
|
|
|
#NoExample
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
SkPoint points[] = { { 0, 0 }, { 250, 0 }, { 100, 100 }, { 0, 250 } };
|
|
SkPoint texs[] = { { 0, 0 }, { 0, 250 }, { 250, 250 }, { 250, 0 } };
|
|
SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
|
|
SkVertices::BoneIndices boneIndices[] = { { 0, 0, 0, 0 },
|
|
{ 1, 0, 0, 0 },
|
|
{ 2, 0, 0, 0 },
|
|
{ 3, 0, 0, 0 } };
|
|
SkVertices::BoneWeights boneWeights[] = { { 0.0f, 0.0f, 0.0f, 0.0f },
|
|
{ 1.0f, 0.0f, 0.0f, 0.0f },
|
|
{ 1.0f, 0.0f, 0.0f, 0.0f },
|
|
{ 1.0f, 0.0f, 0.0f, 0.0f } };
|
|
SkVertices::Bone bones[] = { {{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }},
|
|
{{ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 20.0f }},
|
|
{{ 1.0f, 0.0f, 0.0f, 1.0f, 50.0f, 50.0f }},
|
|
{{ 1.0f, 0.0f, 0.0f, 1.0f, 20.0f, 0.0f }} };
|
|
paint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, 4,
|
|
SkShader::kClamp_TileMode));
|
|
auto vertices = SkVertices::MakeCopy(SkVertices::kTriangleFan_VertexMode,
|
|
SK_ARRAY_COUNT(points), points, texs, colors, boneIndices, boneWeights);
|
|
canvas->drawVertices(vertices, bones, SK_ARRAY_COUNT(bones), SkBlendMode::kDarken, paint);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawPatch drawPicture
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
|
|
const SkPoint texCoords[4], SkBlendMode mode, const SkPaint& paint)
|
|
#In Draw
|
|
#Line # draws Coons_Patch ##
|
|
|
|
Draws a Coons_Patch: the interpolation of four cubics with shared corners,
|
|
associating a color, and optionally a texture Point, with each corner.
|
|
|
|
Coons_Patch uses Clip and Matrix, paint Shader, Color_Filter,
|
|
Color_Alpha, Image_Filter, and Blend_Mode. If Shader is provided it is treated
|
|
as Coons_Patch texture; Blend_Mode mode combines Color colors and Shader if
|
|
both are provided.
|
|
|
|
Point array cubics specifies four Cubics starting at the top-left corner,
|
|
in clockwise order, sharing every fourth point. The last 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 Shader, Point array texCoords maps Shader as texture to
|
|
corners in top-left, top-right, bottom-right, bottom-left order.
|
|
|
|
#Param cubics Path_Cubic array, sharing common points ##
|
|
#Param colors Color array, one for each corner ##
|
|
#Param texCoords Point array of texture coordinates, mapping Shader to corners;
|
|
may be nullptr
|
|
#Param ##
|
|
#Param mode Blend_Mode for colors, and for Shader if paint has one ##
|
|
#Param paint Shader, Color_Filter, Blend_Mode, used to draw ##
|
|
|
|
#Example
|
|
#Image 5
|
|
void draw(SkCanvas* canvas) {
|
|
// SkBitmap source = cmbkygk;
|
|
SkPaint paint;
|
|
paint.setFilterQuality(kLow_SkFilterQuality);
|
|
paint.setAntiAlias(true);
|
|
SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
|
|
/* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
|
|
/* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
|
|
/* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
|
|
SkColor colors[] = { 0xbfff0000, 0xbf0000ff, 0xbfff00ff, 0xbf00ffff };
|
|
SkPoint texCoords[] = { { -30, -30 }, { 162, -30}, { 162, 162}, { -30, 162} };
|
|
paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
|
|
SkShader::kClamp_TileMode, nullptr));
|
|
canvas->scale(15, 15);
|
|
for (auto blend : { SkBlendMode::kSrcOver, SkBlendMode::kModulate, SkBlendMode::kXor } ) {
|
|
canvas->drawPatch(cubics, colors, texCoords, blend, paint);
|
|
canvas->translate(4, 4);
|
|
}
|
|
}
|
|
##
|
|
|
|
#ToDo can patch use image filter? ##
|
|
#SeeAlso SeeAlso drawVertices drawPicture
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawPatch(const SkPoint cubics[12], const SkColor colors[4],
|
|
const SkPoint texCoords[4], const SkPaint& paint)
|
|
|
|
Draws Cubic Coons_Patch: the interpolation of four cubics with shared corners,
|
|
associating a color, and optionally a texture Point, with each corner.
|
|
|
|
Coons_Patch uses Clip and Matrix, paint Shader, Color_Filter,
|
|
Color_Alpha, Image_Filter, and Blend_Mode. If Shader is provided it is treated
|
|
as Coons_Patch texture; Blend_Mode mode combines Color colors and Shader if
|
|
both are provided.
|
|
|
|
Point array cubics specifies four Cubics starting at the top-left corner,
|
|
in clockwise order, sharing every fourth point. The last 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 Shader, Point array texCoords maps Shader as texture to
|
|
corners in top-left, top-right, bottom-right, bottom-left order.
|
|
|
|
#Param cubics Path_Cubic array, sharing common points ##
|
|
#Param colors Color array, one for each corner ##
|
|
#Param texCoords Point array of texture coordinates, mapping Shader to corners;
|
|
may be nullptr
|
|
#Param ##
|
|
#Param paint Shader, Color_Filter, Blend_Mode, used to draw ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkPaint paint;
|
|
paint.setAntiAlias(true);
|
|
SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
|
|
/* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
|
|
/* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
|
|
/* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
|
|
SkColor colors[] = { SK_ColorRED, SK_ColorBLUE, SK_ColorYELLOW, SK_ColorCYAN };
|
|
canvas->scale(30, 30);
|
|
canvas->drawPatch(cubics, colors, nullptr, paint);
|
|
SkPoint text[] = { {3,0.9f}, {4,2.5f}, {5,0.9f}, {7.5f,3.2f}, {5.5f,4.2f},
|
|
{7.5f,5.2f}, {5,7.5f}, {4,5.9f}, {3,7.5f}, {0.5f,5.2f}, {2.5f,4.2f},
|
|
{0.5f,3.2f} };
|
|
paint.setTextSize(18.f / 30);
|
|
paint.setTextAlign(SkPaint::kCenter_Align);
|
|
for (int i = 0; i< 10; ++i) {
|
|
char digit = '0' + i;
|
|
canvas->drawText(&digit, 1, text[i].fX, text[i].fY, paint);
|
|
}
|
|
canvas->drawString("10", text[10].fX, text[10].fY, paint);
|
|
canvas->drawString("11", text[11].fX, text[11].fY, paint);
|
|
paint.setStyle(SkPaint::kStroke_Style);
|
|
canvas->drawPoints(SkCanvas::kPolygon_PointMode, 12, cubics, paint);
|
|
canvas->drawLine(cubics[11].fX, cubics[11].fY, cubics[0].fX, cubics[0].fY, paint);
|
|
}
|
|
##
|
|
|
|
#Example
|
|
#Image 6
|
|
void draw(SkCanvas* canvas) {
|
|
// SkBitmap source = checkerboard;
|
|
SkPaint paint;
|
|
paint.setFilterQuality(kLow_SkFilterQuality);
|
|
paint.setAntiAlias(true);
|
|
SkPoint cubics[] = { { 3, 1 }, { 4, 2 }, { 5, 1 }, { 7, 3 },
|
|
/* { 7, 3 }, */ { 6, 4 }, { 7, 5 }, { 5, 7 },
|
|
/* { 5, 7 }, */ { 4, 6 }, { 3, 7 }, { 1, 5 },
|
|
/* { 1, 5 }, */ { 2, 4 }, { 1, 3 }, /* { 3, 1 } */ };
|
|
SkPoint texCoords[] = { { 0, 0 }, { 0, 62}, { 62, 62}, { 62, 0 } };
|
|
paint.setShader(SkShader::MakeBitmapShader(source, SkShader::kClamp_TileMode,
|
|
SkShader::kClamp_TileMode, nullptr));
|
|
canvas->scale(30, 30);
|
|
canvas->drawPatch(cubics, nullptr, texCoords, paint);
|
|
}
|
|
##
|
|
|
|
#ToDo can patch use image filter? ##
|
|
#SeeAlso SeeAlso drawVertices drawPicture
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[],
|
|
const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
|
|
const SkPaint* paint)
|
|
#In Draw
|
|
#Line # draws sprites using Clip, Matrix, and Paint ##
|
|
|
|
Draws a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
|
|
paint uses Anti_Alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
|
|
to draw, if present. For each entry in the array, Rect tex locates sprite in
|
|
atlas, and RSXform xform transforms it into destination space.
|
|
|
|
xform, text, and colors if present, must contain count entries.
|
|
Optional colors are applied for each sprite using Blend_Mode 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.
|
|
|
|
|
|
|
|
#Param atlas Image containing sprites ##
|
|
#Param xform RSXform mappings for sprites in atlas ##
|
|
#Param tex Rect locations of sprites in atlas ##
|
|
#Param colors one per sprite, blended with sprite using Blend_Mode; may be nullptr ##
|
|
#Param count number of sprites to draw ##
|
|
#Param mode Blend_Mode combining colors and sprites ##
|
|
#Param cullRect bounds of transformed sprites for efficient clipping; may be nullptr ##
|
|
#Param paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
|
|
|
|
#Example
|
|
#Image 3
|
|
void draw(SkCanvas* canvas) {
|
|
// SkBitmap source = mandrill;
|
|
SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
|
|
SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
|
|
SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
|
|
const SkImage* imagePtr = image.get();
|
|
canvas->drawAtlas(imagePtr, xforms, tex, colors, 2, SkBlendMode::kSrcOver, nullptr, nullptr);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawBitmap drawImage
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
|
|
const SkColor colors[], int count, SkBlendMode mode, const SkRect* cullRect,
|
|
const SkPaint* paint)
|
|
|
|
Draws a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
|
|
paint uses Anti_Alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
|
|
to draw, if present. For each entry in the array, Rect tex locates sprite in
|
|
atlas, and RSXform xform transforms it into destination space.
|
|
|
|
xform, text, and colors if present, must contain count entries.
|
|
Optional colors is applied for each sprite using Blend_Mode.
|
|
Optional cullRect is a conservative bounds of all transformed sprites.
|
|
If cullRect is outside of Clip, canvas can skip drawing.
|
|
|
|
#Param atlas Image containing sprites ##
|
|
#Param xform RSXform mappings for sprites in atlas ##
|
|
#Param tex Rect locations of sprites in atlas ##
|
|
#Param colors one per sprite, blended with sprite using Blend_Mode; may be nullptr ##
|
|
#Param count number of sprites to draw ##
|
|
#Param mode Blend_Mode combining colors and sprites ##
|
|
#Param cullRect bounds of transformed sprites for efficient clipping; may be nullptr ##
|
|
#Param paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
|
|
|
|
#Example
|
|
#Image 3
|
|
void draw(SkCanvas* canvas) {
|
|
// SkBitmap source = mandrill;
|
|
SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
|
|
SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
|
|
SkColor colors[] = { 0x7f55aa00, 0x7f3333bf };
|
|
SkPaint paint;
|
|
paint.setAlpha(127);
|
|
canvas->drawAtlas(image, xforms, tex, colors, 2, SkBlendMode::kPlus, nullptr, &paint);
|
|
}
|
|
##
|
|
|
|
#ToDo bug in example on cpu side, gpu looks ok ##
|
|
|
|
#SeeAlso drawBitmap drawImage
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawAtlas(const SkImage* atlas, const SkRSXform xform[], const SkRect tex[], int count,
|
|
const SkRect* cullRect, const SkPaint* paint)
|
|
|
|
Draws a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
|
|
paint uses Anti_Alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
|
|
to draw, if present. For each entry in the array, Rect tex locates sprite in
|
|
atlas, and RSXform xform transforms it into destination space.
|
|
|
|
xform and text must contain count entries.
|
|
Optional cullRect is a conservative bounds of all transformed sprites.
|
|
If cullRect is outside of Clip, canvas can skip drawing.
|
|
|
|
#Param atlas Image containing sprites ##
|
|
#Param xform RSXform mappings for sprites in atlas ##
|
|
#Param tex Rect locations of sprites in atlas ##
|
|
#Param count number of sprites to draw ##
|
|
#Param cullRect bounds of transformed sprites for efficient clipping; may be nullptr ##
|
|
#Param paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
|
|
|
|
#Example
|
|
#Image 3
|
|
void draw(SkCanvas* canvas) {
|
|
// sk_sp<SkImage> image = mandrill;
|
|
SkRSXform xforms[] = { { .5f, 0, 0, 0 }, {0, .5f, 200, 100 } };
|
|
SkRect tex[] = { { 0, 0, 250, 250 }, { 0, 0, 250, 250 } };
|
|
const SkImage* imagePtr = image.get();
|
|
canvas->drawAtlas(imagePtr, xforms, tex, 2, nullptr, nullptr);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawBitmap drawImage
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawAtlas(const sk_sp<SkImage>& atlas, const SkRSXform xform[], const SkRect tex[],
|
|
int count, const SkRect* cullRect, const SkPaint* paint)
|
|
|
|
Draws a set of sprites from atlas, using Clip, Matrix, and optional Paint paint.
|
|
paint uses Anti_Alias, Color_Alpha, Color_Filter, Image_Filter, and Blend_Mode
|
|
to draw, if present. For each entry in the array, Rect tex locates sprite in
|
|
atlas, and RSXform xform transforms it into destination space.
|
|
|
|
xform and text must contain count entries.
|
|
Optional cullRect is a conservative bounds of all transformed sprites.
|
|
If cullRect is outside of Clip, canvas can skip drawing.
|
|
|
|
#Param atlas Image containing sprites ##
|
|
#Param xform RSXform mappings for sprites in atlas ##
|
|
#Param tex Rect locations of sprites in atlas ##
|
|
#Param count number of sprites to draw ##
|
|
#Param cullRect bounds of transformed sprites for efficient clipping; may be nullptr ##
|
|
#Param paint Color_Filter, Image_Filter, Blend_Mode, and so on; may be nullptr ##
|
|
|
|
#Example
|
|
#Image 3
|
|
void draw(SkCanvas* canvas) {
|
|
// sk_sp<SkImage> image = mandrill;
|
|
SkRSXform xforms[] = { { 1, 0, 0, 0 }, {0, 1, 300, 100 } };
|
|
SkRect tex[] = { { 0, 0, 200, 200 }, { 200, 0, 400, 200 } };
|
|
canvas->drawAtlas(image, xforms, tex, 2, nullptr, nullptr);
|
|
}
|
|
##
|
|
|
|
#SeeAlso drawBitmap drawImage
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawDrawable(SkDrawable* drawable, const SkMatrix* matrix = nullptr)
|
|
#In Draw
|
|
#Line # draws Drawable, encapsulated drawing commands ##
|
|
Draws Drawable drawable using Clip and Matrix, concatenated with
|
|
optional matrix.
|
|
|
|
If Canvas has an asynchronous implementation, as is the case
|
|
when it is recording into Picture, 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
|
|
#Height 100
|
|
#Function
|
|
struct MyDrawable : public SkDrawable {
|
|
SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
SkPath path;
|
|
path.conicTo(10, 90, 50, 90, 0.9f);
|
|
SkPaint paint;
|
|
paint.setColor(SK_ColorBLUE);
|
|
canvas->drawRect(path.getBounds(), paint);
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(SK_ColorWHITE);
|
|
canvas->drawPath(path, paint);
|
|
}
|
|
};
|
|
|
|
#Function ##
|
|
void draw(SkCanvas* canvas) {
|
|
sk_sp<SkDrawable> drawable(new MyDrawable);
|
|
SkMatrix matrix;
|
|
matrix.setTranslate(10, 10);
|
|
canvas->drawDrawable(drawable.get(), &matrix);
|
|
}
|
|
##
|
|
|
|
#SeeAlso SkDrawable drawPicture
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawDrawable(SkDrawable* drawable, SkScalar x, SkScalar y)
|
|
|
|
Draws Drawable drawable using Clip and Matrix, offset by (x, y).
|
|
|
|
If Canvas has an asynchronous implementation, as is the case
|
|
when it is recording into Picture, 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 Canvas writable pixels on x-axis ##
|
|
#Param y offset into Canvas writable pixels on y-axis ##
|
|
|
|
#Example
|
|
#Height 100
|
|
#Function
|
|
struct MyDrawable : public SkDrawable {
|
|
SkRect onGetBounds() override { return SkRect::MakeWH(50, 100); }
|
|
|
|
void onDraw(SkCanvas* canvas) override {
|
|
SkPath path;
|
|
path.conicTo(10, 90, 50, 90, 0.9f);
|
|
SkPaint paint;
|
|
paint.setColor(SK_ColorBLUE);
|
|
canvas->drawRect(path.getBounds(), paint);
|
|
paint.setAntiAlias(true);
|
|
paint.setColor(SK_ColorWHITE);
|
|
canvas->drawPath(path, paint);
|
|
}
|
|
};
|
|
|
|
#Function ##
|
|
void draw(SkCanvas* canvas) {
|
|
sk_sp<SkDrawable> drawable(new MyDrawable);
|
|
canvas->drawDrawable(drawable.get(), 10, 10);
|
|
}
|
|
##
|
|
|
|
#SeeAlso SkDrawable drawPicture
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawAnnotation(const SkRect& rect, const char key[], SkData* value)
|
|
#In Draw
|
|
#In Utility
|
|
#Line # associates a Rect with a key-value pair ##
|
|
Associates Rect on Canvas with an annotation; a key-value pair, where the key is
|
|
a null-terminated utf8 string, and optional value is stored as Data.
|
|
|
|
Only some canvas implementations, such as recording to Picture, or drawing to
|
|
Document_PDF, use annotations.
|
|
|
|
#Param rect Rect extent of canvas to annotate ##
|
|
#Param key string used for lookup ##
|
|
#Param value data holding value stored in annotation ##
|
|
|
|
#Example
|
|
#Height 1
|
|
const char text[] = "Click this link!";
|
|
SkRect bounds;
|
|
SkPaint paint;
|
|
paint.setTextSize(40);
|
|
(void)paint.measureText(text, strlen(text), &bounds);
|
|
const char url[] = "https://www.google.com/";
|
|
sk_sp<SkData> urlData(SkData::MakeWithCString(url));
|
|
canvas->drawAnnotation(bounds, "url_key", urlData.get());
|
|
##
|
|
|
|
#SeeAlso SkPicture SkDocument
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method void drawAnnotation(const SkRect& rect, const char key[], const sk_sp<SkData>& value)
|
|
|
|
Associates Rect on Canvas when an annotation; a key-value pair, where the key is
|
|
a null-terminated utf8 string, and optional value is stored as Data.
|
|
|
|
Only some canvas implementations, such as recording to Picture, or drawing to
|
|
Document_PDF, use annotations.
|
|
|
|
#Param rect Rect extent of canvas to annotate ##
|
|
#Param key string used for lookup ##
|
|
#Param value data holding value stored in annotation ##
|
|
|
|
#Example
|
|
#Height 1
|
|
const char text[] = "Click this link!";
|
|
SkRect bounds;
|
|
SkPaint paint;
|
|
paint.setTextSize(40);
|
|
(void)paint.measureText(text, strlen(text), &bounds);
|
|
const char url[] = "https://www.google.com/";
|
|
sk_sp<SkData> urlData(SkData::MakeWithCString(url));
|
|
canvas->drawAnnotation(bounds, "url_key", urlData.get());
|
|
##
|
|
|
|
#SeeAlso SkPicture SkDocument
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method virtual bool isClipEmpty() const
|
|
#In Property
|
|
#Line # returns if Clip is empty ##
|
|
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
|
|
void draw(SkCanvas* canvas) {
|
|
SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
|
|
SkPath path;
|
|
canvas->clipPath(path);
|
|
SkDebugf("clip is%s empty\n", canvas->isClipEmpty() ? "" : " not");
|
|
}
|
|
#StdOut
|
|
clip is not empty
|
|
clip is empty
|
|
##
|
|
##
|
|
|
|
#SeeAlso isClipRect getLocalClipBounds getDeviceClipBounds
|
|
|
|
##
|
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
#Method virtual bool isClipRect() const
|
|
#In Property
|
|
#Line # returns if Clip is Rect and not empty ##
|
|
Returns true if Clip is Rect and not empty.
|
|
Returns false if the clip is empty, or if it is not Rect.
|
|
|
|
#Return true if Clip is Rect and not empty ##
|
|
|
|
#Example
|
|
void draw(SkCanvas* canvas) {
|
|
SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
|
|
canvas->clipRect({0, 0, 0, 0});
|
|
SkDebugf("clip is%s rect\n", canvas->isClipRect() ? "" : " not");
|
|
}
|
|
#StdOut
|
|
clip is rect
|
|
clip is not rect
|
|
##
|
|
##
|
|
|
|
#SeeAlso isClipEmpty getLocalClipBounds getDeviceClipBounds
|
|
|
|
##
|
|
|
|
#Class SkCanvas ##
|
|
|
|
#Topic Canvas ##
|