From 53e3af3a2becc8f67e4c415942df38f2b373fb92 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Jul 2024 14:54:08 +1200 Subject: [PATCH 1/3] Webfonts WIP --- examples/assets/servo.html | 4 +++ packages/dom/src/document.rs | 54 ++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/examples/assets/servo.html b/examples/assets/servo.html index a69165c9..92eec7fe 100644 --- a/examples/assets/servo.html +++ b/examples/assets/servo.html @@ -22,6 +22,10 @@ + + + + diff --git a/packages/dom/src/document.rs b/packages/dom/src/document.rs index 0f54c177..7495ac2a 100644 --- a/packages/dom/src/document.rs +++ b/packages/dom/src/document.rs @@ -1,5 +1,6 @@ use crate::events::{EventData, HitResult, RendererEvent}; use crate::node::TextBrush; +use crate::util::fetch_blob; use crate::{Node, NodeData, TextNodeData, Viewport}; use app_units::Au; use peniko::kurbo; @@ -9,9 +10,11 @@ use selectors::{matching::QuirksMode, Element}; use slab::Slab; use std::any::Any; use std::collections::{HashMap, HashSet, VecDeque}; +use style::font_face::{FontFaceSourceFormat, FontFaceSourceFormatKeyword, Source}; use style::selector_parser::ServoElementSnapshot; use style::servo::media_queries::FontMetricsProvider; use style::servo_arc::Arc as ServoArc; +use style::stylesheets::{CssRule, StylesheetInDocument}; use style::values::computed::ui::CursorKind; use style::{ dom::{TDocument, TNode}, @@ -466,6 +469,57 @@ impl Document { .force_stylesheet_origins_dirty(Origin::Author.into()); } + pub fn add_webfonts_from_stylesheet(&mut self, stylesheet: &Stylesheet) { + let read_guard = self.guard.read(); + + for rule in stylesheet.rules(&read_guard) { + if let CssRule::FontFace(rule) = rule { + let rule = rule.read_with(&read_guard); + if let Some(sources) = rule.sources.as_ref() { + for source in &sources.0 { + if let Source::Url(source) = source { + // Skip sources with source hints for formats we definitely don't support + if let Some(hint) = &source.format_hint { + match hint { + FontFaceSourceFormat::String(s) => { + println!("Skipping unsupported font of custom type {}", s); + continue; + } + FontFaceSourceFormat::Keyword(keyword) => { + use FontFaceSourceFormatKeyword as KW; + if matches!( + keyword, + KW::EmbeddedOpentype | KW::Svg | KW::Woff | KW::Woff2 + ) { + println!( + "Skipping unsupported font of type {:?}", + keyword + ); + continue; + } + } + } + }; + + let Some(url) = source.url.url() else { + println!("Source with no url"); + continue; + }; + let Ok(font_data) = fetch_blob(url.as_str()) else { + println!("Error fetching font {}", url.as_str()); + continue; + }; + + // TODO: Support WOFF + self.font_ctx.collection.register_fonts(font_data); + println!("Registed font {}", url.as_str()); + } + } + } + } + } + } + pub fn snapshot_node(&mut self, node_id: usize) { let node = &mut self.nodes[node_id]; let opaque_node_id = TNode::opaque(&&*node); From cedf1ddc2ac741a83c94474ea089b69641c40e49 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Jul 2024 15:02:13 +1200 Subject: [PATCH 2/3] Support woff2 fonts --- packages/dom/Cargo.toml | 1 + packages/dom/src/document.rs | 22 ++++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/dom/Cargo.toml b/packages/dom/Cargo.toml index 4c207c40..b75540f5 100644 --- a/packages/dom/Cargo.toml +++ b/packages/dom/Cargo.toml @@ -31,6 +31,7 @@ ureq = "2.9" image = "0.25.2" winit = { version = "0.30.4", default-features = false } usvg = "0.42.0" +woff = "0.3.3" # on wasm use the js feature on getrandom diff --git a/packages/dom/src/document.rs b/packages/dom/src/document.rs index 7495ac2a..b977df17 100644 --- a/packages/dom/src/document.rs +++ b/packages/dom/src/document.rs @@ -482,14 +482,14 @@ impl Document { if let Some(hint) = &source.format_hint { match hint { FontFaceSourceFormat::String(s) => { - println!("Skipping unsupported font of custom type {}", s); - continue; + // println!("Skipping unsupported font of custom type {}", s); + // continue; } FontFaceSourceFormat::Keyword(keyword) => { use FontFaceSourceFormatKeyword as KW; if matches!( keyword, - KW::EmbeddedOpentype | KW::Svg | KW::Woff | KW::Woff2 + KW::EmbeddedOpentype | KW::Svg ) { println!( "Skipping unsupported font of type {:?}", @@ -510,9 +510,19 @@ impl Document { continue; }; - // TODO: Support WOFF - self.font_ctx.collection.register_fonts(font_data); - println!("Registed font {}", url.as_str()); + if url.path().ends_with("woff2") || url.path().ends_with("woff") { + if let Some(font_data) = woff::version2::decompress(&font_data) { + self.font_ctx.collection.register_fonts(font_data); + println!("Registed font {}", url.as_str()); + } else { + println!("Error decompressing woff2 data"); + } + + } else { + self.font_ctx.collection.register_fonts(font_data); + println!("Registed font {}", url.as_str()); + } + } } } From 89aa78415253bed9dffdf521b1317b66dc0ae374 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Mon, 29 Jul 2024 15:02:22 +1200 Subject: [PATCH 3/3] Actually call font registration function --- packages/dom/src/document.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/dom/src/document.rs b/packages/dom/src/document.rs index b977df17..371e3d3b 100644 --- a/packages/dom/src/document.rs +++ b/packages/dom/src/document.rs @@ -461,6 +461,8 @@ impl Document { let sheet = DocumentStyleSheet(ServoArc::new(data)); + self.add_webfonts_from_stylesheet(&*sheet.0); + self.stylesheets.insert(css.to_string(), sheet.clone()); self.stylist.append_stylesheet(sheet, &self.guard.read());