Dan*_*ner 5 java embed pdf fonts itext
我们使用iText从Java代码生成PDF文件,在大多数情况下都可以很好地工作.几天前,我们开始生成PDF/A而不是普通的PDF文件,需要嵌入所有字体.iText Document
主要是自定义PdfPTable
和其他类的构建,我们直接控制字体.所有使用的字体都是通过以下代码加载的TTF文件创建的 - 这很好用:
private BaseFont load(String path) {
try {
URL fontResource = PrintSettings.class.getResource(path);
if (fontResource == null) {
return null;
}
String fontPath = fontResource.toExternalForm();
BaseFont baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
baseFont.setSubset(true);
return baseFont;
}
catch (DocumentException ex) {
Logger.getLogger(PrintSettings.class).warn("...");
}
catch (IOException ex) {
Logger.getLogger(PrintSettings.class).warn("...");
}
return FontFactory.getFont(PrintSettings.FONT, "UTF-8", true, 8f, Font.NORMAL, PrintSettings.COLOR_TEXT).getBaseFont();
}
Run Code Online (Sandbox Code Playgroud)
现在我们在PDF中使用一种从HTML代码生成的特定内容类型.我们用它XMLWorker
来处理那部分.只要我们没有嵌入字体,这工作得很好.但是使用PDF/A我们需要嵌入所有字体,现在我们正在努力解决未知的Helvetica使用来源.
我们试图通过使用我们自己的FontProvider类来解决这个问题:
public class PrintFontProvider extends FontFactoryImp {
@Override
public Font getFont(String fontName, String encoding, boolean embedded, float size, int style, BaseColor color, boolean cached) {
// 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) { ... }
}
Run Code Online (Sandbox Code Playgroud)
它与XMLWorker
使用以下代码连接:
HtmlPipelineContext html = new HtmlPipelineContext(null);
html.setTagFactory(Tags.getHtmlTagProcessorFactory());
CSSResolver css = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
// We need to control the FontProdiver!
html.setCssAppliers(new CssAppliersImpl(new PrintFontProvider()));
Pipeline<?> pipeline = new CssResolverPipeline(css, new HtmlPipeline(html, new PdfWriterPipeline(this.document, writer)));
XMLWorker worker = new XMLWorker(pipeline, true);
XMLParser p = new XMLParser(worker);
p.parse(new ByteArrayInputStream(StringUtils.iTextHTML(string).getBytes()));
Run Code Online (Sandbox Code Playgroud)
大多数简单的HTML元素以这种方式工作......但有一些似乎忽略了FontProvider并继续使用Helvetica,它不会嵌入到PDF/A中(我们没有那种字体).例如,<ol><li>...</li></ol>
使用它.
Caused by: com.itextpdf.text.pdf.PdfXConformanceException: All the fonts must be embedded. This one isn't: Helvetica
at com.itextpdf.text.pdf.internal.PdfXConformanceImp.checkPDFXConformance(PdfXConformanceImp.java:225)
at com.itextpdf.text.pdf.PdfWriter.addSimple(PdfWriter.java:2192)
at com.itextpdf.text.pdf.PdfContentByte.setFontAndSize(PdfContentByte.java:1444)
at com.itextpdf.text.pdf.PdfDocument.writeLineToContent(PdfDocument.java:1463)
at com.itextpdf.text.pdf.ColumnText.go(ColumnText.java:968)
at com.itextpdf.text.pdf.ColumnText.go(ColumnText.java:841)
at com.itextpdf.text.pdf.ColumnText.showTextAligned(ColumnText.java:1189)
at com.itextpdf.text.pdf.ColumnText.showTextAligned(ColumnText.java:1208)
at com.itextpdf.text.pdf.PdfDocument.flushLines(PdfDocument.java:1193)
at com.itextpdf.text.pdf.PdfDocument.newPage(PdfDocument.java:830)
at com.itextpdf.text.Document.newPage(Document.java:367)
Run Code Online (Sandbox Code Playgroud)
我现在已经没有想法如何摆脱Helvetica ......现在试图解决这个问题8个小时......还有更多的想法吗?
我挖得更深一点,并从OrderedUnorderedList
那边旅行ListItem
到List
......
/**
* Adds an <CODE>Element</CODE> to the <CODE>List</CODE>.
*
* @param o the element to add.
* @return true if adding the object succeeded
* @since 5.0.1 (signature changed to use Element)
*/
@Override
public boolean add(final Element o) {
if (o instanceof ListItem) {
ListItem item = (ListItem) o;
if (this.numbered || this.lettered) {
Chunk chunk = new Chunk(this.preSymbol, this.symbol.getFont());
chunk.setAttributes(this.symbol.getAttributes());
int index = this.first + this.list.size();
if ( this.lettered )
chunk.append(RomanAlphabetFactory.getString(index, this.lowercase));
else
chunk.append(String.valueOf(index));
chunk.append(this.postSymbol);
item.setListSymbol(chunk);
}
else {
item.setListSymbol(this.symbol);
}
item.setIndentationLeft(this.symbolIndent, this.autoindent);
item.setIndentationRight(0);
return this.list.add(item);
}
else if (o instanceof List) {
List nested = (List) o;
nested.setIndentationLeft(nested.getIndentationLeft() + this.symbolIndent);
this.first--;
return this.list.add(nested);
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
此代码指的this.symbol.getFont()
是在类初始化时设置为未定义...
public class List implements TextElementArray, Indentable {
[...]
/** This is the listsymbol of a list that is not numbered. */
protected Chunk symbol = new Chunk("- ");
Run Code Online (Sandbox Code Playgroud)
我只是使用了另一个Chunk
构造函数,它采用了Font
我的构造函数,瞧……解决了。编号列表不再使用Helvetica,而是使用我自己的字体,该字体已正确嵌入。
这花了我很长时间!另一种方法可能是实现自己的 TagProcessor,<ol>
但我们不再有时间了。我将为此提交一份错误报告...我们将看看它是否得到更灵活的修复。
归档时间: |
|
查看次数: |
3623 次 |
最近记录: |