From 0df643449395983af5057e1b3892533991d417e0 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 5 Nov 2024 22:18:15 +1300 Subject: [PATCH] WPT: reuse FontContext to avoid reloading system fonts Takes runtime for css-flexbox from 12s -> 8s --- apps/readme/src/main.rs | 2 +- apps/wpt/Cargo.toml | 1 + apps/wpt/src/main.rs | 26 ++++++++++++++++++++++--- examples/screenshot.rs | 1 + packages/blitz-dom/src/document.rs | 17 ++++++++-------- packages/blitz-dom/src/html_document.rs | 7 ++++++- packages/dioxus-native/src/lib.rs | 2 +- 7 files changed, 41 insertions(+), 15 deletions(-) diff --git a/apps/readme/src/main.rs b/apps/readme/src/main.rs index 1b16ddb7..231c5bd0 100644 --- a/apps/readme/src/main.rs +++ b/apps/readme/src/main.rs @@ -44,7 +44,7 @@ fn main() { Arc::clone(&net_callback) as SharedCallback, )); - let document = HtmlDocument::from_html(&html, Some(base_url), stylesheets, net_provider); + let document = HtmlDocument::from_html(&html, Some(base_url), stylesheets, net_provider, None); dioxus_native::launch_with_document(document, rt, Some(net_callback)); } diff --git a/apps/wpt/Cargo.toml b/apps/wpt/Cargo.toml index ec83bee9..69c8c8ea 100644 --- a/apps/wpt/Cargo.toml +++ b/apps/wpt/Cargo.toml @@ -10,6 +10,7 @@ blitz-net = { path = "../../packages/blitz-net" } blitz-traits = { path = "../../packages/blitz-traits" } blitz-renderer-vello = { path = "../../packages/blitz-renderer-vello" } dioxus-native = { path = "../../packages/dioxus-native", features = ["tracing"] } +parley = { workspace = true } tokio = { workspace = true } png = { version = "0.17" } glob = {version = "0.3.1"} diff --git a/apps/wpt/src/main.rs b/apps/wpt/src/main.rs index b09f77ea..8f024e77 100644 --- a/apps/wpt/src/main.rs +++ b/apps/wpt/src/main.rs @@ -3,6 +3,7 @@ use blitz_dom::{HtmlDocument, Viewport}; use blitz_net::{MpscCallback, Provider}; use blitz_renderer_vello::VelloImageRenderer; use blitz_traits::net::SharedProvider; +use parley::FontContext; use reqwest::Url; use tower_http::services::ServeDir; @@ -98,6 +99,13 @@ fn setup_blitz() -> BlitzContext { } } +fn clone_font_ctx(ctx: &FontContext) -> FontContext { + FontContext { + collection: ctx.collection.clone(), + source_cache: ctx.source_cache.clone(), + } +} + fn main() { env_logger::init(); let rt = tokio::runtime::Builder::new_current_thread() @@ -141,13 +149,16 @@ fn main() { let num = AtomicU32::new(0); + let base_font_context = parley::FontContext::default(); + test_paths.into_par_iter().for_each_init( || { let renderer = rt.block_on(VelloImageRenderer::new(WIDTH, HEIGHT, SCALE)); + let font_ctx = clone_font_ctx(&base_font_context); let test_buffer = Vec::with_capacity((WIDTH * HEIGHT * 4) as usize); let ref_buffer = Vec::with_capacity((WIDTH * HEIGHT * 4) as usize); let guard = rt.enter(); - (renderer, test_buffer, ref_buffer, guard) + (renderer, font_ctx, test_buffer, ref_buffer, guard) }, |state, path| { let num = num.fetch_add(1, Ordering::SeqCst) + 1; @@ -162,13 +173,15 @@ fn main() { let url = base_url.join(relative_path.as_str()).unwrap(); let renderer = &mut state.0; - let test_buffer = &mut state.1; - let ref_buffer = &mut state.2; + let font_ctx = &state.1; + let test_buffer = &mut state.2; + let ref_buffer = &mut state.3; let result = catch_unwind(AssertUnwindSafe(|| { let mut blitz_context = setup_blitz(); let result = rt.block_on(process_test_file( renderer, + font_ctx, test_buffer, ref_buffer, &url, @@ -231,6 +244,7 @@ async fn serve(app: Router, port: u16) { #[allow(clippy::too_many_arguments)] async fn process_test_file( renderer: &mut VelloImageRenderer, + font_ctx: &FontContext, test_buffer: &mut Vec, ref_buffer: &mut Vec, path: &Url, @@ -255,6 +269,7 @@ async fn process_test_file( if let Some(reference) = reference { process_test_file_with_ref( renderer, + font_ctx, test_buffer, ref_buffer, path, @@ -274,6 +289,7 @@ async fn process_test_file( #[allow(clippy::too_many_arguments)] async fn process_test_file_with_ref( renderer: &mut VelloImageRenderer, + font_ctx: &FontContext, test_buffer: &mut Vec, ref_buffer: &mut Vec, test_url: &Url, @@ -306,6 +322,7 @@ async fn process_test_file_with_ref( render_html_to_buffer( blitz_context, renderer, + font_ctx, test_file_contents, test_url, test_buffer, @@ -317,6 +334,7 @@ async fn process_test_file_with_ref( render_html_to_buffer( blitz_context, renderer, + font_ctx, &reference_file_contents, &ref_url, ref_buffer, @@ -345,6 +363,7 @@ async fn process_test_file_with_ref( async fn render_html_to_buffer( blitz_context: &mut BlitzContext, renderer: &mut VelloImageRenderer, + font_ctx: &FontContext, html: &str, base_url: &Url, buf: &mut Vec, @@ -355,6 +374,7 @@ async fn render_html_to_buffer( Some(base_url.to_string()), Vec::new(), Arc::clone(&blitz_context.net) as SharedProvider, + Some(clone_font_ctx(font_ctx)), ); document diff --git a/examples/screenshot.rs b/examples/screenshot.rs index 8ecf4dab..899ebddc 100644 --- a/examples/screenshot.rs +++ b/examples/screenshot.rs @@ -72,6 +72,7 @@ async fn main() { Some(url_string.clone()), Vec::new(), Arc::clone(&net) as SharedProvider, + None, ); timer.time("Parsed document"); diff --git a/packages/blitz-dom/src/document.rs b/packages/blitz-dom/src/document.rs index 02c0b8ec..6c14e91d 100644 --- a/packages/blitz-dom/src/document.rs +++ b/packages/blitz-dom/src/document.rs @@ -3,7 +3,7 @@ use crate::node::{ImageData, NodeSpecificData, TextBrush}; use crate::{ElementNodeData, Node, NodeData, TextNodeData, Viewport}; use app_units::Au; use html5ever::local_name; -use parley::PlainEditorOp; +use parley::{FontContext, PlainEditorOp}; use peniko::kurbo; use string_cache::Atom; use style::attr::{AttrIdentifier, AttrValue}; @@ -382,6 +382,10 @@ impl DocumentLike for Document { impl Document { pub fn new(viewport: Viewport) -> Self { + Self::with_font_ctx(viewport, parley::FontContext::default()) + } + + pub fn with_font_ctx(viewport: Viewport, mut font_ctx: FontContext) -> Self { let device = viewport.make_device(); let stylist = Stylist::new(device, QuirksMode::NoQuirks); let snapshots = SnapshotMap::new(); @@ -395,7 +399,9 @@ impl Document { style_config::set_bool("layout.legacy_layout", true); style_config::set_bool("layout.columns.enabled", true); - let font_ctx = Self::create_font_context(); + font_ctx + .collection + .register_fonts(include_bytes!("moz-bullet-font.otf").to_vec()); let mut doc = Self { guard, @@ -423,13 +429,6 @@ impl Document { doc } - fn create_font_context() -> parley::FontContext { - let mut ctx = parley::FontContext::default(); - ctx.collection - .register_fonts(include_bytes!("moz-bullet-font.otf").to_vec()); - ctx - } - /// Set base url for resolving linked resources (stylesheets, images, fonts, etc) pub fn set_base_url(&mut self, url: &str) { self.base_url = Some(Url::parse(url).unwrap()); diff --git a/packages/blitz-dom/src/html_document.rs b/packages/blitz-dom/src/html_document.rs index 47dbf877..f5fb6ffc 100644 --- a/packages/blitz-dom/src/html_document.rs +++ b/packages/blitz-dom/src/html_document.rs @@ -4,6 +4,7 @@ use crate::{Document, DocumentHtmlParser, DocumentLike, Viewport}; use crate::net::Resource; use crate::DEFAULT_CSS; use blitz_traits::net::SharedProvider; +use parley::FontContext; pub struct HtmlDocument { inner: Document, @@ -38,10 +39,14 @@ impl HtmlDocument { base_url: Option, stylesheets: Vec, net_provider: SharedProvider, + font_ctx: Option, ) -> Self { // Spin up the virtualdom and include the default stylesheet let viewport = Viewport::new(0, 0, 1.0); - let mut dom = Document::new(viewport); + let mut dom = match font_ctx { + Some(font_ctx) => Document::with_font_ctx(viewport, font_ctx), + None => Document::new(viewport), + }; // Set base url if configured if let Some(url) = &base_url { diff --git a/packages/dioxus-native/src/lib.rs b/packages/dioxus-native/src/lib.rs index 248b8112..e1744e30 100644 --- a/packages/dioxus-native/src/lib.rs +++ b/packages/dioxus-native/src/lib.rs @@ -127,7 +127,7 @@ pub fn launch_static_html_cfg(html: &str, cfg: Config) { Arc::clone(&net_callback) as SharedCallback, )); - let document = HtmlDocument::from_html(html, cfg.base_url, cfg.stylesheets, net_provider); + let document = HtmlDocument::from_html(html, cfg.base_url, cfg.stylesheets, net_provider, None); launch_with_document(document, rt, Some(net_callback)); }