Skip to content

Commit 3c20626

Browse files
committed
Support PDF/A conversion for convertToElements method
DEVSIX-7932
1 parent b2f6aa6 commit 3c20626

File tree

14 files changed

+105
-55
lines changed

14 files changed

+105
-55
lines changed

src/main/java/com/itextpdf/html2pdf/ConverterProperties.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ This file is part of the iText (R) project.
3232
import com.itextpdf.styledxmlparser.css.media.MediaDeviceDescription;
3333
import com.itextpdf.styledxmlparser.resolver.resource.IResourceRetriever;
3434

35+
import java.io.InputStream;
36+
3537
/**
3638
* Properties that will be used by the {@link com.itextpdf.html2pdf.HtmlConverter}.
3739
*/
@@ -409,14 +411,18 @@ public ConverterProperties setCharset(String charset) {
409411
}
410412

411413
/**
412-
* Sets pdf output intent (final destination device) to reproduce the color in the PDF.
414+
* Sets pdf document output intent (final destination device) to reproduce the color in the PDF.
413415
* Required parameter, when converting to pdf/a one have to specify an explicit output intent.
414416
*
417+
* <p>
418+
* Note, output intent isn't applicable for HtmlConverter#convertToElements methods
419+
* (e.g. {@link HtmlConverter#convertToElements(InputStream, ConverterProperties)})
420+
*
415421
* @param outputIntent a {@link PdfOutputIntent} instance
416422
*
417423
* @return the {@link ConverterProperties} instance
418424
*/
419-
public ConverterProperties setOutputIntent(PdfOutputIntent outputIntent) {
425+
public ConverterProperties setDocumentOutputIntent(PdfOutputIntent outputIntent) {
420426
this.outputIntent = outputIntent;
421427
return this;
422428
}
@@ -435,11 +441,15 @@ public ConverterProperties setPdfAConformanceLevel(PdfAConformanceLevel conforma
435441
}
436442

437443
/**
438-
* Gets pdf output intent (final destination device) to reproduce the color in the PDF.
444+
* Gets pdf document output intent (final destination device) to reproduce the color in the PDF.
445+
*
446+
* <p>
447+
* Note, output intent isn't applicable for HtmlConverter#convertToElements methods
448+
* (e.g. {@link HtmlConverter#convertToElements(InputStream, ConverterProperties)})
439449
*
440450
* @return pdf output intent
441451
*/
442-
public PdfOutputIntent getOutputIntent() {
452+
public PdfOutputIntent getDocumentOutputIntent() {
443453
return outputIntent;
444454
}
445455

src/main/java/com/itextpdf/html2pdf/HtmlConverter.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ This file is part of the iText (R) project.
2222
*/
2323
package com.itextpdf.html2pdf;
2424

25+
import com.itextpdf.commons.actions.contexts.IMetaInfo;
26+
import com.itextpdf.commons.utils.FileUtil;
2527
import com.itextpdf.html2pdf.attach.Attacher;
2628
import com.itextpdf.html2pdf.exceptions.Html2PdfException;
27-
import com.itextpdf.commons.utils.FileUtil;
28-
import com.itextpdf.commons.actions.contexts.IMetaInfo;
2929
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
3030
import com.itextpdf.kernel.pdf.DocumentProperties;
3131
import com.itextpdf.kernel.pdf.PdfAConformanceLevel;
@@ -37,10 +37,10 @@ This file is part of the iText (R) project.
3737
import com.itextpdf.layout.element.IElement;
3838
import com.itextpdf.layout.properties.Property;
3939
import com.itextpdf.layout.renderer.MetaInfoContainer;
40+
import com.itextpdf.pdfa.PdfADocument;
4041
import com.itextpdf.styledxmlparser.IXmlParser;
4142
import com.itextpdf.styledxmlparser.node.IDocumentNode;
4243
import com.itextpdf.styledxmlparser.node.impl.jsoup.JsoupHtmlParser;
43-
import com.itextpdf.pdfa.PdfADocument;
4444

4545
import java.io.File;
4646
import java.io.FileInputStream;
@@ -123,7 +123,7 @@ public static void convertToPdf(String html, PdfWriter pdfWriter, ConverterPrope
123123
return;
124124
}
125125
PdfDocument document = new PdfADocument(pdfWriter, converterProperties.getConformanceLevel(),
126-
converterProperties.getOutputIntent(), new DocumentProperties()
126+
converterProperties.getDocumentOutputIntent(), new DocumentProperties()
127127
.setEventCountingMetaInfo(resolveMetaInfo(converterProperties)));
128128
converterProperties = setDefaultFontProviderForPdfA(document, converterProperties);
129129
if ("A".equals(converterProperties.getConformanceLevel().getConformance())) {
@@ -251,7 +251,7 @@ public static void convertToPdf(InputStream htmlStream, PdfWriter pdfWriter, Con
251251
return;
252252
}
253253
PdfDocument document = new PdfADocument(pdfWriter, converterProperties.getConformanceLevel(),
254-
converterProperties.getOutputIntent(), new DocumentProperties()
254+
converterProperties.getDocumentOutputIntent(), new DocumentProperties()
255255
.setEventCountingMetaInfo(resolveMetaInfo(converterProperties)));
256256
converterProperties = setDefaultFontProviderForPdfA(document, converterProperties);
257257
if ("A".equals(converterProperties.getConformanceLevel().getConformance())) {
@@ -405,6 +405,7 @@ public static List<IElement> convertToElements(InputStream htmlStream) throws IO
405405
* @return a list of iText building blocks
406406
*/
407407
public static List<IElement> convertToElements(String html, ConverterProperties converterProperties) {
408+
converterProperties = setDefaultFontProviderForPdfA(null, converterProperties);
408409
IXmlParser parser = new JsoupHtmlParser();
409410
IDocumentNode doc = parser.parse(html);
410411
return Attacher.attach(doc, converterProperties);
@@ -421,6 +422,7 @@ public static List<IElement> convertToElements(String html, ConverterProperties
421422
* @throws IOException Signals that an I/O exception has occurred.
422423
*/
423424
public static List<IElement> convertToElements(InputStream htmlStream, ConverterProperties converterProperties) throws IOException {
425+
converterProperties = setDefaultFontProviderForPdfA(null, converterProperties);
424426
IXmlParser parser = new JsoupHtmlParser();
425427
IDocumentNode doc = parser.parse(htmlStream, converterProperties != null ? converterProperties.getCharset() : null);
426428
return Attacher.attach(doc, converterProperties);
@@ -444,6 +446,10 @@ private static ConverterProperties setDefaultFontProviderForPdfA(PdfDocument doc
444446
if (properties.getFontProvider() == null) {
445447
properties.setFontProvider(new DefaultFontProvider(false, true, false));
446448
}
449+
} else if (document == null && properties != null && properties.getConformanceLevel() != null) {
450+
if (properties.getFontProvider() == null) {
451+
properties.setFontProvider(new DefaultFontProvider(false, true, false));
452+
}
447453
}
448454
return properties;
449455
}

src/main/java/com/itextpdf/html2pdf/attach/ProcessorContext.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ This file is part of the iText (R) project.
3636
import com.itextpdf.html2pdf.resolver.form.RadioCheckResolver;
3737
import com.itextpdf.html2pdf.resolver.resource.HtmlResourceResolver;
3838
import com.itextpdf.io.font.FontProgram;
39+
import com.itextpdf.kernel.pdf.PdfAConformanceLevel;
3940
import com.itextpdf.kernel.pdf.PdfDocument;
4041
import com.itextpdf.layout.font.FontInfo;
4142
import com.itextpdf.layout.font.FontProvider;
@@ -131,6 +132,11 @@ public class ProcessorContext {
131132
*/
132133
private PdfDocument pdfDocument;
133134

135+
/**
136+
* PDF/A conformance level from {@link ConverterProperties} instance.
137+
*/
138+
private final PdfAConformanceLevel pdfAConformanceLevelFromProperties;
139+
134140
/**
135141
* The Processor meta info
136142
*/
@@ -199,6 +205,7 @@ public ProcessorContext(ConverterProperties converterProperties) {
199205
formFieldNameResolver = new FormFieldNameResolver();
200206
radioCheckResolver = new RadioCheckResolver();
201207
immediateFlush = converterProperties.isImmediateFlush();
208+
pdfAConformanceLevelFromProperties = converterProperties.getConformanceLevel();
202209
processingInlineSvg = false;
203210
continuousContainerEnabled = converterProperties.isContinuousContainerEnabled();
204211
}
@@ -239,6 +246,15 @@ public PdfDocument getPdfDocument() {
239246
return pdfDocument;
240247
}
241248

249+
/**
250+
* Get the PDF document conformance level if specified.
251+
*
252+
* @return the {@link PdfAConformanceLevel} will be null if the processing result won't follow PDF/A strictness
253+
*/
254+
public PdfAConformanceLevel getConformanceLevel() {
255+
return pdfDocument == null ? pdfAConformanceLevelFromProperties : pdfDocument.getConformanceLevel();
256+
}
257+
242258
/**
243259
* Gets the font provider.
244260
*

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ public ButtonTagWorker(IElementNode element, ProcessorContext context) {
7676
}
7777
this.name = context.getFormFieldNameResolver().resolveFormName(name);
7878
flatten = !context.isCreateAcroForm();
79-
if (context.getPdfDocument() != null) {
80-
pdfAConformanceLevel = context.getPdfDocument().getConformanceLevel();
79+
if (context.getConformanceLevel() != null) {
80+
pdfAConformanceLevel = context.getConformanceLevel();
8181
}
8282
lang = element.getAttribute(AttributeConstants.LANG);
8383
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,8 @@ public InputTagWorker(IElementNode element, ProcessorContext context) {
161161
if (formElement != null) {
162162
formElement.setProperty(FormProperty.FORM_FIELD_FLATTEN, !context.isCreateAcroForm());
163163
formElement.setProperty(FormProperty.FORM_ACCESSIBILITY_LANGUAGE, lang);
164-
if (context.getPdfDocument() != null) {
165-
formElement.setProperty(FormProperty.FORM_CONFORMANCE_LEVEL,
166-
context.getPdfDocument().getConformanceLevel());
164+
if (context.getConformanceLevel() != null) {
165+
formElement.setProperty(FormProperty.FORM_CONFORMANCE_LEVEL, context.getConformanceLevel());
167166
}
168167
}
169168

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,8 @@ public SelectTagWorker(IElementNode element, ProcessorContext context) {
8484
String lang = element.getAttribute(AttributeConstants.LANG);
8585
selectElement.setProperty(FormProperty.FORM_ACCESSIBILITY_LANGUAGE, lang);
8686
selectElement.setProperty(FormProperty.FORM_FIELD_FLATTEN, !context.isCreateAcroForm());
87-
if (context.getPdfDocument() != null) {
88-
selectElement.setProperty(FormProperty.FORM_CONFORMANCE_LEVEL,
89-
context.getPdfDocument().getConformanceLevel());
87+
if (context.getConformanceLevel() != null) {
88+
selectElement.setProperty(FormProperty.FORM_CONFORMANCE_LEVEL, context.getConformanceLevel());
9089
}
9190
display = element.getStyles() != null ? element.getStyles().get(CssConstants.DISPLAY) : null;
9291
}

src/test/java/com/itextpdf/html2pdf/Html2ElementsTest.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,12 @@ This file is part of the iText (R) project.
3535
import com.itextpdf.io.util.UrlUtil;
3636
import com.itextpdf.kernel.exceptions.KernelExceptionMessageConstant;
3737
import com.itextpdf.kernel.exceptions.PdfException;
38+
import com.itextpdf.kernel.pdf.PdfAConformanceLevel;
3839
import com.itextpdf.kernel.pdf.PdfDocument;
40+
import com.itextpdf.kernel.pdf.PdfOutputIntent;
41+
import com.itextpdf.kernel.pdf.PdfVersion;
3942
import com.itextpdf.kernel.pdf.PdfWriter;
43+
import com.itextpdf.kernel.pdf.WriterProperties;
4044
import com.itextpdf.kernel.utils.CompareTool;
4145
import com.itextpdf.layout.Document;
4246
import com.itextpdf.layout.element.AreaBreak;
@@ -50,11 +54,13 @@ This file is part of the iText (R) project.
5054
import com.itextpdf.layout.properties.Leading;
5155
import com.itextpdf.layout.properties.Property;
5256
import com.itextpdf.layout.properties.UnitValue;
57+
import com.itextpdf.pdfa.PdfADocument;
5358
import com.itextpdf.styledxmlparser.logs.StyledXmlParserLogMessageConstant;
5459
import com.itextpdf.test.ExtendedITextTest;
5560
import com.itextpdf.test.annotations.LogMessage;
5661
import com.itextpdf.test.annotations.LogMessages;
5762
import com.itextpdf.test.annotations.type.IntegrationTest;
63+
import com.itextpdf.test.pdfa.VeraPdfValidator;
5864

5965
import java.io.File;
6066
import java.io.FileInputStream;
@@ -398,6 +404,31 @@ public void htmlToElementsFormTest() throws IOException, InterruptedException {
398404
}
399405

400406

407+
@Test
408+
public void htmlToElementsToPDFATest() throws IOException, InterruptedException {
409+
FileInputStream htmlFile = new FileInputStream(sourceFolder + "formelements.html");
410+
String cmpPdf = sourceFolder + "cmp_htmlToElementsFormsPDFA.pdf";
411+
String outPdf = destinationFolder + "htmlToElementsFormsPDFA.pdf";
412+
413+
PdfOutputIntent intent = new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
414+
new FileInputStream(sourceFolder + "sRGB Color Space Profile.icm"));
415+
List<IElement> elements = HtmlConverter.convertToElements(htmlFile,
416+
new ConverterProperties()
417+
.setBaseUri(sourceFolder)
418+
.setCreateAcroForm(true)
419+
.setPdfAConformanceLevel(PdfAConformanceLevel.PDF_A_4));
420+
try (Document document = new Document(
421+
new PdfADocument(new PdfWriter(outPdf, new WriterProperties().setPdfVersion(PdfVersion.PDF_2_0)),
422+
PdfAConformanceLevel.PDF_A_4, intent))) {
423+
for (IElement element : elements) {
424+
document.add((IBlockElement) element);
425+
}
426+
}
427+
Assert.assertNull(new VeraPdfValidator().validate(outPdf));
428+
Assert.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder));
429+
}
430+
431+
401432
private static void addElementsToDocument(Document document, List<IElement> elements) {
402433
for (IElement elem : elements) {
403434
if (elem instanceof IBlockElement) {

src/test/java/com/itextpdf/html2pdf/HtmlConverterPdfA3Test.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,10 @@ This file is part of the iText (R) project.
3131
import com.itextpdf.pdfa.PdfADocument;
3232
import com.itextpdf.pdfa.exceptions.PdfAConformanceException;
3333
import com.itextpdf.pdfa.exceptions.PdfaExceptionMessageConstant;
34-
import com.itextpdf.test.ExtendedITextTest;
3534
import com.itextpdf.test.LogLevelConstants;
3635
import com.itextpdf.test.annotations.LogMessage;
3736
import com.itextpdf.test.annotations.LogMessages;
3837
import com.itextpdf.test.annotations.type.IntegrationTest;
39-
import com.itextpdf.test.pdfa.VeraPdfValidator;
4038

4139
import java.io.FileInputStream;
4240
import java.io.FileOutputStream;
@@ -66,7 +64,7 @@ public void convertToPdfA3USimpleTest() throws IOException, InterruptedException
6664
String destinationPdf = DESTINATION_FOLDER + "simple.pdf";
6765
ConverterProperties converterProperties = new ConverterProperties();
6866
converterProperties.setPdfAConformanceLevel(PdfAConformanceLevel.PDF_A_3U);
69-
converterProperties.setOutputIntent(
67+
converterProperties.setDocumentOutputIntent(
7068
new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
7169
new FileInputStream(SOURCE_FOLDER + "sRGB Color Space Profile.icm")));
7270
try (FileInputStream fileInputStream = new FileInputStream(sourceHtml)) {
@@ -83,7 +81,7 @@ public void convertToPdfA3USimpleFromStringTest() throws IOException, Interrupte
8381
String destinationPdf = DESTINATION_FOLDER + "simple.pdf";
8482
ConverterProperties converterProperties = new ConverterProperties();
8583
converterProperties.setPdfAConformanceLevel(PdfAConformanceLevel.PDF_A_3U);
86-
converterProperties.setOutputIntent(
84+
converterProperties.setDocumentOutputIntent(
8785
new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
8886
new FileInputStream(SOURCE_FOLDER + "sRGB Color Space Profile.icm")));
8987
HtmlConverter.convertToPdf("<html>\n" +
@@ -105,7 +103,7 @@ public void convertToPdfA3ASimpleTest() throws IOException, InterruptedException
105103
String destinationPdf = DESTINATION_FOLDER + "simple_a.pdf";
106104
ConverterProperties converterProperties = new ConverterProperties();
107105
converterProperties.setPdfAConformanceLevel(PdfAConformanceLevel.PDF_A_3U);
108-
converterProperties.setOutputIntent(
106+
converterProperties.setDocumentOutputIntent(
109107
new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
110108
new FileInputStream(SOURCE_FOLDER + "sRGB Color Space Profile.icm")));
111109
try (FileInputStream fileInputStream = new FileInputStream(sourceHtml)) {
@@ -127,7 +125,7 @@ public void convertToPdfA3ColorsTest() throws IOException, InterruptedException
127125
String cmpPdf = SOURCE_FOLDER + "cmp_pdfA3ColorTest.pdf";
128126
ConverterProperties converterProperties = new ConverterProperties();
129127
converterProperties.setPdfAConformanceLevel(PdfAConformanceLevel.PDF_A_3U);
130-
converterProperties.setOutputIntent(
128+
converterProperties.setDocumentOutputIntent(
131129
new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
132130
new FileInputStream(SOURCE_FOLDER + "sRGB Color Space Profile.icm")));
133131
try (FileInputStream fileInputStream = new FileInputStream(sourceHtml)) {
@@ -144,7 +142,7 @@ public void convertToPdfA3UWithCustomFontProviderTest() throws IOException, Inte
144142
String destinationPdf = DESTINATION_FOLDER + "simple_custom_font.pdf";
145143
ConverterProperties converterProperties = new ConverterProperties();
146144
converterProperties.setPdfAConformanceLevel(PdfAConformanceLevel.PDF_A_3U);
147-
converterProperties.setOutputIntent(
145+
converterProperties.setDocumentOutputIntent(
148146
new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
149147
new FileInputStream(SOURCE_FOLDER + "sRGB Color Space Profile.icm")));
150148
DefaultFontProvider fontProvider = new DefaultFontProvider(false, false, false);
@@ -185,7 +183,7 @@ public void convertToPdfA3UnreferencedGlyphsTest() throws IOException {
185183
"</html>";
186184
ConverterProperties converterProperties = new ConverterProperties();
187185
converterProperties.setPdfAConformanceLevel(PdfAConformanceLevel.PDF_A_3U);
188-
converterProperties.setOutputIntent(
186+
converterProperties.setDocumentOutputIntent(
189187
new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
190188
new FileInputStream(SOURCE_FOLDER + "sRGB Color Space Profile.icm")));
191189
DefaultFontProvider fontProvider = new DefaultFontProvider(false, false, false);
@@ -216,7 +214,7 @@ public void convertToPdfA3ArabicFontTest() throws IOException, InterruptedExcept
216214
"</html>";
217215
ConverterProperties converterProperties = new ConverterProperties();
218216
converterProperties.setPdfAConformanceLevel(PdfAConformanceLevel.PDF_A_3U);
219-
converterProperties.setOutputIntent(
217+
converterProperties.setDocumentOutputIntent(
220218
new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
221219
new FileInputStream(SOURCE_FOLDER + "sRGB Color Space Profile.icm")));
222220
DefaultFontProvider fontProvider = new DefaultFontProvider(false, false, false);
@@ -241,7 +239,7 @@ public void convertToPdfA3UnreferencedEmojiTest() throws IOException {
241239
"</html>";
242240
ConverterProperties converterProperties = new ConverterProperties();
243241
converterProperties.setPdfAConformanceLevel(PdfAConformanceLevel.PDF_A_3U);
244-
converterProperties.setOutputIntent(
242+
converterProperties.setDocumentOutputIntent(
245243
new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
246244
new FileInputStream(SOURCE_FOLDER + "sRGB Color Space Profile.icm")));
247245
DefaultFontProvider fontProvider = new DefaultFontProvider(false, false, false);
@@ -272,7 +270,7 @@ public void convertToPdfA3EmojiTest() throws IOException, InterruptedException {
272270
"</html>";
273271
ConverterProperties converterProperties = new ConverterProperties();
274272
converterProperties.setPdfAConformanceLevel(PdfAConformanceLevel.PDF_A_3U);
275-
converterProperties.setOutputIntent(
273+
converterProperties.setDocumentOutputIntent(
276274
new PdfOutputIntent("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
277275
new FileInputStream(SOURCE_FOLDER + "sRGB Color Space Profile.icm")));
278276
DefaultFontProvider fontProvider = new DefaultFontProvider(false, false, false);

0 commit comments

Comments
 (0)