use crate::render::text::font_assets::cjk_shards::shard_for;
use crate::render::text::runtime_fonts::{register_face, registered_face_count, MAX_RUNTIME_FACES};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ShardLoad {
Loaded,
NotInThisBuild,
NotCovered,
RegistryFull,
}
pub fn load_shard_for(ch: char) -> ShardLoad {
let Some(shard) = shard_for(ch) else {
return ShardLoad::NotCovered;
};
if shard.bytes.is_empty() {
return ShardLoad::NotInThisBuild;
}
if registered_face_count() > 0 && shard_is_registered(shard.id) {
return ShardLoad::Loaded;
}
if register_face(shard.name, shard.bytes) {
ShardLoad::Loaded
} else if registered_face_count() >= MAX_RUNTIME_FACES {
ShardLoad::RegistryFull
} else {
ShardLoad::NotInThisBuild
}
}
fn shard_is_registered(id: &str) -> bool {
let (runtime, len) = crate::render::text::runtime_fonts::active_runtime_faces();
runtime[..len].iter().any(|face| face.name.contains(id))
}
pub fn load_shards_for_text(text: &str) -> usize {
let mut loaded_ids: crate::compat::Vec<&'static str> = crate::compat::Vec::new();
for ch in text.chars() {
if let Some(shard) = shard_for(ch) {
if !shard.bytes.is_empty() && !loaded_ids.contains(&shard.id) {
loaded_ids.push(shard.id);
}
}
}
let mut loaded = 0;
for shard in crate::render::text::font_assets::cjk_shards::active_shards() {
if loaded_ids.contains(&shard.id)
&& load_shard_for_byte_shape(shard.name, shard.bytes) == ShardLoad::Loaded
{
loaded += 1;
}
}
loaded
}
fn load_shard_for_byte_shape(name: &'static str, bytes: &'static [u8]) -> ShardLoad {
if register_face(name, bytes) {
ShardLoad::Loaded
} else if registered_face_count() >= MAX_RUNTIME_FACES {
ShardLoad::RegistryFull
} else {
ShardLoad::NotInThisBuild
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::render::text::font_assets::cjk_shards::{active_shards, SHARDS};
use crate::render::text::{clear_faces, registered_face_count};
#[test]
fn the_shard_ranges_partition_the_coverage() {
let mut previous_high = 0u32;
for shard in SHARDS {
let (low, high) = shard.range;
assert!(low <= high, "shard {} has an inverted range", shard.id);
assert!(
low > previous_high,
"shard {} starts at U+{low:04X}, at or below the previous shard's end U+{previous_high:04X}",
shard.id
);
previous_high = high;
}
for shard in SHARDS {
let (low, high) = shard.range;
let low_char = char::from_u32(low).expect("a shard's first codepoint is a scalar");
let high_char = char::from_u32(high).expect("a shard's last codepoint is a scalar");
assert_eq!(shard_for(low_char).map(|s| s.id), Some(shard.id));
assert_eq!(shard_for(high_char).map(|s| s.id), Some(shard.id));
}
assert!(shard_for('\u{E000}').is_none());
}
#[test]
fn a_carried_shard_loads_once_and_is_then_resident() {
clear_faces();
let carried: crate::compat::Vec<_> = active_shards().collect();
if carried.is_empty() {
let any = SHARDS.first().expect("the shard table is never empty");
let ch = char::from_u32(any.range.0).expect("scalar");
assert_eq!(load_shard_for(ch), ShardLoad::NotInThisBuild);
assert_eq!(registered_face_count(), 0);
return;
}
let shard = carried[0];
let ch = char::from_u32(shard.range.0).expect("scalar");
assert_eq!(load_shard_for(ch), ShardLoad::Loaded, "a carried shard must load");
assert_eq!(registered_face_count(), 1);
assert_eq!(load_shard_for(ch), ShardLoad::Loaded);
assert_eq!(registered_face_count(), 1, "re-loading must not add a second face");
clear_faces();
assert_eq!(registered_face_count(), 0);
}
}