typst / svg2pdf

Converts SVG files to PDF.
Apache License 2.0
273 stars 32 forks source link

svg input differs to pdf output #63

Closed Guelakais closed 5 months ago

Guelakais commented 5 months ago

I thought you might be interested. I am currently creating .svg files using Poloto and was wondering why my plots suddenly become informationless when I save them as .pdf. You can have a look at the files from my gitlab project for comparison. The .svg were first translated with your library and then again with inkscape. So from my point of view you are just as good as inkscape at translating .svg to .pdf.

Guelakais commented 5 months ago

False alarm. Inkscape is better than you.

LaurenzV commented 5 months ago

I'm not following, is there an SVG that is converted differently from what you expected? I tried the bar.svg and it looks fine to me: test.pdf

Guelakais commented 5 months ago

Then please help me with which settings you did that. I have now set up the code like this and all the labels are now gone.

use std::fs::write;
use svg2pdf::{convert_str,Options};

fn main() {
    let data = [
        (2.327473685, "Rust-bio"),
        (38.339006423950195, "Python"),
        (0.258953, "Julia"),
    ];

    let svg = poloto::build::bar::gen_simple("", data, [0.00])
        .label(("Comparison of Programming Language Runtime", "Runtime in Seconds", "Languages"))
        .append_to(poloto::header().light_theme())
        .render_string().unwrap();
    let pdf = convert_str(
        &svg,
        Options::default()
        ).unwrap();

    write("bar.pdf", pdf).unwrap();
}
LaurenzV commented 5 months ago

See the documentation for convert_str, it doesn't load any fonts, and thus cannot convert any text. You should do something like this instead:

use std::fs::write;
use svg2pdf::{Options, usvg};
use svg2pdf::usvg::{fontdb, PostProcessingSteps, TreeParsing, TreePostProc};

fn main() {
    let data = [
        (2.327473685, "Rust-bio"),
        (38.339006423950195, "Python"),
        (0.258953, "Julia"),
    ];

    let svg = poloto::build::bar::gen_simple("", data, [0.00])
        .label(("Comparison of Programming Language Runtime", "Runtime in Seconds", "Languages"))
        .append_to(poloto::header().light_theme())
        .render_string().unwrap();

    let mut tree = usvg::Tree::from_str(&svg, &usvg::Options::default()).unwrap();

    let mut db = fontdb::Database::new();
    db.load_system_fonts();
    tree.postprocess(PostProcessingSteps::default(), &db);

    let pdf = svg2pdf::convert_tree(&tree, Options::default());

    write("bar.pdf", pdf).unwrap();
}
Guelakais commented 5 months ago

That's weird. The labelling is still missing. Are you loading the library with a different version number?

Guelakais commented 5 months ago

I have now rewritten the code as follows and as you can see by simply calling up the two generated files in Firefox, the outputs are not congruent.

use std::fs::write;
use svg2pdf::{
    Options, 
    usvg,
    usvg::{fontdb, PostProcessingSteps, TreeParsing, TreePostProc},
};

fn main() {
    let data = [
        (2.327473685, "Rust-bio"),
        (38.339006423950195, "Python"),
        (0.258953, "Julia"),
    ];

    let svg = poloto::build::bar::gen_simple("", data, [0.00])
        .label(("Comparison of Programming Language Runtime", "Runtime in Seconds", "Languages"))
        .append_to(poloto::header().light_theme())
        .render_string().unwrap();

    let mut tree = usvg::Tree::from_str(&svg, &usvg::Options::default()).unwrap();

    let mut db = fontdb::Database::new();
    db.load_system_fonts();
    tree.postprocess(PostProcessingSteps::default(), &db);

    let pdf = svg2pdf::convert_tree(&tree, Options::default());

    write("bar.svg", svg).unwrap();
    write("bar.pdf", pdf).unwrap();
}

This can also be observed using the following link.

LaurenzV commented 5 months ago

Hmm, as I said, for me the text shows up fine... I suspect that it's a font fallback issue. Are you sure you have Roboto installed on your system? Usually it should fallback to another font in case that is not the case, but looks like it doesn't do that here and fails silently. But you can try the following:

Install resvg 0.38 (it uses the same underlying library as us for font loading, so if it fails there, it's probably an upstream issue): cargo install resvg --version ^0.38

Then run resvg bar.svg bar.png. If the text is missing there as well, it's most likely an upstream issue. If not, then it might be an issue on our side... But since I can't reproduce it, I also can't really investigate it.

You can also verify that svg2pdf can find your fonts by installing the CLI and running svg2pdf fonts.

Guelakais commented 5 months ago

What do you mean by Roboto? I couldn't find any reference to this in the documentation other than the readme.

LaurenzV commented 5 months ago

Roboto is a font. It's the one that is used in your SVG:

.poloto{
  stroke-linecap:round;
  stroke-linejoin:round;
  font-family:Roboto,sans-serif;
  font-size:16px;
}
Guelakais commented 5 months ago

That would be super weird, because the svg is created correctly and also has all the features and only the pdf is suddenly without labelling. I'll give it a try. Since I have a Nixos, I have to compile the operating system for new packages every time. So see you soon.

Guelakais commented 5 months ago

OK, I've installed it. Still not working. I mean, it's not that bad. I can still turn an .svg into a .pdf using inkscape.

LaurenzV commented 5 months ago

Hmm, yeah, sorry then... It's hard for me to debug if I can't reproduce it locally. But I'm still 99% sure it's some kind of font issue, because apart from font loading, everything should work independently from the platform...

LaurenzV commented 5 months ago

Since I'm 99% sure it's a font loading/fallback issue, I'll close this in favor of #65.