使用Apache FOP创建PDF时,可以在配置文件中嵌入字体。当应用程序是Web应用程序并且需要在WAR文件(因此被视为资源)中嵌入字体时,就会出现问题。
使用特定容器的文件夹结构来确定战争的确切位置是不可接受的(在配置xml文件中,我们将标签设置为./
时,它会被设置为运行容器的基本文件夹,例如{{ 1}})。
所以问题是:有人知道以编程方式嵌入字体的方法吗?
答案 0 :(得分:1)
经过大量FOP Java代码后,我设法使其正常工作。
主要思想是强制FOP使用自定义PDFRendererConfigurator
,该自定义getCustomFontCollection()
在执行PDFDocumentHandlerMaker
时将返回所需的字体列表。
为此,我们需要创建自定义PDFDocumentHandler
,该自定义makeIFDocumentHandler()
将返回自定义PDFRendererConfigurator
(表单方法getConfigurator()
),而自定义PDFDocumentHandlerMaker
将返回自定义RendererFactory
(从FopFactory > RendererFactory > PDFDocumentHandlerMaker > PDFDocumentHandler > PDFRendererConfigurator
方法),如上所述,它将列出自定义字体列表。
然后只需将自定义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();
}
}
}
添加到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;
}
}
即可。
public class CustomPDFDocumentHandler extends PDFDocumentHandler {
public CustomPDFDocumentHandler(IFContext context) {
super(context);
}
@Override
public IFDocumentHandlerConfigurator getConfigurator() {
return new CustomPDFRendererConfigurator(getUserAgent(), new PDFRendererConfigParser());
}
}
FopTest.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);
}
}
CustomPDFDocumentHandlerMaker.java
function getVal(){
var firstVal= document.querySelector("input[name='price1']:checked");
if (firstVal.checked){
console.log(firstVal.value);
}
}
CustomPDFDocumentHandler.java
function getVal(){
var firstVal= document.querySelector("input[name='price1']:checked");
if (firstVal.checked){
console.log(firstVal.value);
} else
console.log(0);
}
}
CustomPDFRendererConfigurator.java
function getVal(){
var firstVal= document.querySelector("input[name='price1']:checked");
if (firstVal.checked){
console.log(firstVal.value);
}
if (firstVal.checked === false){
console.log(0);
}
}
答案 1 :(得分:0)
是的,您可以这样做。您需要以编程方式设置FOP的第一个基本目录。
fopFactory = FopFactory.newInstance();
// for image base URL : images from Resource path of project
String serverPath = request.getSession().getServletContext().getRealPath("/");
fopFactory.setBaseURL(serverPath);
// for fonts base URL : .ttf from Resource path of project
fopFactory.getFontManager().setFontBaseURL(serverPath);
然后使用FOB字体配置文件,它将使用以上基本路径。
只需将字体文件放在Web应用程序资源文件夹中,然后在FOP的字体配置文件中引用该路径即可。
注释后:以编程方式读取字体配置(不是首选的方式,还是仍按要求使用的简洁方式)
//This is NON tested and PSEUDO code to get understanding of logic
FontUris fontUris = new FontUris(new URI("<font.ttf relative path>"), null);
EmbedFontInfo fontInfo = new EmbedFontInfo(fontUris, "is kerning enabled boolean", "is aldvaned enabled boolean", null, "subFontName");
List<EmbedFontInfo> fontInfoList = new ArrayList<>();
fontInfoList.add(fontInfo);
//set base URL for Font Manager to use relative path of ttf file.
fopFactory.getFontManager().updateReferencedFonts(fontInfoList);
您可以获取有关FOP相对路径https://xmlgraphics.apache.org/fop/2.2/configuration.html的更多信息