1use wasm_bindgen::prelude::*;
6
7#[wasm_bindgen]
8#[derive(Default, Clone)]
9pub struct Context {
10 fonts: Vec<Vec<u8>>,
11}
12
13#[wasm_bindgen]
14impl Context {
15 #[wasm_bindgen(js_name = registerFontData)]
16 pub fn register_font_data(&mut self, font_data: &[u8]) {
17 self.fonts.push(font_data.to_vec());
18 }
19
20 #[wasm_bindgen]
21 pub fn render(
22 &mut self,
23 svg_xml: &str,
24 scale: Option<f64>,
25 width: Option<u32>,
26 height: Option<u32>,
27 ) -> Option<Vec<u8>> {
28
29 let fontdb = {
30 let mut db = fontdb::Database::new();
31 for font in self.fonts.iter() {
32 db.load_font_data(font.clone())
33 }
34 db
35 };
36
37 let svg_options = usvg::OptionsRef {
38 resources_dir: None,
39 dpi: 192.0,
40 font_family: "Roboto Light",
41 font_size: 0.0,
42 languages: &["en".to_owned()],
43 shape_rendering: usvg::ShapeRendering::GeometricPrecision,
44 text_rendering: usvg::TextRendering::OptimizeLegibility,
45 image_rendering: usvg::ImageRendering::OptimizeQuality,
46 keep_named_groups: false,
47 default_size: usvg::Size::new(100.0, 100.0).unwrap(),
48 fontdb: &fontdb,
49 };
50
51 let scale = scale.unwrap_or(2.0);
52
53 let rtree = usvg::Tree::from_data(svg_xml.as_bytes(), &svg_options).unwrap();
54
55 let pixmap_size = rtree.svg_node().size.to_screen_size();
56 let mut pixmap = tiny_skia::Pixmap::new(
57 (width.unwrap_or_else(|| pixmap_size.width()) as f64 * scale).ceil() as u32,
58 (height.unwrap_or_else(|| pixmap_size.height()) as f64 * scale).ceil() as u32,
59 )
60 .unwrap();
61 resvg::render(&rtree, usvg::FitTo::Zoom(scale as f32), tiny_skia::Transform::identity(), pixmap.as_mut()).unwrap();
62
63 Some(pixmap.encode_png().unwrap())
64 }
65
66 #[wasm_bindgen(js_name = listFonts)]
67 pub fn list_fonts(&self) -> String {
68 let mut svg_options = usvg::Options::default();
69
70 let mut s = "fonts:\n".to_owned();
71 for font in self.fonts.iter() {
72 s += &*format!("loading buf len {}\n", font.len());
73 svg_options.fontdb.load_font_data(font.clone())
74 }
75
76 for face in svg_options.fontdb.faces() {
77 if let usvg::fontdb::Source::Binary(_) = &face.source {
78 s += &*format!(
79 "binary: '{}', {}, {:?}, {:?}, {:?}\n",
80 face.family, face.index, face.style, face.weight.0, face.stretch
81 );
82 }
83 }
84 s
85 }
86}
87
88#[wasm_bindgen(js_name = newContext)]
89pub fn new_context() -> Context {
90 Context::default()
91}