16

次のような単純なテキストを挿入できます。

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();

しかし、幅属性を使用して HTML に似た段落を作成するにはどうすればよいでしょうか?

<p style="width:200px;">test text</p>
4

2 に答える 2

25

警告:この回答は古いバージョンのPDFBoxに適用され、その後廃止された機能に依存しています。詳細については、以下のコメントを参照してください。

この回答によると、一部のテキストに改行を挿入してPDFで正しく表示することはできません(PDFBoxなどを使用しているかどうかに関係なく)。したがって、一部のテキストを自動折り返しして幅に合わせることができない場合もあると思います。自動的に行います。(さらに、テキストを折り返す方法はたくさんあります-単語全体のみ、小さな部分に分割するなど)

別の質問(文字列の中央揃えについて)に対するこの回答は、これを自分で行う方法に関するいくつかの指針を示しています。ワードラップが発生する可能性のあるテキスト内のすべてのポイントを一覧表示する関数possibleWrapPoints(String):int[]を作成したとすると(「テキストの長さ」を含む「ゼロ」を除く)、考えられる解決策の1つは次のとおりです。

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の一部ではない任意のポイントで折り返しを許可するの1つの例は、次のようになります。

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の場合)があります。これは、段落を簡単に作成する方法があり、実際のP​​DFレンダリングを行うために低レベルのReportLab関数に依存しています。私はPDFBoxの同様のツールを知りませんが、この投稿では、無料で利用できるツールを使用して、Java環境でHTMLコンテンツをPDFに変換する方法についていくつかのヒントを提供します。自分で試したことはありませんが、役に立つかもしれないのでここに投稿します(上記の手作りの試みでは不十分な場合に備えて)。

于 2013-01-01T01:21:49.117 に答える
7

私は Lukas の回答と mgibsonbr を組み合わせて作業しており、これに到達しました。すぐに使えるソリューションを探している人にとっては、より役立つと思います。

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;
    }

}
于 2013-12-21T10:11:34.000 に答える