Table of Contents

Namespace Egami.Drawing

Classes

Annotation

A link or a destination for DrawAnnotation(RectF, Annotation): what a document backend writes, and pixels never show.

BlendPaint

Two paints combined pixel by pixel with a blend mode, as Skia's blend shader: Source is blended onto Destination, and the result is what this paint draws. Each part keeps its own LocalMatrix and Opacity (its blend mode, blur and dithering are not used), inside this paint's own local matrix.

Canvas

A surface to draw paths, shapes, strokes and images on, through a current transform and clip. The canvas itself is abstract: RasterCanvas<TPixel> draws into pixels, and other backends (a PDF page, a recorder) keep the calls as vectors. Every public call is checked and tracked here (the transform, the clip bounds, the save stack) and then ends in exactly one protected On hook, which is all a backend overrides; hooks added in later versions get default bodies, so adding them never breaks a backend.

Coordinates are float pixels, y down; the pixel at (0, 0) covers the square from 0 to 1. Calls draw when they are made. A canvas is for one thread at a time; one large call may still spread its rows over several cores.

CanvasOptions

Settings for a raster canvas.

ColorMatrixPaint

Another paint with a color matrix run on its colors, as Skia's color-filtered shader: each color, unpremultiplied, goes through the matrix, is clamped to 0 to 1 and is premultiplied again. WithColorMatrix(ColorMatrix) makes one.

ConicalGradient

A gradient between two circles, as the HTML canvas's createRadialGradient, Skia's two-point conical gradient and a PDF type 3 shading define it: for each t, the circle whose center and radius are t of the way from the start circle to the end one; a pixel takes the largest t whose circle passes through it with a radius of at least 0. It covers a focal point inside a circle (a start radius of 0), one circle inside the other, and cones drawn on one side only.

ContourMeasure

One measured contour of a PathMeasure. Distances run from 0 at the contour's start to Length at its end; distances outside are clamped to them, as in Skia.

CustomPaint

A paint whose colors come from C# code: override Shade(int, int, Span<PremulRgbaF32>, in Matrix3x2) to fill a row of premultiplied float colors. Rows are shaded in parallel bands, so Shade(int, int, Span<PremulRgbaF32>, in Matrix3x2) must be thread-safe and must give a pixel the same color whichever band or thread asks; then the result is the same at any core count. A backend that keeps vectors, such as a PDF page, cannot run C# and draws the call through its raster fallback instead. Derive a record class from it.

DashPattern

The dashes of a stroke: lengths of drawn and skipped stretches in turn, in path units, and where in the pattern each contour starts, as PDF's d, SVG's stroke-dasharray and stroke-dashoffset, and Skia's dash effect define them. An odd number of lengths repeats once to make an even one, as SVG says, and a pattern whose lengths add up to 0 draws a solid line. Each dash is an open piece of the path that follows its curves and gets the stroke's caps; the pattern starts afresh on each contour.

DrawingExtensions

Ways into a canvas from Egami's rasters and operation chains.

EncodedImage

An image kept as its file's bytes, such as a JPEG, for DrawImage(EncodedImage, RectF, SamplingOptions?, Paint?): a backend that can store the bytes as they are, as a PDF page stores a JPEG as DCTDecode, gets them through OnDrawEncodedImage without decoding and encoding again; every other backend draws the decoded pixels. The bytes are probed when the image is made and decoded at most once, on first need. Immutable and thread-safe.

FallbackImage

A drawing call rendered into pixels by Canvas.RasterizeFallback, for a backend to place as an image.

FontExtensions

Glyphs and text as Paths in canvas units, y down, for clipping, stroking or measuring them as shapes.

GdiPlusText

Text placement as GDI+ (System.Drawing) does it, for callers that put text in a box themselves and want it where Graphics.DrawString would put it. Measured from GDI+ on Windows; Egami's own layout (DrawText(string, RectF, ParagraphStyle, VerticalAlign)) is unchanged.

GlyphCache

The process-wide cache of glyph coverage masks the raster canvas draws small text from: one mask per typeface (each variation position its own), glyph, device em size, axis scales, subpixel phase, edging, hinting and synthesis, for glyphs up to 256 device pixels per em under a scale-and-translate transform. Masks hold one byte per pixel, or three for LCD edging. Bigger, rotated or skewed glyphs fill as paths and are not cached. Masks are rendered by the same rasterizer as paths and drawn at the same rounded positions either way, so the cache changes speed, never pixels. Shared by every canvas on every thread; least recently used masks go first when the budget is spent.

Gradient

A paint whose color changes along a line, around a center or between two circles by its stops. Each pixel center maps back through the canvas transform and LocalMatrix to a position t along the gradient, which Tile brings into 0 to 1 and the stops turn into a color. On 8-bit targets t picks one of 1024 colors made once per paint; float and 16-bit targets mix the stops exactly.

GradientInterpolation

How a gradient mixes its stops: the color space, as CSS Color 4 defines them, and for Oklch the way around the hue circle.

ImagePaint

An image as a paint: shapes are filled with the image's pixels, pixel (0, 0) covering the paint-space square from 0 to 1, under LocalMatrix and the canvas transform. TileX and TileY say what lies past its edges, so it tiles as a pattern, and Decal leaves the outside transparent, as image masks and stencils need. When the paint shrinks the image, sampling reads the nearest smaller level of a MipChain.

InkCanvas

A canvas that draws into an InkRaster's plates: printing inks instead of RGB. It shares RasterCanvas<TPixel>'s rasterizer, clips and layers, so shapes, strokes and text cover exactly the same pixels; where the RGB canvas blends colours, this one sets each plate. A paint's Ink prints its inks by name (inks the raster lacks through their appearance into the process inks); RGB colours, gradients and images convert into the process inks through RgbSource and the ink set's profile.

InkCanvasOptions

How an InkCanvas turns colours that are not inks into its process inks.

Lattice

A grid over an image for DrawImageLattice(Raster, Lattice, RectF, SamplingOptions?, Paint?), as Skia's lattice: the x and y divisions cut the image into columns and rows that alternate fixed and stretchable, starting with fixed, so a division at the image's left or top edge makes the first column or row stretchable. Fixed columns and rows keep their size when the destination is large enough and shrink in proportion when it is not; stretchable ones share what is left. A nine-patch is the lattice with two divisions each way.

LayerOptions

How a layer started by SaveLayer(LayerOptions?) is merged at the matching Restore(): filtered, masked, faded by Opacity and blended into what lies below with BlendMode, through the clip. A layer is what PDF calls a transparency group.

LcdFilter

The five-tap filter LCD text spreads each subpixel's coverage with, across the subpixel and its two neighbours on each side. The weights add up to 256. A wider filter has softer colour fringes; a narrower one is sharper and more coloured.

LinearGradient

A gradient along a line: t is 0 on the line through Start square to it, and 1 through End.

MarkedContent

A tag that brackets a run of drawing for a document backend, as PDF's marked content (BMC, BDC and EMC): a structure element of tagged PDF (a paragraph, a heading, a figure), an artifact such as a page number, or a span with replacement text.

Mesh

Triangles with an optional color, texture coordinate or value at each vertex, for DrawMesh(Mesh, Paint?, BlendMode, ReadOnlySpan<GradientStop>): Gouraud-shaded triangles, textured triangles (a paint mapped through the texture coordinates) and PDF's free-form and lattice-form shadings (one value per vertex, mapped through gradient stops). Immutable: the constructor copies what it is given.

NinePatch

An image with its Lattice, as Android's nine-patch (.9.png) files hold them.

NoisePaint

Procedural noise as a paint. Fractal(float, float, int, int, Size?) and Turbulence(float, float, int, int, Size?) follow SVG 1.1's feTurbulence step by step (its random table, lattice and gradients), so the pixels match Skia's noise shaders and browsers within rounding; Simplex(float, int, int, Size?) is smoother and can tile. Each of the four channels is its own noise, straight alpha included. The noise lives in paint coordinates: it scales and turns with the canvas transform and LocalMatrix.

Paint

What a drawing call puts on the canvas, and how it combines with what is there: the colors (from the subclass), the BlendMode, an Opacity, whether edges are antialiased, and for shapes an optional Blur. The kinds are SolidPaint, the gradients (LinearGradient, RadialGradient, ConicalGradient, SweepGradient), ImagePaint, NoisePaint, BlendPaint, ColorMatrixPaint and CustomPaint. A color converts to a solid paint where a paint is expected. A paint is an ITextPaint, so a paragraph's text style can carry it.

A paint other than a solid one has its own coordinates: LocalMatrix maps them into the canvas's local coordinates, so a gradient or an image turns and scales with the canvas transform, and further with its own matrix.

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.

Path

An outline of contours made of lines, quadratic and cubic Bézier curves, with the FillRule that says which points it covers when filled. A path never changes after it is built, so one path can be drawn from many threads and kept by any canvas backend. Coordinates are float pixels, y down. Build one with PathBuilder or a shape helper such as Circle(Vector2, float).

PathBuilder

Builds a Path one command at a time. Arcs, ovals and round corners become cubic curves as they are added, so a path holds only lines, quadratics and cubics. A line or curve with no contour open starts one at the last contour's start (or the origin), as SVG and Skia do. Building takes time in proportion to the points added; ToPath(FillRule) copies them, so the builder can go on or be reused.

PathEffect

Turns one path into another before it is filled or stroked: dashes, rounded corners, trimming, jitter, shapes stamped along the path, hatching. Effects are immutable, so one can be shared and reused; Then(PathEffect) and Plus(PathEffect) combine them. Apply one with Apply(PathEffect), or set it on Effect to have the canvas apply it before stroking. The set is Skia's: dash, corner, trim, discrete, 1D path, 2D line and 2D path effects, composed and summed.

PathMeasure

Measures a path: the length of each contour, and the point, direction and pieces at any distance along it. Lengths are exact to about 1e-4 units, curves included: each curve's length is integrated by adaptive Gauss–Legendre quadrature, and a distance is turned back into a point on the curve by Newton steps, so long curves do not gather the errors of a flattened outline. Contours of zero length are left out, as Skia's SkContourMeasureIter leaves them. Measuring is done once, here; the queries are cheap and safe from many threads.

Picture

Recorded canvas calls, from a PictureRecorder or Load(Stream, EgamiContext?): replay them on any canvas with DrawPicture(Picture, Matrix3x2?, Paint?, bool) or Playback(Canvas), fill shapes with them through a PicturePaint, render them with ToRaster<TPixel>(float, CanvasOptions?, EgamiContext?), or keep them in an .egdr file with Save(Stream). Replay is always vector, so a picture stays sharp at any scale. Immutable, and safe to replay on several threads and canvases at once.

PicturePaint

A Picture as a paint: a tiling pattern, the shape of PDF's and SVG's tiling patterns and Skia's picture shader. The Tile rectangle of the picture, in its own coordinates, is repeated by TileX and TileY under LocalMatrix and the canvas transform. The raster backend renders one tile at the device scale the paint is drawn at and keeps it with the picture, so a pattern stays sharp when zoomed and is rendered once for repeated fills at one scale. A tile is at most 4096 pixels a side.

PictureRecorder

A canvas that records instead of picture: every hook call is kept with its arguments, and Finish() returns them as an immutable Picture to replay on any canvas, at any scale, as often as needed, as Skia's SkPictureRecorder. Any code that draws on a Canvas can draw into it. Paths, paints, images and nested pictures are kept by reference: images must not change while the picture is in use.

RadialGradient

A gradient in circles around a center: t is the distance from Center divided by Radius.

RasterCanvas<TPixel>

The raster backend: a canvas that draws into a raster's pixels, with exact-area antialiasing, blended through Egami's Compositor in the pixel type's own precision. A clip that is a pixel-aligned rectangle stays a rectangle; any other clip becomes a coverage mask over the clip's bounds. A call whose area exceeds 256 KiB of destination rows spreads its rows over up to MaxParallelism cores, with the same pixels at any core count.

A layer from SaveLayer(LayerOptions?) is premultiplied in the raster's class (PremulRgba8 for 8-bit rasters, PremulRgbaF32 for deeper ones) and covers only its bounds inside the clip, grown by its filter's reach; its memory comes from the raster's EgamiContext and is released at Restore().

ShadowOptions

The light and colors of DrawShadow(Path, ShadowOptions?), after Skia's shadow model (the Material Design one): a shape lifted Elevation above the canvas casts an ambient shadow, blurred by its height, and a spot shadow from a round light at LightPosition, moved away from the light and blurred by the light's size.

SoftMask

A mask made by drawing, as a PDF soft mask: Draw runs on a canvas of its own with the layer's transform and clip, and its alpha, or its luminosity over Backdrop, through the optional Transfer curve, multiplies the layer. A luminosity mask of a white shape on black shows the layer only inside the shape.

SolidPaint

One color everywhere, with straight alpha. The color keeps float precision, so float and 16-bit targets get it in full; values outside 0 to 1 are kept on the paint, and the blend clamps them as Egami's Compositor does.

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.

SvgPathException

Thrown by ParseSvg(ReadOnlySpan<char>, FillRule, bool) when SVG path data breaks the grammar.

SvgPathFormat

How ToSvg(SvgPathFormat?) writes SVG path data.

SweepGradient

A gradient around a center, as Skia's sweep gradient and CSS's conic-gradient: t goes from 0 at StartAngle to 1 at EndAngle, in degrees clockwise (on a y-down screen) from the positive x axis.

TextOnPathOptions

How ShapeOnPath(Font, string, Path, TextOnPathOptions?) lays text along a path.

Structs

CornerRadii

The x and y radius of each corner of a RoundRect, clockwise from the top-left. A radius below 0 counts as 0, and a corner with either radius 0 is square.

GradientStop

One color of a gradient at a position along it, from 0 (the start) to 1 (the end). Two stops at the same offset make a hard edge: the later one applies from that offset on. A gradient whose first stop is after 0 or whose last is before 1 repeats the nearest stop's color to the end, as CSS does.

MaskBlur

A Gaussian blur of a shape's coverage before the paint is applied, as Skia's blur mask filter: Sigma is in device pixels, so it does not scale with the canvas transform. Set it as Blur. Egami blurs with its fast blur; an axis-aligned rectangle with Normal is computed exactly from the error function, which is faster still.

RectF

A rectangle in float pixels, y down: the left edge at X, the top at Y. A width or height of 0 or less makes it empty. Pixel (0, 0) covers the square from (0, 0) to (1, 1), so a rectangle with whole-number edges covers whole pixels.

RoundRect

A rectangle with an x and y radius per corner. Radii that would overlap are scaled down together, as CSS and Skia do: every radius is multiplied by the smallest ratio of a side's length to the sum of the two radii along it, when that ratio is below 1. A radius below 0 counts as 0, and a corner with either radius 0 is square.

SpriteTransform

A sprite's placement in DrawAtlas(Raster, ReadOnlySpan<SpriteTransform>, ReadOnlySpan<RectF>, ReadOnlySpan<RgbaF32>, BlendMode, SamplingOptions?, RectF?, Paint?), as Skia's RSXform: a rotation with a uniform scale, then a move. A point (x, y) of the sprite, measured from its source rectangle's top-left corner, goes to (ScaleCos·x − ScaleSin·y + Tx, ScaleSin·x + ScaleCos·y + Ty).

Interfaces

IColorGlyphRenderer

Draws color glyphs of a format Egami.Drawing does not draw itself, such as the SVG documents of an OpenType SVG table (Egami.Svg's SvgGlyphRenderer). Set on ColorGlyphRenderer, it is asked first for every glyph whose font has that format, except where the font has a COLR version 1 glyph, so the order is COLR v1, the renderer, COLR v0, sbix, CBDT, then the outline.

Enums

AnnotationKind

What an Annotation marks, as Skia's annotations do.

Antialiasing

How a canvas antialiases shapes.

BlurStyle

How a MaskBlur keeps or removes the blurred shape's inside and outside, as Skia's blur styles.

ClipOp

Whether a clip keeps what is inside a shape or what is outside it.

FillRule

Which points a filled path covers, from how often its outline winds around them.

HueMethod

Which way around the hue circle an Oklch gradient goes between two stops, as CSS Color 4's hue interpolation methods.

InterpolationSpace

The color space a gradient's stops are mixed in.

LatticeCellKind

What a cell of a Lattice draws.

LcdSampling

How LCD text samples a glyph before filtering.

LineCap

How the ends of an open stroked contour look.

LineJoin

How a stroke turns the corner where two segments meet.

MeshMode

How a Mesh reads its vertices (or its indices, when it has them) as triangles.

NoisePaintKind

The kind of noise a NoisePaint makes.

Overprint

Which plates a paint prints on an ink canvas, as PDF's overprint; see Overprint.

PatchKind

Which surface a Patch is: its boundary only, or a full tensor-product net.

PathDirection

The direction a shape's outline runs, on a y-down screen.

PathOp

How Op(Path, PathOp, float) and Combine(IEnumerable<Path>, PathOp, float) combine the areas of two paths: Skia's five operations.

PathVerb

One drawing command of a Path; the comment on each says how many points it takes.

PixelGeometry

The order of a display's color subpixels, which LCD text edging needs to know.

PixelOffset

Where a canvas puts its pixel centres, for paths and unhinted text: GDI+'s PixelOffsetMode.

PointMode

How DrawPoints(PointMode, ReadOnlySpan<Vector2>, Stroke, Paint) reads its points.

RoundRectKind

What a RoundRect reduces to, so backends and the rasterizer can take a shortcut.

SoftMaskKind

Which value of a soft mask's drawing becomes the mask, as PDF's soft mask subtypes.

StampStyle

How Stamp(Path, float, float, StampStyle) places its shape along a path.

TextAnchor

Where text on a path is anchored at its start point, as SVG's text-anchor.

TextPathSide

Which side of a path text stands on.

TileMode

What a gradient or an image paint does past its ends or edges, as Skia's tile modes.

VerticalAlign

Where DrawText(string, RectF, ParagraphStyle, VerticalAlign) puts a paragraph across its lines, in a rectangle taller (or, for vertical lines, wider) than the lines.

Delegates

PlaceholderPainter

Draws a placeholder's content where DrawTextLayout(TextLayout, Vector2, RectF?, PlaceholderPainter?) left room for it.