moonbitlang/pagelayout/fonts does not have a README file

    FaceMetricsError

    pub(all) suberror FaceMetricsError {
    InvalidFaceMetrics(String)
    } derive(Eq)

    Why FaceMetrics::new refused its arguments.

    FaceMetricsError::equal

    FaceMetricsError::not_equal

    fn FaceMetricsError::not_equal(x : FaceMetricsError, y : FaceMetricsError) -> Bool

    FaceMetricsError::output

    fn FaceMetricsError::output(self : FaceMetricsError, logger : &Logger) -> Unit

    FaceMetricsError::to_string

    fn FaceMetricsError::to_string(self : FaceMetricsError) -> String

    FontRegistryError

    pub(all) suberror FontRegistryError {
    Sealed(String)
    Duplicate(String)
    UnsupportedStandard(String)
    } derive(Eq)

    Why a FontRegistry refused a face.

    FontRegistryError::equal

    FontRegistryError::not_equal

    fn FontRegistryError::not_equal(x : FontRegistryError, y : FontRegistryError) -> Bool

    FontRegistryError::output

    fn FontRegistryError::output(self : FontRegistryError, logger : &Logger) -> Unit

    FontRegistryError::to_string

    fn FontRegistryError::to_string(self : FontRegistryError) -> String

    FaceMetrics

    pub struct FaceMetrics {
    family : String
    bold : Bool
    italic : Bool
    units_per_em : Int
    ascender : Int
    descender : Int
    line_gap : Int
    // private fields
    }

    Metrics of one face, bundled or registered. For a face parsed from an sfnt the vertical metrics come from hhea; one built with FaceMetrics::new carries what it was given (an AFM's, say). Advances are raw font units scaled by units_per_em on lookup.

    A face is immutable. Its glyph tables are private and read through glyph_id, cmap_entries and advance_pt, because the same value is shared by every lookup — the bundled cache, a FontRegistry, the layout that measured with it and the renderer that draws with it — and a change made through one of them would silently reach all the others.

    FaceMetrics::advance_pt

    fn FaceMetrics::advance_pt(self : FaceMetrics, codepoint : Int, size_pt : Double) -> Double

    Horizontal advance of codepoint at size_pt, in points. Codepoints missing from the face use the .notdef (glyph 0) advance; glyphs past numberOfHMetrics share the table's final advance, per TrueType.

    FaceMetrics::ascent_pt

    fn FaceMetrics::ascent_pt(self : FaceMetrics, size_pt : Double) -> Double

    Baseline-to-top extent at size_pt, in points (positive).

    FaceMetrics::cmap_entries

    fn FaceMetrics::cmap_entries(self : FaceMetrics) -> Iter2[Int, Int]

    Every (codepoint, glyph) pair of the face's cmap, in no particular order. The pairs are read from the face; nothing done with them can reach it.

    FaceMetrics::descent_pt

    fn FaceMetrics::descent_pt(self : FaceMetrics, size_pt : Double) -> Double

    Baseline-to-bottom extent at size_pt, in points (negative, per hhea).

    FaceMetrics::glyph_id

    fn FaceMetrics::glyph_id(self : FaceMetrics, codepoint : Int) -> Int?

    The glyph codepoint maps to in the face's cmap, or None when it maps to none. A mapping to glyph 0 (.notdef) is reported as it is; see has_char for whether the face can really draw the character.

    FaceMetrics::has_char

    fn FaceMetrics::has_char(self : FaceMetrics, codepoint : Int) -> Bool

    Whether the face maps codepoint to a real glyph.

    FaceMetrics::line_height_pt

    fn FaceMetrics::line_height_pt(self : FaceMetrics, size_pt : Double) -> Double

    Single line spacing at size_pt: ascender − descender + line gap.

    FaceMetrics::new

    fn FaceMetrics::new(family~ : String, bold? : Bool, italic? : Bool, units_per_em~ : Int, ascender~ : Int, descender~ : Int, line_gap~ : Int, advances~ : Array[Int], cmap~ : Map[Int, Int]) -> FaceMetrics raise FaceMetricsError

    Metrics given outright rather than parsed from an sfnt: for a face whose metrics come from elsewhere, such as the AFM metrics of a PDF standard font (see FontRegistry::register_standard). advances are indexed by glyph, in units of units_per_em; cmap maps codepoints to glyphs. Both tables are copied, so changing them afterwards cannot reach the face.

    Preconditions, checked (raising FaceMetricsError when one fails), so that every measurement of the face is a finite number and no lookup can fall outside a table:

    • units_per_em is positive;
    • advances is not empty, and no advance is negative;
    • every cmap key is a codepoint (0 to 0x10FFFF), and every glyph it maps to indexes advances (0 ≤ glyph < advances.length()).

    A character the cmap lacks measures as glyph 0 (.notdef), as in any face; has_char reports it missing. The vertical metrics are taken as given (font units, descender negative below the baseline).

    FontRegistry

    pub struct FontRegistry {
    // private fields
    }

    A set of faces registered by the caller, consulted before the bundled ones. See the module comment for its open/sealed lifetime.

    FontRegistry::cjk_fallback

    fn FontRegistry::cjk_fallback(self : FontRegistry, bold? : Bool, italic? : Bool) -> FaceMetrics

    The face for CJK codepoints the requested face lacks, as this registry resolves it: the fallback family (Noto Sans SC) through face, so a registered face of that family is the fallback — style fallback included — and shadows the bundled one entirely. Seals.

    This is exactly the face a renderer resolves for a run the layout placed in the fallback family with this style, so a fallback character is measured with the metrics it is drawn with. When the registered fallback lacks a character, the bundled one is not consulted: a run cannot name it apart from the registered face. See uncovered.

    FontRegistry::default

    #deprecated("implicit trait-method promotion is being removed; call via the trait")
    fn FontRegistry::default() -> FontRegistry

    FontRegistry::face

    fn FontRegistry::face(self : FontRegistry, family : String, bold? : Bool, italic? : Bool) -> FaceMetrics

    The metrics for a family name as resolve_family returns it: the registered face (see registered_face for style fallback), else the bundled one (see the package-level face). Seals.

    FontRegistry::is_registered

    fn FontRegistry::is_registered(self : FontRegistry, family : String) -> Bool

    Whether any face of family (matched exactly) is registered. Seals.

    FontRegistry::is_sealed

    fn FontRegistry::is_sealed(self : FontRegistry) -> Bool

    Whether the registry has stopped accepting faces.

    FontRegistry::new

    An empty, open registry. With nothing registered it resolves exactly as the package-level functions do: bundled faces only.

    FontRegistry::register

    fn FontRegistry::register(self : FontRegistry, family : String, sfnt : Bytes, bold? : Bool, italic? : Bool) -> FaceMetrics raise

    Register a face from a complete, uncompressed sfnt (a .ttf file's bytes) and return its metrics. Metrics and program are registered together, from the same bytes.

    A registered family resolves to itself (matched exactly, case and all) and shadows a bundled family of the same name — Noto Sans SC, the CJK fallback, included (see cjk_fallback). Raises FontRegistryError when the registry is sealed or the face is already registered, and a parse error when the bytes are not a usable sfnt.

    FontRegistry::register_standard

    fn FontRegistry::register_standard(self : FontRegistry, family : String, metrics : FaceMetrics, standard~ : String, bold? : Bool, italic? : Bool) -> FaceMetrics raise FontRegistryError

    Register a PDF standard font under family and return the metrics layout will measure it with. standard is its PostScript name, one of the twelve Latin faces of standard_fonts (Helvetica, Helvetica-Bold, Times-Roman, Courier-Oblique, ...); metrics are its metrics, built with FaceMetrics::new from the font's AFM.

    A PDF declares the font by name as a Type1 font with /WinAnsiEncoding and embeds nothing, so a viewer draws it with its own copy of the font and advances each glyph by that copy's width. Its text is encoded over the whole of WinAnsi (0x80–0x9F included: €, ’, ™, ...); characters WinAnsi lacks are dropped, their advances kept. For glyphs to land where the layout put them, metrics must measure each character WinAnsi encodes with the font's AFM width: conventionally a cmap from each such character to its WinAnsi code and advances indexed by code, at 1000 units per em. Kerning is not part of the metrics; a caller that kerns puts the kerned advances in its runs (GlyphRun::advances_pt) and the renderer shows the difference as a displacement.

    Like register, the face is registered under family and the style given: the returned metrics are metrics with that family, bold and italic (the tables unchanged), so that a run laid out with them names the registered family and is drawn in this face — not in whatever metrics.family (say Helvetica) would otherwise resolve to.

    Raises FontRegistryError when the registry is sealed, the face is already registered, or standard is not a supported name (UnsupportedStandard).

    FontRegistry::registered_face

    fn FontRegistry::registered_face(self : FontRegistry, family : String, bold? : Bool, italic? : Bool) -> RegisteredFace?

    The registered face that stands for family in the requested style, or None when no face of family is registered. Seals.

    A missing style falls back within the family, never outside it: the exact face, then the face without italic, then without bold, then the regular face, then whichever face the family does have. Metrics and program always come from that one face, so a document asking for a style the catalog lacks is measured and drawn in the same substitute.

    FontRegistry::resolve_family

    fn FontRegistry::resolve_family(self : FontRegistry, name : String) -> String

    resolve_family, with registered families passed through unchanged. Seals.

    FontRegistry::seal

    fn FontRegistry::seal(self : FontRegistry) -> Unit

    Stop accepting faces. Every lookup does this implicitly; calling it makes the point explicit (before sharing the registry, say).

    FontRegistry::uncovered

    fn FontRegistry::uncovered(self : FontRegistry, text : String, family : String, bold? : Bool, italic? : Bool) -> Array[(Int, Int)]

    The package-level uncovered, asked of this registry's faces: the requested face as face resolves it, then cjk_fallback in the same style — the two faces layout measures with. Seals.

    RegisteredFace

    pub struct RegisteredFace {
    metrics : FaceMetrics
    program : Bytes?
    standard : String?
    }

    One registered face: the metrics layout measures with and how a PDF draws it. A face registered from an sfnt (register) takes both its metrics and its program from the same bytes, so that they cannot disagree about glyph ids or widths. A standard font (register_standard) has no program: the viewer draws it with its own copy of the font, whose widths the metrics must be (see register_standard).

    bundled_families

    fn bundled_families() -> Array[String]

    Every bundled family, in registry order (deduplicated).

    cjk_fallback

    fn cjk_fallback() -> FaceMetrics

    The face used for CJK codepoints the Latin faces lack.

    face

    fn face(family : String, bold? : Bool, italic? : Bool) -> FaceMetrics

    The bundled face for a resolved family name (see resolve_family). Falls back to the family's regular face when the exact bold/italic face is not bundled (Noto Sans SC ships regular only), then to Carlito. The face returned says which one it is (family, bold, italic), so a caller that needs the matching font program can ask for exactly that face. For registered faces see FontRegistry::face.

    resolve_family

    fn resolve_family(name : String) -> String

    Map a document-authored family name to a bundled family. Matching is case-insensitive. Metric-compatible pairs: Calibri→Carlito, Arial→Liberation Sans, Times New Roman→Liberation Serif, Courier New→Liberation Mono. CJK families map to Noto Sans SC. Only bundled families come out; FontRegistry::resolve_family also passes a registered family through.

    standard_fonts

    fn standard_fonts() -> Array[String]

    The PDF standard fonts FontRegistry::register_standard accepts, by PostScript name: the twelve Latin faces of Helvetica, Times and Courier, all declared with /WinAnsiEncoding. The two symbolic standard fonts, Symbol and ZapfDingbats, are not among them: their text would be encoded in each font's own built-in encoding (Prawn omits /Encoding for them), which the renderer does not implement.

    uncovered

    fn uncovered(text : String, family : String, bold? : Bool, italic? : Bool) -> Array[(Int, Int)]

    Codepoints in text that the face this run is set in cannot draw, counted.

    This asks the same question layout asks, and in the same order: the requested face, then the CJK fallback. Asking the whole bundle instead would under-report, because layout never reaches a third family — U+05D0 lives in Liberation but not in Carlito or Noto Sans SC, so Hebrew in a Carlito run is dropped even though some bundled face has the glyph.

    A character neither face covers is measured with .notdef and then dropped by the backends: a simple font cannot encode it, and a composite font would draw a blank box at the wrong width. That is a silent loss worth reporting — a document whose evidence ratings or equation variables are missing still renders, still validates, and is still wrong.