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/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 0f54c177..371e3d3b 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}, @@ -458,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()); @@ -466,6 +471,67 @@ 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 + ) { + 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; + }; + + 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()); + } + + } + } + } + } + } + } + pub fn snapshot_node(&mut self, node_id: usize) { let node = &mut self.nodes[node_id]; let opaque_node_id = TNode::opaque(&&*node);