diff --git a/sixtyfps_runtime/corelib/Cargo.toml b/sixtyfps_runtime/corelib/Cargo.toml index b79377992..3314cb4bb 100644 --- a/sixtyfps_runtime/corelib/Cargo.toml +++ b/sixtyfps_runtime/corelib/Cargo.toml @@ -43,6 +43,7 @@ auto_enums = "0.7" stretch = "0.3.2" weak-table = "0.3" femtovg = { git = "https://github.com/femtovg/femtovg", branch = "master", optional = true } +fontdb = "0.5.1" [target.'cfg(target_arch = "wasm32")'.dependencies] instant = { version = "0.1", features = [ "wasm-bindgen", "now" ] } diff --git a/sixtyfps_runtime/corelib/graphics.rs b/sixtyfps_runtime/corelib/graphics.rs index 83b3a5f84..59ae81081 100644 --- a/sixtyfps_runtime/corelib/graphics.rs +++ b/sixtyfps_runtime/corelib/graphics.rs @@ -28,7 +28,7 @@ use crate::{Callback, SharedString}; use auto_enums::auto_enum; use const_field_offset::FieldOffsets; use sixtyfps_corelib_macros::*; -use std::rc::Rc; +use std::{cell::RefCell, rc::Rc}; /// 2D Rectangle pub type Rect = euclid::default::Rect; @@ -688,22 +688,17 @@ pub(crate) mod ffi { } } +thread_local! { + /// Database used to keep track of fonts added by the application + pub static APPLICATION_FONTS: RefCell = RefCell::new(fontdb::Database::new()) +} + /// This function can be used to register a custom TrueType font with SixtyFPS, /// for use with the `font-family` property. The provided slice must be a valid TrueType /// font. pub fn register_application_font_from_memory( data: &'static [u8], ) -> Result<(), Box> { - /* - let platform_font = PlatformFont::new_from_slice(data).map_err(Box::new)?; - - FONT_CACHE.with(|fc| { - fc.application_fonts - .borrow_mut() - .insert(platform_font.family_name(), FontMatch::new(platform_font)) - }); - + APPLICATION_FONTS.with(|fontdb| fontdb.borrow_mut().load_font_data(data.into())); Ok(()) - */ - todo!() } diff --git a/sixtyfps_runtime/rendering_backends/gl/Cargo.toml b/sixtyfps_runtime/rendering_backends/gl/Cargo.toml index 09df09608..345c7c023 100644 --- a/sixtyfps_runtime/rendering_backends/gl/Cargo.toml +++ b/sixtyfps_runtime/rendering_backends/gl/Cargo.toml @@ -34,6 +34,7 @@ by_address = "1.0.4" femtovg = { git = "https://github.com/femtovg/femtovg", branch = "master" } euclid = "0.22.1" pin-weak = "1" +fontdb = "0.5.1" [target.'cfg(target_arch = "wasm32")'.dependencies] web_sys = { version = "0.3", package = "web-sys", features=["console", "WebGlContextAttributes"] } diff --git a/sixtyfps_runtime/rendering_backends/gl/lib.rs b/sixtyfps_runtime/rendering_backends/gl/lib.rs index b8ae2f5b0..cf4412508 100644 --- a/sixtyfps_runtime/rendering_backends/gl/lib.rs +++ b/sixtyfps_runtime/rendering_backends/gl/lib.rs @@ -58,35 +58,71 @@ impl Default for FontDatabase { } } +fn try_load_app_font(canvas: &CanvasRc, request: &FontRequest) -> Option { + let family = if request.family.is_empty() { + fontdb::Family::SansSerif + } else { + fontdb::Family::Name(&request.family) + }; + let query = fontdb::Query { + families: &[family], + weight: fontdb::Weight(request.weight as u16), + ..Default::default() + }; + sixtyfps_corelib::graphics::APPLICATION_FONTS.with(|font_db| { + let font_db = font_db.borrow(); + font_db.query(&query).and_then(|id| font_db.face_source(id)).map(|(source, _index)| { + GLFont { + // pass index to femtovg once femtovg/femtovg/pull/21 is merged + font_id: match source.as_ref() { + fontdb::Source::Binary(data) => { + canvas.borrow_mut().add_font_mem(&data).unwrap() + } + fontdb::Source::File(path) => canvas.borrow_mut().add_font(path).unwrap(), + }, + canvas: canvas.clone(), + } + }) + }) +} + +fn load_system_font(canvas: &CanvasRc, request: &FontRequest) -> GLFont { + let family_name = if request.family.len() == 0 { + font_kit::family_name::FamilyName::SansSerif + } else { + font_kit::family_name::FamilyName::Title(request.family.to_string()) + }; + + let handle = font_kit::source::SystemSource::new() + .select_best_match( + &[family_name, font_kit::family_name::FamilyName::SansSerif], + &font_kit::properties::Properties::new() + .weight(font_kit::properties::Weight(request.weight as f32)), + ) + .unwrap(); + + // pass index to femtovg once femtovg/femtovg/pull/21 is merged + let canvas_font = match handle { + font_kit::handle::Handle::Path { path, font_index: _ } => { + canvas.borrow_mut().add_font(path) + } + font_kit::handle::Handle::Memory { bytes, font_index: _ } => { + canvas.borrow_mut().add_font_mem(bytes.as_slice()) + } + } + .unwrap(); + GLFont { font_id: canvas_font, canvas: canvas.clone() } +} + impl FontDatabase { fn font(&mut self, canvas: &CanvasRc, request: FontRequest) -> Rc { self.0 .entry(FontCacheKey::new(&request)) .or_insert_with(|| { - let family_name = if request.family.len() == 0 { - font_kit::family_name::FamilyName::SansSerif - } else { - font_kit::family_name::FamilyName::Title(request.family.to_string()) - }; - - let handle = font_kit::source::SystemSource::new() - .select_best_match( - &[family_name, font_kit::family_name::FamilyName::SansSerif], - &font_kit::properties::Properties::new() - .weight(font_kit::properties::Weight(request.weight as f32)), - ) - .unwrap(); - - let canvas_font = match handle { - font_kit::handle::Handle::Path { path, font_index } => { - canvas.borrow_mut().add_font(path) - } - font_kit::handle::Handle::Memory { bytes, font_index } => { - canvas.borrow_mut().add_font_mem(bytes.as_slice()) - } - } - .unwrap(); - Rc::new(GLFont { font_id: canvas_font, canvas: canvas.clone() }) + Rc::new( + try_load_app_font(canvas, &request) + .unwrap_or_else(|| load_system_font(canvas, &request)), + ) }) .clone() }