从 FOP 的 JAR 加载字体

问题描述 投票:0回答:2

我的应用程序 JAR 中的

fonts
目录中有 TTF 字体。

 myapp.jar /
     fop /
        config.xml
        font.ttf

我这样创建我的 FOP:

    FopFactory fopFactory = FopFactory.newInstance();
    fopFactory.setStrictValidation(false);
    fopFactory.setUserConfig(getClasspathFile("/fop/config.xml"));
    FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
   ...

如何配置

config.xml
font.ttf
嵌入到我正在渲染的 PDF 文件中?

java pdf apache-fop
2个回答
8
投票

我的帖子似乎太晚了,但可能对其他人有用。 [java 8,fop 2.1]

import lombok.SneakyThrows;
...
        @SneakyThrows
            private FopFactory getFopFactory(){
                InputStream fopConfigStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("/fop/config.xml");
                FopFactoryBuilder builder = new FopFactoryBuilder(new File(".").toURI(), new CustomPathResolver());
                FopFactory factory = builder.setConfiguration(new DefaultConfigurationBuilder().build(fopConfigStream)).build();
                fopConfigStream.close();
                return factory;
            }
    ...
        private static final class CustomPathResolver implements ResourceResolver {
            @Override
            public OutputStream getOutputStream(URI uri) throws IOException {
                return Thread.currentThread().getContextClassLoader().getResource(uri.toString()).openConnection()
                        .getOutputStream();
            }

            @Override
            public Resource getResource(URI uri) throws IOException {
                InputStream inputStream = ClassLoader.getSystemResourceAsStream("fop/" + FilenameUtils.getName(uri));
                return new Resource(inputStream);
            }
        }

配置.xml:

<fop version="1.0">
    <renderers>
        <renderer mime="application/pdf">
            <fonts>
              <font kerning="yes" embed-url="font.ttf" embedding-mode="subset">
                <font-triplet name="Font name" style="normal" weight="normal"/>
              </font>
            </fonts>
        </renderer>
    </renderers>
</fop>

0
投票

我终于有了一个针对 apache fop 2.9 的解决方案,用于在 jar 文件中引用和使用字体(我还包含了图像和 xsl 文件 - 因为您很可能也想这样做)。

完整的项目代码可以找到:https://github.com/synapticloop/pdf-embed-test

出于我的目的 - 我希望所有内容都通过 jar 文件运行,而不依赖于文件系统。我的意思是:

  • 字体(即
    <font kerning="yes" embed-url="classpath:///fonts/Poppins-LightItalic.ttf" embedding-mode="subset">
  • 图像(即
    <fo:external-graphic src="classpath:///images/puppy.jpg" content-width="7.02cm" />
  • 包含样式表(即
    <xsl:include href="/xsl/includes/page-templates.xsl" />

对于字体

要引用 jar 文件中的字体,您需要在 fopFactory 上设置内部资源解析器(这是从 fop 配置文件加载字体的内容)。

FopFactory fopFactory = fopFactoryBuilder.build();

// This will allow you to load fonts from the fopconfig.xml i.e.
// <font kerning="yes" embed-url="classpath:///fonts/Poppins-LightItalic.ttf" embedding-mode="subset">
fopFactory.getFontManager().setResourceResolver(
        ResourceResolverFactory.createInternalResourceResolver(
                DEFAULT_BASE_URI,
                new ClasspathResourceResolver()));

对于图像

(即外部显卡,需要在

FopFactoryBuilder
上设置解析器):

// this will allow you to reference external graphics from within a jar file
// i.e. <fo:external-graphic src="classpath:///images/puppy.jpg" content-width="7.02cm" />
FopFactoryBuilder fopFactoryBuilder = new FopFactoryBuilder(
        DEFAULT_BASE_URI,
        new ClasspathResourceResolver())
        .setConfiguration(cfg);

对于 xsl 包括

您需要在

TransformerFactory

上设置资源解析器
    TransformerFactory factory = TransformerFactory.newInstance();

    // This allows you to reference includes within the xsl file
    // <xsl:include href="/xsl/includes/page-templates.xsl" />
    factory.setURIResolver(new ClasspathResourceURIResolver());

完整的主文件

import org.apache.fop.apps.*;
import org.apache.fop.apps.io.ResourceResolverFactory;
import org.apache.fop.configuration.DefaultConfiguration;
import org.apache.fop.configuration.DefaultConfigurationBuilder;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;
import java.net.URI;

public class Main {

    public static final URI DEFAULT_BASE_URI = new File(".").toURI();

    public static void main(String[] args) throws Exception {
        StreamSource xmlSource = new StreamSource(Main.class.getResourceAsStream("/xml/blank.xml"));

        DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
        DefaultConfiguration cfg = cfgBuilder.build(Main.class.getResourceAsStream("/config/fopconfig.xml"));

        // this will allow you to reference external graphics from within a jar file
        // i.e. <fo:external-graphic src="classpath:///images/puppy.jpg" content-width="7.02cm" />
        FopFactoryBuilder fopFactoryBuilder = new FopFactoryBuilder(
                DEFAULT_BASE_URI,
                new ClasspathResourceResolver())
                .setConfiguration(cfg);

        FopFactory fopFactory = fopFactoryBuilder.build();

        // This will allow you to load fonts from the fopconfig.xml i.e.
        // <font kerning="yes" embed-url="classpath:///fonts/Poppins-LightItalic.ttf" embedding-mode="subset">
        fopFactory.getFontManager().setResourceResolver(
                ResourceResolverFactory.createInternalResourceResolver(
                        DEFAULT_BASE_URI,
                        new ClasspathResourceResolver()));


        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        // Setup output
        try (OutputStream out = new FileOutputStream("./embed-test.pdf")) {

            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);

            TransformerFactory factory = TransformerFactory.newInstance();

            // This allows you to reference includes within the xsl file
            // <xsl:include href="/xsl/includes/page-templates.xsl" />
            factory.setURIResolver(new ClasspathResourceURIResolver());

            InputStream resourceAsStream = Main.class.getResourceAsStream("/xsl/embed-test.xsl");
            Transformer transformer = factory.newTransformer(new StreamSource(resourceAsStream));

            SAXResult res = new SAXResult(fop.getDefaultHandler());
            transformer.transform(xmlSource, res);
        }
    }
}

类路径资源解析器

import org.apache.xmlgraphics.io.Resource;
import org.apache.xmlgraphics.io.ResourceResolver;

import java.io.*;
import java.net.URI;

public class ClasspathResourceResolver implements ResourceResolver {
    @Override
    public Resource getResource(URI uri) throws IOException {
        String uriString = uri.toASCIIString();
        System.out.println(uriString);

        if(uriString.startsWith("classpath://")) {
            String substring = uriString.substring(12);
            System.out.println(substring);
            InputStream resourceAsStream = ClasspathResourceResolver.class.getResourceAsStream(substring);
            return (new Resource(resourceAsStream));
        } else if(uriString.startsWith("file://")) {
            String substring = uriString.substring(7);
            InputStream resourceAsStream = new FileInputStream(new File(substring));
            return(new Resource(resourceAsStream));
        } else {
            return new Resource(ClasspathResourceResolver.class.getResourceAsStream(uriString));
        }
    }

    @Override
    public OutputStream getOutputStream(URI uri) throws IOException {
        return new FileOutputStream(new File(uri));
    }
}

类路径资源URI解析器

import javax.xml.transform.Source;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamSource;
import java.io.InputStream;

public class ClasspathResourceURIResolver implements URIResolver {
    @Override
    public Source resolve(String href, String base) {
        InputStream resourceAsStream = ClasspathResourceURIResolver.class.getResourceAsStream(href);
        return new StreamSource(resourceAsStream);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.