merman-render 0.8.0-alpha.4

Headless layout + SVG renderer for Mermaid (parity-focused; upstream SVG goldens).
Documentation
// Generated by `xtask gen-font-metrics` from reusable browser font/DOM probes.
// Fixture ids and complete-text answers are intentionally excluded.
// Binary schema: MRMFNT05 (little-endian).
// Binary bytes: 899158.
// SHA-256: 5a40f3db0401cc244e9b6495466140a257249f0bdd9a8719cf0498a04740890b.
// Browser probe: Chrome 131.0.6778.204.
// SVG vertical profiles: exact DOM-shape bbox facts at integer sizes 1..=64px; explicitly approximate 1024px-scaled fallback outside the canonical domain.
// - courier Regular: chars=100, pairs=8836, spaces=8836, trigrams=0, left-overhangs=5, right-overhangs=5, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=175
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=239
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=246
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=251
// - courier Bold: chars=100, pairs=8836, spaces=8836, trigrams=0, left-overhangs=6, right-overhangs=9, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=163
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=227
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=234
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=239
// - courier Italic: chars=100, pairs=8836, spaces=8836, trigrams=0, left-overhangs=2, right-overhangs=100, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=175
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=239
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=246
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=251
// - courier BoldItalic: chars=100, pairs=8836, spaces=8836, trigrams=0, left-overhangs=5, right-overhangs=97, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=163
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=227
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=234
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=239
// - helveticaneue,helvetica,sans-serif Regular: chars=100, pairs=5025, spaces=7220, trigrams=0, left-overhangs=6, right-overhangs=9, vertical-glyphs=100
//   raw-text: capability=profiled-approximate-composition, pair-union-max-delta-px=9.536743181826068e-7, sizes=64, buckets=174
//   single-tspan: capability=profiled-approximate-composition, pair-union-max-delta-px=9.536743181826068e-7, sizes=64, buckets=238
//   create-formatted-text: capability=profiled-approximate-composition, pair-union-max-delta-px=9.536743146298932e-7, sizes=64, buckets=240
//   create-formatted-text-middle: capability=profiled-approximate-composition, pair-union-max-delta-px=9.536743146298932e-7, sizes=64, buckets=248
// - helveticaneue,helvetica,sans-serif Bold: chars=100, pairs=3887, spaces=6580, trigrams=0, left-overhangs=11, right-overhangs=13, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=118
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=182
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=184
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=190
// - helveticaneue,helvetica,sans-serif Italic: chars=100, pairs=5655, spaces=7707, trigrams=0, left-overhangs=32, right-overhangs=36, vertical-glyphs=100
//   raw-text: capability=profiled-approximate-composition, pair-union-max-delta-px=9.536743181826068e-7, sizes=64, buckets=157
//   single-tspan: capability=profiled-approximate-composition, pair-union-max-delta-px=9.536743181826068e-7, sizes=64, buckets=221
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=225
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=229
// - helveticaneue,helvetica,sans-serif BoldItalic: chars=100, pairs=4490, spaces=7107, trigrams=0, left-overhangs=100, right-overhangs=47, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=120
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=184
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=184
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=190
// - sans-serif Regular: chars=100, pairs=3780, spaces=7906, trigrams=0, left-overhangs=3, right-overhangs=5, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=117
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=181
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=188
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=195
// - sans-serif Bold: chars=100, pairs=4803, spaces=8284, trigrams=0, left-overhangs=7, right-overhangs=6, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=145
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=209
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=216
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=223
// - sans-serif Italic: chars=100, pairs=3779, spaces=7906, trigrams=0, left-overhangs=10, right-overhangs=97, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=148
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=212
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=219
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=226
// - sans-serif BoldItalic: chars=100, pairs=4803, spaces=8284, trigrams=0, left-overhangs=10, right-overhangs=100, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=128
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=192
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=199
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=206
// - trebuchetms,verdana,arial,sans-serif Regular: chars=100, pairs=1046, spaces=5176, trigrams=0, left-overhangs=2, right-overhangs=4, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=103
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=167
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=171
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=178
// - trebuchetms,verdana,arial,sans-serif Bold: chars=100, pairs=1226, spaces=5473, trigrams=0, left-overhangs=3, right-overhangs=6, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=123
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=187
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=191
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=198
// - trebuchetms,verdana,arial,sans-serif Italic: chars=100, pairs=1089, spaces=5115, trigrams=0, left-overhangs=13, right-overhangs=41, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=136
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=200
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=204
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=211
// - trebuchetms,verdana,arial,sans-serif BoldItalic: chars=100, pairs=1426, spaces=5756, trigrams=0, left-overhangs=14, right-overhangs=30, vertical-glyphs=100
//   raw-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=130
//   single-tspan: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=194
//   create-formatted-text: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=198
//   create-formatted-text-middle: capability=exact, pair-union-max-delta-px=0.0, sizes=64, buckets=205

use crate::text::{FontMetricsTable, FontMetricsVariant, decode_font_metrics_tables};
use std::sync::OnceLock;

const PROFILE_BYTES: &[u8] = include_bytes!("mermaid_font_metrics_11_16_0.bin");
static FONT_METRICS_TABLES: OnceLock<&'static [FontMetricsTable]> = OnceLock::new();

fn font_metrics_tables() -> &'static [FontMetricsTable] {
    FONT_METRICS_TABLES.get_or_init(|| {
        decode_font_metrics_tables(PROFILE_BYTES)
            .unwrap_or_else(|error| panic!("invalid generated font metrics profile: {error}"))
    })
}

pub fn lookup_font_metrics(
    font_key: &str,
    variant: FontMetricsVariant,
) -> Option<&'static FontMetricsTable> {
    FontMetricsTable::lookup(font_metrics_tables(), font_key, variant)
}

pub fn lookup_exact_font_metrics(
    font_key: &str,
    variant: FontMetricsVariant,
) -> Option<&'static FontMetricsTable> {
    FontMetricsTable::lookup_exact(font_metrics_tables(), font_key, variant)
}