Pathdescribes a sequence of potentially disjoint movements on a plane. Paths tracks a current point as well as one or more subpaths (created via
Path.moveTo). Subpaths may be closed (i.e., the first and last points are coincident), open (i.e., the first and last points are distinct), or self intersecting (i.e., movements within the path intersect). Paths incorporate lines, arcs, beziers, and more; each operation begins at the current point and, once complete, defines the new current point. The current point begins at the origin. Paths can be queried (via
Path.contains), transformed (via
Path.transform), and merged (via
Path.combine, which accepts a
PathFillTypedefines the criteria determining whether a point is contained by the path.
PathFillType.evenOddcasts a ray from the point outward, summing the number of edge crossings; an odd count indicates that the point is internal.
PathFillType.nonZeroconsiders the path’s directionality. Again casting a ray from the point outward, this method sums the number of clockwise and counterclockwise crossings. If the counts aren’t equal, the point is considered to be internal.
Canvasrepresents a graphical context supporting a number of drawing operations. These operations are captured by an associated
PictureRecorderand, once finalized, transformed into a
Canvasis associated with a clip region (i.e., an area within which painting will be visible), and a current transform (i.e., a matrix to be applied to any drawing), both managed using a stack (i.e., clip regions and transforms can be pushed and popped as drawing proceeds). Any drawing outside of the canvas’s culling box (“
cullRect”) may be discarded; by default, however, affected pixels are retained. Many operations accept a
Paintparameter which describes how the drawing will be composited (e.g., the fill, stroke, blending, etc).
Canvasexposes a rich API for drawing. The majority of these operations are implemented within the engine.
Canvas.clipRect, etc., refine (i.e., reduce) the clip region. These operations compute the intersection of the current clip region and the provided geometry to define a new clip region. The clip region can be anti-aliased to provide a gradual blending.
Canvas.transform, etc., alter the current transformation matrix (i.e., by multiplying it by an additional transform). The former methods apply standard transformations, whereas the latter applies an arbitrary 4x4 matrix (specified in column-major order).
Canvas.drawPath, etc., perform fundamental drawing operations.
Canvas.drawPicture, etc., copy pixels from a rendered image or recorded picture into the current canvas.
Canvas.drawParagraphpaints text into the canvas (via
Canvas.drawPoints, etc., describe solids using a collection of points. The former constructs triangles from a set of vertices (Vertices) and a vertex mode (
VertexMode); this mode describes how vertices are composed into triangles (e.g.,
VertexMode.trianglesspecifies that each sequence of three points defines a new triangle). The resulting triangles are filled and composited using the provided
BlendMode. The latter paints a set of points using a
PointModedescribing how the collection of points is to be interpreted (e.g., as defining line segments or disconnected points).
- The save stack tracks the current transformation and clip region. New entries can be pushed (via
Canvas.saveLayer) and popped (via
Canvas.restore). The number of items in this stack can also be queried (via
Canvas.getSaveCount); there is always at least one item on the stack. All drawing operations are subject to the transform and clip at the top of the stack.
- All drawing operations are performed sequentially (by default or when using
Canvas.restore). If the operation utilizes blending, it will be blended immediately after completing.
Canvas.saveLayerallows drawing operations to be grouped together and composited as a whole. Each individual operation will still be blended within the saved layer; however, once the layer is completed, the composite drawing will be blended as a whole using the provided
- For example, an arbitrary drawing can be made consistently translucent by first painting it using an opaque fill, and then blending the resulting layer with the canvas. If instead each component of the drawing were individually blended, overlapping regions would appear darker.
- This is particularly useful for antialiased clip regions (i.e., regions that aren’t pixel aligned). Without layers, any operations intersecting the clip would needed to be antialiased (i.e., blended with the background). If a subsequent operation intersects the clip at this same point, it would be blended with both the background and the previous operation; this produces visual artifacts (e.g., color bleed). If both operations were combined into a layer and composited as a whole, only the final operation would be blended.
- Note that though this doesn’t introduce a new framework layer, it does cause the engine to switch to a new rendering target. This is fairly expensive as it flushes the
GPU’s command buffer and requires data to be shuffled.
Paintdescribes how a drawing operation is to be applied to the canvas. In particular, it specifies a number of graphical parameters including the color to use when filling or stroking lines (
Paint.shader), how new painting is to be blended with old painting (
Paint.maskFilter), and how edges are to be drawn (
Paint.strokeCap). Fundamental to most drawing is whether the result is to be stroked (e.g., drawn as an outline) or filled;
PaintingStyleinstance specifying the mode to be used.
- If stroking,
Paint.strokeWidthis measured in logical pixels orthogonal to the path being painted. A value of
0.0will cause the line to be rendered as thin as possible (“hairline rendering”).
- Any lines that are drawn will be capped at their endpoints according to a
StrokeCap.buttis the default and does not paint a cap). Caps extend the overall length of lines in proportion to the stroke width.
- Discrete segments are joined according to a
StrokeJoin.miteris the default and extends the original line such that the next can be drawn directly from it). A limit may be specified to prevent the original line from extending too far (via
Paint.strokeMiterLimit; once exceeded, the join reverts to
ColorFilterdescribes a function mapping from two input colors (e.g., the paint’s color and the destination’s color) to a final output color (e.g., the final composited color). If a
ColorFilteris provided, it overrides both the paint color and shader; otherwise, the shader overrides the color.
MaskFilterapplies a filter (e.g., a blur) to the drawing once it is complete but before it is composited. Currently, this is limited to a Gaussian blur.
Shaderis a handle to a Skia shader utilized by the engine. Several are exposed within the framework, including
ImageShader. These are analogous, with the former generating pixels by smoothly blending colors and the latter reading them directly from an image. Both support tiling so that the original pixels can be extended beyond their bounds (a different
TileModemay be specified in either direction);
ImageShaderalso supports an arbitrary matrix to be applied to the source image.