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;
|
throw e;
|
||||||
});
|
});
|
||||||
configureBuilder(builder, this.loadedConfig || {});
|
configureBuilder(builder, this.loadedConfig || {});
|
||||||
this.instance = await builder.build(this.container, this).catch((e) => {
|
builder.setVolume(this.volumeSettings.get_volume());
|
||||||
console.error(`Serious error loading Ruffle: ${e}`);
|
|
||||||
this.panic(e);
|
|
||||||
throw e;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.loadedConfig?.fontSources) {
|
if (this.loadedConfig?.fontSources) {
|
||||||
for (const url of this.loadedConfig.fontSources) {
|
for (const url of this.loadedConfig.fontSources) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
this.instance!.add_font(
|
builder.addFont(
|
||||||
url,
|
url,
|
||||||
new Uint8Array(await response.arrayBuffer()),
|
new Uint8Array(await response.arrayBuffer()),
|
||||||
);
|
);
|
||||||
|
@ -739,25 +735,29 @@ export class RufflePlayer extends HTMLElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.loadedConfig?.defaultFonts?.sans) {
|
if (this.loadedConfig?.defaultFonts?.sans) {
|
||||||
this.instance!.set_default_font(
|
builder.setDefaultFont(
|
||||||
"sans",
|
"sans",
|
||||||
this.loadedConfig?.defaultFonts.sans,
|
this.loadedConfig?.defaultFonts.sans,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (this.loadedConfig?.defaultFonts?.serif) {
|
if (this.loadedConfig?.defaultFonts?.serif) {
|
||||||
this.instance!.set_default_font(
|
builder!.setDefaultFont(
|
||||||
"serif",
|
"serif",
|
||||||
this.loadedConfig?.defaultFonts.serif,
|
this.loadedConfig?.defaultFonts.serif,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (this.loadedConfig?.defaultFonts?.typewriter) {
|
if (this.loadedConfig?.defaultFonts?.typewriter) {
|
||||||
this.instance!.set_default_font(
|
builder!.setDefaultFont(
|
||||||
"typewriter",
|
"typewriter",
|
||||||
this.loadedConfig?.defaultFonts.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();
|
this.rendererDebugInfo = this.instance!.renderer_debug_info();
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
use crate::{set_panic_hook, JavascriptPlayer, RuffleHandle, SocketProxy, RUFFLE_GLOBAL_PANIC};
|
use crate::{set_panic_hook, JavascriptPlayer, RuffleHandle, SocketProxy, RUFFLE_GLOBAL_PANIC};
|
||||||
use js_sys::Promise;
|
use js_sys::Promise;
|
||||||
use ruffle_core::backend::navigator::OpenURLMode;
|
use ruffle_core::backend::navigator::OpenURLMode;
|
||||||
|
use ruffle_core::backend::ui::FontDefinition;
|
||||||
use ruffle_core::compatibility_rules::CompatibilityRules;
|
use ruffle_core::compatibility_rules::CompatibilityRules;
|
||||||
use ruffle_core::config::{Letterbox, NetworkingAccessMode};
|
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 ruffle_render::quality::StageQuality;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
@ -37,8 +39,9 @@ pub struct RuffleInstanceBuilder {
|
||||||
pub(crate) socket_proxy: Vec<SocketProxy>,
|
pub(crate) socket_proxy: Vec<SocketProxy>,
|
||||||
pub(crate) credential_allow_list: Vec<String>,
|
pub(crate) credential_allow_list: Vec<String>,
|
||||||
pub(crate) player_runtime: PlayerRuntime,
|
pub(crate) player_runtime: PlayerRuntime,
|
||||||
// TODO: Add font related options
|
pub(crate) volume: f32,
|
||||||
// TODO: Add volume
|
pub(crate) default_fonts: HashMap<DefaultFont, Vec<String>>,
|
||||||
|
pub(crate) custom_fonts: Vec<(String, Vec<u8>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RuffleInstanceBuilder {
|
impl Default for RuffleInstanceBuilder {
|
||||||
|
@ -72,6 +75,9 @@ impl Default for RuffleInstanceBuilder {
|
||||||
socket_proxy: vec![],
|
socket_proxy: vec![],
|
||||||
credential_allow_list: vec![],
|
credential_allow_list: vec![],
|
||||||
player_runtime: PlayerRuntime::FlashPlayer,
|
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
|
// TODO: This should be split into two methods that either load url or load data
|
||||||
// Right now, that's done immediately afterwards in TS
|
// Right now, that's done immediately afterwards in TS
|
||||||
pub async fn build(&self, parent: HtmlElement, js_player: JavascriptPlayer) -> Promise {
|
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 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 input::{web_key_to_codepoint, web_to_ruffle_key_code, web_to_ruffle_text_control};
|
||||||
use js_sys::{Error as JsError, Uint8Array};
|
use js_sys::{Error as JsError, Uint8Array};
|
||||||
use ruffle_core::backend::ui::FontDefinition;
|
|
||||||
use ruffle_core::config::NetworkingAccessMode;
|
use ruffle_core::config::NetworkingAccessMode;
|
||||||
use ruffle_core::context::UpdateContext;
|
use ruffle_core::context::UpdateContext;
|
||||||
use ruffle_core::events::{MouseButton, MouseWheelDelta, TextControlCode};
|
use ruffle_core::events::{MouseButton, MouseWheelDelta, TextControlCode};
|
||||||
use ruffle_core::tag_utils::SwfMovie;
|
use ruffle_core::tag_utils::SwfMovie;
|
||||||
use ruffle_core::{swf, DefaultFont};
|
|
||||||
use ruffle_core::{
|
use ruffle_core::{
|
||||||
Player, PlayerBuilder, PlayerEvent, SandboxType, StaticCallstack, ViewportDimensions,
|
Player, PlayerBuilder, PlayerEvent, SandboxType, StaticCallstack, ViewportDimensions,
|
||||||
};
|
};
|
||||||
|
@ -332,65 +330,6 @@ impl RuffleHandle {
|
||||||
// Instance is dropped at this point.
|
// 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
|
#[allow(clippy::boxed_local)] // for js_bind
|
||||||
pub fn call_exposed_callback(&self, name: &str, args: Box<[JsValue]>) -> JsValue {
|
pub fn call_exposed_callback(&self, name: &str, args: Box<[JsValue]>) -> JsValue {
|
||||||
let args: Vec<_> = args.iter().map(js_to_external_value).collect();
|
let args: Vec<_> = args.iter().map(js_to_external_value).collect();
|
||||||
|
@ -481,11 +420,11 @@ impl RuffleHandle {
|
||||||
allow_script_access,
|
allow_script_access,
|
||||||
allow_networking,
|
allow_networking,
|
||||||
config.upgrade_to_https,
|
config.upgrade_to_https,
|
||||||
config.base_url,
|
config.base_url.clone(),
|
||||||
log_subscriber.clone(),
|
log_subscriber.clone(),
|
||||||
config.open_url_mode,
|
config.open_url_mode,
|
||||||
config.socket_proxy,
|
config.socket_proxy.clone(),
|
||||||
config.credential_allow_list,
|
config.credential_allow_list.clone(),
|
||||||
));
|
));
|
||||||
|
|
||||||
match window.local_storage() {
|
match window.local_storage() {
|
||||||
|
@ -514,7 +453,7 @@ impl RuffleHandle {
|
||||||
.with_max_execution_duration(config.max_execution_duration)
|
.with_max_execution_duration(config.max_execution_duration)
|
||||||
.with_player_version(config.player_version)
|
.with_player_version(config.player_version)
|
||||||
.with_player_runtime(config.player_runtime)
|
.with_player_runtime(config.player_runtime)
|
||||||
.with_compatibility_rules(config.compatibility_rules)
|
.with_compatibility_rules(config.compatibility_rules.clone())
|
||||||
.with_quality(config.quality)
|
.with_quality(config.quality)
|
||||||
.with_align(config.stage_align, config.force_align)
|
.with_align(config.stage_align, config.force_align)
|
||||||
.with_scale_mode(config.scale, config.force_scale)
|
.with_scale_mode(config.scale, config.force_scale)
|
||||||
|
@ -527,10 +466,12 @@ impl RuffleHandle {
|
||||||
let mut callstack = None;
|
let mut callstack = None;
|
||||||
if let Ok(mut core) = core.try_lock() {
|
if let Ok(mut core) = core.try_lock() {
|
||||||
// Set config parameters.
|
// Set config parameters.
|
||||||
|
core.set_volume(config.volume);
|
||||||
core.set_background_color(config.background_color);
|
core.set_background_color(config.background_color);
|
||||||
core.set_show_menu(config.show_menu);
|
core.set_show_menu(config.show_menu);
|
||||||
core.set_allow_fullscreen(config.allow_fullscreen);
|
core.set_allow_fullscreen(config.allow_fullscreen);
|
||||||
core.set_window_mode(config.wmode.as_deref().unwrap_or("window"));
|
core.set_window_mode(config.wmode.as_deref().unwrap_or("window"));
|
||||||
|
config.setup_fonts(&mut core);
|
||||||
callstack = Some(core.callstack());
|
callstack = Some(core.callstack());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue