You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PDFBox 2.0.27中更改文本渲染方向?

解决PDFBox文本从上到下渲染及多行重叠问题

PDFBox默认以页面左下角为坐标原点,Y轴向上延伸,所以showText()看起来是从下往上绘制文本。要实现从上到下的逐行排版,核心是主动调整文本绘制的Y坐标,而非修改渲染方向。针对不同字号文本重叠的问题,可通过以下步骤解决:

关键思路

  1. 计算每行文本的实际高度(结合字体字号与字体自身的边界框)
  2. 每完成一行文本绘制后,将当前Y坐标减去该行高度,确保下一行落在当前行的视觉下方

具体实现步骤

1. 获取单行文本的实际高度

字体字号代表em-square的大小,实际行高需结合字体边界框计算,公式为:
实际行高 = 字号 * (字体边界框高度 / 1000)
(PDF字体的边界框默认以1000为基准单位)

通过PDFont的API获取边界框并计算高度:

float getLineHeight(PDFont font, float fontSize) {
    BoundingBox bbox = font.getFontDescriptor().getFontBoundingBox();
    return fontSize * (bbox.getHeight() / 1000);
}

2. 逐行绘制并调整位置

初始化时从页面顶部附近开始绘制,每写完一行就下移Y坐标,示例代码:

try (PDDocument doc = new PDDocument();
     PDPage page = new PDPage(PDRectangle.A4);
     PDPageContentStream contentStream = new PDPageContentStream(doc, page)) {

    // 页面基础参数
    float pageWidth = page.getMediaBox().getWidth();
    float pageHeight = page.getMediaBox().getHeight();
    float margin = 50;
    float currentX = margin;
    float currentY = pageHeight - margin; // 从页面顶部内侧开始绘制

    // 待绘制的多行文本(搭配不同字号)
    List<String> texts = Arrays.asList("第一行(12号字)", "第二行(16号字)", "第三行(10号字)");
    List<Float> sizes = Arrays.asList(12f, 16f, 10f);
    PDFont font = PDType1Font.HELVETICA;

    for (int i = 0; i < texts.size(); i++) {
        String text = texts.get(i);
        float fontSize = sizes.get(i);
        float lineHeight = getLineHeight(font, fontSize);

        // 设置字体与字号
        contentStream.setFont(font, fontSize);
        // 绘制文本
        contentStream.beginText();
        contentStream.newLineAtOffset(currentX, currentY);
        contentStream.showText(text);
        contentStream.endText();

        // 调整Y坐标,下移一行高度(额外加2作为行间距)
        currentY -= lineHeight + 2;
    }

    doc.save("从上到下排版.pdf");
} catch (IOException e) {
    e.printStackTrace();
}

3. 精准行高计算(可选)

若需要更精确的文本高度(考虑字体的上升、下降值),可使用以下方法:

float getPreciseLineHeight(PDFont font, float fontSize) {
    float ascent = font.getFontDescriptor().getAscent() * fontSize / 1000;
    float descent = font.getFontDescriptor().getDescent() * fontSize / 1000;
    return ascent - descent; // descent为负数,实际是上升值加下降值的绝对值
}

注意事项

  • 自定义字体需确保加载正确,且getFontDescriptor()能正常返回边界框信息
  • 行间距可根据需求自行调整,示例中的+2为额外空白间距
  • 若文本过长需自动换行,还需结合PDFont.getStringWidth()计算文本宽度,判断是否超出页面宽度后手动拆分

内容的提问来源于stack exchange,提问作者Tomas Sexenian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 05:07:27