网上很多ttf转xml的文章,不多说
但是字体配置一节 是在<renderer mime="application/pdf"> 里面添加 <fonts> 的配置. 尝试了很多次,没有成功.
把<fonts>节点放在 <fop> 下即可 详见 org.apache.fop.fonts.FontManagerConfigurator.configure() 79行
另外: <base>./</base> 是指项目根目录, 找不到字体,代码会报错
如果不报错,还是乱码,那么,配置未生效
<?xml version="1.0"?>
<fop version="1.0">
<base>./</base>
<source-resolution>72</source-resolution>
<target-resolution>72</target-resolution>
<default-page-settings height="11.00in"
width="8.50in" />
<fonts>
<font metrics-url="HYShangWeiShouShuW-Regular.xml"
embed-url="ad5b584b3ec5a50f74028a8e03080654.ttf">
<font-triplet name="HYShangWeiShouShuW-Regular"
style="normal" weight="normal" />
<font-triplet name="HYShangWeiShouShuW-Regular"
style="normal" weight="bold" />
<font-triplet name="HYShangWeiShouShuW-Regular"
style="italic" weight="normal" />
<font-triplet name="HYShangWeiShouShuW-Regular"
style="italic" weight="bold" />
</font>
</fonts>
</fop>
// svg文件转成PDF
public static void convert2Pdf(File svg, File pdf) {
OutputStream outs = null;
InputStream ins = null;
try {
File file = ResourceUtils.getFile("classpath:fop.xml");
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
cfg = cfgBuilder.buildFromFile(file);
outs = new BufferedOutputStream(new FileOutputStream(pdf));
ins = new FileInputStream(svg);
PDFTranscoder transcoder = new PDFTranscoder();
transcoder.configure(cfg); //配置.. 这里只是示例,不用每次都读...
TranscoderInput input = new TranscoderInput(ins);
TranscoderOutput output = new TranscoderOutput(outs);
transcoder.transcode(input, output);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
ins.close();
outs.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
彩蛋: 简化配置
<?xml version="1.0"?>
<fop version="1.0">
<base>./</base>
<!-- Source resolution in dpi (dots/pixels per inch) for determining the
size of pixels in SVG and bitmap images, default: 72dpi -->
<source-resolution>72</source-resolution>
<!-- Target resolution in dpi (dots/pixels per inch) for specifying the
target resolution for generated bitmaps, default: 72dpi -->
<target-resolution>72</target-resolution>
<default-page-settings height="11.00in"
width="8.50in" />
<fonts>
<auto-detect/> <!-- 这就扫描系统字体了,我因为要管理字体,所以还是需要手工配置 -->
</fonts>
时隔一年... 把字体配置到数据库的方式一并放上来. 由于是定制项目,fop代码被我修改了不少,比如不支持svg中特殊字符,透明背景, cmyk单黑问题.
项目是一个印刷品在线编辑. 浏览器读取模板,在canvas中编辑排版,导出svg到后台,用fop转pdf这么个流程.前端用的fabricjs
------------------------------------------
fop配置文件中字体配置一项放进数据库.
1. 读取数据库配置到Configuration
@PostConstruct //必须在系统初始化,或者操作fop之前做
public void init() {
try {
File file = ResourceUtils.getFile("classpath:fop.xml");
log.debug("fop配置文件" + file.getAbsolutePath() + " , " + file.exists());
DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
String generateFontXML = printingFontsService.generateFontXML(); //这里是读取数据库生成xml节点
String conf = FileUtil.readString(file, "UTF-8");
String source = StrUtil.format(conf, generateFontXML );
InputStream confStream = new StringInputStream(source, "UTF-8");
cfg = cfgBuilder.build(confStream );
FopFactoryBuilder fopFactoryBuilder = new FopFactoryBuilder(new File(".").toURI()).setConfiguration(cfg);
fac = fopFactoryBuilder.build();
log.debug("svgUtil inited");
} catch (Exception e) {
e.printStackTrace();
}
}
2. 读取数据库 代码
public String generateFontXML() throws Exception {
List<PrintingFonts> allEntitys = this.getAllEntitys();
StringBuilder sb = new StringBuilder();
for (PrintingFonts f : allEntitys) {
String fontname = f.getFontname();
String md5 = EncryptUtil.MD5(fontname);
// 注意,这里的 md5值是名称,实际操作下,发现有些中文,英文字体,自身有空格时,不生效.SVG属性中同样用这个md5作为font-family的值
sb.append("<font kerning=\"yes\" embed-url=\"/data/fonts/"+f.getUuid()+".ttf\">\n" +
" <font-triplet name=\""+ md5 +"\" style=\"normal\" weight=\"normal\" />\n" +
" <font-triplet name=\""+ md5 +"\" style=\"normal\" weight=\"bold\" />\n" +
" <font-triplet name=\""+ md5 +"\" style=\"italic\" weight=\"normal\" />\n" +
" <font-triplet name=\""+ md5 +"\" style=\"italic\" weight=\"bold\" />\n" +
" <font-triplet name=\""+ fontname +"\" style=\"normal\" weight=\"normal\" />\n" +
" <font-triplet name=\""+ fontname +"\" style=\"normal\" weight=\"bold\" />\n" +
" <font-triplet name=\""+ fontname +"\" style=\"italic\" weight=\"normal\" />\n" +
" <font-triplet name=\""+ fontname +"\" style=\"italic\" weight=\"bold\" />\n" +
"</font>\n");
}
return sb.toString();
}
3. fop.xml
<?xml version="1.0"?>
<fop version="1.0">
<base>./</base>
<target-resolution>300</target-resolution>
<default-page-settings height="11.00in"
width="8.50in" />
<!-- 动态上传字体并设置, 解决配置动态读取的问题 -->
<fonts>
{} <!-- 占位符,数据库配置被放在这里 -->
<referenced-fonts>
<match font-family="Helvetica" />
<match font-family="DejaVu.*" />
</referenced-fonts>
<!-- <auto-detect /> --> <!-- 扫描系统字体 -->
</fonts>
<renderers>
<renderer mime="application/pdf">
<filterList>
<value>flate</value>
</filterList>
<output-profile>/data/pdf_icc/PSO_LWC_Standard_bas.ICC</output-profile>
<pdf-x-mode>PDF/X-4</pdf-x-mode><!-- 符合印刷标准的pdf -->
<pdf-vt-mode>PDF/VT-1</pdf-vt-mode>
</renderer>
<renderer mime="application/postscript">
</renderer>
<renderer mime="application/vnd.hp-PCL">
</renderer>
</renderer> -->
<renderer mime="image/svg+xml">
<format type="paginated" />
<link value="true" />
<strokeText value="false" />
<images mode="color" cmyk="true"/>
</renderer>
<renderer mime="application/awt">
</renderer>
<renderer mime="image/png">
<images mode="color" cmyk="true"/>
<color-mode>rgba</color-mode>
</renderer>
<renderer mime="image/jpg">
<images mode="color" cmyk="true"/>
</renderer>
<renderer mime="image/tiff">
</renderer>
<renderer mime="text/xml">
</renderer>
</renderers>
</fop>