3

我正在尝试向现有 PDF 文件添加页眉。它可以工作,但现有 PDF 中的表头被字体更改弄乱了。如果我删除设置字体,则标题不会显示。这是我的代码:

    // the document
    PDDocument doc = null;
    try
    {
        doc = PDDocument.load( file );

        List allPages = doc.getDocumentCatalog().getAllPages();
        //PDFont font = PDType1Font.HELVETICA_BOLD;

        for( int i=0; i<allPages.size(); i++ )
        {
            PDPage page = (PDPage)allPages.get( i );
            PDRectangle pageSize = page.findMediaBox();
            PDPageContentStream contentStream = new PDPageContentStream(doc, page, true, true,true);
            PDFont font = PDType1Font.TIMES_ROMAN;
            float fontSize = 15.0f;
            contentStream.beginText();
            // set font and font size
            contentStream.setFont( font, fontSize);
            contentStream.moveTextPositionByAmount(700, 1150);
            contentStream.drawString( message);
            contentStream.endText();

            //contentStream.
            contentStream.close();}

        doc.save( outfile );
    }
    finally
    {
        if( doc != null )
        {
            doc.close();
        }
    }
}`
4

1 回答 1

8

Essentially you are running into a PDFBox bug in the current version 1.8.2.

A workaround:

Add a getFonts call of the page resources after creating the new content stream before using a font:

PDPage page = (PDPage)allPages.get( i );
PDRectangle pageSize = page.findMediaBox();
PDPageContentStream contentStream = new PDPageContentStream(doc, page, true, true,true);
page.getResources().getFonts();  // <<<<<<<<
PDFont font = PDType1Font.TIMES_ROMAN;
float fontSize = 15.0f;
contentStream.beginText();

The bug itself:

The bug is in the method PDResources.addFont which is called from PDPageContentStream.setFont:

public String addFont(PDFont font) 
{
    return addFont(font, MapUtil.getNextUniqueKey( fonts, "F" ));
}

It uses the current content of the fonts member variable to determine a unique name for the new font resource on the page at hand. Unfortunately this member variable still can be (and in your case is) uninitialized at this time. This results in the MapUtil.getNextUniqueKey( fonts, "F" ) call to always return F0.

The font variable then is initialized implicitly during the addFont(PDFont, String) call later.

Thus, if unfortunately there already existed a font named F0 on that page, it is replaced by the new font.

Having tested with your PDF this is exactly what happens in your case. As the existing font F0 uses some custom encoding while your replacement font uses a standard one, the text originally written using F0 now looks like gibberish.

The work-around mentioned above implicitly initializes that member variable and, thus, prevents the font replacement.

If you plan to use PDFBox in production for this task, you might want to report the bug.

PS: As mentioned in the comments above there is another bug to observe in context with inherited resources. It should be brought to the PDFBox development's attention, too.

PPS: The issue at hand meanwhile has been fixed in PDFBox for versions 1.8.3 and 2.0.0, cf. PDFBOX-1753.

于 2013-10-22T08:22:38.243 回答