rocketsplash-rt 0.3.0

Runtime library for loading and rendering Rocketsplash assets (.rst, .rsf)
Documentation
// <FILE>crates/rocketsplash-rt/src/font/fnc_load_font.rs</FILE>
// <DESC>Font deserialization and validation</DESC>
// <VERS>VERSION: 2.0.0</VERS>
// <WCTX>Foundation crates 0.3.0 (RELEASE_PLAN D3 hardening, F2 cycle-break)</WCTX>
// <CLOG>2.0.0: delegate decode/version/structural checks to rocketsplash_formats::read_font_atlas; house Font::load/from_bytes here so cls_font stays a leaf; direct sibling imports. 1.1.0: extract glyph conversion helper.</CLOG>

use std::collections::BTreeMap;
use std::path::Path;

use log::debug;
use rocketsplash_formats::{read_font_atlas, AllocationTracker, GlyphData, GlyphVariants};

use super::cls_font::{Font, RuntimeGlyph, RuntimeGlyphVariants};
use super::fnc_convert_glyph::convert_glyph;
use crate::Error;

impl Font {
    pub fn load(path: impl AsRef<Path>) -> Result<Self, Error> {
        let bytes = std::fs::read(path)?;
        load_font_from_bytes(&bytes)
    }

    pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
        load_font_from_bytes(bytes)
    }
}

pub fn load_font_from_bytes(bytes: &[u8]) -> Result<Font, Error> {
    // read_font_atlas enforces the size cap, version window, glyph count,
    // line height, and per-glyph structure (RELEASE_PLAN D3).
    let atlas = read_font_atlas(bytes)?;

    let mut tracker = AllocationTracker::new();
    let mut glyphs = BTreeMap::new();
    for (ch, variants) in atlas.glyphs {
        let runtime_variants = convert_variants(&mut tracker, variants)?;
        glyphs.insert(ch, runtime_variants);
    }

    debug!("Loaded font atlas with {} glyphs", glyphs.len());

    Ok(Font {
        meta: atlas.meta,
        line_height: atlas.line_height,
        mode: atlas.mode,
        available_styles: atlas.available_styles,
        glyphs,
    })
}

fn convert_variants(
    tracker: &mut AllocationTracker,
    variants: GlyphVariants,
) -> Result<RuntimeGlyphVariants, Error> {
    Ok(RuntimeGlyphVariants {
        base: convert_glyph(tracker, variants.base)?,
        bold: convert_optional(tracker, variants.bold)?,
        italic: convert_optional(tracker, variants.italic)?,
        bold_italic: convert_optional(tracker, variants.bold_italic)?,
        reverse: convert_optional(tracker, variants.reverse)?,
    })
}

fn convert_optional(
    tracker: &mut AllocationTracker,
    glyph: Option<GlyphData>,
) -> Result<Option<RuntimeGlyph>, Error> {
    glyph.map(|value| convert_glyph(tracker, value)).transpose()
}

// <FILE>crates/rocketsplash-rt/src/font/fnc_load_font.rs</FILE>
// <VERS>END OF VERSION: 2.0.0</VERS>