问题
The following code is being used for converting HTML file with CSS to PDF/A-2 using iText5 (this code is from the example provided online):
public static final String HTML = "D:\\PDFA2\\html\\sample.html";
public static final String CSS = "D:\\PDFA2\\html\\sample.css";
public static final String DEST = "D:\\PDFA2\\html\\sample.pdf";
public void createPdf(String file) throws IOException, DocumentException {
Document document = new Document();
PdfAWriter writer = PdfAWriter.getInstance(document, new FileOutputStream(file),PdfAConformanceLevel.PDF_A_2A);
writer.setInitialLeading(12.5f);
document.open();
CSSResolver cssResolver = new StyleAttrCSSResolver();
CssFile cssFile = XMLWorkerHelper.getCSS(new FileInputStream(CSS));
cssResolver.addCss(cssFile);
HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
XMLWorker worker = new XMLWorker(css, true);
XMLParser p = new XMLParser(worker);
p.parse(new FileInputStream(HTML));
document.close();
}
public static void main(String[] args) throws IOException, DocumentException {
File file = new File(DEST);
file.getParentFile().mkdirs();
new HTMLtoPDFA2_V2().createPdf(DEST);
}
The following is the HTML file content:
<h1>Test</h1><p>Hello World</p>
And the CSS file content is:
{
font-family: "Arial";
font-style: normal;
}
However this gives the following exception:
Exception in thread "main" com.itextpdf.text.pdf.PdfAConformanceException: All the fonts must be embedded. This one isn't: Helvetica
at com.itextpdf.text.pdf.internal.PdfAConformanceImp.checkPdfAConformance(PdfAConformanceImp.java:90)
at com.itextpdf.text.pdf.PdfAWriter.checkPdfIsoConformance(PdfAWriter.java:204)
at com.itextpdf.text.pdf.PdfWriter.checkPdfIsoConformance(PdfWriter.java:3281)
at com.itextpdf.text.pdf.PdfWriter.addSimple(PdfWriter.java:2208)
at com.itextpdf.text.pdf.PdfContentByte.setFontAndSize(PdfContentByte.java:1624)
at com.itextpdf.text.pdf.PdfDocument.writeLineToContent(PdfDocument.java:1584)
at com.itextpdf.text.pdf.PdfDocument.flushLines(PdfDocument.java:1275)
at com.itextpdf.text.pdf.PdfDocument.newPage(PdfDocument.java:869)
at com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:793)
at com.itextpdf.text.Document.close(Document.java:416)
at in.test.util.pdf.HTMLtoPDFA2_V2.createPdf(HTMLtoPDFA2_V2.java:67)
at in.test.util.pdf.HTMLtoPDFA2_V2.main(HTMLtoPDFA2_V2.java:76)
How can this exception be avoided? I do not need to use Helvetica font. There are many posts on SO but none of them seem to provide a resolution.
回答1:
Add the Font Provider to HtmlPipelineContext instead of null
XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
fontProvider.register("arial.ttf", "Arial");
CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
For each tag in HTML file define font in the CSS file
p, h2 {
font-family: "Arial";
font-style: normal;
}
Alternatively, define a common font for complete html file
html {
font-family: "Arial";
font-style: normal;
}
回答2:
We are using our very own PrintFontProvider
. This should get you going:
private static final CSSResolver cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
private static final HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
static {
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
htmlContext.autoBookmark(false);
// Our own PrintFontProvider provides Fonts as needed...
htmlContext.setCssAppliers(new CssAppliersImpl(new PrintFontProvider()));
// We apply some default styles to the pdf generation...
try {
String styling = "* { font-size: 8pt; line-height: 1.3em; }\n";
styling += "* * { font-size: inherit; }\n";
styling += "p { margin: 5px 2.5pt; }\n";
styling += "ul, ol { margin: 2px 0; }\n";
cssResolver.clear();
cssResolver.addCss(styling, true);
}
catch (CssResolverException ex) {
// Handle errors as needed...
}
}
Here is our implementation:
public class PrintFontProvider extends FontFactoryImp {
public static final String DEFAULT_FONT = "LiberationSans";
@Override
public Font getFont(String fontName, String encoding, boolean embedded, float size, int style, BaseColor color, boolean cached) {
LogUtils.debug(PrintFontProvider.class, "in getFont with fontName = '" + fontName + "'");
// ZapfDingbats ist ein Sonderfall... die wollen wir auch liefern!
if ("ZapfDingbats".equals(fontName)) {
return new Font(this.load("fonts/ZapfDingbats/zapf-dingbats-bt.ttf"), size, style, color);
}
// LiberationSans – http://de.wikipedia.org/wiki/Liberation_(Schriftart) – http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web
if (style == Font.NORMAL) return new Font(this.load("fonts/Liberation/LiberationSans-Regular.ttf"), size, Font.NORMAL, color);
if (style == Font.BOLD) return new Font(this.load("fonts/Liberation/LiberationSans-Bold.ttf"), size, Font.NORMAL, color);
if (style == Font.BOLDITALIC) return new Font(this.load("fonts/Liberation/LiberationSans-BoldItalic.ttf"), size, Font.NORMAL, color);
if (style == Font.ITALIC) return new Font(this.load("fonts/Liberation/LiberationSans-Italic.ttf"), size, Font.NORMAL, color);
return new Font(this.load("fonts/Liberation/LiberationSans-Regular.ttf"), size, style, color);
}
private BaseFont load(String path) {
LogUtils.debug(PrintFontProvider.class, "path = {0}", path);
try {
URL fontResource = PrintSettings.class.getResource(path);
if (fontResource == null) {
LogUtils.warn(PrintFontProvider.class, "Kann Font {0} nicht finden... liefere null!", path);
return null;
}
String fontPath = fontResource.toExternalForm();
if (fontPath.startsWith("vfs:")) fontPath = fontPath.substring(4);
if (fontPath.startsWith("/content/")) fontPath = fontPath.substring(fontPath.indexOf("/our/package"));
BaseFont baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
baseFont.setSubset(true); // Nur die benutzen Chars einbetten!
return baseFont;
}
catch (DocumentException ex) {
LogUtils.warn(PrintFontProvider.class, "Kann Font {0} nicht erzeugen... liefere DEFAULT_FONT!", path);
}
catch (IOException ex) {
LogUtils.warn(PrintFontProvider.class, "Kann Font {0} nicht erzeugen... liefere DEFAULT_FONT!", path);
}
return FontFactory.getFont(DEFAULT_FONT, "UTF-8", true, 8f, Font.NORMAL, PrintSettings.COLOR_TEXT).getBaseFont();
}
private static boolean notInitialized = true;
public static void initFactory() {
if (notInitialized) {
FontFactory.defaultEmbedding = true;
FontFactory.setFontImp(new PrintFontProvider());
notInitialized = false;
}
}
}
You should call PrintFontProvider.initFactory()
to make it your default.
来源:https://stackoverflow.com/questions/52736441/itext-5-htmlcss-to-pdf-a-2-helvetica-font-not-embedded-error