resvg_wasm/
lib.rs

1// Copyright 2021 Bobby Powers. All rights reserved.
2// Use of this source code is governed by the Mozilla Public
3// License, Version 2.0, that can be found in the LICENSE file.
4
5use 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}