Skip to content

Commit

Permalink
avm2: Sort enumerated fonts properly
Browse files Browse the repository at this point in the history
Flash orders enumerated fonts by their name (case insensitive).
In case of duplicates (e.g. bold/italic variants), the order is
nondeterministic.
  • Loading branch information
kjarosh committed Jan 14, 2025
1 parent 428ed70 commit 3e169e4
Showing 1 changed file with 18 additions and 7 deletions.
25 changes: 18 additions & 7 deletions core/src/avm2/globals/flash/text/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::string::AvmString;

pub use crate::avm2::object::font_allocator;
use crate::character::Character;
use crate::font::FontType;
use crate::font::{Font, FontType};

/// Implements `Font.fontName`
pub fn get_font_name<'gc>(
Expand Down Expand Up @@ -90,8 +90,7 @@ pub fn enumerate_fonts<'gc>(
_this: Value<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let mut storage = ArrayStorage::new(0);
let font_class = activation.avm2().classes().font;
let mut fonts: Vec<Font<'gc>> = Vec::new();

if args.get_bool(0) {
// We could include the ones we know about, but what to do for the ones that weren't eagerly loaded?
Expand All @@ -103,9 +102,7 @@ pub fn enumerate_fonts<'gc>(
);
}

for font in activation.context.library.global_fonts() {
storage.push(FontObject::for_font(activation.gc(), font_class, font).into());
}
fonts.append(&mut activation.context.library.global_fonts());

if let Some(library) = activation
.context
Expand All @@ -116,11 +113,25 @@ pub fn enumerate_fonts<'gc>(
// TODO: EmbeddedCFF isn't supposed to show until it's been used (some kind of internal initialization method?)
// Device is only supposed to show when arg0 is true - but that's supposed to be "all known" device fonts, not just loaded ones
if font.has_layout() && font.font_type() == FontType::Embedded {
storage.push(FontObject::for_font(activation.gc(), font_class, font).into());
fonts.push(font);
}
}
}

// The output from Flash is sorted by font name (case insensitive).
// If two fonts have the same name (e.g. bold/italic variants),
// the order is nondeterministic.
fonts.sort_unstable_by(|a, b| {
a.descriptor()
.lowercase_name()
.cmp(b.descriptor().lowercase_name())
});

let font_class = activation.avm2().classes().font;
let mut storage = ArrayStorage::new(fonts.len());
for font in fonts {
storage.push(FontObject::for_font(activation.gc(), font_class, font).into());
}
Ok(ArrayObject::from_storage(activation, storage).into())
}

Expand Down

0 comments on commit 3e169e4

Please sign in to comment.