danfickle / openhtmltopdf

An HTML to PDF library for the JVM. Based on Flying Saucer and Apache PDF-BOX 2. With SVG image support. Now also with accessible PDF support (WCAG, Section 508, PDF/UA)!
https://danfickle.github.io/pdf-templates/index.html
Other
1.86k stars 348 forks source link

SVG images not supported as background via CSS #750

Open nukul4r opened 2 years ago

nukul4r commented 2 years ago

In our project, we are using PdfRendererBuilder.withW3cDocument to convert a HTML document to PDF. In this input, we use CSS to define a background image:

.logo {
  background-image: url("logo.svg");
}

When the PDF is rendered, we get the following stacktrace:

Can't read image file; unexpected problem for URI '.../logo.svg'

java.io.IOException: Unrecognized Image format
    at com.openhtmltopdf.pdfboxout.PdfBoxImage.<init>(PdfBoxImage.java:44)
    at com.openhtmltopdf.pdfboxout.PdfBoxUserAgent.getImageResource(PdfBoxUserAgent.java:90)
    at com.openhtmltopdf.render.AbstractOutputDevice.getBackgroundImage(AbstractOutputDevice.java:210)
    at com.openhtmltopdf.render.AbstractOutputDevice.paintBackground0(AbstractOutputDevice.java:295)
    at com.openhtmltopdf.render.AbstractOutputDevice.paintBackground(AbstractOutputDevice.java:234)
    at com.openhtmltopdf.pdfboxout.PdfBoxFastOutputDevice.paintBackground(PdfBoxFastOutputDevice.java:283)
    at com.openhtmltopdf.render.Box.paintBackground(Box.java:583)
    at com.openhtmltopdf.render.displaylist.DisplayListPainter.paintBackgroundAndBorders(DisplayListPainter.java:75)
    at com.openhtmltopdf.render.displaylist.DisplayListPainter.paint(DisplayListPainter.java:251)
    at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.paintPageFast(PdfBoxRenderer.java:921)
    at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.writePDFFast(PdfBoxRenderer.java:617)
    at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.createPdfFast(PdfBoxRenderer.java:554)
    at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.createPDF(PdfBoxRenderer.java:480)
    at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.createPDF(PdfBoxRenderer.java:417)
    at com.openhtmltopdf.pdfboxout.PdfBoxRenderer.createPDF(PdfBoxRenderer.java:399)
    at com.openhtmltopdf.pdfboxout.PdfRendererBuilder.run(PdfRendererBuilder.java:46)
[...]

When we add the SVG directly to the HTML (with <img src="classpath:static/public/img/logo.svg"></img>), the image is rendered correctly. To make this work, we add the com.openhtmltopdf.svgsupport.BatikSVGDrawer inPdfRendererBuilder.useSVGDrawer.

The cause seems to be, that the SVG drawer is not used when rendering the background.

Thanks!

omna-manz commented 2 years ago

Hi, we face to exactly same problem during rendering the SVG file, when we use CSS to define a background image. I have tested it with both relative address and data-URI:

.icon-at {
  background-image: url("images/flag-at.svg");
}

//////// OR ///////

.icon-at {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='1000' height='600' viewBox='0 0 5 3'><desc>Flag of Germany</desc><rect id='red_stripe ' width='5' height='3' y='0' x='0' fill='#ed2939'/><rect id='white_stripe' width='5' height='2' y='1' x='0' fill='#FFF'/><rect id='red_stripe2' width='5' height='1' y='2' x='0' fill='#ed2939'/></svg>");
}
omna-manz commented 2 years ago

Hello again,

By my last check, I have found that might be change code in AbstractOutputDevice.paintBackground0() where is checkd whether backgroundImage is GRADIENT or URI. I think it should be check again if URI contains ".svg", then draws a SVG file instead of Image.

In other words, It should create XMLResource instead of ImageResource.

I hope it was helpful. :)

danfickle commented 2 years ago

Thanks @omna-manz,

SVG background images are likely to get in the next release. Stay tuned.

omna-manz commented 2 years ago

Thank you @danfickle, It is a great news :)

NiroshaDilan commented 1 year ago

@danfickle Is there a fix for this issue?

jochenberger commented 1 year ago

Has anybody found a way to get this to work? Or can we come up with a PR?

jochenberger commented 1 year ago

See also #583.

jochenberger commented 1 year ago

I tried to create a PR but I'm not sure where to put the logic. My first attempt was to add the code to the AbstractOutputDevice, but we have no access to the Box there. Then I tried to use the ReplacedElementFactory to turn the SVG into PNG and replace the url, but that didn't seem to have an effect. Can somebody advise? In the meantime, my workaround is to replace the SVG data-urls with PNG data-urls in the HTML as a pre-processing step.

Abhinandan578 commented 7 months ago

I am also facing the same issue with SVG binary images. They are not getting loaded. I am using docx4j-ImportXHTML (11.4.8) which is calling openhtmltopdf-core(1.0.10). Can someone please help here

jochenberger commented 1 month ago

See https://github.com/openhtmltopdf/openhtmltopdf/issues/32