diff --git a/Cargo.lock b/Cargo.lock index d808b4f3..8aa61a43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -560,8 +560,9 @@ dependencies = [ [[package]] name = "fontdb" -version = "0.16.2" -source = "git+https://github.com/LaurenzV/fontdb?branch=custom#ad8e8061fc78270cd01f30a47b02982e3407fc54" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e32eac81c1135c1df01d4e6d4233c47ba11f6a6d07f33e0bba09d18797077770" dependencies = [ "fontconfig-parser", "log", @@ -1331,7 +1332,7 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "resvg" version = "0.41.0" -source = "git+https://github.com/LaurenzV/resvg?branch=new_fontdb#d92ab2067e84427048e35e2ad660e4addb4f69cd" +source = "git+https://github.com/RazrFalcon/resvg#0b33ace4cb9cbe272bfa051eaf60a1458975420b" dependencies = [ "gif", "jpeg-decoder", @@ -1394,9 +1395,9 @@ dependencies = [ [[package]] name = "rustybuzz" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88117946aa1bfb53c2ae0643ceac6506337f44887f8c9fbfb43587b1cc52ba49" +checksum = "7730060ad401b0d1807c904ea56735288af101430aa0d2ab8358b789f5f37002" dependencies = [ "bitflags 2.5.0", "bytemuck", @@ -1587,9 +1588,9 @@ dependencies = [ [[package]] name = "svgtypes" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97ca9a891c9c70da8139ac9d8e8ea36a210fa21bb50eccd75d4a9561c83e87f" +checksum = "fae3064df9b89391c9a76a0425a69d124aee9c5c28455204709e72c39868a43c" dependencies = [ "kurbo", "siphasher", @@ -1748,9 +1749,9 @@ dependencies = [ [[package]] name = "ttf-parser" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" +checksum = "2c591d83f69777866b9126b24c6dd9a18351f177e49d625920d19f989fd31cf8" [[package]] name = "typed-arena" @@ -1803,7 +1804,7 @@ checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94" [[package]] name = "usvg" version = "0.41.0" -source = "git+https://github.com/LaurenzV/resvg?branch=new_fontdb#d92ab2067e84427048e35e2ad660e4addb4f69cd" +source = "git+https://github.com/RazrFalcon/resvg#0b33ace4cb9cbe272bfa051eaf60a1458975420b" dependencies = [ "base64", "data-url", diff --git a/Cargo.toml b/Cargo.toml index 21224e2c..44cdef86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ svg2pdf = { path = ".", default-features = false, version = "0.9.1" } clap = { version = "4.4.2", features = ["derive"] } clap_complete = "4.4.3" clap_mangen = "0.2.14" -fontdb = {git = "https://github.com/LaurenzV/fontdb", branch = "custom"} +fontdb = "0.18.0" image = { version = "0.25.1", default-features = false, features = ["jpeg", "png", "gif"] } miniz_oxide = "0.7" once_cell = "1.18.0" @@ -25,12 +25,12 @@ oxipng = { version = "9", default-features = false, features = ["filetime", "par pdf-writer = "0.9" pdfium-render = "0.8.6" termcolor = "1.2" -usvg = { git = "https://github.com/LaurenzV/resvg", branch = "new_fontdb", default-features = false } +usvg = { git = "https://github.com/RazrFalcon/resvg", default-features = false } tiny-skia = "0.11.4" unicode-properties = "0.1.1" -resvg = { git = "https://github.com/LaurenzV/resvg", branch = "new_fontdb", default-features = false } +resvg = { git = "https://github.com/RazrFalcon/resvg", default-features = false } subsetter = "0.1.1" -ttf-parser = { version = "0.20.0" } +ttf-parser = { version = "0.21.1" } siphasher = { version = "1.0.1"} [package] diff --git a/cli/src/convert.rs b/cli/src/convert.rs index 6d49f18e..8b5b0e90 100644 --- a/cli/src/convert.rs +++ b/cli/src/convert.rs @@ -11,15 +11,22 @@ pub fn convert_( log::set_max_level(log::LevelFilter::Warn); } - // Prepare the font database. - let mut fontdb = fontdb::Database::new(); - fontdb.load_system_fonts(); + #[cfg(feature = "text")] + let mut options = usvg::Options::default(); - fontdb.set_serif_family("Times New Roman"); - fontdb.set_sans_serif_family("Arial"); - fontdb.set_cursive_family("Comic Sans MS"); - fontdb.set_fantasy_family("Impact"); - fontdb.set_monospace_family("Courier New"); + #[cfg(not(feature = "text"))] + let options = usvg::Options::default(); + + #[cfg(feature = "text")] + { + options.fontdb_mut().load_system_fonts(); + + options.fontdb_mut().set_serif_family("Times New Roman"); + options.fontdb_mut().set_sans_serif_family("Arial"); + options.fontdb_mut().set_cursive_family("Comic Sans MS"); + options.fontdb_mut().set_fantasy_family("Impact"); + options.fontdb_mut().set_monospace_family("Courier New"); + } // Convert the file. let name = Path::new(input.file_name().ok_or("Input path does not point to a file")?); @@ -27,23 +34,10 @@ pub fn convert_( let svg = std::fs::read_to_string(input).map_err(|_| "Failed to load SVG file")?; - let options = usvg::Options::default(); + let tree = usvg::Tree::from_str(&svg, &options).map_err(|err| err.to_string())?; - let tree = usvg::Tree::from_str( - &svg, - &options, - #[cfg(feature = "text")] - &fontdb, - ) - .map_err(|err| err.to_string())?; - - let pdf = svg2pdf::to_pdf( - &tree, - conversion_options, - page_options, - #[cfg(feature = "text")] - &fontdb, - ); + let pdf = + svg2pdf::to_pdf(&tree, conversion_options, page_options, options.fontdb.as_ref()); std::fs::write(output, pdf).map_err(|_| "Failed to write PDF file")?; diff --git a/src/lib.rs b/src/lib.rs index baf27a7e..d51115d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,15 +16,20 @@ This example reads an SVG file and writes the corresponding PDF back to the disk # fn main() -> Result<(), Box> { use svg2pdf::usvg::fontdb; use svg2pdf::{ConversionOptions, PageOptions}; +use std::sync::Arc; let input = "tests/svg/custom/integration/matplotlib/stairs.svg"; let output = "target/stairs.pdf"; let svg = std::fs::read_to_string(input)?; -let options = svg2pdf::usvg::Options::default(); let mut db = fontdb::Database::new(); db.load_system_fonts(); -let tree = svg2pdf::usvg::Tree::from_str(&svg, &options, &db)?; +let db = Arc::new(db); +let options = svg2pdf::usvg::Options { + fontdb: db.clone(), + ..svg2pdf::usvg::Options::default() +}; +let tree = svg2pdf::usvg::Tree::from_str(&svg, &options)?; let pdf = svg2pdf::to_pdf(&tree, ConversionOptions::default(), PageOptions::default(), &db); std::fs::write(output, pdf)?; @@ -140,15 +145,20 @@ impl Default for ConversionOptions { /// # fn main() -> Result<(), Box> { /// use svg2pdf::usvg::fontdb; /// use svg2pdf::{ConversionOptions, PageOptions}; +/// use std::sync::Arc; /// /// let input = "tests/svg/custom/integration/matplotlib/stairs.svg"; /// let output = "target/stairs.pdf"; /// /// let svg = std::fs::read_to_string(input)?; -/// let options = svg2pdf::usvg::Options::default(); /// let mut db = fontdb::Database::new(); /// db.load_system_fonts(); -/// let mut tree = svg2pdf::usvg::Tree::from_str(&svg, &options, &db)?; +/// let db = Arc::new(db); +/// let options = svg2pdf::usvg::Options { +/// fontdb: db.clone(), +/// ..svg2pdf::usvg::Options::default() +/// }; +/// let mut tree = svg2pdf::usvg::Tree::from_str(&svg, &options)?; /// /// /// let pdf = svg2pdf::to_pdf(&tree, ConversionOptions::default(), PageOptions::default(), &db); @@ -245,6 +255,7 @@ pub fn to_pdf( /// ``` /// # fn main() -> Result<(), Box> { /// use std::collections::HashMap; +/// use std::sync::Arc; /// use svg2pdf; /// use pdf_writer::{Content, Finish, Name, Pdf, Rect, Ref, Str}; /// use svg2pdf::usvg::fontdb; @@ -264,7 +275,12 @@ pub fn to_pdf( /// let svg = std::fs::read_to_string(path)?; /// let mut db = fontdb::Database::new(); /// db.load_system_fonts(); -/// let tree = svg2pdf::usvg::Tree::from_str(&svg, &svg2pdf::usvg::Options::default(), &db)?; +/// let db = Arc::new(db); +/// let options = svg2pdf::usvg::Options { +/// fontdb: db.clone(), +/// ..svg2pdf::usvg::Options::default() +/// }; +/// let tree = svg2pdf::usvg::Tree::from_str(&svg, &options)?; /// let (mut svg_chunk, svg_id) = svg2pdf::to_chunk(&tree, svg2pdf::ConversionOptions::default(), &db); /// /// // Renumber the chunk so that we can embed it into our existing workflow, and also make sure diff --git a/tests/src/api.rs b/tests/src/api.rs index 122494ba..e1ca6cbe 100644 --- a/tests/src/api.rs +++ b/tests/src/api.rs @@ -1,7 +1,6 @@ -use crate::create_fontdb; -use once_cell::sync::Lazy; #[allow(unused_imports)] use { + crate::FONTDB, crate::render_pdf, crate::{convert_svg, run_test_impl}, pdf_writer::{Content, Finish, Name, Pdf, Rect, Ref, Str}, @@ -11,9 +10,6 @@ use { svg2pdf::PageOptions, }; -#[allow(dead_code)] -static FONTDB3: Lazy> = Lazy::new(|| create_fontdb()); - #[test] fn text_to_paths() { let options = ConversionOptions { embed_text: false, ..ConversionOptions::default() }; @@ -51,12 +47,11 @@ fn to_chunk() { let path = "svg/custom/integration/wikimedia/coat_of_the_arms_of_edinburgh_city_council.svg"; let svg = std::fs::read_to_string(path).unwrap(); - let db = FONTDB3.lock().unwrap(); - let tree = - svg2pdf::usvg::Tree::from_str(&svg, &svg2pdf::usvg::Options::default(), &db) - .unwrap(); + let mut options = svg2pdf::usvg::Options::default(); + options.fontdb = FONTDB.clone(); + let tree = svg2pdf::usvg::Tree::from_str(&svg, &options).unwrap(); let (svg_chunk, svg_id) = - svg2pdf::to_chunk(&tree, svg2pdf::ConversionOptions::default(), &db); + svg2pdf::to_chunk(&tree, svg2pdf::ConversionOptions::default(), &FONTDB.as_ref()); let mut map = HashMap::new(); let svg_chunk = diff --git a/tests/src/lib.rs b/tests/src/lib.rs index b5bbe775..b565741c 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -5,6 +5,7 @@ mod api; use std::cmp::max; use std::fs; use std::path::{Path, PathBuf}; +use std::sync::Arc; use image::io::Reader; use image::{Rgba, RgbaImage}; @@ -16,8 +17,7 @@ use usvg::Tree; use svg2pdf::{ConversionOptions, PageOptions}; -static FONTDB1: Lazy> = Lazy::new(|| create_fontdb()); -static FONTDB2: Lazy> = Lazy::new(|| create_fontdb()); +static FONTDB: Lazy> = Lazy::new(|| create_fontdb()); /// The global pdfium instance. static PDFIUM: Lazy> = Lazy::new(|| { @@ -51,7 +51,7 @@ pub fn render_pdf(pdf: &[u8]) -> RgbaImage { result } -pub fn create_fontdb() -> std::sync::Mutex { +pub fn create_fontdb() -> Arc { let mut fontdb = fontdb::Database::new(); fontdb.load_fonts_dir("fonts"); @@ -61,13 +61,14 @@ pub fn create_fontdb() -> std::sync::Mutex { fontdb.set_fantasy_family("Sedgwick Ave Display"); fontdb.set_monospace_family("Noto Mono"); - std::sync::Mutex::new(fontdb) + Arc::new(fontdb) } /// Converts an SVG string into a usvg Tree pub fn read_svg(svg_string: &str) -> Tree { - let options = usvg::Options::default(); - Tree::from_str(svg_string, &options, &FONTDB1.lock().unwrap()).unwrap() + let mut options = usvg::Options::default(); + options.fontdb = FONTDB.clone(); + Tree::from_str(svg_string, &options).unwrap() } /// Converts an image into a PDF and returns the PDF as well as a rendered version @@ -79,12 +80,7 @@ pub fn convert_svg( ) -> (Vec, RgbaImage) { let svg = fs::read_to_string(svg_path).unwrap(); let tree = read_svg(&svg); - let pdf = svg2pdf::to_pdf( - &tree, - conversion_options, - page_options, - &FONTDB2.lock().unwrap(), - ); + let pdf = svg2pdf::to_pdf(&tree, conversion_options, page_options, &FONTDB.as_ref()); let image = render_pdf(pdf.as_slice()); (pdf, image) }