Class Patch
A curved four-sided surface with a color, value or texture coordinate at each corner, for DrawPatch(Patch, Paint?, BlendMode, ReadOnlySpan<GradientStop>): PDF's Coons and tensor-product patch shadings (types 6 and 7) and Skia's drawPatch. The surface's parameters u (left to right) and v (top to bottom) run from 0 to 1; corner data is interpolated bilinearly in them. Immutable.
Corners are in the order top-left (u 0, v 0), top-right, bottom-right, bottom-left. A Coons patch's 12 points go clockwise from the top-left corner, as Skia's: the top curve left to right (points 0 to 3), the right curve down (3 to 6), the bottom curve right to left (6 to 9) and the left curve up (9, 10, 11, 0). A tensor patch's 16 points are its net row by row, top row first, each row left to right.
public sealed class Patch
- Inheritance
-
Patch
- Inherited Members
Examples
// A Coons patch: four cubic edges, clockwise from the top-left corner, and a color at each corner.
Vector2[] edges =
[
new(20, 20), new(80, 0), new(150, 40), new(220, 20), // top, left to right
new(200, 80), new(240, 140), new(220, 180), // right, down
new(150, 160), new(80, 200), new(20, 180), // bottom, right to left
new(40, 120), new(0, 60), // left, up
];
Patch patch = Patch.Coons(edges, [new RgbaF32(1, 0, 0, 1), new RgbaF32(1, 1, 0, 1), new RgbaF32(0, 0, 1, 1), new RgbaF32(0, 1, 0, 1)]);
using (RasterCanvas<Rgba8> canvas = raster.CreateCanvas())
{
canvas.DrawPatch(patch);
// PDF's function-based shadings give each corner a value instead, mapped through a gradient's stops.
Patch shaded = Patch.Tensor(patch.ToTensorNet().Span, cornerValues: [0, 0.3f, 1, 0.6f]);
canvas.Translate(10, 10);
canvas.Scale(0.3f);
canvas.DrawPatch(shaded, valueStops: [new GradientStop(0, Rgba8.Black), new GradientStop(1, Rgba8.White)]);
}
Properties
Bounds
Gets the bounds of the control points, which hold the whole surface.
public RectF Bounds { get; }
Property Value
CornerColors
Gets the corner colors, or empty when there are none: for a patch with inks, their appearances in sRGB.
public ReadOnlyMemory<RgbaF32> CornerColors { get; }
Property Value
CornerInks
Gets the corner colours as inks, or empty when the patch has none (see WithInks(ReadOnlySpan<InkColor>)).
public ReadOnlyMemory<InkColor> CornerInks { get; }
Property Value
CornerTexCoords
Gets the corner texture coordinates, or empty when there are none.
public ReadOnlyMemory<Vector2> CornerTexCoords { get; }
Property Value
CornerValues
Gets the corner values, or empty when there are none.
public ReadOnlyMemory<float> CornerValues { get; }
Property Value
Kind
Gets which surface the patch is.
public PatchKind Kind { get; }
Property Value
Points
Gets the control points: 12 for a Coons patch, 16 for a tensor patch, in the orders the class describes.
public ReadOnlyMemory<Vector2> Points { get; }
Property Value
Methods
Coons(ReadOnlySpan<Vector2>, ReadOnlySpan<RgbaF32>, ReadOnlySpan<Vector2>, ReadOnlySpan<float>)
Creates a Coons patch from its four boundary curves.
public static Patch Coons(ReadOnlySpan<Vector2> points, ReadOnlySpan<RgbaF32> cornerColors = default, ReadOnlySpan<Vector2> cornerTexCoords = default, ReadOnlySpan<float> cornerValues = default)
Parameters
pointsReadOnlySpan<Vector2>The 12 boundary points, clockwise from the top-left corner.
cornerColorsReadOnlySpan<RgbaF32>Four straight-alpha corner colors, or empty.
cornerTexCoordsReadOnlySpan<Vector2>Four corner points in the paint's coordinates, or empty.
cornerValuesReadOnlySpan<float>Four corner values, mapped through the stops given to DrawPatch(Patch, Paint?, BlendMode, ReadOnlySpan<GradientStop>), or empty.
Returns
- Patch
The patch.
Examples
// A Coons patch: four cubic edges, clockwise from the top-left corner, and a color at each corner.
Vector2[] edges =
[
new(20, 20), new(80, 0), new(150, 40), new(220, 20), // top, left to right
new(200, 80), new(240, 140), new(220, 180), // right, down
new(150, 160), new(80, 200), new(20, 180), // bottom, right to left
new(40, 120), new(0, 60), // left, up
];
Patch patch = Patch.Coons(edges, [new RgbaF32(1, 0, 0, 1), new RgbaF32(1, 1, 0, 1), new RgbaF32(0, 0, 1, 1), new RgbaF32(0, 1, 0, 1)]);
using (RasterCanvas<Rgba8> canvas = raster.CreateCanvas())
{
canvas.DrawPatch(patch);
// PDF's function-based shadings give each corner a value instead, mapped through a gradient's stops.
Patch shaded = Patch.Tensor(patch.ToTensorNet().Span, cornerValues: [0, 0.3f, 1, 0.6f]);
canvas.Translate(10, 10);
canvas.Scale(0.3f);
canvas.DrawPatch(shaded, valueStops: [new GradientStop(0, Rgba8.Black), new GradientStop(1, Rgba8.White)]);
}
Exceptions
- ArgumentException
There are not 12 points or four of each corner list, both colors and values are given, or a number is not finite.
Evaluate(float, float)
Returns the point of the surface at parameters (u, v).
public Vector2 Evaluate(float u, float v)
Parameters
Returns
- Vector2
The point, in the canvas's local coordinates.
Tensor(ReadOnlySpan<Vector2>, ReadOnlySpan<RgbaF32>, ReadOnlySpan<Vector2>, ReadOnlySpan<float>)
Creates a tensor-product patch from its 4×4 net.
public static Patch Tensor(ReadOnlySpan<Vector2> points, ReadOnlySpan<RgbaF32> cornerColors = default, ReadOnlySpan<Vector2> cornerTexCoords = default, ReadOnlySpan<float> cornerValues = default)
Parameters
pointsReadOnlySpan<Vector2>The 16 points, row by row from the top, each row left to right.
cornerColorsReadOnlySpan<RgbaF32>Four straight-alpha corner colors, or empty.
cornerTexCoordsReadOnlySpan<Vector2>Four corner points in the paint's coordinates, or empty.
cornerValuesReadOnlySpan<float>Four corner values, or empty.
Returns
- Patch
The patch.
Exceptions
- ArgumentException
There are not 16 points or four of each corner list, both colors and values are given, or a number is not finite.
ToTensorNet()
Returns the patch's 4×4 tensor net. A Coons patch's inner points come from its boundary as PDF section 8.7.4.5.8 gives them, so the tensor patch of that net is the same surface.
public ReadOnlyMemory<Vector2> ToTensorNet()
Returns
- ReadOnlyMemory<Vector2>
The 16 points, row by row from the top.
WithInks(ReadOnlySpan<InkColor>)
Returns this patch with its four corner colours given as inks: an ink canvas blends their tints across the surface (an ink a corner does not name counts as 0 there); other canvases use the appearances in sRGB, which become CornerColors.
public Patch WithInks(ReadOnlySpan<InkColor> cornerInks)
Parameters
cornerInksReadOnlySpan<InkColor>Four corner colours, in the order of CornerColors.
Returns
- Patch
The new patch.
Exceptions
- ArgumentException
There are not four, or the patch has corner values.
- ArgumentNullException
A colour is null.