如何使用嵌入式字体用iText调用Graphics2D.drawString(...)(DefaultFontMapper?)

d0x*_*d0x 6 java itext

要生成有效的PDF/X文档,必须嵌入所有字体.不知怎的,我不可能在Graphics2D上下文中使用这些字体.

这个Unittests显示了问题(评论的行是我做的一些测试):

import java.awt.Font;
import java.awt.Graphics2D;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Map.Entry;

import org.junit.Test;

import com.itextpdf.awt.DefaultFontMapper;
import com.itextpdf.awt.DefaultFontMapper.BaseFontParameters;
import com.itextpdf.awt.PdfGraphics2D;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfWriter;

public class TestFont
{

    @Test
    public void shouldBeAbleToAddFountsAndDrawOnCanvas() throws FileNotFoundException, DocumentException
    {
        final DefaultFontMapper mapper = new DefaultFontMapper();
        mapper.insertDirectory(".");

        final PrintStream out2 = new PrintStream(System.out);
        for (final Entry<String, BaseFontParameters> entry : mapper.getMapper().entrySet())
        {
            out2.println(String.format("%s: %s", entry.getKey(), entry.getValue().fontName));
        }
        out2.flush();

        final float width = 150;
        final float height = 150;

        final Document document = new Document(new Rectangle(width, height));
        final PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("fonts.pdf"));
        writer.setPDFXConformance(PdfWriter.PDFX32002);

        document.open();
        final Graphics2D g2d = new PdfGraphics2D(writer.getDirectContent(), width, height, mapper);

        g2d.setFont(new Font("Comicate", Font.PLAIN, 12));

        g2d.drawString("Hello world", 5, 24);

        g2d.dispose();

        document.close();
    }

}
Run Code Online (Sandbox Code Playgroud)

它将抛出一条PdfXConformanceException消息:"所有字体都必须嵌入.这不是:Helvetica.

我已经浏览过PdfGraphics2D类来检查setFont()实现并发现,FontMapper将使用a.我已将此添加到上面的Unittest中.

public void setFont(Font f) {
    if (f == null)
        return;
    if (onlyShapes) {
        font = f;
        return;
    }
    if (f == font)
        return;
    font = f;
    fontSize = f.getSize2D();
    baseFont = getCachedBaseFont(f);
}

private BaseFont getCachedBaseFont(Font f) {
    synchronized (baseFonts) {
        BaseFont bf = (BaseFont)baseFonts.get(f.getFontName());
        if (bf == null) {
            bf = fontMapper.awtToPdf(f);
            baseFonts.put(f.getFontName(), bf);
        }
        return bf;
    }
}
Run Code Online (Sandbox Code Playgroud)

Unittest基于iText in Action手册中的这个例子.以下是有关FontMapper的其他一些示例.

要运行Unittest,您需要以下依赖项:

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.3.2</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

您在这里找到自定义字体(位于".").

控制台输出显示了这一点(以识别fontName):

Comicate: ./COMICATE.TTF
Run Code Online (Sandbox Code Playgroud)

sor*_*end 2

我不确定纠正代码中错误的确切方法,但有一些简单的解决方法:

解决方法 1) 创建一个 BufferedImage 来执行所有图形绘制。然后,您可以使用所有普通java.awt.Graphics功能,例如iText,drawString并且无论setColoriText 是什么,完成后只需将图像绘制为 PDF。警告缩放时文本质量会降低,但这里有一个示例:

//create doccument and writer    
Rectangle pagesize = new Rectangle(200, 100);
Document document= new Document(pagesize);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("C:\\sample.pdf"));

BufferedImage bf = new BufferedImage(BorderWidth, BorderHeight, BorderWidth);
//Do all graphics code here, draw strings and images etc
    //Some code to set font (java.awt.Font)
    //Some code to draw string
    //Some code to draw image?

//Convert BufferedImage to Image
Image img = (Image)bf;
//draw image to PDF using writer
writer.getDirectContentUnder().addImage(img);
Run Code Online (Sandbox Code Playgroud)

解决方法 2) 这使用 iText 功能来绘制字符串,无需创建任何图形对象,通过使用 a 来处理字体,BaseFont如下所示:

//create doccument and writer    
Rectangle pagesize = new Rectangle(200, 100);
Document document= new Document(pagesize);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("C:\\sample.pdf"));

document.open();
//This sample uses the "GOTHIC.TTF" font file located in the "Template" package
BaseFont bf = BaseFont.createFont(GUI.class.getClass().getResource("/Template/GOTHIC.TTF") + "", BaseFont.WINANSI, BaseFont.EMBEDDED);

//set font type, size and color
Font font = new Font(bf, 13.5f);

PdfContentByte canvas = writer.getDirectContent();

canvas.beginText();
canvas.setFontAndSize(bf, 10);
//Method Usage: showTextAligned(Align, String, x, y, rotation);
canvas.showTextAligned(Element.ALIGN_TOP, "My Text Here", 75, 40, 0);
canvas.endText();

document.close();
Run Code Online (Sandbox Code Playgroud)

我知道这并没有给出您正在寻找的答案,但是如果您只是绘制少量文本,那么解决方法 2 效果很好,我之前使用过类似于解决方法 2 的方法。如果这没有帮助,那么我相信布鲁诺会有答案。