* Alongside http different URI protocols are supported. These are handled by classes extending
* {@link PdfReplaceHandler}.
@@ -32,6 +38,8 @@
public class ImageReplacedElementFactory extends ITextReplacedElementFactory {
private static final String TAG_TYPE_IMG = "img";
+ private static final String TAG_TYPE_SVG = "svg";
+
private static final String ATTR_SRC = "src";
@PriorityParts(PdfReplaceHandler.class)
@@ -57,25 +65,60 @@ public ReplacedElement createReplacedElement(LayoutContext layoutContext,
return null;
}
+ return this.tryCreateReplacedImageElement(element, userAgentCallback, cssWidth, cssHeight)
+ .or(() -> this.tryCreateReplacedSvgElement(element, cssWidth, cssHeight))
+ .orElseGet(() -> super.createReplacedElement(layoutContext,
+ box,
+ userAgentCallback,
+ cssWidth,
+ cssHeight));
+ }
+
+ private Optional
+ * The SVG is rendered into a PDF template via Apache Batik and then placed into the PDF.
+ *
+ * @see Stackoverflow
+ */
+public class InlinedSvgElement implements ITextReplacedElement {
+
+ private final Point location = new Point(0, 0);
+ private final Document svg;
+ private final int cssWidth;
+ private final int cssHeight;
+
+ protected InlinedSvgElement(Document svg, int cssWidth, int cssHeight) {
+ this.svg = svg;
+ this.cssWidth = cssWidth;
+ this.cssHeight = cssHeight;
+ }
+
+ @Override
+ public void paint(RenderingContext renderingContext, ITextOutputDevice outputDevice, BlockBox blockBox) {
+ PdfContentByte contentByte = outputDevice.getWriter().getDirectContent();
+ float width = cssWidth / outputDevice.getDotsPerPoint();
+ float height = cssHeight / outputDevice.getDotsPerPoint();
+
+ Paper paper = new Paper();
+ paper.setSize(width, height);
+ paper.setImageableArea(0, 0, width, height);
+
+ PageFormat pageFormat = new PageFormat();
+ pageFormat.setPaper(paper);
+
+ PdfTemplate template = contentByte.createTemplate(width, height);
+ Graphics2D graphics = template.createGraphics(width, height);
+ PrintTranscoder printTranscoder = new PrintTranscoder();
+ TranscoderInput transcoderInput = new TranscoderInput(svg);
+ printTranscoder.transcode(transcoderInput, null);
+ printTranscoder.print(graphics, pageFormat, 0);
+ graphics.dispose();
+
+ PageBox page = renderingContext.getPage();
+ float x = (float) blockBox.getAbsX() + page.getMarginBorderPadding(renderingContext, CalculatedStyle.LEFT);
+ float y = (float) (page.getBottom() - (blockBox.getAbsY() + cssHeight)) + page.getMarginBorderPadding(
+ renderingContext,
+ CalculatedStyle.BOTTOM);
+ x /= outputDevice.getDotsPerPoint();
+ y /= outputDevice.getDotsPerPoint();
+
+ contentByte.addTemplate(template, x, y);
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return cssWidth;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return cssHeight;
+ }
+
+ @Override
+ public Point getLocation() {
+ return location;
+ }
+
+ @Override
+ public void setLocation(int x, int y) {
+ location.setLocation(x, y);
+ }
+
+ @Override
+ public void detach(LayoutContext layoutContext) {
+ // nothing to do
+ }
+
+ @Override
+ public boolean isRequiresInteractivePaint() {
+ return false;
+ }
+
+ @Override
+ public boolean hasBaseline() {
+ return false;
+ }
+
+ @Override
+ public int getBaseline() {
+ return 0;
+ }
+}