OpenPDF icon indicating copy to clipboard operation
OpenPDF copied to clipboard

svg file support in OpenPDF

Open pronabb opened this issue 7 years ago • 3 comments

Hi, We want to use SVG files to add icons in PDF. Is there any standard way to do that using OpenPDF?

pronabb avatar Jun 06 '18 20:06 pronabb

In the old iText version you could use PDF files in the src Attribute of img Tags - if done so it does include the vector graphics inside this other PDF - that's what I've used in the past to workaround adding SVGs

peda avatar Sep 04 '18 13:09 peda

You can try to use Apache Batik library for that. It’s need to make the following steps:

  1. Create org.w3c.dom.svg.SVGDocument:
SAXSVGDocumentFactory factory = new org.apache.batik.anim.dom.SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName());
factory.createSVGDocument("", InputStream);
  1. Create a org.apache.batik.gvt.GraphicsNode from the org.w3c.dom.svg.SVGDocument:
org.apache.batik.bridge.UserAgent userAgent = new 
org.apache.batik.bridge.UserAgentAdapter();
org.apache.batik.bridge.DocumentLoader loader = new org.apache.batik.bridge.DocumentLoader(userAgent);
// Notice, that you should use org.apache.batik.bridge.svg12.SVG12BridgeContext.SVG12BridgeContext for the svg version 1.2

org.apache.batik.bridge.BridgeContext context = new org.apache.batik.bridge.BridgeContext(userAgent, loader);
context.setDynamicState(
org.apache.batik.bridge.BridgeContext.DYNAMIC);

org.apache.batik.bridge.GVTBuilder builder = new 
org.apache.batik.bridge.GVTBuilder();
org.apache.batik.gvt.GraphicsNode rootGraphicsNode = builder.build(context, SVGDocument);
  1. Define the size attributes in the SVGDocument if they are absent, sinse GVTBuilder analyzes the size attributes of the SVGDocument later by painting (otherwise exception will be thrown).
  2. Create PDFTemplate: PdfTemplate template = com.lowagie.text.pdf.PdfTemplate.createTemplate(PdfWriter writer, float svgImageWidthInPx, float svgImageHeightInPx);
  3. Create graphics from this template and draw the graphic node with it:
Graphics2D g2d = template.createGraphics(template.getWidth(), template.getHeight(), FontMapper);
try {
    rootGraphicsNode.paint(g2d);
} finally {
    g2d.dispose();
}
  1. Create com.lowagie.text.Image object that you can use where you want. new com.lowagie.text.ImgTemplate.ImgTemplate (template);

Notice, that you can use the same instance of the image object as you need to use the same image in pdf file. It helps to reduce the size of the generated pdf file.

V-F avatar Sep 17 '19 10:09 V-F

This solution is partially works for me. But result image is cut off by height. So i have to increase height for template creation. Getting of size code:

float svgImageWidthInPx = (float) rootGraphicsNode.getPrimitiveBounds().getWidth();
float svgImageHeightInPx = (float) rootGraphicsNode.getPrimitiveBounds().getHeight();

Is i made something wrong?

RangerMak avatar Mar 19 '20 12:03 RangerMak

@RangerMak I have notice, that rootGraphicsNode.getPrimitiveBounds() gets the size of the content from the SVG, not the viewbox. To have the correct size and avoid the image to be cut, I need to add a rectangle as a "background" with the same size that the desired viewbox size. Then, all image is shown on the PDF without cutting it.

From my tests, you can use a transparent rectangle, and the size will be obtained correctly, without adding any undesired background color to the image.

softwaremagico avatar Feb 22 '24 11:02 softwaremagico