Skip to content

Commit 19c9293

Browse files
committed
Support of SVG tag when using HtmlConverter#convertToElements
DEVSIX-3891
1 parent 7691ca9 commit 19c9293

22 files changed

+204
-116
lines changed

src/main/java/com/itextpdf/html2pdf/attach/impl/tags/ImgTagWorker.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ This file is part of the iText (R) project.
3636
import com.itextpdf.layout.element.Image;
3737
import com.itextpdf.layout.properties.ObjectFit;
3838
import com.itextpdf.styledxmlparser.node.IElementNode;
39+
import com.itextpdf.svg.element.SvgImage;
40+
import com.itextpdf.svg.xobject.SvgImageXObject;
3941
import org.slf4j.Logger;
4042
import org.slf4j.LoggerFactory;
4143

@@ -71,6 +73,8 @@ public ImgTagWorker(IElementNode element, ProcessorContext context) {
7173
if (imageXObject != null) {
7274
if (imageXObject instanceof PdfImageXObject) {
7375
image = new HtmlImage((PdfImageXObject) imageXObject);
76+
} else if (imageXObject instanceof SvgImageXObject) {
77+
image = new SvgImage((SvgImageXObject) imageXObject);
7478
} else if (imageXObject instanceof PdfFormXObject) {
7579
image = new HtmlImage((PdfFormXObject) imageXObject);
7680
} else {

src/main/java/com/itextpdf/html2pdf/attach/impl/tags/ObjectTagWorker.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ This file is part of the iText (R) project.
3131
import com.itextpdf.html2pdf.util.SvgProcessingUtil;
3232
import com.itextpdf.commons.utils.FileUtil;
3333
import com.itextpdf.commons.utils.MessageFormatUtil;
34-
import com.itextpdf.kernel.pdf.PdfDocument;
3534
import com.itextpdf.layout.IPropertyContainer;
3635
import com.itextpdf.layout.element.Image;
3736
import com.itextpdf.styledxmlparser.node.IElementNode;
@@ -117,17 +116,10 @@ private boolean isSvgImage(String typeAttribute) {
117116

118117
@Override
119118
public void processEnd(IElementNode element, ProcessorContext context) {
120-
if (context.getPdfDocument() != null) {
121-
PdfDocument document = context.getPdfDocument();
122-
//Create Image object
123-
124-
if (res != null) {
125-
image = processUtil.createImageFromProcessingResult(res, document);
126-
AccessiblePropHelper.trySetLangAttribute(image, element);
127-
}
128-
129-
} else {
130-
LOGGER.error(Html2PdfLogMessageConstant.PDF_DOCUMENT_NOT_PRESENT);
119+
// Create Image object
120+
if (res != null) {
121+
image = processUtil.createSvgImageFromProcessingResult(res);
122+
AccessiblePropHelper.trySetLangAttribute(image, element);
131123
}
132124
}
133125

src/main/java/com/itextpdf/html2pdf/attach/impl/tags/SvgTagWorker.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ public SvgTagWorker(IElementNode element, ProcessorContext context) {
6868

6969
@Override
7070
public void processEnd(IElementNode element, ProcessorContext context) {
71-
if (context.getPdfDocument() != null && processingResult != null) {
71+
if (processingResult != null) {
7272
SvgProcessingUtil util = new SvgProcessingUtil(context.getResourceResolver());
73-
svgImage = util.createImageFromProcessingResult(processingResult, context.getPdfDocument());
73+
svgImage = util.createSvgImageFromProcessingResult(processingResult);
7474

7575
AccessiblePropHelper.trySetLangAttribute(svgImage, element);
7676
context.endProcessingInlineSvg();

src/main/java/com/itextpdf/html2pdf/css/apply/util/BackgroundApplierUtil.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ This file is part of the iText (R) project.
2626
import com.itextpdf.html2pdf.attach.ProcessorContext;
2727
import com.itextpdf.html2pdf.css.CssConstants;
2828
import com.itextpdf.commons.utils.MessageFormatUtil;
29-
import com.itextpdf.kernel.colors.Color;
30-
import com.itextpdf.kernel.colors.DeviceRgb;
3129
import com.itextpdf.kernel.colors.gradients.StrategyBasedLinearGradientBuilder;
3230
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
3331
import com.itextpdf.kernel.pdf.xobject.PdfImageXObject;

src/main/java/com/itextpdf/html2pdf/css/apply/util/ListStyleApplierUtil.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ This file is part of the iText (R) project.
5353
import com.itextpdf.styledxmlparser.node.IElementNode;
5454
import com.itextpdf.styledxmlparser.node.IStylesContainer;
5555

56+
import com.itextpdf.svg.element.SvgImage;
57+
import com.itextpdf.svg.xobject.SvgImageXObject;
5658
import org.slf4j.Logger;
5759
import org.slf4j.LoggerFactory;
5860

@@ -145,6 +147,8 @@ public static void applyListStyleImageProperty(Map<String, String> cssProps, Pro
145147
Image image = null;
146148
if (imageXObject instanceof PdfImageXObject) {
147149
image = new Image((PdfImageXObject) imageXObject);
150+
} else if (imageXObject instanceof SvgImageXObject) {
151+
image = new SvgImage((SvgImageXObject) imageXObject);
148152
} else if (imageXObject instanceof PdfFormXObject) {
149153
image = new Image((PdfFormXObject) imageXObject);
150154
} else {

src/main/java/com/itextpdf/html2pdf/logs/Html2PdfLogMessageConstant.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public final class Html2PdfLogMessageConstant {
119119
public static final String PAGE_SIZE_VALUE_IS_INVALID = "Page size value {0} is invalid.";
120120

121121
/** The Constant PDF_DOCUMENT_NOT_PRESENT. */
122+
@Deprecated
122123
public static final String PDF_DOCUMENT_NOT_PRESENT = "PdfDocument is not present";
123124

124125
/** The Constant QUOTES_PROPERTY_INVALID. */

src/main/java/com/itextpdf/html2pdf/resolver/resource/HtmlResourceResolver.java

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ This file is part of the iText (R) project.
3232
import com.itextpdf.styledxmlparser.resolver.resource.IResourceRetriever;
3333
import com.itextpdf.styledxmlparser.resolver.resource.ResourceResolver;
3434
import com.itextpdf.svg.converter.SvgConverter;
35+
import com.itextpdf.svg.element.SvgImage;
3536
import com.itextpdf.svg.processors.ISvgProcessorResult;
3637
import com.itextpdf.svg.processors.impl.SvgConverterProperties;
3738

@@ -49,7 +50,7 @@ public class HtmlResourceResolver extends ResourceResolver {
4950
private static final String SVG_PREFIX = "data:image/svg+xml";
5051
private static final Pattern SVG_IDENTIFIER_PATTERN = Pattern.compile(",[\\s]*(<svg )");
5152

52-
private ProcessorContext context;
53+
private final ProcessorContext context;
5354

5455
/**
5556
* Creates a new {@link HtmlResourceResolver} instance.
@@ -108,7 +109,7 @@ protected PdfXObject tryResolveBase64ImageSource(String src) {
108109
if (fixedSrc.startsWith(SVG_PREFIX)) {
109110
fixedSrc = fixedSrc.substring(fixedSrc.indexOf(BASE64_IDENTIFIER) + BASE64_IDENTIFIER.length() + 1);
110111
try (ByteArrayInputStream stream = new ByteArrayInputStream(Base64.decode(fixedSrc))) {
111-
PdfFormXObject xObject = processAsSvg(stream, context, null);
112+
PdfFormXObject xObject = HtmlResourceResolver.processAsSvg(stream, context, null);
112113
if (xObject != null) {
113114
return xObject;
114115
}
@@ -131,7 +132,7 @@ protected PdfXObject createImageByUrl(URL url) throws Exception {
131132

132133
private PdfXObject tryResolveSvgImageSource(String src) {
133134
try (ByteArrayInputStream stream = new ByteArrayInputStream(src.getBytes(StandardCharsets.UTF_8))) {
134-
PdfFormXObject xObject = processAsSvg(stream, context, null);
135+
PdfFormXObject xObject = HtmlResourceResolver.processAsSvg(stream, context, null);
135136
if (xObject != null) {
136137
return xObject;
137138
}
@@ -147,11 +148,7 @@ private static PdfFormXObject processAsSvg(InputStream stream, ProcessorContext
147148
svgConverterProperties.setBaseUri(parentDir);
148149
}
149150
ISvgProcessorResult res = SvgConverter.parseAndProcess(stream, svgConverterProperties);
150-
if (context.getPdfDocument() != null) {
151-
SvgProcessingUtil processingUtil = new SvgProcessingUtil(context.getResourceResolver());
152-
return processingUtil.createXObjectFromProcessingResult(res, context.getPdfDocument());
153-
} else {
154-
return null;
155-
}
151+
SvgProcessingUtil processingUtil = new SvgProcessingUtil(context.getResourceResolver());
152+
return processingUtil.createXObjectFromProcessingResult(res, context.getPdfDocument());
156153
}
157154
}

src/main/java/com/itextpdf/html2pdf/util/SvgProcessingUtil.java

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,14 @@ This file is part of the iText (R) project.
2424

2525
import com.itextpdf.kernel.geom.Rectangle;
2626
import com.itextpdf.kernel.pdf.PdfDocument;
27-
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
2827
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
2928
import com.itextpdf.layout.element.Image;
3029
import com.itextpdf.styledxmlparser.resolver.resource.ResourceResolver;
3130
import com.itextpdf.svg.converter.SvgConverter;
31+
import com.itextpdf.svg.element.SvgImage;
3232
import com.itextpdf.svg.processors.ISvgProcessorResult;
33-
import com.itextpdf.svg.processors.impl.SvgProcessorResult;
3433
import com.itextpdf.svg.renderers.ISvgNodeRenderer;
35-
import com.itextpdf.svg.renderers.SvgDrawContext;
36-
import com.itextpdf.svg.renderers.impl.PdfRootSvgNodeRenderer;
37-
import com.itextpdf.svg.utils.SvgCssUtils;
34+
import com.itextpdf.svg.xobject.SvgImageXObject;
3835

3936
/**
4037
* Utility class for handling operations related to SVG
@@ -53,45 +50,48 @@ public SvgProcessingUtil(ResourceResolver resourceResolver) {
5350
}
5451

5552
/**
56-
* Create an {@code Image} layout object tied to the passed {@code PdfDocument} using the SVG processing result.
57-
* @param result Processing result containing the SVG information
53+
* Create {@code SvgImage} layout object tied to the passed {@code PdfDocument} using the SVG processing result.
54+
*
55+
* @param result processing result containing the SVG information
5856
* @param pdfDocument pdf that shall contain the image
59-
* @return image layout object
57+
*
58+
* @return SVG image layout object
6059
*/
6160
public Image createImageFromProcessingResult(ISvgProcessorResult result, PdfDocument pdfDocument) {
62-
PdfFormXObject xObject = createXObjectFromProcessingResult(result, pdfDocument);
63-
return new Image(xObject);
61+
SvgImageXObject xObject = (SvgImageXObject) createXObjectFromProcessingResult(result, pdfDocument);
62+
return new SvgImage(xObject);
63+
}
64+
65+
/**
66+
* Create {@code SvgImage} layout object using the SVG processing result.
67+
*
68+
* @param result processing result containing the SVG information
69+
*
70+
* @return SVG image layout object
71+
*/
72+
public Image createSvgImageFromProcessingResult(ISvgProcessorResult result) {
73+
return createImageFromProcessingResult(result, null);
6474
}
6575

6676
/**
6777
* Create an {@link PdfFormXObject} tied to the passed {@code PdfDocument} using the SVG processing result.
68-
* @param result Processing result containing the SVG information
69-
* @param pdfDocument pdf that shall contain the image
70-
* @return PdfFormXObject instance
78+
*
79+
* @param result processing result containing the SVG information
80+
* @param pdfDocument pdf that shall contain the SVG image
81+
*
82+
* @return {@link SvgImageXObject} instance
7183
*/
72-
public PdfFormXObject createXObjectFromProcessingResult(ISvgProcessorResult result, PdfDocument pdfDocument){
84+
public PdfFormXObject createXObjectFromProcessingResult(ISvgProcessorResult result, PdfDocument pdfDocument) {
7385
ISvgNodeRenderer topSvgRenderer = result.getRootRenderer();
7486
float width, height;
7587
float[] wh = SvgConverter.extractWidthAndHeight(topSvgRenderer);
7688
width = wh[0];
7789
height = wh[1];
78-
PdfFormXObject pdfForm = new PdfFormXObject(new Rectangle(0, 0, width, height));
79-
PdfCanvas canvas = new PdfCanvas(pdfForm, pdfDocument);
80-
81-
ResourceResolver tempResolver = new ResourceResolver(null, resourceResolver.getRetriever());
82-
// TODO DEVSIX-4107 pass the resourceResolver variable (not tempResolver variable) to the
83-
// SvgDrawContext constructor so that the SVG inside the SVG is processed.
84-
SvgDrawContext context = new SvgDrawContext(tempResolver, result.getFontProvider());
85-
if (result instanceof SvgProcessorResult) {
86-
context.setCssContext(((SvgProcessorResult) result).getContext().getCssContext());
90+
SvgImageXObject svgImageXObject =
91+
new SvgImageXObject(new Rectangle(0, 0, width, height), result, resourceResolver);
92+
if (pdfDocument != null) {
93+
svgImageXObject.generate(pdfDocument);
8794
}
88-
context.addNamedObjects(result.getNamedObjects());
89-
context.pushCanvas(canvas);
90-
91-
ISvgNodeRenderer root = new PdfRootSvgNodeRenderer(topSvgRenderer);
92-
93-
root.draw(context);
94-
95-
return pdfForm;
95+
return svgImageXObject;
9696
}
9797
}

0 commit comments

Comments
 (0)