Make rendering of svg that has text work out of the box (#2560)

* 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>
This commit is contained in:
Jovansonlee Cesar 2024-09-14 05:43:00 +08:00 committed by GitHub
parent e0da42efed
commit 0c502801e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 42 additions and 19 deletions

View file

@ -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 {
@ -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)]
@ -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()
}
};

View file

@ -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 {
@ -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]>;
@ -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,
}