我的应用程序 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 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>
我终于有了一个针对 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);
您需要在
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));
}
}
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);
}
}