Implement basic font fallbacks for WASM and macOS

Our demos use some symbols such as the back arrow and the ugly style
uses a down arrow for the combo box. These symbols are not in Roboto and
also not in the default font font_kit gives us on macOS.

Therefore for WASM we switch over to DejaVu, which is bigger than
Roboto.

For macOS this patch implements rudimentary fallback list generation
using CTFontCopyDefaultCascadeListForLanguages. This needs further work
to respect the locale and correctly translate styles - eventually this
should go into font-kit.

A general aspect with the font fallback handling is that femtovg doesn't
support on-demand loading yet. Instead it uses owned_ttf_parser, so
every font will be read entirely off disk. That's why for macOS we trim
the list. We could perhaps do the analysis ourselves.

Linux and Windows are to follow.
This commit is contained in:
Simon Hausmann 2021-01-13 15:58:56 +01:00
parent cd1ef1c80e
commit de67b865dc
11 changed files with 253 additions and 271 deletions

View file

@ -92,25 +92,32 @@ pub use fonts_wasm::register_application_font_from_memory;
use fonts_wasm::*;
impl FontCache {
fn load_single_font(&mut self, canvas: &CanvasRc, request: &FontRequest) -> femtovg::FontId {
self.0
.entry(FontCacheKey { family: request.family.clone(), weight: request.weight.unwrap() })
.or_insert_with(|| {
try_load_app_font(canvas, &request)
.unwrap_or_else(|| load_system_font(canvas, &request))
})
.clone()
}
fn font(&mut self, canvas: &CanvasRc, mut request: FontRequest, scale_factor: f32) -> GLFont {
request.pixel_size = request.pixel_size.or(Some(DEFAULT_FONT_SIZE * scale_factor));
request.weight = request.weight.or(Some(DEFAULT_FONT_WEIGHT));
GLFont {
fonts: smallvec::smallvec![self
.0
.entry(FontCacheKey {
family: request.family.clone(),
weight: request.weight.unwrap(),
})
.or_insert_with(|| {
try_load_app_font(canvas, &request)
.unwrap_or_else(|| load_system_font(canvas, &request))
})
.clone()],
canvas: canvas.clone(),
pixel_size: request.pixel_size.unwrap(),
}
let primary_font = self.load_single_font(canvas, &request);
let fallbacks = font_fallbacks_for_request(&request);
let fonts = core::iter::once(primary_font)
.chain(
fallbacks
.iter()
.map(|fallback_request| self.load_single_font(canvas, &fallback_request)),
)
.collect::<Vec<_>>();
GLFont { fonts, canvas: canvas.clone(), pixel_size: request.pixel_size.unwrap() }
}
}
@ -861,7 +868,7 @@ struct FontCacheKey {
}
struct GLFont {
fonts: smallvec::SmallVec<[femtovg::FontId; 4]>,
fonts: Vec<femtovg::FontId>,
pixel_size: f32,
canvas: CanvasRc,
}