【问题标题】:How to move to the next line when adding text using Apache PDFBox使用 Apache PDFBox 添加文本时如何移动到下一行
【发布时间】:2015-03-06 09:31:26
【问题描述】:

我刚刚开始使用 Apache PDFBox,并一直在尝试我找到的各种示例。

但是,在添加文本时,我无法找到一种简单的方法来移动到下一行。

例如

PDPageContentStream content = new PDPageContentStream(document, page);
PDFont font = PDType1Font.HELVETICA;
content.beginText();
content.setFont(font, 12);
content.moveTextPositionByAmount(x, y);
content.drawString("Some text.");
content.endText();

要在下面添加另一行文本,我不得不反复试验moveTextPositionByAmount 中的 y 值,直到它没有覆盖前一行。

有没有更直观的方法可以算出下一行的坐标是什么?

TIA

【问题讨论】:

    标签: java pdf pdf-generation pdfbox


    【解决方案1】:

    PDFBox API 允许生成低级内容。这意味着您必须自己完成(但您也可以完成)大部分布局工作,其中包括决定向下移动多少才能到达下一个基线。

    该距离(在此上下文中称为领先)取决于许多因素:

    • 使用的字体大小(显然)
    • 文本的间距应该是多紧还是松散
    • 所涉及的行上存在位于常规行之外的元素,例如上标、下标、公式……

    标准是这样安排的,对于以 1 号绘制的字体,紧密间隔的文本行的标称高度为 1 个单位因此,通常您将使用 1 的前导。 .1.5 倍字体大小,除非线条上有超出它的材料。

    顺便说一句,如果您必须经常以相同的数量转发到下一行,您可以使用PDPageContentStream 方法setLeadingnewLine 的组合,而不是moveTextPositionByAmount

    content.setFont(font, 12);
    content.setLeading(14.5f);
    content.moveTextPositionByAmount(x, y);
    content.drawString("Some text.");
    content.newLine();
    content.drawString("Some more text.");
    content.newLine();
    content.drawString("Still some more text.");
    

    PS:看起来moveTextPositionByAmount 将在 2.0.0 版本中被弃用并被newLineAtOffset 取代。

    PPS:正如 OP 在评论中指出的那样,

    没有称为 setLeading 的 PDPageContentStream 方法。我使用的是 PDFBox 1.8.8 版。

    确实,我正在查看当前的 2.0.0-SNAPSHOT 开发版本。它们目前是这样实现的:

    /**
     * Sets the text leading.
     *
     * @param leading The leading in unscaled text units.
     * @throws IOException If there is an error writing to the stream.
     */
    public void setLeading(double leading) throws IOException
    {
        writeOperand((float) leading);
        writeOperator("TL");
    }
    
    /**
     * Move to the start of the next line of text. Requires the leading to have been set.
     *
     * @throws IOException If there is an error writing to the stream.
     */
    public void newLine() throws IOException
    {
        if (!inTextMode)
        {
            throw new IllegalStateException("Must call beginText() before newLine()");
        }
        writeOperator("T*");
    }
    

    使用appendRawCommands((float) leading); appendRawCommands(" TL");appendRawCommands("T*"); 可以轻松实现外部辅助方法

    【讨论】:

    • 感谢@mkl 的回复。没有称为 setLeading 的 PDPageContentStream 方法。我使用的是 PDFBox 1.8.8 版。
    • 你能解释一下@mkl 向内容流添加原始命令的实际含义吗?
    • 将原始命令添加到内容流实际上意味着什么 - PDF 文件包含作为一系列基本操作(例如绘制文本、设置文本前导或前进)的页面内容由当前文本前导)。 添加原始命令意味着您直接将数据(操作及其操作数)添加到该序列。
    【解决方案2】:

    像这样在y轴上添加一个偏移量的新线

    PDPageContentStream content = new PDPageContentStream(document, page);
    PDFont font = PDType1Font.HELVETICA;
    content.beginText();
    content.setFont(font, 12);
    // by default y = 0 pdf text start in the left bottom corner 
    //  so you may need to put y = 700 or something to see the new line below 
    content.moveTextPositionByAmount(x, y);
    content.drawString("Some text.");
    content.newLineAtOffset(0, -15);
    content.drawString("some text ");
    content.endText();
    

    【讨论】:

    • 如果我有 10000 行的文本,是否意味着我应该调用 drawString 10000 次?
    猜你喜欢
    • 2017-01-29
    • 1970-01-01
    • 2014-10-04
    • 2012-06-28
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    • 2014-05-31
    • 1970-01-01
    相关资源
    最近更新 更多