From 064dcc663dc350def1df809f2e16ee435df905ec Mon Sep 17 00:00:00 2001 From: MrCheeze Date: Mon, 20 Nov 2023 00:05:51 -0500 Subject: [PATCH] core: Allow Regular/Bold/Italic device fonts to be registered separately --- core/src/backend/ui.rs | 17 +++++++++++++++-- core/src/html/layout.rs | 2 ++ core/src/library.rs | 26 ++++++++++++++++---------- desktop/src/backends/ui.rs | 9 ++++++++- tests/framework/src/backends/ui.rs | 9 ++++++++- web/src/ui.rs | 8 +++++++- 6 files changed, 56 insertions(+), 15 deletions(-) diff --git a/core/src/backend/ui.rs b/core/src/backend/ui.rs index b62f582da592..cd4f3fad5723 100644 --- a/core/src/backend/ui.rs +++ b/core/src/backend/ui.rs @@ -91,7 +91,13 @@ pub trait UiBackend: Downcast { /// You may call `register` any amount of times with any amount of found device fonts. /// If you do not call `register` with any fonts that match the request, /// then the font will simply be marked as not found - this may or may not fall back to another font. - fn load_device_font(&self, name: &str, register: &dyn FnMut(FontDefinition)); + fn load_device_font( + &self, + name: &str, + is_bold: bool, + is_italic: bool, + register: &dyn FnMut(FontDefinition), + ); /// Displays a file selection dialog, returning None if the dialog cannot be displayed /// (e.g because it is already open) @@ -267,7 +273,14 @@ impl UiBackend for NullUiBackend { fn display_unsupported_video(&self, _url: Url) {} - fn load_device_font(&self, _name: &str, _register: &dyn FnMut(FontDefinition)) {} + fn load_device_font( + &self, + _name: &str, + _is_bold: bool, + _is_italic: bool, + _register: &dyn FnMut(FontDefinition), + ) { + } fn open_virtual_keyboard(&self) {} diff --git a/core/src/html/layout.rs b/core/src/html/layout.rs index a41f329ee9b2..bb4c088cd146 100644 --- a/core/src/html/layout.rs +++ b/core/src/html/layout.rs @@ -488,6 +488,8 @@ impl<'a, 'gc> LayoutContext<'a, 'gc> { if let Some(font) = context.library.get_or_load_device_font( &font_name, + span.bold, + span.italic, context.ui, context.renderer, context.gc_context, diff --git a/core/src/library.rs b/core/src/library.rs index 4a1fbb2678d6..c9eea7d18b72 100644 --- a/core/src/library.rs +++ b/core/src/library.rs @@ -373,7 +373,7 @@ pub struct Library<'gc> { /// A cache of seen device fonts. // TODO: Descriptors shouldn't be stored in fonts. Fonts should be a list that we iterate and ask "do you match". A font can have zero or many names. - device_fonts: FnvHashMap>, + device_fonts: FontMap<'gc>, /// "Global" embedded fonts, registered through AVM2 `Font.registerFont`. /// These should be checked before any Movie-specific library's own fonts. @@ -381,7 +381,7 @@ pub struct Library<'gc> { /// A set of which fonts we've asked from the backend already, to help with negative caching. /// If we've asked for a specific font, record it here and don't ask again. - font_lookup_cache: FnvHashSet, + font_lookup_cache: FnvHashSet<(String, bool, bool)>, /// The implementation names of each default font. default_font_names: FnvHashMap>, @@ -454,7 +454,9 @@ impl<'gc> Library<'gc> { let mut result = vec![]; for name in self.default_font_names.entry(name).or_default().clone() { - if let Some(font) = self.get_or_load_device_font(&name, ui, renderer, gc_context) { + if let Some(font) = + self.get_or_load_device_font(&name, false, false, ui, renderer, gc_context) + { result.push(font); } } @@ -467,35 +469,39 @@ impl<'gc> Library<'gc> { 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> { // If we have the font already, use that // TODO: We should instead ask each font if it matches a given name. Partial matches are allowed, and fonts may have any amount of names. - if let Some(font) = self.device_fonts.get(name) { - return Some(*font); + if let Some(font) = self.device_fonts.find(name, is_bold, is_italic) { + return Some(font); } // We don't have this font already. Did we ask for it before? - let new_request = self.font_lookup_cache.insert(name.to_string()); + let new_request = self + .font_lookup_cache + .insert((name.to_string(), is_bold, is_italic)); if new_request { // First time asking for this font, see if our backend can provide anything relevant - ui.load_device_font(name, &|definition| { + ui.load_device_font(name, is_bold, is_italic, &|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) { + match self.device_fonts.find(name, is_bold, is_italic) { None => { if new_request { warn!("Unknown device font \"{name}\""); } None } - Some(font) => Some(*font), + Some(font) => Some(font), } } @@ -516,7 +522,7 @@ impl<'gc> Library<'gc> { Font::from_swf_tag(gc_context, renderer, tag, encoding, FontType::Device); let name = font.descriptor().name().to_owned(); info!("Loaded new device font \"{name}\" from swf tag"); - self.device_fonts.insert(name, font); + self.device_fonts.register(font); } } self.default_font_cache.clear(); diff --git a/desktop/src/backends/ui.rs b/desktop/src/backends/ui.rs index ea4bb629d145..115fc205e59b 100644 --- a/desktop/src/backends/ui.rs +++ b/desktop/src/backends/ui.rs @@ -247,7 +247,14 @@ impl UiBackend for DesktopUiBackend { }; } - fn load_device_font(&self, _name: &str, _register: &dyn FnMut(FontDefinition)) {} + fn load_device_font( + &self, + _name: &str, + _is_bold: bool, + _is_italic: bool, + _register: &dyn FnMut(FontDefinition), + ) { + } // Unused on desktop fn open_virtual_keyboard(&self) {} diff --git a/tests/framework/src/backends/ui.rs b/tests/framework/src/backends/ui.rs index 132144f89171..07eaae0690d4 100644 --- a/tests/framework/src/backends/ui.rs +++ b/tests/framework/src/backends/ui.rs @@ -110,7 +110,14 @@ impl UiBackend for TestUiBackend { fn display_unsupported_video(&self, _url: Url) {} - fn load_device_font(&self, _name: &str, _register: &dyn FnMut(FontDefinition)) {} + fn load_device_font( + &self, + _name: &str, + _is_bold: bool, + _is_italic: bool, + _register: &dyn FnMut(FontDefinition), + ) { + } fn display_file_open_dialog(&mut self, filters: Vec) -> Option { Some(Box::pin(async move { diff --git a/web/src/ui.rs b/web/src/ui.rs index e1483559525b..2ea64feb3d64 100644 --- a/web/src/ui.rs +++ b/web/src/ui.rs @@ -260,7 +260,13 @@ impl UiBackend for WebUiBackend { self.js_player.display_unsupported_video(url.as_str()); } - fn load_device_font(&self, _name: &str, _register: &dyn FnMut(FontDefinition)) { + fn load_device_font( + &self, + _name: &str, + _is_bold: bool, + _is_italic: bool, + _register: &dyn FnMut(FontDefinition), + ) { // Because fonts must be loaded instantly (no async), // we actually just provide them all upfront at time of Player creation. }