Class Stroke
How a path is outlined: the pen's width, caps, joins and miter limit. The settings travel with the drawing call as data, so a
vector backend can write them as they are (PDF's w, J, j and M). The pen is applied in the canvas's
local space and then transformed, so a non-uniform scale gives an elliptical pen, as in PDF, SVG and Skia.
public sealed record Stroke : IEquatable<Stroke>
- Inheritance
-
Stroke
- Implements
- Inherited Members
Examples
// The pen is data: width, caps, joins and miter limit. Width 1, butt caps and miter joins by default.
Stroke thick = new(12) { Cap = LineCap.Round, Join = LineJoin.Round };
canvas.DrawLine(new Vector2(20, 20), new Vector2(280, 20), thick, new Rgba8(30, 90, 200, 255));
Path zigzag = Path.Polygon([new(20, 120), new(80, 60), new(140, 120), new(200, 60), new(260, 120)], close: false);
canvas.StrokePath(zigzag, new Stroke(8) { Join = LineJoin.Miter, MiterLimit = 4 }, Rgba8.Black);
// A hairline is one device pixel wide whatever the transform.
canvas.StrokeCircle(new Vector2(150, 160), 30, Stroke.Hairline, Rgba8.Red);
Constructors
Stroke(float)
Initializes a new instance of the Stroke class.
public Stroke(float width = 1)
Parameters
Exceptions
- ArgumentOutOfRangeException
widthis negative or not finite.
Properties
Cap
Gets how open contours end. Defaults to Butt.
public LineCap Cap { get; init; }
Property Value
Exceptions
- ArgumentOutOfRangeException
The value is not defined.
Dash
Gets the dashes, or null for a solid line. The pattern travels with the drawing call as data, so a vector
backend writes it as it is (PDF's d, SVG's stroke-dasharray); the raster backend cuts the path into dashes
before outlining it. Lengths are in local units, like the width. Defaults to null.
public DashPattern? Dash { get; init; }
Property Value
Effect
Gets an effect the canvas applies to the path before it is dashed and stroked, as Skia orders them, or null for none. Backends receive the effect's result as the path to stroke. Defaults to null.
public PathEffect? Effect { get; init; }
Property Value
Hairline
Gets a hairline: one device pixel wide whatever the transform, as PDF's thinnest line and Skia's width 0 are.
public static Stroke Hairline { get; }
Property Value
IsHairline
Gets a value indicating whether this is a hairline: width 0.
public bool IsHairline { get; }
Property Value
Join
Gets how corners are joined. Defaults to Miter.
public LineJoin Join { get; init; }
Property Value
Exceptions
- ArgumentOutOfRangeException
The value is not defined.
MiterLimit
Gets the longest miter allowed, as a multiple of the width: a miter join whose point lies further out than this is drawn as a bevel, as SVG, PDF and Skia define it. Defaults to 4, as in SVG and Skia (PDF's default is 10).
public float MiterLimit { get; init; }
Property Value
Exceptions
- ArgumentOutOfRangeException
The value is below 1 or not finite.
Width
Gets the pen's width in local units. 0 draws a hairline. Defaults to 1.
public float Width { get; init; }
Property Value
Exceptions
- ArgumentOutOfRangeException
The value is negative or not finite.
Methods
ToPath(Path, float, bool)
Returns the outline this pen draws around a path, as a path to fill with the nonzero rule: the effect and dashes applied,
then each piece offset by half the width with the joins and caps, as the raster backend fills it. Curves become straight
pieces within a tenth of a unit divided by scale, so filling the outline at that scale gives exactly
the pixels stroking does. The raw outline overlaps itself where the path turns sharply or crosses itself; with
simplify the overlaps are removed by Simplify(float), for export or hit testing.
public Path ToPath(Path path, float scale = 1, bool simplify = false)
Parameters
pathPathThe path to outline.
scalefloatHow much larger the outline will be drawn, which sets how finely curves are cut.
simplifyboolWhether to remove overlaps.
Returns
- Path
The outline; empty for a hairline, which has no width in path units.
Examples
// A dashed route: the pattern travels with the stroke, so a PDF backend writes [8 4] 0 d instead of hundreds of pieces.
Path route = new PathBuilder().MoveTo(10, 90).CubicTo(60, 0, 140, 160, 190, 60).ToPath();
Stroke dashed = new(3) { Cap = LineCap.Round, Dash = new DashPattern([8, 4]) };
using Raster<Rgba8> map = Raster.Create(200, 120, Rgba8.White);
using (RasterCanvas<Rgba8> canvas = map.CreateCanvas())
{
canvas.StrokePath(route, dashed, new Rgba8(200, 60, 30, 255));
}
// The outline the stroke fills, as a path: for hit testing, or to export without strokes.
Path outline = dashed.ToPath(route, simplify: true);
Exceptions
- ArgumentOutOfRangeException
scaleis not positive and finite.- ArgumentException
The outline does not fit in float coordinates.