# `tecs.gfx.truetype` TrueType outlines, metrics, coverage rasterization, and signed distance fields. A face is parsed once from the bytes of a `.ttf` or `.ttc`-free single-font file and answers three questions: which glyph a codepoint selects, what that glyph advances, and where its outline runs. `rasterize` turns one outline into an antialiased coverage bitmap and `distanceField` turns that bitmap into the field a distance-field text shader samples. ```nupp const face, reason = tecs.gfx.truetype.parse(bytes) assert(face, reason) const glyph = face:glyphIndex(0x41) const contours = tecs.gfx.truetype.outline(face, glyph, 48.0 / face.unitsPerEm) ``` Everything here works in font units until a scale is supplied. A font unit is one of `unitsPerEm` divisions of the em square, so dividing by `unitsPerEm` gives em units and multiplying those by a point size gives pixels. Only the `glyf` outline format is read. A face whose outlines live in a `CFF ` table, which is what an OpenType font built from PostScript curves carries, parses to a failure reason rather than to empty glyphs. Kerning comes from a format-zero `kern` table when one is present; `GPOS` positioning is not read, so a font that kerns only through `GPOS` lays out with its advance widths alone. ## Types ### `Face` _record_ ```nupp record Face unitsPerEm: integer ascender: integer descender: integer lineGap: integer numGlyphs: integer glyphIndex: function(borrows self: Face, codepoint: integer): integer advanceOf: function(borrows self: Face, glyph: integer): number bearingOf: function(borrows self: Face, glyph: integer): number kerningOf: function(exclusive self: Face, left: integer, right: integer): number end ``` A parsed font file. Immutable once `parse` returns, apart from the kerning table it fills in on first use. #### Methods ##### `glyphIndex` ```nupp glyphIndex: function(borrows self: Face, codepoint: integer): integer ``` Returns the glyph one codepoint selects. Zero is the `.notdef` glyph rather than an error, which is the glyph a font draws for a character it does not carry, so a caller renders it instead of branching. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `borrows self` | `Face` | | | `codepoint` | `integer` | | ###### Returns | Type | Description | | --- | --- | | `integer` | | ##### `advanceOf` ```nupp advanceOf: function(borrows self: Face, glyph: integer): number ``` Returns one glyph's horizontal advance in font units. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `borrows self` | `Face` | | | `glyph` | `integer` | | ###### Returns | Type | Description | | --- | --- | | `number` | | ##### `bearingOf` ```nupp bearingOf: function(borrows self: Face, glyph: integer): number ``` Returns one glyph's left side bearing in font units. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `borrows self` | `Face` | | | `glyph` | `integer` | | ###### Returns | Type | Description | | --- | --- | | `number` | | ##### `kerningOf` ```nupp kerningOf: function(exclusive self: Face, left: integer, right: integer): number ``` Returns the kerning between two glyphs in font units. Reads the pairs on first use and keeps them, because a face that kerns is asked about most of its adjacent pairs within one line of text. ###### Arguments | Name | Type | Description | | --- | --- | --- | | `exclusive self` | `Face` | | | `left` | `integer` | | | `right` | `integer` | | ###### Returns | Type | Description | | --- | --- | | `number` | | #### Fields ##### `unitsPerEm` ```nupp unitsPerEm: integer ``` Read-only. Reports the em square's divisions, which every font unit in this face is one of. ##### `ascender` ```nupp ascender: integer ``` Read-only. Reports the distance from the baseline to the top of the typographic ascent, in font units. ##### `descender` ```nupp descender: integer ``` Read-only. Reports the distance from the baseline to the bottom of the typographic descent, in font units. It is negative in every ordinary font. ##### `lineGap` ```nupp lineGap: integer ``` Read-only. Reports the extra leading between two lines, in font units. ##### `numGlyphs` ```nupp numGlyphs: integer ``` Read-only. Reports how many glyphs the face holds, including `.notdef` at index zero. ### `Outline` _type_ ```nupp type Outline = {{number}} ``` One glyph outline, as closed contours of flattened points. Each contour is a flat array of alternating x and y in font units, with y increasing upward the way the font file stores it. The last point joins the first; the closing segment is not repeated. ## Functions ### `distanceField` _function_ ```nupp function distanceField(coverage: {integer}, width: integer, height: integer, spread: number): {integer} ``` Turns one coverage bitmap into a signed distance field. The field is stored the way a distance-field shader expects it: `0.5` sits on the outline, values above it are inside, and one texel of distance is `0.5 / spread` of the stored range. A shader recovers coverage by smoothstepping around `0.5`. Distance comes from a two-pass sequential Euclidean transform over the thresholded coverage, which is exact for the texel centers it visits and within a fraction of a texel elsewhere. That is well inside what a spread of several texels can represent. #### Arguments | Name | Type | Description | | --- | --- | --- | | `coverage` | `{integer}` | the bitmap `rasterize` produced | | `width` | `integer` | the bitmap width in texels | | `height` | `integer` | the bitmap height in texels | | `spread` | `number` | the distance in texels the field reaches on each side of the outline, which must be positive | #### Returns | Type | Description | | --- | --- | | `{integer}` | a `width` times `height` array of field values from zero to 255, indexed from one, which the caller owns | ### `outline` _function_ ```nupp function outline(self: Face, glyph: integer, scale: number): Outline, number, number, number, number ``` Returns one glyph's flattened outline and its bounding box. The box comes from the flattened points rather than from the glyph header, so it encloses exactly what `rasterize` will fill. An empty glyph, which is what a space is, returns no contours and a zero box. #### Arguments | Name | Type | Description | | --- | --- | --- | | `self` | `Face` | the parsed face | | `glyph` | `integer` | the glyph index | | `scale` | `number` | the font units to pixels factor the flattening is tuned for | #### Returns | Type | Description | | --- | --- | | `Outline` | the contours, in font units with y increasing upward | | `number` | the smallest x, then the smallest y, then the largest x, then the largest y, all in font units | | `number` | | | `number` | | | `number` | | ### `parse` _function_ ```nupp function parse(bytes: string): Face?, string? ``` Parses a single-font TrueType file. #### Arguments | Name | Type | Description | | --- | --- | --- | | `bytes` | `string` | the complete contents of a `.ttf` or `.otf` file | #### Returns | Type | Description | | --- | --- | | `Face?` | the face, or nil when the bytes are not a readable TrueType font | | `string?` | why the bytes were rejected, when unsuccessful | ### `rasterize` _function_ ```nupp function rasterize(contours: Outline, width: integer, height: integer, originX: number, originY: number, scale: number): {integer} ``` Fills one outline into an antialiased coverage bitmap. The bitmap runs left to right and top to bottom, so it uploads as image rows without a flip. Font y increases upward and texel y increases downward, which is the only place the two conventions meet. #### Arguments | Name | Type | Description | | --- | --- | --- | | `contours` | `Outline` | the flattened contours, in font units | | `width` | `integer` | the bitmap width in texels, which must be positive | | `height` | `integer` | the bitmap height in texels, which must be positive | | `originX` | `number` | the font-unit x that lands on the bitmap's left edge | | `originY` | `number` | the font-unit y that lands on the bitmap's top edge | | `scale` | `number` | the font units to texels factor | #### Returns | Type | Description | | --- | --- | | `{integer}` | a `width` times `height` array of coverage from zero to 255, indexed from one, which the caller owns |