当前位置: 首页 > 工具软件 > FOP > 使用案例 >

Apache FOP2.6 SVG导出PDF配置,解决中文字体变成####

卫焕
2023-12-01

网上很多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>

 类似资料: