From 00f7588755faac7982fda54371e3f29662010d5f Mon Sep 17 00:00:00 2001 From: Laurenz Date: Fri, 17 May 2024 11:27:05 +0200 Subject: [PATCH] Tweak `usvg` options (#4163) --- crates/typst/src/visualize/image/svg.rs | 36 +++++++++++++++---------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/crates/typst/src/visualize/image/svg.rs b/crates/typst/src/visualize/image/svg.rs index d5cae6fe0..de53a8589 100644 --- a/crates/typst/src/visualize/image/svg.rs +++ b/crates/typst/src/visualize/image/svg.rs @@ -4,8 +4,9 @@ use std::sync::Arc; use comemo::Tracked; use ecow::EcoString; +use once_cell::sync::Lazy; use siphasher::sip128::Hasher128; -use usvg::{Node, PostProcessingSteps, TreeParsing, TreePostProc}; +use usvg::{ImageHrefResolver, Node, PostProcessingSteps, TreeParsing, TreePostProc}; use crate::diag::{format_xml_like_error, StrResult}; use crate::foundations::Bytes; @@ -31,7 +32,7 @@ impl SvgImage { #[comemo::memoize] pub fn new(data: Bytes) -> StrResult { let mut tree = - usvg::Tree::from_data(&data, &options()).map_err(format_usvg_error)?; + usvg::Tree::from_data(&data, &OPTIONS).map_err(format_usvg_error)?; tree.calculate_bounding_boxes(); Ok(Self(Arc::new(Repr { data, @@ -50,7 +51,7 @@ impl SvgImage { families: &[String], ) -> StrResult { let mut tree = - usvg::Tree::from_data(&data, &options()).map_err(format_usvg_error)?; + usvg::Tree::from_data(&data, &OPTIONS).map_err(format_usvg_error)?; let mut font_hash = 0; if tree.has_text_nodes() { let (fontdb, hash) = load_svg_fonts(world, &mut tree, families); @@ -124,20 +125,27 @@ impl Hash for Repr { } /// The conversion options. -fn options() -> usvg::Options { +static OPTIONS: Lazy = Lazy::new(|| usvg::Options { // Disable usvg's default to "Times New Roman". Instead, we default to // the empty family and later, when we traverse the SVG, we check for // empty and non-existing family names and replace them with the true - // fallback family. This way, we can memoize SVG decoding with and without - // fonts if the SVG does not contain text. - usvg::Options { - font_family: String::new(), - // We override the DPI here so that we get the correct the size when - // scaling the image to its natural size. - dpi: Image::DEFAULT_DPI as f32, - ..Default::default() - } -} + // fallback family. This way, we can memoize SVG decoding with and + // without fonts if the SVG does not contain text. + font_family: String::new(), + + // We override the DPI here so that we get the correct the size when + // scaling the image to its natural size. + dpi: Image::DEFAULT_DPI as f32, + + // Override usvg's resource loading defaults. + resources_dir: None, + image_href_resolver: ImageHrefResolver { + resolve_data: ImageHrefResolver::default_data_resolver(), + resolve_string: Box::new(|_, _| None), + }, + + ..Default::default() +}); /// Discover and load the fonts referenced by an SVG. fn load_svg_fonts(