Skip to content

Commit

Permalink
Make rendering of svg that has text work out of the box (#2560)
Browse files Browse the repository at this point in the history
* fix: load system fonts to usvg font_db, this will make rendering of text in svg that has it

* feat: add an example that renders svg that has text on it

* Initialize `fontdb` only once for `vector` images

* Remove `svg_text` example

* Set `fontdb` for `usvg::Options` in `tiny_skia::vector`

---------

Co-authored-by: Héctor Ramón Jiménez <hector@hecrj.dev>
  • Loading branch information
ivanceras and hecrj authored Sep 13, 2024
1 parent e0da42e commit 0c50280
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 19 deletions.
31 changes: 21 additions & 10 deletions tiny_skia/src/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use tiny_skia::Transform;
use std::cell::RefCell;
use std::collections::hash_map;
use std::fs;
use std::sync::Arc;

#[derive(Debug)]
pub struct Pipeline {
Expand Down Expand Up @@ -68,6 +69,7 @@ struct Cache {
tree_hits: FxHashSet<u64>,
rasters: FxHashMap<RasterKey, tiny_skia::Pixmap>,
raster_hits: FxHashSet<RasterKey>,
fontdb: Option<Arc<usvg::fontdb::Database>>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
Expand All @@ -81,23 +83,32 @@ impl Cache {
fn load(&mut self, handle: &Handle) -> Option<&usvg::Tree> {
let id = handle.id();

// TODO: Reuse `cosmic-text` font database
if self.fontdb.is_none() {
let mut fontdb = usvg::fontdb::Database::new();
fontdb.load_system_fonts();

self.fontdb = Some(Arc::new(fontdb));
}

let options = usvg::Options {
fontdb: self
.fontdb
.as_ref()
.expect("fontdb must be initialized")
.clone(),
..usvg::Options::default()
};

if let hash_map::Entry::Vacant(entry) = self.trees.entry(id) {
let svg = match handle.data() {
Data::Path(path) => {
fs::read_to_string(path).ok().and_then(|contents| {
usvg::Tree::from_str(
&contents,
&usvg::Options::default(), // TODO: Set usvg::Options::fontdb
)
.ok()
usvg::Tree::from_str(&contents, &options).ok()
})
}
Data::Bytes(bytes) => {
usvg::Tree::from_data(
bytes,
&usvg::Options::default(), // TODO: Set usvg::Options::fontdb
)
.ok()
usvg::Tree::from_data(bytes, &options).ok()
}
};

Expand Down
30 changes: 21 additions & 9 deletions wgpu/src/image/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use resvg::tiny_skia;
use resvg::usvg;
use rustc_hash::{FxHashMap, FxHashSet};
use std::fs;
use std::sync::Arc;

/// Entry in cache corresponding to an svg handle
pub enum Svg {
Expand Down Expand Up @@ -37,6 +38,7 @@ pub struct Cache {
svg_hits: FxHashSet<u64>,
rasterized_hits: FxHashSet<(u64, u32, u32, ColorFilter)>,
should_trim: bool,
fontdb: Option<Arc<usvg::fontdb::Database>>,
}

type ColorFilter = Option<[u8; 4]>;
Expand All @@ -48,23 +50,33 @@ impl Cache {
return self.svgs.get(&handle.id()).unwrap();
}

// TODO: Reuse `cosmic-text` font database
if self.fontdb.is_none() {
let mut fontdb = usvg::fontdb::Database::new();
fontdb.load_system_fonts();

self.fontdb = Some(Arc::new(fontdb));
}

let options = usvg::Options {
fontdb: self
.fontdb
.as_ref()
.expect("fontdb must be initialized")
.clone(),
..usvg::Options::default()
};

let svg = match handle.data() {
svg::Data::Path(path) => fs::read_to_string(path)
.ok()
.and_then(|contents| {
usvg::Tree::from_str(
&contents,
&usvg::Options::default(), // TODO: Set usvg::Options::fontdb
)
.ok()
usvg::Tree::from_str(&contents, &options).ok()
})
.map(Svg::Loaded)
.unwrap_or(Svg::NotFound),
svg::Data::Bytes(bytes) => {
match usvg::Tree::from_data(
bytes,
&usvg::Options::default(), // TODO: Set usvg::Options::fontdb
) {
match usvg::Tree::from_data(bytes, &options) {
Ok(tree) => Svg::Loaded(tree),
Err(_) => Svg::NotFound,
}
Expand Down

0 comments on commit 0c50280

Please sign in to comment.