特殊字体扩展

目录

概述

对于一些商业字体或自定义字体,普通的 字体扩展 即可满足需求。但还有一类特殊字体,直接输出到 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

使用步骤

  1. 实现 FontRenderRegister 接口:在 getFontName 返回原始字体名,getFontPath 返回字体库在 classpath 下的路径;
  2. 提供 getFontRender() 返回文本渲染器(如需转换),getRenderFontName() 返回最终可正常显示的字体名;
  3. META-INF/services/com.basksoft.report.core.export.pdf.font.FontRegister 中登记实现类的全限定名;
  4. 启动报表服务后,选用该原始字体的单元格在 PDF 导出时,会自动经过文本转换并以最终字体渲染。

results matching ""

    No results matching ""