生成的 pdf 中的文本是反向的

Text is reverse in generated pdf

我正在使用 pdfbox 向 pdf 文件添加一行。但是我添加的文字是颠倒的。

File file = new File(filePath);
PDDocument document = PDDocument.load(file);

PDPage page = document.getPage(0);
PDPageContentStream contentStream = new PDPageContentStream(document, page,PDPageContentStream.AppendMode.APPEND,true);

int stampFontSize = grailsApplication.config.pdfStamp.stampFontSize ? grailsApplication.config.pdfStamp.stampFontSize : 20
contentStream.beginText();
contentStream.setFont(PDType1Font.TIMES_ROMAN, stampFontSize);

int leftOffset = grailsApplication.config.pdfStamp.leftOffset ? grailsApplication.config.pdfStamp.leftOffset : 10
int bottomOffset = grailsApplication.config.pdfStamp.bottomOffset ? grailsApplication.config.pdfStamp.bottomOffset : 20
contentStream.moveTextPositionByAmount(grailsApplication.config.xMove,grailsApplication.config.yMove)
contentStream.newLineAtOffset(leftOffset, bottomOffset)

String text = "i have added this line...!!!!";
contentStream.showText(text);
contentStream.endText();

contentStream.close();

document.save(new File(filePath));
document.close();

byte[] pdfData;
pdfData = Files.readAllBytes(file.toPath());
return pdfData;

我尝试使用 moveTextPositionByAmount 方法,但这似乎对文本没有任何影响。为什么我的文本是颠倒的,我该如何设置它以正确的方向。

您的代码本身并没有导致镜像输出,因此原因一定在您正在标记的 PDF 内部。很遗憾,您没有提供相关的 PDF,所以我们只能在这里猜测。

问题很可能是由于预先存在的页面内容将当前变换矩阵设置为镜像仿射变换而没有在最后重置它造成的。

如果确实如此,PDFBox 提供了一个简单的解决方法:

你这样构造你的PDPageContentStream

PDPageContentStream contentStream = new PDPageContentStream(document, page,PDPageContentStream.AppendMode.APPEND,true);

还有另一个构造函数接受额外的 boolean 参数。如果您使用该构造函数将附加参数设置为 true,PDFBox 会尝试重置内容的图形状态:

PDPageContentStream contentStream = new PDPageContentStream(document, page,PDPageContentStream.AppendMode.APPEND,true,true);

注意: 如果这确实解决了问题,则您当前使用的坐标和偏移量依赖于按原样更改的变换矩阵。在这种情况下,您将不得不相应地更新它们。


或者引入反镜像可能会有所帮助,例如通过在每个文本对象的开头设置这样的文本矩阵:

contentStream.beginText();
contentStream.setTextMatrix(new Matrix(1f, 0f, 0f, -1f, 0f, 0f));

此后所有 y 坐标变化都需要取反,特别是 contentStream.moveTextPositionByAmountcontentStream.newLineAtOffset.

的第二个参数

(顺便说一下,moveTextPositionByAmountnewLineAtOffset 做同样的事情,前者只是被弃用的变体,所以你可能想在这两种情况下都使用后者。)