特殊字体扩展
目录
概述
对于一些商业字体或自定义字体,普通的 字体扩展 即可满足需求。但还有一类特殊字体,直接输出到 PDF 后显示不正常(例如高棉语常用的 Khmer OS 字体)。这类问题通常需要对文本做字节码/字形转换后再输出,有时还需额外指定最终渲染所用的字体。针对这种需求,报表提供了 FontRenderRegister 扩展点。
适用场景
- 字体本身能被加载,但按原字形输出到 PDF 后显示错乱、缺字或乱码;
- 需要在输出前对文本内容做转换(如 Unicode 重排、字形替换),并指定一个可正常显示的最终字体。
注意:该扩展仅作用于 PDF 导出(在生成 PDF 文本短语时调用渲染器对内容做转换)。Web 预览、Excel、Word、CSV 等导出不受此机制影响。
与"字体扩展"的区别
| 维度 | 字体扩展(FontRegister) | 特殊字体扩展(FontRenderRegister) |
|---|---|---|
| 解决的问题 | 补充默认字体列表,注册字体库 | 字体能注册但 PDF 显示不正常,需文本转换 |
| 接口 | FontRegister |
FontRenderRegister(继承 FontRegister) |
| 是否转换文本 | 否 | 是(通过 FontRender.render) |
| 是否指定最终字体 | 否 | 是(通过 getRenderFontName) |
| 适用导出 | 主要影响 PDF | 仅 PDF |
扩展机制(SPI)
FontRenderRegister 同样基于 Java 的 SPI(Service Provider Interface) 机制:实现该接口并在 META-INF/services 中登记后,报表引擎在启动时自动加载。引擎加载时会识别其为 FontRenderRegister,进而额外登记"字体名称 → 最终渲染字体名称"的映射,以及对应的 FontRender 文本渲染器。
详见 【SPI 集成说明】。
FontRenderRegister 接口
package com.basksoft.report.core.export.pdf.font;
public interface FontRenderRegister extends FontRegister {
/**
* @return 返回自定义的字体名称
*/
String getFontName();
/**
* 返回字体所在位置,需要注意的是字体文件需要放置到classpath下,这里返回的值就是该字体文件所在classpath下位置即可
* @return 返回字体所在位置
*/
String getFontPath();
/**
* 通过文本渲染对象的处理返回新的渲染字符串,如果为空则不做处理
* @return 返回文字渲染对象
*/
FontRender getFontRender();
/**
* 获取最终被渲染的字体名称,如果为空则还用原来的字体显示
* @return 返回最终被渲染的字体名称
*/
String getRenderFontName();
}
getFontName():原始字体的名称(与单元格选用的字体名对应);getFontPath():字体库文件在classpath下的相对路径;getFontRender():返回文本渲染器,在输出前对文本内容做转换(返回null则不转换);getRenderFontName():最终真正用于渲染的字体名称(返回空则仍使用原字体)。
FontRender 接口
public interface FontRender {
/**
* @return 返回重新渲染后的文本内容
*/
public String render(final String strInput);
}
render 方法接收原始文本,返回转换后的文本。引擎在生成 PDF 文本短语时会先调用它,再用 getRenderFontName() 指定的字体输出。
参考实现
以高棉语 Khmer OS 为例,演示如何做字形转换并指定最终字体 Khmer OS Battambang:
public class KhmerFontRegister implements FontRenderRegister {
public String getFontName() {
return "Khmer OS";
}
public String getFontPath() {
return "com/basksoft/baskreport/demo/font/KHMEROS.TTF";
}
@Override
public FontRender getFontRender() {
return new KhmerFontRender();
}
@Override
public String getRenderFontName() {
return "Khmer OS Battambang";
}
}
其中 getFontRender 用于返回字体的自定义字节码替换的渲染器对象,getRenderFontName 用于告诉报表引擎最终渲染采用的字体名称。
渲染器参考实现(对文本做 Unicode 重排转换):
public class KhmerFontRender implements FontRender {
private final static UnicodeRender render = new UnicodeRender();
@Override
public String render(String strInput) {
return render.render(strInput);
}
}
高棉语 UnicodeRender 的参考实现可参考:https://github.com/Seuksa/iTextKhmer
使用步骤
- 实现
FontRenderRegister接口:在getFontName返回原始字体名,getFontPath返回字体库在classpath下的路径; - 提供
getFontRender()返回文本渲染器(如需转换),getRenderFontName()返回最终可正常显示的字体名; - 在
META-INF/services/com.basksoft.report.core.export.pdf.font.FontRegister中登记实现类的全限定名; - 启动报表服务后,选用该原始字体的单元格在 PDF 导出时,会自动经过文本转换并以最终字体渲染。