use std::sync::Arc;
use resvg::{tiny_skia, usvg};
use crate::error::ChartError;
const FONTS: [&[u8]; 4] = [
include_bytes!("../fonts/Inter-Regular-latin.ttf"),
include_bytes!("../fonts/Inter-SemiBold-latin.ttf"),
include_bytes!("../fonts/Inter-Regular-latin-ext.ttf"),
include_bytes!("../fonts/Inter-SemiBold-latin-ext.ttf"),
];
pub(crate) const MAX_SCALE: f32 = 4.0;
pub(crate) fn rasterize(svg: &str, scale: f32) -> Result<Vec<u8>, ChartError> {
let mut fonts = usvg::fontdb::Database::new();
for font in FONTS {
fonts.load_font_data(font.to_vec());
}
fonts.set_sans_serif_family("Inter");
let options = usvg::Options {
font_family: "Inter".to_owned(),
fontdb: Arc::new(fonts),
..usvg::Options::default()
};
let tree = usvg::Tree::from_str(svg, &options).map_err(|error| {
ChartError::new(
"png_failed",
"/render/format",
format!("could not read the chart SVG: {error}"),
)
})?;
let size = tree
.size()
.to_int_size()
.scale_by(scale)
.expect("a validated scale keeps the chart larger than a pixel");
let mut pixmap = tiny_skia::Pixmap::new(size.width(), size.height())
.expect("a validated scale keeps the image within memory limits");
resvg::render(
&tree,
tiny_skia::Transform::from_scale(scale, scale),
&mut pixmap.as_mut(),
);
pixmap.encode_png().map_err(|error| {
ChartError::new(
"png_failed",
"/render/format",
format!("could not encode the PNG: {error}"),
)
})
}