///|
priv struct WebFontRuntime {
mut generation : UInt
mut metrics_revision : UInt
mut dom_ready_generation : UInt?
mut bytes_ready_generation : UInt?
}
///|
let web_font_runtimes : Map[String, WebFontRuntime] = Map([])
///|
fn web_font_runtime(family : String) -> WebFontRuntime {
web_font_runtimes.get_or_init(family, () => {
generation: 0U,
metrics_revision: 0U,
dom_ready_generation: None,
bytes_ready_generation: None,
})
}
///|
fn begin_web_font_load(family : String) -> UInt {
let runtime = web_font_runtime(family)
runtime.generation += 1U
runtime.dom_ready_generation = None
runtime.bytes_ready_generation = None
runtime.generation
}
///|
fn web_font_load_is_current(family : String, generation : UInt) -> Bool {
web_font_runtime(family).generation == generation
}
///|
/// Invalidates both the MoonBit layout cache and GPU textures because a
/// family may switch from browser fallback metrics to Cosmic metrics.
fn invalidate_web_font_metrics() -> Unit {
cosmic_text_cache.clear()
webgpu_clear_text_textures()
}
///|
/// The DOM face provides a valid Canvas fallback while the font bytes are
/// still being prepared for Cosmic rendering.
fn mark_web_font_dom_ready(family : String, generation : UInt) -> Unit {
let runtime = web_font_runtime(family)
guard runtime.generation == generation else { return }
guard runtime.dom_ready_generation != Some(generation) else { return }
runtime.dom_ready_generation = Some(generation)
if runtime.bytes_ready_generation != Some(generation) {
runtime.metrics_revision += 1U
invalidate_web_font_metrics()
}
}
///|
/// Cosmic metrics are the canonical WebGPU measurement and rendering source.
fn mark_web_font_bytes_ready(family : String, generation : UInt) -> Unit {
let runtime = web_font_runtime(family)
guard runtime.generation == generation else { return }
guard runtime.bytes_ready_generation != Some(generation) else { return }
runtime.bytes_ready_generation = Some(generation)
runtime.metrics_revision += 1U
invalidate_web_font_metrics()
}
///|
pub fn font_metrics_revision(family : String) -> UInt {
web_font_runtime(family).metrics_revision
}
///|
pub fn load_font(family : String, path : String) -> Unit {
let resolved_path = resolve_asset_path(path)
let generation = begin_web_font_load(family)
load_font_async(
family,
resolved_path,
fn() { web_font_load_is_current(family, generation) },
fn() { mark_web_font_dom_ready(family, generation) },
fn(_message) { () },
)
webgpu_preload_font_bytes(
family,
resolved_path,
fn() { web_font_load_is_current(family, generation) },
fn() { mark_web_font_bytes_ready(family, generation) },
fn(_message) { () },
)
}