web: Move font registration to builder, not after we've made the instance
This commit is contained in:
parent
aa804e520b
commit
85ca0aeff8
|
@ -715,17 +715,13 @@ export class RufflePlayer extends HTMLElement {
|
|||
throw e;
|
||||
});
|
||||
configureBuilder(builder, this.loadedConfig || {});
|
||||
this.instance = await builder.build(this.container, this).catch((e) => {
|
||||
console.error(`Serious error loading Ruffle: ${e}`);
|
||||
this.panic(e);
|
||||
throw e;
|
||||
});
|
||||
builder.setVolume(this.volumeSettings.get_volume());
|
||||
|
||||
if (this.loadedConfig?.fontSources) {
|
||||
for (const url of this.loadedConfig.fontSources) {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
this.instance!.add_font(
|
||||
builder.addFont(
|
||||
url,
|
||||
new Uint8Array(await response.arrayBuffer()),
|
||||
);
|
||||
|
@ -739,25 +735,29 @@ export class RufflePlayer extends HTMLElement {
|
|||
}
|
||||
|
||||
if (this.loadedConfig?.defaultFonts?.sans) {
|
||||
this.instance!.set_default_font(
|
||||
builder.setDefaultFont(
|
||||
"sans",
|
||||
this.loadedConfig?.defaultFonts.sans,
|
||||
);
|
||||
}
|
||||
if (this.loadedConfig?.defaultFonts?.serif) {
|
||||
this.instance!.set_default_font(
|
||||
builder!.setDefaultFont(
|
||||
"serif",
|
||||
this.loadedConfig?.defaultFonts.serif,
|
||||
);
|
||||
}
|
||||
if (this.loadedConfig?.defaultFonts?.typewriter) {
|
||||
this.instance!.set_default_font(
|
||||
builder!.setDefaultFont(
|
||||
"typewriter",
|
||||
this.loadedConfig?.defaultFonts.typewriter,
|
||||
);
|
||||
}
|
||||
|
||||
this.instance!.set_volume(this.volumeSettings.get_volume());
|
||||
this.instance = await builder.build(this.container, this).catch((e) => {
|
||||
console.error(`Serious error loading Ruffle: ${e}`);
|
||||
this.panic(e);
|
||||
throw e;
|
||||
});
|
||||
|
||||
this.rendererDebugInfo = this.instance!.renderer_debug_info();
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use crate::{set_panic_hook, JavascriptPlayer, RuffleHandle, SocketProxy, RUFFLE_GLOBAL_PANIC};
|
||||
use js_sys::Promise;
|
||||
use ruffle_core::backend::navigator::OpenURLMode;
|
||||
use ruffle_core::backend::ui::FontDefinition;
|
||||
use ruffle_core::compatibility_rules::CompatibilityRules;
|
||||
use ruffle_core::config::{Letterbox, NetworkingAccessMode};
|
||||
use ruffle_core::{Color, PlayerRuntime, StageAlign, StageScaleMode};
|
||||
use ruffle_core::{swf, Color, DefaultFont, Player, PlayerRuntime, StageAlign, StageScaleMode};
|
||||
use ruffle_render::quality::StageQuality;
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
@ -37,8 +39,9 @@ pub struct RuffleInstanceBuilder {
|
|||
pub(crate) socket_proxy: Vec<SocketProxy>,
|
||||
pub(crate) credential_allow_list: Vec<String>,
|
||||
pub(crate) player_runtime: PlayerRuntime,
|
||||
// TODO: Add font related options
|
||||
// TODO: Add volume
|
||||
pub(crate) volume: f32,
|
||||
pub(crate) default_fonts: HashMap<DefaultFont, Vec<String>>,
|
||||
pub(crate) custom_fonts: Vec<(String, Vec<u8>)>,
|
||||
}
|
||||
|
||||
impl Default for RuffleInstanceBuilder {
|
||||
|
@ -72,6 +75,9 @@ impl Default for RuffleInstanceBuilder {
|
|||
socket_proxy: vec![],
|
||||
credential_allow_list: vec![],
|
||||
player_runtime: PlayerRuntime::FlashPlayer,
|
||||
volume: 1.0,
|
||||
default_fonts: HashMap::new(),
|
||||
custom_fonts: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -262,6 +268,35 @@ impl RuffleInstanceBuilder {
|
|||
};
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setVolume")]
|
||||
pub fn set_volume(&mut self, value: f32) {
|
||||
self.volume = value;
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "addFont")]
|
||||
pub fn add_font(&mut self, font_name: String, data: Vec<u8>) {
|
||||
self.custom_fonts.push((font_name, data))
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = "setDefaultFont")]
|
||||
pub fn set_default_font(&mut self, default_name: &str, fonts: Vec<JsValue>) {
|
||||
let default = match default_name {
|
||||
"sans" => DefaultFont::Sans,
|
||||
"serif" => DefaultFont::Serif,
|
||||
"typewriter" => DefaultFont::Typewriter,
|
||||
_ => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
self.default_fonts.insert(
|
||||
default,
|
||||
fonts
|
||||
.into_iter()
|
||||
.flat_map(|value| value.as_string())
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: This should be split into two methods that either load url or load data
|
||||
// Right now, that's done immediately afterwards in TS
|
||||
pub async fn build(&self, parent: HtmlElement, js_player: JavascriptPlayer) -> Promise {
|
||||
|
@ -281,3 +316,54 @@ impl RuffleInstanceBuilder {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl RuffleInstanceBuilder {
|
||||
pub fn setup_fonts(&self, player: &mut Player) {
|
||||
for (font_name, bytes) in &self.custom_fonts {
|
||||
if let Ok(swf_stream) = swf::decompress_swf(&bytes[..]) {
|
||||
if let Ok(swf) = swf::parse_swf(&swf_stream) {
|
||||
let encoding = swf::SwfStr::encoding_for_version(swf.header.version());
|
||||
for tag in swf.tags {
|
||||
match tag {
|
||||
swf::Tag::DefineFont(_font) => {
|
||||
tracing::warn!("DefineFont1 tag is not yet supported by Ruffle, inside font swf {font_name}");
|
||||
}
|
||||
swf::Tag::DefineFont2(font) => {
|
||||
tracing::debug!(
|
||||
"Loaded font {} from font swf {font_name}",
|
||||
font.name.to_str_lossy(encoding)
|
||||
);
|
||||
player
|
||||
.register_device_font(FontDefinition::SwfTag(*font, encoding));
|
||||
}
|
||||
swf::Tag::DefineFont4(font) => {
|
||||
let name = font.name.to_str_lossy(encoding);
|
||||
if let Some(data) = font.data {
|
||||
tracing::debug!("Loaded font {name} from font swf {font_name}");
|
||||
player.register_device_font(FontDefinition::FontFile {
|
||||
name: name.to_string(),
|
||||
is_bold: font.is_bold,
|
||||
is_italic: font.is_bold,
|
||||
data: data.to_vec(),
|
||||
index: 0,
|
||||
})
|
||||
} else {
|
||||
tracing::warn!(
|
||||
"Font {name} from font swf {font_name} contains no data"
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
tracing::warn!("Font source {font_name} was not recognised (not a valid SWF?)");
|
||||
}
|
||||
|
||||
for (default, names) in &self.default_fonts {
|
||||
player.set_default_font(*default, names.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,12 +15,10 @@ use crate::builder::RuffleInstanceBuilder;
|
|||
use external_interface::{external_to_js_value, js_to_external_value, JavascriptInterface};
|
||||
use input::{web_key_to_codepoint, web_to_ruffle_key_code, web_to_ruffle_text_control};
|
||||
use js_sys::{Error as JsError, Uint8Array};
|
||||
use ruffle_core::backend::ui::FontDefinition;
|
||||
use ruffle_core::config::NetworkingAccessMode;
|
||||
use ruffle_core::context::UpdateContext;
|
||||
use ruffle_core::events::{MouseButton, MouseWheelDelta, TextControlCode};
|
||||
use ruffle_core::tag_utils::SwfMovie;
|
||||
use ruffle_core::{swf, DefaultFont};
|
||||
use ruffle_core::{
|
||||
Player, PlayerBuilder, PlayerEvent, SandboxType, StaticCallstack, ViewportDimensions,
|
||||
};
|
||||
|
@ -332,65 +330,6 @@ impl RuffleHandle {
|
|||
// Instance is dropped at this point.
|
||||
}
|
||||
|
||||
pub fn add_font(&mut self, font_name: &str, data: Uint8Array) {
|
||||
let _ = self.with_core_mut(|core| {
|
||||
let bytes: Vec<u8> = data.to_vec();
|
||||
if let Ok(swf_stream) = swf::decompress_swf(&bytes[..]) {
|
||||
if let Ok(swf) = swf::parse_swf(&swf_stream) {
|
||||
let encoding = swf::SwfStr::encoding_for_version(swf.header.version());
|
||||
for tag in swf.tags {
|
||||
match tag {
|
||||
swf::Tag::DefineFont(_font) => {
|
||||
tracing::warn!("DefineFont1 tag is not yet supported by Ruffle, inside font swf {font_name}");
|
||||
}
|
||||
swf::Tag::DefineFont2(font) => {
|
||||
tracing::debug!(
|
||||
"Loaded font {} from font swf {font_name}",
|
||||
font.name.to_str_lossy(encoding)
|
||||
);
|
||||
core.register_device_font(FontDefinition::SwfTag(*font, encoding));
|
||||
}
|
||||
swf::Tag::DefineFont4(font) => {
|
||||
let name = font.name.to_str_lossy(encoding);
|
||||
if let Some(data) = font.data {
|
||||
tracing::debug!("Loaded font {name} from font swf {font_name}");
|
||||
core.register_device_font(FontDefinition::FontFile { name: name.to_string(), is_bold: font.is_bold, is_italic: font.is_bold, data: data.to_vec(), index: 0 })
|
||||
} else {
|
||||
tracing::warn!("Font {name} from font swf {font_name} contains no data");
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
tracing::warn!("Font source {font_name} was not recognised (not a valid SWF?)");
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_default_font(&mut self, default_name: &str, fonts: Vec<JsValue>) {
|
||||
let _ = self.with_core_mut(|core| {
|
||||
let default = match default_name {
|
||||
"sans" => DefaultFont::Sans,
|
||||
"serif" => DefaultFont::Serif,
|
||||
"typewriter" => DefaultFont::Typewriter,
|
||||
name => {
|
||||
tracing::error!("Unknown default font name '{name}'");
|
||||
return;
|
||||
}
|
||||
};
|
||||
core.set_default_font(
|
||||
default,
|
||||
fonts
|
||||
.into_iter()
|
||||
.flat_map(|value| value.as_string())
|
||||
.collect(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[allow(clippy::boxed_local)] // for js_bind
|
||||
pub fn call_exposed_callback(&self, name: &str, args: Box<[JsValue]>) -> JsValue {
|
||||
let args: Vec<_> = args.iter().map(js_to_external_value).collect();
|
||||
|
@ -481,11 +420,11 @@ impl RuffleHandle {
|
|||
allow_script_access,
|
||||
allow_networking,
|
||||
config.upgrade_to_https,
|
||||
config.base_url,
|
||||
config.base_url.clone(),
|
||||
log_subscriber.clone(),
|
||||
config.open_url_mode,
|
||||
config.socket_proxy,
|
||||
config.credential_allow_list,
|
||||
config.socket_proxy.clone(),
|
||||
config.credential_allow_list.clone(),
|
||||
));
|
||||
|
||||
match window.local_storage() {
|
||||
|
@ -514,7 +453,7 @@ impl RuffleHandle {
|
|||
.with_max_execution_duration(config.max_execution_duration)
|
||||
.with_player_version(config.player_version)
|
||||
.with_player_runtime(config.player_runtime)
|
||||
.with_compatibility_rules(config.compatibility_rules)
|
||||
.with_compatibility_rules(config.compatibility_rules.clone())
|
||||
.with_quality(config.quality)
|
||||
.with_align(config.stage_align, config.force_align)
|
||||
.with_scale_mode(config.scale, config.force_scale)
|
||||
|
@ -527,10 +466,12 @@ impl RuffleHandle {
|
|||
let mut callstack = None;
|
||||
if let Ok(mut core) = core.try_lock() {
|
||||
// Set config parameters.
|
||||
core.set_volume(config.volume);
|
||||
core.set_background_color(config.background_color);
|
||||
core.set_show_menu(config.show_menu);
|
||||
core.set_allow_fullscreen(config.allow_fullscreen);
|
||||
core.set_window_mode(config.wmode.as_deref().unwrap_or("window"));
|
||||
config.setup_fonts(&mut core);
|
||||
callstack = Some(core.callstack());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue