1

我试图用 itextpdf 在 pdf 中强调合理的测试,我想我发现了一个错误,我真的很想解决这个问题。

当我按照邮件列表中的描述调用 getBaseline() 时,下划线会远远超出文本末尾,进入下一列。

        float lx = renderInfos.get(i).getBaseline().getStartPoint().get(0);
        float rx = renderInfos.get(i).getBaseline().getEndPoint().get(0);

在此处输入图像描述

您可以从出版商的网站下载原始pdf

谢谢!

我在我尝试过的所有版本的 itextpdf 上都看到了这一点,从4.1.0最新的5.5.0.

将下划线代码与我无法共享的其他专有代码分开需要一些努力。如果你认为这会有所帮助,我可以做到。

如果这是一个错误,是否有我可以记录的问题跟踪器?

PS(mkl):这里有一个简短的代码片段来重现该问题:

PdfReader reader = new PdfReader(...);

PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(...));

for (int page = 1; page <= reader.getNumberOfPages(); page++)
{
    final List<TextRenderInfo> infos = new ArrayList<TextRenderInfo>();
    PdfTextExtractor.getTextFromPage(reader, page, new TextExtractionStrategy()
    {
        public void renderText(TextRenderInfo renderInfo)
        {
            infos.add(renderInfo);
        }

        public void renderImage(ImageRenderInfo renderInfo) { }
        public void endTextBlock() { }
        public void beginTextBlock() { }
        public String getResultantText() { return "";}
    });

    PdfContentByte content = stamper.getOverContent(page);
    for (TextRenderInfo info : infos)
    {
        float lx = info.getBaseline().getStartPoint().get(0);
        float rx = info.getBaseline().getEndPoint().get(0);
        float y = info.getBaseline().getEndPoint().get(1);
        content.moveTo(lx, y);
        content.lineTo(rx, y);
        content.stroke();
    }
}

stamper.close();
4

1 回答 1

2

此问题下的错误是 OP 将他在某个列表中TextRenderInfo检索到的对象收集起来,然后再使用它们。(在我添加到问题中以重现问题的示例代码中,我同样使用了 list 。)renderTextrenderInfosinfos

对象在TextRenderInfo它们发生时不存储整个图形状态,它们也没有计算出以后可以查询的所有属性。相反,在请求其属性时,它们是使用属性请求时的当前信息计算的。

例如,当调用TextRenderInfo实例的getBaseline()方法时,基线是使用getBaseline()调用时解析器的图形状态计算的。在代码重现问题的情况下,这意味着基线是使用页面末尾的内容流的图形状态设置计算的。这尤其包括图形状态属性,例如对基线长度有影响的字符和字间距。

因此,要修复 OP 的代码,TextRenderInfo必须在renderText调用期间计算实例所需的所有信息。

例如,要修复我添加到问题中以重现问题的代码,可以这样更改:

PdfReader reader = new PdfReader(...);

PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(...));

for (int page = 1; page <= reader.getNumberOfPages(); page++)
{
    final List<LineSegment> lines = new ArrayList<LineSegment>();
    PdfTextExtractor.getTextFromPage(reader, page, new TextExtractionStrategy()
    {
        public void renderText(TextRenderInfo renderInfo)
        {
            lines.add(renderInfo.getBaseline());
        }

        public void renderImage(ImageRenderInfo renderInfo) { }
        public void endTextBlock() { }
        public void beginTextBlock() { }
        public String getResultantText() { return "";}
    });

    PdfContentByte content = stamper.getOverContent(page);
    for (LineSegment line : lines)
    {
        float lx = line.getStartPoint().get(0);
        float rx = line.getEndPoint().get(0);
        float y = line.getEndPoint().get(1);
        content.moveTo(lx, y);
        content.lineTo(rx, y);
        content.stroke();
    }
}

stamper.close();

现在基线是在renderText通话期间计算的,因此是正确的:

在此处输入图像描述

PS:@Bruno 可能的 JavaDoc 警告应该附加到renderText方法和TextRenderInfo类中。

于 2014-03-12T10:09:14.903 回答