diff --git a/core/src/html/layout.rs b/core/src/html/layout.rs index c4ef734e5..7ca634b94 100644 --- a/core/src/html/layout.rs +++ b/core/src/html/layout.rs @@ -486,6 +486,30 @@ impl<'a, 'gc> LayoutContext<'a, 'gc> { // return None; } + // For better compatibility we also match the font-family name usually + // used for that specific default font. + if let Some(default_font) = match font_name.deref() { + "_serif" | "Times New Roman" | "" => Some(DefaultFont::Serif), + "_sans" | "Arial" => Some(DefaultFont::Sans), + "_typewriter" | "Courier New" => Some(DefaultFont::Typewriter), + // [NA] I suspect that there might be undocumented more aliases. + // I think I've seen translated versions of these used in the wild... + _ => None, + } { + return context + .library + .default_font( + default_font, + span.bold, + span.italic, + context.ui, + context.renderer, + context.gc_context, + ) + .first() + .copied(); + } + if let Some(font) = context.library.get_or_load_device_font( &font_name, span.bold, @@ -497,19 +521,13 @@ impl<'a, 'gc> LayoutContext<'a, 'gc> { return Some(font); } - // [NA] I suspect that there might be undocumented more aliases. - // I think I've seen translated versions of these used in the wild... - let default_font = match font_name.deref() { - "_serif" => DefaultFont::Serif, - "_typewriter" => DefaultFont::Typewriter, - _ => DefaultFont::Sans, - }; - // TODO: handle multiple fonts for a definition, each covering different sets of glyphs + + // Use the default serif font, when no other matching font was found. context .library .default_font( - default_font, + DefaultFont::Serif, span.bold, span.italic, context.ui, diff --git a/core/src/library.rs b/core/src/library.rs index 10ae6b5fc..2517e54e1 100644 --- a/core/src/library.rs +++ b/core/src/library.rs @@ -456,21 +456,31 @@ impl<'gc> Library<'gc> { } let mut result = vec![]; + // First try to find any exactly matching fonts. for name in self.default_font_names.entry(name).or_default().clone() { - if let Some(font) = - self.get_or_load_device_font(&name, is_bold, is_italic, ui, renderer, gc_context) + if let Some(font) = self + .get_or_load_exact_device_font(&name, is_bold, is_italic, ui, renderer, gc_context) { result.push(font); } } + // Nothing found, try a compatible font. + if result.is_empty() { + for name in self.default_font_names.entry(name).or_default().clone() { + if let Some(font) = self.device_fonts.find(&name, is_bold, is_italic) { + result.push(font); + } + } + } + self.default_font_cache .insert((name, is_bold, is_italic), result.clone()); result } - /// Returns the device font for use when a font is unavailable. - pub fn get_or_load_device_font( + /// Returns the device font exactly matching the requested options. + fn get_or_load_exact_device_font( &mut self, name: &str, is_bold: bool, @@ -494,26 +504,38 @@ impl<'gc> Library<'gc> { ui.load_device_font(name, is_bold, is_italic, &mut |definition| { self.register_device_font(gc_context, renderer, definition) }); - } - // Check again. A backend may or may not have provided some new fonts, - // and they may or may not be relevant to the one we're asking for. - match self.device_fonts.get(name, is_bold, is_italic) { - None => { - if new_request { - warn!("Unknown device font \"{name}\" (bold: {is_bold} italic: {is_italic})"); - } - - // The default fallback: - // Try to find an existing font to re-use instead of giving up. - if let Some(font) = self.device_fonts.find(name, is_bold, is_italic) { - return Some(font); - } - - None + // Check again. A backend may or may not have provided some new fonts, + // and they may or may not be relevant to the one we're asking for. + if let Some(font) = self.device_fonts.get(name, is_bold, is_italic) { + return Some(*font); } - Some(font) => Some(*font), + + warn!("Unknown device font \"{name}\" (bold: {is_bold}, italic: {is_italic})"); } + + None + } + + /// Returns the device font compatible with the requested options. + pub fn get_or_load_device_font( + &mut self, + name: &str, + is_bold: bool, + is_italic: bool, + ui: &dyn UiBackend, + renderer: &mut dyn RenderBackend, + gc_context: &Mutation<'gc>, + ) -> Option> { + // Try to find an exactly matching font. + if let Some(font) = + self.get_or_load_exact_device_font(name, is_bold, is_italic, ui, renderer, gc_context) + { + return Some(font); + } + + // Fallback: Try to find an existing font to re-use instead of giving up. + self.device_fonts.find(name, is_bold, is_italic) } pub fn set_default_font(&mut self, font: DefaultFont, names: Vec) {