From 1e8f5025c6bf4ca770239c906b76d1e10182b61e Mon Sep 17 00:00:00 2001 From: Lucas Leroux <128176798+lcslrx@users.noreply.github.com> Date: Thu, 15 Oct 2026 12:40:00 +0200 Subject: [PATCH] Render, SVG: vello_cpu and usvg without their text features: one skrifa, read-fonts and harfrust fewer in the engine The default `text` features of vello_cpu (glyph runs, through glifo) and usvg (fontdb, harfrust 0.12, skrifa 0.44 and its read-fonts 0.41) build another copy of the font stack into the engine, next to the workspace's skrifa 0.47 and harfrust 0.13. Neither is used: the renderer draws the glyph outlines vectorcraft-text gives it, and SVG import reads from the XML itself and never gives usvg a font (usvg leaves out text it has no font for). - vello_cpu: its default features but `text` (std, png, u8_pipeline), plus f32_pipeline as before. - usvg: `svgz` only, for gzipped SVG images inside an SVG; `text`, `system-fonts`, `memmap-fonts` and `writer` are off. text_layout.rs uses usvg as a reference viewer with a font, so crates/svg turns `text` on as a dev-dependency feature, as crates/pdf does for krilla's `simple-text`. - A test pins `svgz`: SVGZ images, linked or as a data URL, import as vector art. Co-Authored-By: Claude Opus 5.5 --- Cargo.lock | 11 ----------- Cargo.toml | 9 +++++++-- crates/svg/Cargo.toml | 2 ++ crates/svg/tests/import_details.rs | 21 +++++++++++++++++++++ 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f85d88263..03217449e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1383,24 +1383,13 @@ dependencies = [ "bytemuck", ] -[[package]] -name = "fontconfig-parser" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbc773e24e02d4ddd8395fd30dc147524273a83e54e0f312d986ea30de5f5646" -dependencies = [ - "roxmltree 0.20.0", -] - [[package]] name = "fontdb" version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2660c5e9157bf76d2db1294e4a9feba604ef610819a3b591088d0d8392a3290f" dependencies = [ - "fontconfig-parser", "log", - "memmap2", "slotmap", "tinyvec", ] diff --git a/Cargo.toml b/Cargo.toml index 0d3fcb76f..a04729748 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,9 +59,14 @@ wasmi = { version = "2.0.0", default-features = false, features = ["std", "valid wat = "1.228" # rendering / formats -vello_cpu = { version = "0.2", features = ["f32_pipeline"] } +# Without `text` (glyph runs, through glifo and a second skrifa): the renderer draws the outlines +# vectorcraft-text gives it. The other default features stay. +vello_cpu = { version = "0.2", default-features = false, features = ["std", "png", "u8_pipeline", "f32_pipeline"] } image = { version = "0.25", default-features = false, features = ["png", "jpeg", "webp", "gif", "tiff", "bmp"] } -usvg = "0.48" +# Without `text` and the system fonts (fontdb, harfrust and skrifa, at other versions than ours): +# SVG import reads `` from the XML itself and never gives usvg a font. A test of the SVG +# crate turns `text` on. +usvg = { version = "0.48", default-features = false, features = ["svgz"] } # Without `simple-text` (its text shaping, the only user of rustybuzz and ttf-parser, which are # unmaintained, #1730): the PDF writer places glyphs itself. A test of the PDF crate turns it on. krilla = { version = "0.8", default-features = false, features = ["raster-images"] } diff --git a/crates/svg/Cargo.toml b/crates/svg/Cargo.toml index 1ac02e466..7b679365f 100644 --- a/crates/svg/Cargo.toml +++ b/crates/svg/Cargo.toml @@ -33,6 +33,8 @@ skrifa = { workspace = true } # A variable font built in code (no font file is committed). vectorcraft-text = { workspace = true, features = ["test-fonts"] } resvg = { version = "0.45", default-features = false } +# usvg as a reference viewer that lays text out in a font (text_layout.rs). +usvg = { workspace = true, features = ["text"] } vectorcraft-testkit = { workspace = true } proptest = { workspace = true } image = { workspace = true } diff --git a/crates/svg/tests/import_details.rs b/crates/svg/tests/import_details.rs index abd219723..b38e54648 100644 --- a/crates/svg/tests/import_details.rs +++ b/crates/svg/tests/import_details.rs @@ -126,6 +126,27 @@ fn svg_images_import_as_vector_art() { assert!((boxes[1].x0 - 100.0).abs() < 1e-6 && (boxes[1].height() - 20.0).abs() < 1e-6, "{boxes:?}"); } +/// usvg unpacks gzipped SVG images itself (its `svgz` feature, which the workspace keeps). +#[test] +fn svgz_images_import_as_vector_art() { + let dir = folder("svgzimage"); + let inner = + r##""##; + let gz = vectorcraft_svg::compress(inner); + std::fs::write(dir.join("img").join("logo.svgz"), &gz).unwrap(); + let data = format!("data:image/svg+xml;base64,{}", vectorcraft_svg::base64_encode(&gz)); + let body = + format!(r#""#); + let (d, w) = open_in(&dir, &body); + assert!(w.is_empty(), "{w:?}"); + assert!(images(&d).is_empty()); + let mut boxes: Vec = art(&d).iter().filter(|n| n.path_data().is_some()).filter_map(|n| n.geometric_bounds()).collect(); + boxes.sort_by(|a, b| a.x0.total_cmp(&b.x0)); + assert_eq!(boxes.len(), 2, "{:?}", art(&d)); + assert!((boxes[0].x0 - 10.0).abs() < 1e-6 && (boxes[0].width() - 20.0).abs() < 1e-6, "{boxes:?}"); + assert!((boxes[1].x0 - 100.0).abs() < 1e-6 && (boxes[1].height() - 20.0).abs() < 1e-6, "{boxes:?}"); +} + #[test] fn nested_clips_intersect() { let body = r##"