Fix some missing glyphs in the slide puzzle on stm32h7

Implement some very rudimentary font fallback handling and add some the
glyphs the puzzle needs.

The font fallback handling deserves to go into a module shared between
GL backend and the compiler.

For the character selection we should scan the text elements for
literals just like we do for the font size.
This commit is contained in:
Simon Hausmann 2022-06-10 18:20:14 +02:00 committed by Simon Hausmann
parent 3bc43cdcfa
commit 9f957e7db5

View file

@ -59,6 +59,40 @@ pub fn embed_glyphs<'a>(
fontdb.set_sans_serif_family(default_sans_serif_family);
}
let fallback_families = if cfg!(target_os = "macos") {
["Menlo", "Apple Symbols", "Apple Color Emoji"].iter()
} else if cfg!(not(any(
target_family = "windows",
target_os = "macos",
target_os = "ios",
target_arch = "wasm32"
))) {
["Noto Sans Symbols", "Noto Sans Symbols2", "DejaVu Sans"].iter()
} else {
[].iter()
};
let fallback_fonts = fallback_families
.filter_map(|fallback_family| {
fontdb
.query(&fontdb::Query {
families: &[fontdb::Family::Name(*fallback_family)],
..Default::default()
})
.and_then(|face_id| {
fontdb
.with_face_data(face_id, |face_data, face_index| {
fontdue::Font::from_bytes(
face_data,
fontdue::FontSettings { collection_index: face_index, scale: 40. },
)
.ok()
})
.flatten()
})
})
.collect::<Vec<_>>();
let fallback_font = fontdb
.query(&fontdb::Query { families: &[fontdb::Family::SansSerif], ..Default::default() })
.expect("internal error: Failed to locate default system font");
@ -142,7 +176,12 @@ pub fn embed_glyphs<'a>(
fontdue::FontSettings { collection_index: face_index, scale: 40. },
)
.expect("internal error: fontdb returned a font that ttf-parser/fontdue could not parse");
embed_font(fontdb.face(face_id).unwrap().family.clone(), font, &pixel_sizes)
embed_font(
fontdb.face(face_id).unwrap().family.clone(),
font,
&pixel_sizes,
&fallback_fonts,
)
})
.unwrap();
@ -177,7 +216,12 @@ pub fn embed_glyphs<'a>(
}
#[cfg(not(target_arch = "wasm32"))]
fn embed_font(family_name: String, font: fontdue::Font, pixel_sizes: &[i16]) -> BitmapFont {
fn embed_font(
family_name: String,
font: fontdue::Font,
pixel_sizes: &[i16],
fallback_fonts: &[fontdue::Font],
) -> BitmapFont {
// TODO: configure coverage
let coverage = ('a'..='z')
.chain('A'..='Z')
@ -202,7 +246,15 @@ fn embed_font(family_name: String, font: fontdue::Font, pixel_sizes: &[i16]) ->
glyph_data.resize(character_map.len(), Default::default());
for CharacterMapEntry { code_point, glyph_index } in &character_map {
let (metrics, bitmap) = font.rasterize(*code_point, *pixel_size as _);
let (metrics, bitmap) = core::iter::once(&font)
.chain(fallback_fonts.iter())
.find_map(|font| {
font.chars()
.contains_key(code_point)
.then(|| font.rasterize(*code_point, *pixel_size as _))
})
.unwrap_or_else(|| font.rasterize(*code_point, *pixel_size as _));
let glyph = BitmapGlyph {
x: i16::try_from(metrics.xmin).expect("large glyph x coordinate"),
y: i16::try_from(metrics.ymin).expect("large glyph y coordinate"),