如何使用 PDFbox 创建固定宽度的段落?

问题描述 投票:0回答:3

我可以插入这样的简单文本:

document = new PDDocument();
page = new PDPage(PDPage.PAGE_SIZE_A4);
document.addPage(page);
PDPageContentStream content = new PDPageContentStream(document, page);
content.beginText();
content.moveTextPositionByAmount (10 , 10);
content.drawString ("test text");
content.endText();
content.close();

但是如何使用 width 属性创建类似于 HTML 的段落?

<p style="width:200px;">test text</p>
html pdfbox paragraph
3个回答
24
投票

警告:此答案适用于旧版本的 PDFBox,并依赖于已弃用的功能。请参阅下面的评论了解更多详情。

根据这个答案,不可能在某些文本中插入换行符并让PDF正确显示它(无论是使用PDFBox还是其他东西),所以我相信自动换行一些文本以适应某些宽度也可能是这样不能自动做。 (此外,有很多方法可以对文本进行换行 - 仅整个单词、将其分成较小的部分等)

这个答案另一个问题(关于字符串居中)给出了一些关于如何自己做到这一点的指示。假设您编写了一个函数

possibleWrapPoints(String):int[]
来列出文本中可能发生自动换行的所有点(不包括“零”,包括“文本长度”),一种可能的解决方案可能是:

PDFont font = PDType1Font.HELVETICA_BOLD; // Or whatever font you want.
int fontSize = 16; // Or whatever font size you want.
int paragraphWidth = 200;
String text = "test text";

int start = 0;
int end = 0;
int height = 10;
for ( int i : possibleWrapPoints(text) ) {
    float width = font.getStringWidth(text.substring(start,i)) / 1000 * fontSize;
    if ( start < end && width > paragraphWidth ) {
        // Draw partial text and increase height
        content.moveTextPositionByAmount(10 , height);
        content.drawString(text.substring(start,end));
        height += font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * fontSize;
        start = end;
    }
    end = i;
}
// Last piece of text
content.moveTextPositionByAmount(10 , height);
content.drawString(text.substring(start));

possibleWrapPoints
的一个示例,允许在不属于单词的任何点处换行(参考),可以是:

int[] possibleWrapPoints(String text) {
    String[] split = text.split("(?<=\\W)");
    int[] ret = new int[split.length];
    ret[0] = split[0].length();
    for ( int i = 1 ; i < split.length ; i++ )
        ret[i] = ret[i-1] + split[i].length();
    return ret;
}

更新:一些附加信息:

  • PDF 文件格式被设计为在不同情况下看起来相同,您所请求的功能在 PDF 编辑器/创建器中有意义,但在 PDF 文件本身中则不然。因此,大多数“低级”工具倾向于专注于处理文件格式本身,而忽略类似的内容。

  • 更高级别的工具 OTOH 通常有办法进行这种转换。一个例子是
  • Platypus

    (不过适用于 Python),do 具有创建段落的简单方法,并依赖于较低级别的 ReportLab 函数来执行实际的 PDF 渲染。我不知道 PDFBox 有类似的工具,但是这篇文章 给出了一些关于如何在 Java 环境中使用免费工具将 HTML 内容转换为 PDF 的提示。我自己还没有尝试过,但我在这里发帖,因为它可能有用(以防我上面的手工尝试还不够)。


7
投票

private void write(Paragraph paragraph) throws IOException { out.beginText(); out.appendRawCommands(paragraph.getFontHeight() + " TL\n"); out.setFont(paragraph.getFont(), paragraph.getFontSize()); out.moveTextPositionByAmount(paragraph.getX(), paragraph.getY()); out.setStrokingColor(paragraph.getColor()); List<String> lines = paragraph.getLines(); for (Iterator<String> i = lines.iterator(); i.hasNext(); ) { out.drawString(i.next().trim()); if (i.hasNext()) { out.appendRawCommands("T*\n"); } } out.endText(); } public class Paragraph { /** position X */ private float x; /** position Y */ private float y; /** width of this paragraph */ private int width = 500; /** text to write */ private String text; /** font to use */ private PDType1Font font = PDType1Font.HELVETICA; /** font size to use */ private int fontSize = 10; private int color = 0; public Paragraph(float x, float y, String text) { this.x = x; this.y = y; this.text = text; } /** * Break the text in lines * @return */ public List<String> getLines() throws IOException { List<String> result = Lists.newArrayList(); String[] split = text.split("(?<=\\W)"); int[] possibleWrapPoints = new int[split.length]; possibleWrapPoints[0] = split[0].length(); for ( int i = 1 ; i < split.length ; i++ ) { possibleWrapPoints[i] = possibleWrapPoints[i-1] + split[i].length(); } int start = 0; int end = 0; for ( int i : possibleWrapPoints ) { float width = font.getStringWidth(text.substring(start,i)) / 1000 * fontSize; if ( start < end && width > this.width ) { result.add(text.substring(start,end)); start = end; } end = i; } // Last piece of text result.add(text.substring(start)); return result; } public float getFontHeight() { return font.getFontDescriptor().getFontBoundingBox().getHeight() / 1000 * fontSize; } public Paragraph withWidth(int width) { this.width = width; return this; } public Paragraph withFont(PDType1Font font, int fontSize) { this.font = font; this.fontSize = fontSize; return this; } public Paragraph withColor(int color) { this.color = color; return this; } public int getColor() { return color; } public float getX() { return x; } public float getY() { return y; } public int getWidth() { return width; } public String getText() { return text; } public PDType1Font getFont() { return font; } public int getFontSize() { return fontSize; } }



0
投票
© www.soinside.com 2019 - 2024. All rights reserved.