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

将文本添加到现有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)

2 years ago

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

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

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

ISO 32000告诉您文本对象中只允许使用文本状态运算符 . 通过下划线文本,您将引入图形状态运算符 mmoveTo() ),_ 279447lineTo() )和 Sstroke() ) . 这是被禁止的,这也是你的错误告诉你的 .

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

此外,由于您使用的是 ColumnText.showTextAligned() ,因此无需创建文本对象 . showTextAligned() 方法为您做到了这一点 . 通过添加额外的 beginText() ,您正在嵌套 BTET 运算符,这也违反了ISO 32000,所以请首先删除行 over.beginText(); 该行应该从未添加过 .

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

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

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