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.05.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取得したオブジェクトをrenderText何らかのリストで収集し、renderInfos後でそれらを使用することです。(問題を再現するために質問に追加したサンプル コードでは、同様に list を使用しましたinfos。)

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 に答える