Class TextShaper
OpenType text shaping in managed code: a run of text in one font becomes positioned glyphs with GSUB substitutions, GPOS positioning and the script rules HarfBuzz applies.
public static class TextShaper
- Inheritance
-
TextShaper
- Inherited Members
Examples
// One run, one font, as HarfBuzz's hb_shape: ligatures, kerning and marks from the font's GSUB and GPOS.
var font = new Font(face, 24);
var glyphs = new GlyphBuffer();
string text = "office";
TextShaper.ShapeRun(text, 0, text.Length, font, new RunProperties { Script = Script.Latin }, glyphs);
for (int i = 0; i < glyphs.Count; i++)
{
ushort id = glyphs.GlyphIds[i];
int cluster = glyphs.Clusters[i]; // index in text the glyph came from
GlyphPosition position = glyphs.Positions[i]; // in the font's units (pixels here)
bool breakable = (glyphs.Flags[i] & GlyphFlags.UnsafeToBreak) == 0;
}
float width = glyphs.Advance;
Remarks
Stateless and thread-safe; each call needs its own GlyphBuffer.
Methods
Shape(string, Font, ShapingOptions?)
Shapes text: splits it into lines at hard breaks, resolves each line's bidi levels, splits it into runs of one level, script, span and font (falling back per grapheme cluster as Fallback says), shapes each run as ShapeRun(ReadOnlySpan<char>, int, int, Font, RunProperties, GlyphBuffer) does and orders the runs for display. Control characters other than the breaks (a tab, for one) give no glyph. Nothing wraps.
public static ShapedText Shape(string text, Font font, ShapingOptions? options = null)
Parameters
textstringThe text.
fontFontThe font and size.
optionsShapingOptionsThe direction, language, script, features, fallback, cluster level and spans; null for Default.
Returns
- ShapedText
The shaped lines; an empty text gives one empty line.
Examples
// Whole text: lines at hard breaks, bidi levels, script runs, fallback fonts, runs in display order.
var font = new Font(face, 24);
var options = new ShapingOptions { Fallback = new FontFallback(fonts.Families) };
ShapedText shaped = TextShaper.Shape("Shalom: \u05E9\u05DC\u05D5\u05DD!", font, options);
float x = 0;
foreach (ShapedRun run in shaped.Lines[0].Runs)
{
GlyphRun glyphs = run.ToGlyphRun(new System.Numerics.Vector2(x, 0), shaped.Text); // what a canvas draws
x += run.Advance;
}
Exceptions
- ArgumentNullException
textis null, orfonthas no typeface.- ArgumentOutOfRangeException
A span is not inside the text, or two spans overlap.
ShapeRun(ReadOnlySpan<char>, int, int, Font, RunProperties, GlyphBuffer)
Shapes one run, as HarfBuzz's hb_shape: no bidi, script or font splitting; the run is one script in one direction. Clusters
are UTF-16 indexes into text; the characters around the run are context for joining scripts.
public static void ShapeRun(ReadOnlySpan<char> text, int start, int length, Font font, RunProperties properties, GlyphBuffer buffer)
Parameters
textReadOnlySpan<char>The text the run is part of.
startintThe index of the run's first UTF-16 unit.
lengthintThe number of UTF-16 units in the run.
fontFontThe font and size; positions are in its units.
propertiesRunPropertiesThe run's script, language, direction, features and cluster level.
bufferGlyphBufferReceives the glyphs in visual order.
Exceptions
- ArgumentNullException
bufferis null, orfonthas no typeface.- ArgumentOutOfRangeException
The run is not inside
text.