Table of Contents

Class GlyphRun

Namespace
Egami.Fonts
Assembly
Egami.Fonts.dll

Positioned glyphs of one font, ready to draw: glyph ids, one position per glyph relative to the run's origin (the first baseline's left end, y down, in canvas units), and optionally the source text with the UTF-16 index each glyph came from, which lets a PDF writer keep text searchable.

public sealed class GlyphRun
Inheritance
GlyphRun
Inherited Members
Extension Methods

Examples

// A caption on a photo: white text with a dark shadow, its baseline 24 pixels above the bottom.
using Raster<Rgba8> photo = Raster.Create(640, 360, new Rgba8(90, 120, 160, 255));
var font = new Font(Typeface.FromFile(FontFile), 28);
using (RasterCanvas<Rgba8> canvas = photo.CreateCanvas())
{
    var origin = new Vector2(24, photo.Height - 24);
    canvas.DrawText("Lofoten, March", origin + new Vector2(2, 2), font, new Rgba8(0, 0, 0, 160));
    canvas.DrawText("Lofoten, March", origin, font, Rgba8.White);
}

Properties

Advance

Gets the end of the last glyph's advance on its line: the pen position after the run (for a transformed run, along x from each glyph's origin).

public float Advance { get; }

Property Value

float

BidiLevel

Gets the bidi embedding level the run was shaped at: odd for right to left, 0 for a run not built by the shaper.

public int BidiLevel { get; }

Property Value

int

Bounds

Gets the exact box around the run's ink, relative to its origin, y down; empty when nothing has ink.

public TextBounds Bounds { get; }

Property Value

TextBounds

Clusters

Gets the index in Text each glyph came from; empty when there is no text.

public ReadOnlySpan<int> Clusters { get; }

Property Value

ReadOnlySpan<int>

Count

Gets the number of glyphs.

public int Count { get; }

Property Value

int

Font

Gets the font every glyph is drawn in.

public Font Font { get; }

Property Value

Font

Glyphs

Gets the glyph ids.

public ReadOnlySpan<ushort> Glyphs { get; }

Property Value

ReadOnlySpan<ushort>

Language

Gets the BCP 47 language tag the run was shaped with, or null.

public string? Language { get; }

Property Value

string

Positions

Gets each glyph's origin on its baseline, relative to the run's origin, y down; for a run with Transforms, the translation of each glyph's transform.

public ReadOnlySpan<Vector2> Positions { get; }

Property Value

ReadOnlySpan<Vector2>

Script

Gets the script the run was shaped as, or Common when it is not one script.

public Script Script { get; }

Property Value

Script

Text

Gets the source text, or null when the run was built from glyphs alone.

public string? Text { get; }

Property Value

string

Transforms

Gets each glyph's rotation, scale and origin, which replace Positions when present (a run from CreateTransformed(Font, ReadOnlySpan<ushort>, ReadOnlySpan<GlyphTransform>, string?, ReadOnlySpan<int>), such as text on a path); empty for a run of plain positions.

public ReadOnlySpan<GlyphTransform> Transforms { get; }

Property Value

ReadOnlySpan<GlyphTransform>

Methods

Create(Font, ReadOnlySpan<ushort>, ReadOnlySpan<Vector2>, string?, ReadOnlySpan<int>)

Creates a run from glyphs and positions, such as a layout engine's or a PDF content stream's.

public static GlyphRun Create(Font font, ReadOnlySpan<ushort> glyphs, ReadOnlySpan<Vector2> positions, string? text = null, ReadOnlySpan<int> clusters = default)

Parameters

font Font

The font.

glyphs ReadOnlySpan<ushort>

The glyph ids.

positions ReadOnlySpan<Vector2>

One position per glyph, relative to the run's origin, y down.

text string

The source text, or null.

clusters ReadOnlySpan<int>

The index in text of each glyph; empty when text is null.

Returns

GlyphRun

The run, holding copies of the spans.

Exceptions

ArgumentException

The spans differ in length, or clusters are given without text or point outside it.

CreateTransformed(Font, ReadOnlySpan<ushort>, ReadOnlySpan<GlyphTransform>, string?, ReadOnlySpan<int>)

Creates a run whose glyphs each have their own rotation, uniform scale and origin, as Skia's RSXform runs: text on a path, or labels around a dial. Glyphs that only move are drawn as any run's; turned or scaled ones fill as paths.

public static GlyphRun CreateTransformed(Font font, ReadOnlySpan<ushort> glyphs, ReadOnlySpan<GlyphTransform> transforms, string? text = null, ReadOnlySpan<int> clusters = default)

Parameters

font Font

The font.

glyphs ReadOnlySpan<ushort>

The glyph ids.

transforms ReadOnlySpan<GlyphTransform>

One transform per glyph, relative to the run's origin, y down.

text string

The source text, or null.

clusters ReadOnlySpan<int>

The index in text of each glyph; empty when text is null.

Returns

GlyphRun

The run, holding copies of the spans.

Examples

// A label along a curve: each glyph's midpoint on the path, turned to its direction, as SVG's textPath. The result is
// still a glyph run, so a PDF backend writes it as searchable text.
Path curve = new PathBuilder().MoveTo(20, 150).CubicTo(80, 20, 240, 20, 300, 150).ToPath();
var font = new Font(face, 18);
using (RasterCanvas<Rgba8> canvas = image.CreateCanvas())
{
    canvas.DrawTextOnPath("Text that follows the curve", curve, font, Rgba8.Black,
        new TextOnPathOptions { StartFraction = 0.5f, Anchor = TextAnchor.Center, BaselineShift = 4 });
}

// Or place glyphs yourself, each with its own turn and scale.
GlyphRun dial = GlyphRun.CreateTransformed(font, [face.GetGlyph('N'), face.GetGlyph('E')],
    [GlyphTransform.FromRotationScale(1, 0, new Vector2(150, 30)), GlyphTransform.FromRotationScale(1, 90, new Vector2(290, 90))]);

Exceptions

ArgumentException

The spans differ in length, a transform is not finite, or clusters are given without text or point outside it.