Table of Contents

Class Patch

Namespace
Egami.Drawing
Assembly
Egami.Drawing.dll

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

RectF

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

ReadOnlyMemory<RgbaF32>

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

ReadOnlyMemory<InkColor>

CornerTexCoords

Gets the corner texture coordinates, or empty when there are none.

public ReadOnlyMemory<Vector2> CornerTexCoords { get; }

Property Value

ReadOnlyMemory<Vector2>

CornerValues

Gets the corner values, or empty when there are none.

public ReadOnlyMemory<float> CornerValues { get; }

Property Value

ReadOnlyMemory<float>

Kind

Gets which surface the patch is.

public PatchKind Kind { get; }

Property Value

PatchKind

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

ReadOnlyMemory<Vector2>

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

points ReadOnlySpan<Vector2>

The 12 boundary points, clockwise from the top-left corner.

cornerColors ReadOnlySpan<RgbaF32>

Four straight-alpha corner colors, or empty.

cornerTexCoords ReadOnlySpan<Vector2>

Four corner points in the paint's coordinates, or empty.

cornerValues ReadOnlySpan<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

u float

The horizontal parameter, 0 to 1.

v float

The vertical parameter, 0 to 1.

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

points ReadOnlySpan<Vector2>

The 16 points, row by row from the top, each row left to right.

cornerColors ReadOnlySpan<RgbaF32>

Four straight-alpha corner colors, or empty.

cornerTexCoords ReadOnlySpan<Vector2>

Four corner points in the paint's coordinates, or empty.

cornerValues ReadOnlySpan<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

cornerInks ReadOnlySpan<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.