Apache FOP - 有没有办法以编程方式嵌入字体?

Mr.*_*. P 3 java apache-fop web

使用 Apache FOP 创建 PDF 时,可以使用配置文件嵌入字体。当应用程序是 Web 应用程序并且需要在 WAR 文件中嵌入字体(因此被视为资源)时,就会出现问题。

使用特定容器的文件夹结构来确定 war 的确切位置是不可接受的(当我们在配置 xml 文件中将 tag 设置为 时./,它被设置为运行容器的基本文件夹,如C:\Tomcat\bin)。

所以问题是:有人知道以编程方式嵌入字体的方法吗?

Mr.*_*. P 5

在经历了大量 FOP java 代码之后,我设法让它工作。

描述性版本

主要思想是强制 FOP 使用自定义PDFRendererConfigurator,在getCustomFontCollection()执行时将返回所需的字体列表。

为了做到这一点,我们需要创建PDFDocumentHandlerMaker将返回自定义PDFDocumentHandler(表单方法makeIFDocumentHandler())的自定义,然后返回我们的自定义PDFRendererConfigurator(来自getConfigurator()方法),如上所述,它将列出自定义字体列表。

然后,只需定制添加PDFDocumentHandlerMakerRendererFactory,它会工作。

FopFactory > RendererFactory > PDFDocumentHandlerMaker > PDFDocumentHandler > PDFRendererConfigurator

完整代码

FopTest.java

public class FopTest {

    public static void main(String[] args) throws Exception {

        // the XSL FO file
        StreamSource xsltFile = new StreamSource(
                Thread.currentThread().getContextClassLoader().getResourceAsStream("template.xsl"));
        // the XML file which provides the input
        StreamSource xmlSource = new StreamSource(
                Thread.currentThread().getContextClassLoader().getResourceAsStream("employees.xml"));
        // create an instance of fop factory
        FopFactory fopFactory = new FopFactoryBuilder(new File(".").toURI()).build();

        RendererFactory rendererFactory = fopFactory.getRendererFactory();
        rendererFactory.addDocumentHandlerMaker(new CustomPDFDocumentHandlerMaker());

        // a user agent is needed for transformation
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        // Setup output
        OutputStream out;
        out = new java.io.FileOutputStream("employee.pdf");

        try {
            // Construct fop with desired output format
            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

            // Setup XSLT
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer transformer = factory.newTransformer(xsltFile);

            // Resulting SAX events (the generated FO) must be piped through to
            // FOP
            Result res = new SAXResult(fop.getDefaultHandler());

            // Start XSLT transformation and FOP processing
            // That's where the XML is first transformed to XSL-FO and then
            // PDF is created
            transformer.transform(xmlSource, res);
        } finally {
            out.close();
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

自定义PDFDocumentHandlerMaker.java

public class CustomPDFDocumentHandlerMaker extends PDFDocumentHandlerMaker {

    @Override
    public IFDocumentHandler makeIFDocumentHandler(IFContext ifContext) {
        CustomPDFDocumentHandler handler = new CustomPDFDocumentHandler(ifContext);
        FOUserAgent ua = ifContext.getUserAgent();
        if (ua.isAccessibilityEnabled()) {
            ua.setStructureTreeEventHandler(handler.getStructureTreeEventHandler());
        }
        return handler;
    }

}
Run Code Online (Sandbox Code Playgroud)

自定义PDFDocumentHandler.java

public class CustomPDFDocumentHandler extends PDFDocumentHandler {

    public CustomPDFDocumentHandler(IFContext context) {
        super(context);
    }

    @Override
    public IFDocumentHandlerConfigurator getConfigurator() {
        return new CustomPDFRendererConfigurator(getUserAgent(), new PDFRendererConfigParser());
    }

}
Run Code Online (Sandbox Code Playgroud)

CustomPDFRendererConfigurator.java

public class CustomPDFRendererConfigurator extends PDFRendererConfigurator {

    public CustomPDFRendererConfigurator(FOUserAgent userAgent, RendererConfigParser rendererConfigParser) {
        super(userAgent, rendererConfigParser);
    }

    @Override
    protected FontCollection getCustomFontCollection(InternalResourceResolver resolver, String mimeType)
            throws FOPException {

        List<EmbedFontInfo> fontList = new ArrayList<EmbedFontInfo>();
        try {
            FontUris fontUris = new FontUris(Thread.currentThread().getContextClassLoader().getResource("UbuntuMono-Bold.ttf").toURI(), null);
            List<FontTriplet> triplets = new ArrayList<FontTriplet>();
            triplets.add(new FontTriplet("UbuntuMono", Font.STYLE_NORMAL, Font.WEIGHT_NORMAL));
            EmbedFontInfo fontInfo = new EmbedFontInfo(fontUris, false, false, triplets, null, EncodingMode.AUTO, EmbeddingMode.AUTO);
            fontList.add(fontInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return createCollectionFromFontList(resolver, fontList);
    }

}
Run Code Online (Sandbox Code Playgroud)