wkhtmltopdf missing SVG paths (Rendering)
Asked Answered
T

2

16

I'm using a image inside the HMTL code like here below:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Test</title>
  </head>
  <body>
    <svg height="291pt" version="1.1" viewBox="0 0 291 291" width="291pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs>  <style type="text/css">*{stroke-linecap:butt;stroke-linejoin:round;}  </style> </defs> <g id="figure_1">  <g id="patch_1">   <path d="M 0 291.4 L 291.4 291.4 L 291.4 0 L 0 0 z" style="fill:none;"></path>  </g>  <g id="axes_1">   <g id="line2d_1">    <path clip-path="url(#p6e64365aaf)" d="M 268.427273 145.7 L 207.063636 251.984936 " style="fill:none;stroke:#000000;stroke-linecap:square;stroke-width:1.2;"></path>   </g>   <g id="line2d_2">    <path clip-path="url(#p6e64365aaf)" d="M 248.397453 148.307103 L 199.306544 233.335052 " style="fill:none;stroke:#000000;stroke-linecap:square;stroke-width:1.2;"></path>   </g>   <g id="line2d_3">    <path clip-path="url(#p6e64365aaf)" d="M 207.063636 251.984936 L 84.336364 251.984936 " style="fill:none;stroke:#000000;stroke-linecap:square;stroke-width:1.2;"></path>   </g>   <g id="line2d_4">    <path clip-path="url(#p6e64365aaf)" d="M 84.336364 251.984936 L 22.972727 145.7 " style="fill:none;stroke:#000000;stroke-linecap:square;stroke-width:1.2;"></path>   </g>   <g id="line2d_5">    <path clip-path="url(#p6e64365aaf)" d="M 92.093456 233.335052 L 43.002547 148.307103 " style="fill:none;stroke:#000000;stroke-linecap:square;stroke-width:1.2;"></path>   </g>   <g id="line2d_6">    <path clip-path="url(#p6e64365aaf)" d="M 22.972727 145.7 L 84.336364 39.415064 " style="fill:none;stroke:#000000;stroke-linecap:square;stroke-width:1.2;"></path>   </g>   <g id="line2d_7">    <path clip-path="url(#p6e64365aaf)" d="M 84.336364 39.415064 L 207.063636 39.415064 " style="fill:none;stroke:#000000;stroke-linecap:square;stroke-width:1.2;"></path>   </g>   <g id="line2d_8">    <path clip-path="url(#p6e64365aaf)" d="M 96.609091 55.457845 L 194.790909 55.457845 " style="fill:none;stroke:#000000;stroke-linecap:square;stroke-width:1.2;"></path>   </g>   <g id="line2d_9">    <path clip-path="url(#p6e64365aaf)" d="M 207.063636 39.415064 L 268.427273 145.7 " style="fill:none;stroke:#000000;stroke-linecap:square;stroke-width:1.2;"></path>   </g>  </g> </g> <defs>  <clipPath id="p6e64365aaf">   <rect height="270" width="270" x="10.7" y="10.7"></rect>  </clipPath> </defs></svg>
  </body>
</html>

When I'm using the wkhtmltopdf to convert it to PDF, some of the SVG paths is missing. Has anyone had the same problem? Some workaround to this issue?

I tried using the relative path, full path, base64 source and the SVG by itself within the code (as in the example).

wkhtmltopdf version: 0.12.4

The image on the PDF file

Taperecord answered 23/4, 2018 at 17:38 Comment(1)
I'm not sure if it helps, but it looks like the new versions from wkhtmltopdf (bitbucket) has solved this issue.Taperecord
M
6

So not a exact solution but a far better alternative now is to use a chrome in headless mode

$ chrome --headless --disable-gpu --print-to-pdf test.html
[0427/011400.636954:WARNING:dns_config_service_posix.cc(174)] dns_config has unhandled options!
[0427/011400.638406:ERROR:gpu_process_transport_factory.cc(1007)] Lost UI shared context.
[0427/011400.801881:INFO:headless_shell.cc(586)] Written to file output.pdf. 

PDF output

Also if you want better control on the process, you would use NodeJS and puppeteer

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('https://news.ycombinator.com', {waitUntil: 'networkidle2'});
  await page.pdf({path: 'hn.pdf', format: 'A4'});

  await browser.close();
})();
Melanoma answered 26/4, 2018 at 19:52 Comment(4)
Thanks a lot, but I really need to use Wkhtmltopdf because this is just a part of a big document that is converted from html to pdf in a Python (jinja2/pdfkit).Taperecord
Then I would suggest you open a bug on that repo, also chrome puppeteer has python bindings also, if I am not wrongMelanoma
I did it, but still no answer. I'll look for the google puppeteer.Taperecord
@IurySousa, If you do feel this answer will help don't forget to assign the bounty before it expires.Melanoma
B
1

A workaround is to convert the .SVG files to .PNG files before converting to .PDF. The .SVG code can be extracted via AgilityPack or read the files as a string. Then use the Svg library to convert to .PNG as follows:

var svg = SvgDocument.FromSvg<SvgDocument>(svgXmlAsString);
var bitmap = svg.Draw();
var codec = "image/png".ParseImageCodecInfo();
// intermediaryStream required due to image.Save attempting read access
using (var intermediaryStream = new MemoryStream())
{
    bitmap.Save(intermediaryStream, codec);
    intermediaryStream.Position = 0;
    await intermediaryStream.CopyToAsync(responseStream);
    await intermediaryStream.FlushAsync();
    await responseStream.FlushAsync();
}
Bravo answered 7/4, 2020 at 12:8 Comment(2)
Thank you @Joshcodes. It turned out I'm not in this project anymore, but your solution is very similar to what we did. We were looking for a way to keep in SVG format for printing quality reasons. Also, we were putting the images on a stripped table with different row colors. Which mean we needed to use an alpha for the PNG background color. But anyway, it worked this way.Taperecord
Thank you for the response. Our situation was very similar with regard to print quality and the alpha background.Bravo

© 2022 - 2024 — McMap. All rights reserved.