【发布时间】:2013-10-19 08:32:15
【问题描述】:
我使用PDFTextReplacement 示例。
它按预期进行替换,以防我的文本左对齐。
但是,如果我的输入 pdf 文本居中,它会将文本替换为左对齐。
好的,所以我必须重新计算正确的起点。
因此,我有两个目标或问题:
- 如何确定对齐方式?
- 如何计算正确的起点?
这是我的代码:
public PDDocument doIt(String inputFile, Map<String, String> text)
throws IOException, COSVisitorException {
// the document
PDDocument doc = null;
doc = PDDocument.load(inputFile);
List pages = doc.getDocumentCatalog().getAllPages();
for (int i = 0; i < pages.size(); i++) {
PDPage page = (PDPage) pages.get(i);
PDStream contents = page.getContents();
PDFStreamParser parser = new PDFStreamParser(contents.getStream());
parser.parse();
List tokens = parser.getTokens();
for (int j = 0; j < tokens.size(); j++) {
Object next = tokens.get(j);
if (next instanceof PDFOperator) {
PDFOperator op = (PDFOperator) next;
// Tj and TJ are the two operators that display
// strings in a PDF
String pstring = "";
int prej = 0;
if (op.getOperation().equals("Tj")) {
// Tj takes one operator and that is the string
// to display so lets update that operator
COSString previous = (COSString) tokens.get(j - 1);
String string = previous.getString();
// System.out.println(j + " " + string);
if (j == prej) {
pstring += string;
} else {
prej = j;
pstring = string;
}
previous.reset();
previous.append(string.getBytes("ISO-8859-1"));
} else if (op.getOperation().equals("TJ")) {
COSArray previous = (COSArray) tokens.get(j - 1);
for (int k = 0; k < previous.size(); k++) {
Object arrElement = previous.getObject(k);
if (arrElement instanceof COSString) {
COSString cosString = (COSString) arrElement;
String string = cosString.getString();
if (j == prej) {
pstring += string;
} else {
prej = j;
pstring = string;
}
cosString.reset();
// cosString.append(string
// .getBytes("ISO-8859-1"));
}
}
COSString cosString2 = (COSString) previous
.getObject(0);
for (int t = 1; t < previous.size(); t++)
previous.remove(t);
// cosString2.setNeedToBeUpdate(true);
if (text.containsKey(pstring.trim())) {
String textValue = text.get(pstring.trim());
cosString2.append(textValue.getBytes("ISO-8859-1"));
for (int k = 1; k < previous.size(); k++) {
previous.remove(k);
}
}
}
}
}
// now that the tokens are updated we will replace the
// page content stream.
PDStream updatedStream = new PDStream(doc);
OutputStream out = updatedStream.createOutputStream();
ContentStreamWriter tokenWriter = new ContentStreamWriter(out);
tokenWriter.writeTokens(tokens);
page.setContents(updatedStream);
}
return doc;
}
【问题讨论】:
-
如何确定对齐方式 - PDF 不知道对齐方式。它从当前原点开始绘制文本,仅此而已。您可以尝试通过比较当前“行”的文本位置与页面尺寸以及“行”前后(“行”)上的文本位置来确定对齐方式,因为 PDF 不一定遵循文本行概念)。但是,如果某些文本看起来居中,您确定它是要居中的吗?它也可能只是缩进了一段距离,现在偶然看起来居中。
-
@mkl 是的,这正是我在 PDDocument 中看到的。所以我必须完善我的问题。 1. 那么如何获取内容使用的确切空间(icepdf 使用 lineText.getBounds() )? 2.如何计算新字符串的已用空间(基于BASE14字体)
-
您的代码在非常低的级别上工作,它检查来自页面内容流的各个指令。因此,它不会从更高级别的功能中受益。这尤其意味着在该级别上,您必须自己跟进当前图形状态的变化。为了能够做到这一点,你应该先学习PDF specification ISO 32000-1,尤其是第8章(了解图形状态如何变化)和第9章(了解文本是如何绘制的)。
-
不过,大部分编码已经在 PDFBox 中完成。
PDFStreamEngine遍历页面内容流中的指令,并使用文本块及其位置和尺寸调用processTextPosition。所以在那个层面上,你最终会得到你要求的尺寸。不幸的是,您与要操作的实际页面内容流相距甚远。因此,您必须稍微调整该类,以使低级指令和高级解释以同步的方式可用。