iText失败时将带下划线的文本添加到PDF / A文档中

时间:2018-06-08 09:05:44

标签: itext

将文本添加到现有PDF / A文档时,只要文本没有加下划线,一切正常。如果是这样,我会得到一个例外:

com.itextpdf.text.exceptions.IllegalPdfSyntaxException: Path construction or drawing operators aren't allowed inside a text object.
at com.itextpdf.text.pdf.PdfContentByte.moveTo(PdfContentByte.java:919)
at com.itextpdf.text.pdf.PdfContentByte.moveTo(PdfContentByte.java:904)
at com.itextpdf.text.pdf.PdfDocument.writeLineToContent(PdfDocument.java:1615)
at com.itextpdf.text.pdf.ColumnText.go(ColumnText.java:1160)
at com.itextpdf.text.pdf.ColumnText.go(ColumnText.java:993)
at com.itextpdf.text.pdf.ColumnText.go(ColumnText.java:981)
at com.itextpdf.text.pdf.ColumnText.showTextAligned(ColumnText.java:1400)
at com.itextpdf.text.pdf.ColumnText.showTextAligned(ColumnText.java:1418)
at de.arbeitsagentur.kiwi.common.drucken.itext.PdfUtils.stampVerworfen(PdfUtils.java:97)

以下是代码:

PdfReader reader = new PdfReader(inputStream);
PdfStamper stamp = new PdfStamper(reader, outputStream);
PdfContentByte over = stamp.getOverContent(1);
over.beginText();
BaseFont bf = BaseFont.createFont(FONT, BaseFont.WINANSI, true);
Font font = new Font(bf, 14, Font.BOLD | Font.UNDERLINE);
Phrase phrase = new Phrase("Hello World!", font);
ColumnText.showTextAligned(over, Element.ALIGN_LEFT, phrase, 67, 727, 0);

如果省略Font.UNDERLINE,则没有问题。

我的iText版本是5.5.13

1 个答案:

答案 0 :(得分:1)

页面上的内容是使用ISO 32000中描述的PDF语法定义的。如果您在iText中使用高级对象,则不必担心细节:iText负责处理它们。

iText还有一系列低级方法,允许您创建PDF语法。 ISO 32000中描述的每个操作员在iText中都有相应的低级方法。

例如:可以使用BT方法添加beginText()运算符,可以使用ET方法添加endText()运算符。这两个运算符BTET定义了一个文本对象。

ISO 32000告诉您文本对象中只允许文本状态运算符。通过下划线文字,您可以介绍图形状态运算符 mmoveTo()),llineTo())和Sstroke())。这是被禁止的,这也是你的错误告诉你的。

然而,这不是唯一的问题。您的代码段中有beginText(),但您没有endText(),因此您正在创建一个永不关闭的文本对象。这违反了ISO 32000。

此外,由于您使用的是ColumnText.showTextAligned(),因此您无需创建文本对象。 showTextAligned()方法适合您。通过添加额外的beginText(),您正在嵌套BTET运算符,这也违反了ISO 32000,因此请首先删除行{{1}那条线永远不应该被添加到那里。

最后,强调字体的属性是错误的。这是iText 5中众多设计缺陷之一,最终导致了iText的完全重写,从而产生了iText 7。

over.beginText();用于普通文本会更好,然后使用ColumnText.showTextAligned()moveTo()lineTo()来绘制线条。您知道stroke()坐标(727 - 基线与您想要绘制的线之间的距离)起始Y位置(67);您需要根据X的长度计算结束X位置(有不同的方法可以计算该长度)。

当然:如果你升级到iText 7(它具有与iText 5相同的许可证:AGPL或商业版),你会发现在绝对位置添加文本要容易得多。