Skip to content

Commit

Permalink
core: Allow Regular/Bold/Italic device fonts to be registered separately
Browse files Browse the repository at this point in the history
  • Loading branch information
MrCheeze authored and Dinnerbone committed Nov 24, 2023
1 parent 96059a8 commit 5920a64
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 15 deletions.
17 changes: 15 additions & 2 deletions core/src/backend/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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) {}

Expand Down
2 changes: 2 additions & 0 deletions core/src/html/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
26 changes: 16 additions & 10 deletions core/src/library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,15 +373,15 @@ 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<String, Font<'gc>>,
device_fonts: FontMap<'gc>,

/// "Global" embedded fonts, registered through AVM2 `Font.registerFont`.
/// These should be checked before any Movie-specific library's own fonts.
global_fonts: FontMap<'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<String>,
font_lookup_cache: FnvHashSet<(String, bool, bool)>,

/// The implementation names of each default font.
default_font_names: FnvHashMap<DefaultFont, Vec<String>>,
Expand Down Expand Up @@ -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);
}
}
Expand All @@ -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<Font<'gc>> {
// 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),
}
}

Expand All @@ -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();
Expand Down
9 changes: 8 additions & 1 deletion desktop/src/backends/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
Expand Down
9 changes: 8 additions & 1 deletion tests/framework/src/backends/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<FileFilter>) -> Option<DialogResultFuture> {
Some(Box::pin(async move {
Expand Down
8 changes: 7 additions & 1 deletion web/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
}
Expand Down

0 comments on commit 5920a64

Please sign in to comment.