Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

resvg Rust, SVG rendering as blank png

Tags:

svg

rust

Could someone please explain to me why the resulting PNG file is blank?

pub fn render_svg_directly(svg_data: &str) -> Option<Pixmap> {
    println!("svg_dat: {}", svg_data);
    let opt = Options::default();
    let rtree = Tree::from_str(svg_data, &opt).ok()?;
    let pixmap_size = rtree.size;
    let mut pixmap = Pixmap::new(pixmap_size.width() as u32, pixmap_size.height() as u32)?;
    resvg::render(&rtree, tiny_skia::Transform::identity(), &mut pixmap.as_mut());
    pixmap.save_png("test_output.png").expect("Failed to save pixmap to PNG");
    Some(pixmap)
}
let svg_data = fs::read_to_string("../test.svg").expect("Failed to read SVG file");
let pixmap = plutonium::render_svg_directly(&svg_data).expect("Failed to render SVG");

output:

zeke plutonium_tester$ cargo run
   Compiling plutonium v0.1.0 (/Users/zeke/dev/plutonium_farm/plutonium)
   Compiling plutonium_tester v0.1.0 (/Users/zeke/dev/plutonium_farm/plutonium_tester)
    Finished dev [unoptimized + debuginfo] target(s) in 1.18s
     Running `target/debug/plutonium_tester`
svg_dat: <?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 28.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
         viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
<style type="text/css">
        .st0{fill:#92278F;stroke:#9E1F63;stroke-miterlimit:10;}
</style>
<rect class="st0" width="100" height="100"/>
</svg>

rtree: Tree { size: Size { width: NonZeroPositiveF32(FiniteF32(100.0)), height: NonZeroPositiveF32(FiniteF32(100.0)) }, view_box: ViewBox { rect: NonZeroRect { left: 0.0, top: 0.0, right: 100.0, bottom: 100.0 }, aspect: AspectRatio { defer: false, align: XMidYMid, slice: false } }, root: Group { id: "", transform: Transform { sx: 1.0, kx: 0.0, ky: 0.0, sy: 1.0, tx: 0.0, ty: 0.0 }, abs_transform: Transform { sx: 1.0, kx: 0.0, ky: 0.0, sy: 1.0, tx: 0.0, ty: 0.0 }, opacity: NormalizedF32(FiniteF32(1.0)), blend_mode: Normal, isolate: false, clip_path: None, mask: None, filters: [], bounding_box: None, stroke_bounding_box: None, layer_bounding_box: None, children: [Path(Path { id: "", visibility: Visible, fill: Some(Fill { paint: Color(Color { red: 146, green: 39, blue: 143 }), opacity: NormalizedF32(FiniteF32(1.0)), rule: NonZero }), stroke: Some(Stroke { paint: Color(Color { red: 158, green: 31, blue: 99 }), dasharray: None, dashoffset: 0.0, miterlimit: StrokeMiterlimit(10.0), opacity: NormalizedF32(FiniteF32(1.0)), width: NonZeroPositiveF32(FiniteF32(1.0)), linecap: Butt, linejoin: Miter }), paint_order: FillAndStroke, rendering_mode: GeometricPrecision, data: Path { segments: "M 0 0 L 100 0 L 100 100 L 0 100 Z", bounds: Rect { left: 0.0, top: 0.0, right: 100.0, bottom: 100.0 } }, abs_transform: Transform { sx: 1.0, kx: 0.0, ky: 0.0, sy: 1.0, tx: 0.0, ty: 0.0 }, bounding_box: None, stroke_bounding_box: None })] } }

I have tried different SVGs from both inkscape and illustrator formats.

like image 557
zeke Avatar asked Oct 21 '25 10:10

zeke


1 Answers

You must call postprocess after parsing the Tree as stated in the documentation:

Must be called after parsing a usvg::Tree.

Here is the fixed render_svg_directly function:

pub fn render_svg_directly(svg_data: &str) -> Option<Pixmap> {
    println!("svg_dat: {}", svg_data);
    let opt = Options::default();
    let mut rtree = Tree::from_str(svg_data, &opt).ok()?;
    rtree.postprocess(PostProcessingSteps::default(), &fontdb::Database::new());
    let pixmap_size = rtree.size;
    let mut pixmap = Pixmap::new(pixmap_size.width() as u32, pixmap_size.height() as u32)?;
    resvg::render(&rtree, tiny_skia::Transform::identity(), &mut pixmap.as_mut());
    pixmap.save_png("test_output.png").expect("Failed to save pixmap to PNG");
    Some(pixmap)
}

Note however that this will only work if the SVG does not contain inline text, otherwise you would need to transform that text into paths in the postprocessing before rendering, like so:

let mut fontdb = fontdb::Database::new();
fontdb.load_system_fonts();

let mut rtree = usvg::Tree::from_str(&svg_data, &opt).unwrap();
let steps = usvg::PostProcessingSteps {
    convert_text_into_paths: true,
};
rtree.postprocess(steps, &fontdb);
like image 71
frankenapps Avatar answered Oct 23 '25 23:10

frankenapps



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!