KDocs 研发资料库
  • 音频技术应用文档入口汇总
  • 杰理WINDOWS环境安装及其他事项
  • LINUX安装和编译
  • Linux环境编译SDK教程(ubuntu18.04)
  • 音频类补丁汇总表
  • 认证资料获取汇总(最新资料后台会更新)
  • 《Hi-Res申请指南v1.0》
  • FreeRTOS 开源协议版本
  • uCOS 开源协议版本信息
  • 各个模块关键资料汇总
  • 软件调试方法
  • Makefile编译
  • 提bug的规范
  • 常规设备使用指导
  • 对外特别发布开发注意点信息汇总
  • AD697X软件问题整理
  • AC700N软件问题整理
  • AC701X耳机软件问题整理
  • 951&961软件问题整理
  • AC104X软件问题整理
  • AC128N问题整理文档
  • 可视化工具调试问题整理
  • 耳机资料汇总
  • AC704N、 AC705N相关应用
  • AC695N&AC696N&AC608N音箱问题整理
  • JL701N音箱问题整理
  • AC692X软件问题整理
  • AC706N音箱问题整理
  • JL701N音箱问题整理(可视化工具SDK)
  • JL703N音箱问题整理
  • JL709N(JL689N)音箱问题整理
  • JL7094系列-入门到进阶开发指导
  • AC210N音箱问题整理
  • 无线麦系列版本支持指南
  • AW32N无线麦问题整理
  • lAD697X&JL701X 无线麦软件共性问题整理
  • AC706N无线麦问题整理
  • AW36N无线麦问题整理
  • AC710X无线麦问题整理
  • 唤醒源获取及唤醒IO设置
  • 电源
  • LVD
  • 长按复位配置方法
  • 低功耗应用
  • TIMER
  • UART
  • SPI
  • 内部FLASH空间添加用户自定义区域
  • IIC
  • GPIO
  • MCPWM
  • SD&U盘
  • 时钟&晶振
  • GPCNT
  • IO口crossbar映射功能
  • 文件系统使用总结
  • 复用应用
  • LINEIN_AUX相关应用
  • IIS音频接口应用
  • SPDIF模式相关(HDMI_ARC、光纤、同轴)
  • PDM LINK
  • 外设相关应用
  • 蓝牙相关
  • 杰理蓝牙距离调试文档
  • TWS耳机配对方式使用及生产把控指南
  • GFP谷歌快连及其认证流程指引
  • 蓝牙发射器(bt_emitter)相关
  • BLE应用
  • 关于提升BLE传输速率说明
  • BLE测试数据
  • MUSIC 模式相关应用
  • MIDI音乐实现
  • PC相关应用
  • FM相关应用
  • AC695N_AC696N FM天线ESD静电防护措施说明V2.0_20250107
  • fm应用详细设计说明书
  • 杰理FM硬件指南-20230315
  • ADC模块
  • AUDIO相关应用
  • 新Tools的音效调试使用
  • 混响应用使用说明
  • 音效调式
  • 音箱耳机低音小音量增强实现方法
  • DAC输出功率调试
  • DAC性能测试指南
  • 针对各类底噪、电流声分析流程
  • 录音相关应用
  • OPUS编解码相关
  • RTC相关应用
  • 升级相关
  • UI相关应用
  • 通话调试流程指南
  • 通话相关应用
  • 省电容mic使用手册
  • 如何测试验证手表通话系统的语音失真 V1.0
  • AC695X_AC696X_AD697X 常见通话问题处理参考资料
  • 通话调试问题确定步骤
  • 内置触摸调试指南
  • 低功耗内置触摸介绍V2.2
  • 触摸相关文档
  • AC697X、AC698X内置触摸调试及整改方法V1.0
  • 产测相关应用
  • AC63X BLE DUT测试介绍
  • 兆华序列使用简易说明
  • JL_1T2蓝牙测试盒音频文件更换说明
  • ENC相关应用入口汇总
  • ANC相关应用入口汇总
  • JL DMS通话调试手册-V3.9.4
  • ANC-ENC结构设计要点-20240407
  • 半入耳式ANC耳机器件选型与结构设计指南V1.0
  • JL 耳道自适应调试指南
  • ANC相关问题处理
  • ANC调试文档
  • 评估蓝牙耳机通话上行降噪性能的方法 V1.0 (2)
  • FCC 或者 BQB 认证相关应用
  • BQB profile 测试中常遇到的问题点汇总
  • 蓝牙参数整理20210811
  • 杰理科技认证问题参考
  • 无线音频产品开发指南
  • 无线麦系列从入门到进阶开发指导
  • 量产烧录相关说明
  • 一拖八烧录器远程过程调用说明
  • 量产相关建议
  • EffectTool(eq)调试工具说明文档
  • AC897AD697系列的EQ调试方法-V3
  • 杰理调音指南-20220622
  • 音效模块总结
  • 简要调音步骤指引(可视化)
  • 耳机充电与通信调试指南
  • 充电仓硬件调试指南
  • 充电仓软件问题整理
  • AC951常用说明
  • AC951_AC961_开发板使用说明V1.0
  • 彩屏仓AC982 入门指导及FAQ
  • 蓝牙音频APP相关应用
  • 手机APP的简介和开发流程
  • 蓝牙音频系列-硬件设计指南
  • 静电测试及整改方法-20220706
  • TWS耳机底噪整改指南V1.2
  • 杰理蓝牙距离调试文档
  • 蓝牙RF硬件设计与调试V1.1-20250219
  • AC695N_AC696N FM天线ESD静电防护措施说明V2.0_20241228
  • 音效调试指南
  • 无线话筒K歌音箱标准开发流程
  • 杰理科技 700N TWS耳机产品标准-202303
  • 杰理科技 701N 广播产品标准-202303
  • JL-HAT ANC高效产测自适应
  • 无线话筒测试板使用介绍
  • 一拖八频偏校准使用说明
  • 领夹麦产测工具使用介绍
  • Dongle量产测试说明
  • Dongle+Tws或头戴式 SDK通过工具绑定配对功能说明文档
  • 双麦ENC产测宏配置验证方法 V1.0
  • JL耳机方案麦克风声学测试指令_V1.0
  • JL耳机方案麦克风声学测试指令_V2.0
  • JL_ENC自动测试命令_V0.0.1
  • JL蓝牙测试盒用例说明
  • LDAC自测环境搭建_ubuntu
  • 延迟小板使用手册
  • 杰理库文件的制作及添加实现过程
  • 关于 AC635N&AC636N系列免晶振兼容性补丁 说明
  • 关于 AC63系列VM兼容性修复补丁_20250224 说明
  • 关于 AC632N &AE632N_ 蓝牙& 低功耗兼容性修复补丁 说明
  • AD698N和AC638N电压优化补丁V3说明
  • 关于 AC635N&AC636N漏电和E&G版兼容联合补丁 说明
  • AD698N和AC638N电压优化补丁V2说明
  • 702相关应用
  • 2024-4-30 发布歌词显示SDK开发注意事项
  • BQB RF & FCC 认证测试固件问题汇总及源码
  • BQB profile 测试中常遇到的问题点汇总
  • 进dut测试模式方法及固件
  • 704-频偏修改bin文件合集
  • 701手表BQB PROFILE认证注意事项
  • 认证的干扰规避整改
  • 海外CRA认证报告生成说明
  • JL700N可视化工具问题处理文档
  • JL701X可视化工具问题处理文档
  • JL701N_earphone_release_v1.6.0_ANC 低功耗问题补丁
  • JL708X可视化工具问题处理文档
  • JL709N可视化工具问题处理文档
  • JLstudio可视化工具使用说明
  • 一拖二-串口_蓝牙_app在线EQ、通话参数及调试方式和内置触摸调试
  • 可视化JL701M_DONGLE_SDK添加MIC为发射源
  • 可视化JL701M_DONGLE_SDK添加按键切换usb audio与MIC发射源
  • JL701M_DONGLE_SDK_1.0.0_dongle输入linein输出dac
  • 701可视化_a2dp_to_le_demo说明
  • 耳机系列demo汇总
  • JL7018F&JL7006F_7003F AUX IIS
  • 一键连接应用
  • 普通SDK动态开关一拖二功能
  • 蓝牙分析仪(EllisysBluetoothAnalyzer)抓包例程
  • TWS配对常见应用
  • APP自定义按键的demo
  • AC700N 播歌双EQ DEMO示例及说明
  • AC698V164 MIC与蓝牙音乐共同输出DAC demo
  • 添加第三方算法以及多算法授权流程
  • 空间音频配置方法
  • 普通高低电平TWS耳机控制通讯
  • 入耳检测状态更新demo解析
  • 资源优化(非可视化的SDK)
  • 资源优化(可视化SDK)
  • 翻译耳机、语音识别应用demo
  • 耳机抗干扰问题排查和优化
  • AC698D2 抗干扰优化
  • AC696X软件问题整理
  • AC695X软件问题整理
  • AC695X软件问题整理_1722249702
  • AC608X软件问题整理
  • JL701N_2T1_DUPLEX 应用软件问题汇总
  • le_audio_1.0.0_patch05 以及之前的版本IRkey 功能异常修改
  • AC706N-le_audio-200SDK有线_无线麦录音demo
  • jl701n_le_audio_v200patch02 IO串口升级修改串口单次发送字节长度的修改办法
  • 703创建IIS 输入dac输出音频流demo
  • 703将媒体流音频同时上传PC_mic录音demo实现
  • 703四路IIS输入输出demo
  • 底噪调试
  • AW328A烧录说明
  • 文档合集
  • AC706N_wireless_mic_release_PATCH_20240712 补丁 说明
  • AC706N_wireless_mic_release_PATCH_20240726 补丁 说明
  • AC706N_wireless_mic_release_V1.0.0、1.0.1、1.0.2 补丁 说明
  • AC706N_wireless_mic_release_V1.1.2 中的2T1应用 RX端不绑定配对,TX端实现绑定配对的修改方法
  • 各系列省晶振实现方法
  • iis tx rx说明文档
  • spdif信号
  • 蓝牙电话本
  • 安卓手机同步时间补丁
  • CDC配置
  • PC模式下增加Teams唤起功能
  • 杰理HDMIARC开发实现过程
  • AC701N patch06之前的版本用第三方算法节点实现新版本的pcm delay节点功能
  • (K歌音箱)各SDK音效配置相关说明
  • 长文件录音
  • 点阵屏歌词字库相关(蓝牙歌词,普通歌词)
  • 字模提取工具说明
  • 音箱可视化彩屏-入门到进阶开发指导
  • 彩屏LVGL UI设计及工具使用
  • 使用内部UI框架进行UI调试的系列步骤
  • AD101C使用强制升级工具spi 烧录不了问题处理(测试版本)
  • AD161扩展灯板说明文档
  • 歌词显示器开发注意项
  • 使用硬件数字增益控制通话下行音量(可视化)
  • 杰理小牛产测资料
  • ENC配置说明
  • 通话调试流程指引
  • ANC相关功能demo
  • 无线麦硬件资料汇总
  • 无线麦相关应用
  • 无线麦复杂功能补丁包汇总
  • 无线话筒形态SDK程序&开发经验&问题点分享
  • 双模式结合应用问题汇总
  • 无线麦距离优化案例
  • 无线麦系列中的双工形态(duplex)演变开发对讲机方案开发资料
  • 音箱入门到进阶指导文档(编写中)
  • 蓝牙耳机品控和生产技巧
  • 982过_欠压标志获取异常
  • 如何获取最新涂鸦SDK及库文件
  • 无线话筒K歌音响-调音标准流程
  • 无线话筒产测流程

字模提取工具说明

📎 原始文档:https://www.kdocs.cn/l/cerF6EpBYZor 字模提取工具说明
字模提取工具下载链接
在线字符编码查询
在线字符编码转换
unicode区段查找
开源ttf查看工具
font creator
txt转xml工具

↑↑↑(≧∇≦)ノ 工具下载链接&常用字符转换网站↑↑↑

(一)简介:

该工具的作用是根据ttf生成对应.PIX和.TAB文件,用于杰理ui框架的文字显示,适用于701所有版本,可裁剪,可改字体,可换字号。其中FontTool.exe会根据font.xml文件的配置进行采集,在font.xml中可以配置对应代码页使用的ttf文件以及每个代码页中需要提取字符的范围,故可以理解为.xml文件即FontTool.exe的配置,可以通过修改.xml文件来达到修改FontTool.exe提取范围的效果。工具流程图如下:

image 即从用户角度来看,通过修改font.xml可以裁剪出自己需要的国家的语言,而通过修改charset路径下的.xml文件可以进一步修改对应国家语言的字符范围。

需要注意的是,charset路径下的.xml文件的字符编码范围可以重复,工具会自动去重。

(二)字模提前工具目录结构:

image 需重点留意的文件有如下几个:

  1. charset文件夹 存放各个代码页的.xml文件,可以修改对应.xml文件里的编码范围进行进一步的裁剪,需要注意的是里面存放的是unicode编码,只有对应的unicode编码被包含在这些xml文件里面,工具才会去采集对应字符的字模。
    image

  2. Fonts文件夹 存放常用ttf文件,可以通过更换ttf文件达到修改字体的目的,为了让目录结构不混乱,后面新增字体可以将相应ttf放到该文件夹,比如添加思源雅黑.ttf。
    image

  3. Codepage.txt文件 可以根据该文件找到对应语言的代码页,从而进行代码页裁剪。
    image

  4. font.xml文件 配置文件,工具会根据该文件的配置去采集对应字模,可以通过配置该文件去控制字模的采集,如代码页裁剪,以及ttf选择等。
    image 默认ttf:font.xml文件中第4行中的Sun-ExtA.ttf为默认ttf,也就是下面big5,gb2312,gbk,ksc和sjis用到的ttf;
    可选代码页:可以根据上面的代码页进行删减从而实现字库裁剪;
    字体宽高设置:fix为固定宽高,多用于中日韩字符;valid为截取有效部分,多用于印地语,泰语和藏语;variable为可变,对于这部分设置不建议随意修改;
    ttf配置:可以给对应代码页配置特定的字体,只需要在对应代码页中更换目录下自行添加的ttf即可。

Tips:修改font.xml文件后可以重新打开一下FontTool.exe以确保配置被重新加载,防止配置被覆盖。

  1. FontTool.exe 字模提取工具,具体按钮功能如下:
    image (SDK 220以前的工具)
    image (SDK 220以后的工具)

选择字体:点击后可以在目录下选取默认的ttf,默认ttf应用于上文font.xml文件中提到的big5,gb2312,gbk,ksc和sjis这几个代码页,这意味着这里选取的ttf直接应用于简体中文、繁体中文、日语和韩语。若想要修改指定代码页的ttf,可以在Font.xml中进行修改;
采集字模:采集当前选择的代码页,如unicode V2就是采集unicode字库的.PIX文件,而ANSI采集的是F_ASCII.PIX,该文件也就是ascii.res,是数字控件,文字控件的内置字库;
全部采集:无视当前选择代码页,将所有代码页的字模提取到.PIX,.TAB文件中;
字体大小:可以设置字模字号,如上图为设置16字号;
粗体/斜体/固定宽度:可根据需求进行勾选,从而提取对应需求的字模;
位深度(SDK 220后新增):每像素所占位数,该值越高,字体抗锯齿效果越好,但占用空间也会增大;
字符预览:如下图所示
image “啊”字符的unicode编码为0000554a,在红色框框中输入554a即可出现“啊”的预览。

其他_bak后缀的为备份文件。

(三)字模提取工具常用功能:

  1. 提取字模 image 双击FontTool.exe,此时“采集字模”选项为失能状态,也就是不可点击状态,则需要点击“选择字体”,点击后会需要选择默认的ttf,若本来即处于可点击状态,则可以跳过该步骤,如下:
    image 这里随机选一个,如选arial unicode ms.ttf。
    image 选择字体后,工具的标题变成了默认ttf的名字,同时“采集字模”选项也变为可点击状态,此时若要采集unicode字库对应的字模,“代码页”选项中选择unicode v2即可,若使用内码字库,也可自行选择1251、1252等代码页,去采集对应代码页的字模。选择代码页结束后,点击采集字模即可。
    image 采集结束后,会有弹窗提醒已采集完成,同时同级路径下会多出一个文件,我们可以把该文件的文件名由F_UNIC.PIX.arial unicode ms.28.1bpp改为F_UNIC.PIX,去掉相关后缀,至于改的名字可由用户自行决定,但为了方便定位问题,建议使用F_UNIC.PIX或者F_UNIC_ALL.PIX的名称,在用户不是随机命名的情况下,根据以上两个名称可以直接了解到当前使用的是unicode字库。

  2. 根据语言裁剪字库并提取 需要注意的是,目前只支持unicode字库的裁剪,也就是代码页选择unicode V2时才能裁剪。这里以裁剪掉其他语言,只保留泰语,捷克语,法语和英语等拉丁语系语言,土耳其语,希伯来语,阿拉伯语,越南语,中文简体为例,进行一个简单的裁剪示范:
    image 在Codepage.txt中,可以找到需要用到的代码页为acsii,2312,874,1250,1252,1254,1255,1256和1258,那么在配置文件中只保留这几项即可:
    image 其中ascii为公共字库,包含了ascii码表的内容,建议保留。

配置结束后,打开FontTool.exe,设置相应字号,这里以字号24为例,采集unicode字库,故代码页设置unicode V2,点击“采集字模”,等待裁剪即可。
image

采集结束后会出现弹窗,并生成对应.PIX到当前路径下:
image 采集结束后需要修改字库文件名称,公版unicode字库的.PIX文件默认为F_UNIC_ALL.PIX,故在这里将F_UNIC.PIX.Sun-ExtA.24重命名为F_UNIC_ALL.PIX即可,之所以这样命名是为了方便判断当前使用的是什么字库,从而快速跟进问题,若有其他需求也可以修改为其他名字,在fontinit.c中匹配上即可,但需要注意名字长度有要求,不能超过15bytes,否则无法下载到flash。

至于采集其他代码页,以1252为例,选中1252 拉丁文后,点击采集字模:
image 最终生成的文件,将.PIX的后缀去掉,更改为F_CP1252.PIX即可。

若需要用到生成的.PIX文件和.TAB文件,需将其放到ui_resource路径下,并在批处理添加上相应文件。

而对于在Codepage.txt中找不到的语言,可以先自行上网搜索该语言使用的字符,是否在常用的代码页里面,如果在常用代码页里面,则可以选取对应代码页去生成.PIX进行显示。

  1. 根据代码页编码范围裁剪字库 当前裁剪方式也是只有在选择unicode V2的情况下才能进行。若有对字库进一步压缩的需求,可以选择将一个代码页中的字符进行进一步的裁剪,目前提供两种方式:

第一种是直接根据编码范围去裁剪对应的代码页的编码,如gb2312的字符进行裁剪,仅保留常用的,可以把不需要用到的字符编码范围给去掉(查询字符编码的链接在文档顶部),比如不需要显示0x00f9~0x00fa的字符,则可以根据下图,把红色框的内容删除掉即可:
image 但需要注意的是,删除掉相应字符后,当输入相应字符进行显示时会显示default_code的内容,默认是“_”。

第二种是利用txt转xml工具(链接在文档顶部)进行裁剪,输入为所需的文字字符,存放在input.txt文本内,工具会将这些字符转换为合规格的xml文件进行输出。进入工具路径下会找到unicode2xml.exe文件如下图:
image

直接双击运行,即可输出output.xml文件,如下图:
image 用户可自行编辑input.txt,将所需字符填充进去,再运行unicode2xml.exe即可,生成的xml文件后进行重命名,放入字模采集工具的charset文件夹后使用。

  1. 更换字体 这里以将1252代码页的字体换为苹方粗体为例:

将对应ttf添加到Fonts路径下:
image 把1252代码页的ttf更换为对应ttf:
image 然后重新采集字模即可,其中ttf文件杰理不提供,用户需要根据自身需求自行寻找ttf进行生成。

(四)fontforge常用功能:

fontforge是一个开源免费的工具,可以帮助我们查看ttf,编辑ttf以及导出ttf,支持对单个字符进行修改,用户可以利用这个工具去生成自己所需的ttf文件,在此列出一些常用功能:

  1. 根据字符查找编码 imageimageimage 菜单栏View->Goto,输入unicode编码即可跳转到对应字符,比如上图的u00f6,点击ok即可。

  2. 隐藏空字符 imageimageimage 菜单栏Encoding->Compact(hide unused glyphs)即可隐藏空字符。

  3. 导出ttf非空字符的unicode编码范围

import fontforge

# 打开字体文件
font = fontforge.open("E:/ttf/KhmerUI.ttf") # 可以修改为自己ttf的路径

# 获取所有非空字符的Unicode编码
unicode_ranges = []
for glyph in font.glyphs():
    if glyph.unicode != -1:
        unicode_ranges.append(glyph.unicode)

# 导出Unicode编码范围
unicode_ranges.sort()
start_range = unicode_ranges[0]
end_range = unicode_ranges[0]
ranges = []
for i in range(1, len(unicode_ranges)):
    if unicode_ranges[i] == end_range + 1:
        end_range = unicode_ranges[i]
    else:
        ranges.append((start_range, end_range))
        start_range = unicode_ranges[i]
        end_range = unicode_ranges[i]
ranges.append((start_range, end_range))

# 打印Unicode编码范围
for start, end in ranges:
    print(f"{start}-{end}")

# 保存Unicode编码范围到文件,txt文件默认输出桌面,可以按需求修改
with open("C:/Users/admin/Desktop/unicode_ranges.txt", "w") as file:
    for start, end in ranges:
        file.write(f"{start}-{end}\n")

# 关闭字体文件
font.close()

把以上脚本复制下来,打开菜单栏File->Execute Script:
image

贴上对应脚本,点击ok即可:
image

此时可以在桌面找到对应文件:
image 以上包含的就是当前ttf所包含的unicode编码范围。

也可以使用以下脚本一步到位,直接生成杰理字库工具所需要的xml文件:

import fontforge

# 输入输出路径需要根据用户路径来配置
input_path = r'D:/TTF/Indic.ttf'
output_path = r'D:/TTF/unicode_ranges.xml'

# @brief    合并连续编码,如0x0003 0x0004 0x0005合并为0x0003-0x0005
# @param    unicode编码列表
# @return   合并后的unicode编码列表
def merge_continuous(nums):
    intervals = [[nums[0]]]  # 初始化一个二维列表
    for num in nums[1:]:
        if num == intervals[-1][-1] + 0x1:  # 如当前数字与上一个区间的最后一个数字相差1,则将该数字添加到上一个区间
            intervals[-1].append(num)
        else:  # 否则新建一个区间并以当前数字为起始
            intervals.append([num])

    # 如果区间长度大于1则以‘起始值-结束值’的形式输出,否则只输出起始值
    return ['0x{:04X}-0x{:04X}'.format(x[0], x[-1]) if len(x) > 1 else '0x{:04X}'.format(x[0]) for x in intervals]

# @brief    转化为xml内容
# @param    unicode编码列表
# @return   合并后的unicode编码列表
def convert_to_xml(unicode_list):

    # 用于记录xml内容
    xml_content = ""

    # 遍历unicode编码列表
    for unicode_item in unicode_list:
        if '-' in unicode_item:  # 若内容包含‘-’则输出为“<Char>{起始值}-{结束值}</Char>”
            start_u, end_u = unicode_item.split('-')
            xml_content += f"\t<Char>{start_u}-{end_u}</Char>\n"
        else:  #否则输出<Char>{起始值}</Char>
            xml_content += f"\t<Char>{unicode_item}</Char>\n"
    
    # 去除头尾空格
    return xml_content.strip()

# 打开字体文件
font = fontforge.open(input_path) # 可以修改为自己ttf的路径

# 获取所有非空字符的Unicode编码
unicode_ranges = []
for glyph in font.glyphs():
    if glyph.unicode != -1:
        unicode_ranges.append(glyph.unicode)

# 导出Unicode编码范围
unicode_ranges.sort()

merged = merge_continuous(unicode_ranges)

# 保存Unicode编码范围到文件,txt文件默认输出桌面,可以按需求修改
with open(output_path, "w") as file:
    file.write('<?xml version="1.0" encoding="UTF-8"?>\n<CharSet>\n\t')
    # 转换为xml文件输出
    merged_str = convert_to_xml(merged)
    file.write(merged_str)

    # 写入xml结尾信息:
    # </CharSet>
    file.write('\n</CharSet>')

# 关闭字体文件
font.close()

其中用户需要将脚本开头的input_path和output_path分别配置为自己的ttf输入路径以及xml的输出路径,除了脚本不同以外其他操作均一致,生成xml格式如下:
image

  1. 根据unicode编码范围裁剪.ttf文件
# main.py
import xml.etree.ElementTree as ET

input_file = r"D:/ttf/noto_hans.ttf" # 输入ttf路径
output_file = r"D:/ttf/noto_hans_simplified.ttf" # 输出ttf路径
xml_file = r"D:/ttf/config.xml" # 包含字符范围的xml文件

class TTFSubsetter:
    def __init__(self, input_file, output_file, xml_file):
        self.input_file = input_file
        self.output_file = output_file
        self.xml_file = xml_file
    def __extract_char_ranges(self):
        """提取字符串范围

        Args:
            xml_path (str): 输入xml文件路径

        Returns:
            list: 返回字符串范围列表
        """
        # 解析XML文件
        tree = ET.parse(self.xml_file)
        root = tree.getroot()

        # 提取Char元素内的文本内容
        char_ranges = [char.text for char in root.findall('Char')]

        return char_ranges

    def __convert_unicode_to_chars(self, unicode_list):
        """将unicode码点范围转码点列表

        Args:
            unicode_list (list): 输入unicode码点范围列表

        Returns:
            list: 返回码点列表
        """
        chars_list = []

        for item in unicode_list:
            if '-' in item:  # 处理编码范围
                start, end = item.split('-')
                start, end = int(start[2:], 16), int(end[2:], 16)
                for code_point in range(start, end + 1):
                    chars_list.append(code_point)
            else:  # 处理单个编码
                code_point = int(item[2:], 16)
                chars_list.append(code_point)

        return chars_list

    def __remove_unprintable_chars(self, s):
        """过滤不可见字符

        Args:
            s (list): 需要过滤的字符串列表

        Returns:
            list: 返回可见字符的字符串
        """
        return ''.join(char for char in s if char.isprintable())

    def get_xml_unicode(self):
        # 执行提取范围
        ranges_list = self.__extract_char_ranges()
        # 输出结果
        # print(ranges_list)
        
        # 转换并打印结果
        converted_chars = self.__convert_unicode_to_chars(ranges_list)
        # print(converted_chars)
        
        return set(converted_chars)

    def generate_subset_font(self, input_file, output_file, used_unicodes):
        font = fontforge.open(input_file)
        for char_name in font:
            glyph = font[char_name]
            unicode = glyph.unicode
            if unicode  not in used_unicodes:
                glyph.clear()

        font.generate(output_file)
        font.close()

if __name__ == "__main__":
    ttf_subbetter = TTFSubsetter(input_file, output_file, xml_file)
    used_chars = ttf_subbetter.get_xml_unicode()
    ttf_subbetter.generate_subset_font(input_file, output_file, used_chars)

用户需要手动修改input_file,output_file和xml_file的路径,分别为输入原始.ttf文件,输出裁剪后的.ttf文件,设置裁剪范围.xml文件的路径。
其中config.xml示例如下,xml中出现的unicode码点为要保留的码点:

<?xml version="1.0" encoding="UTF-8"?>
<CharSet>
    <Char>0x0020</Char>
    <Char>0x002D</Char>
    <Char>0x0061-0x007A</Char>
</CharSet>

裁剪前.ttf如下:
image 裁剪后.ttf文件如下:
image 如上,使用该脚本基本可以满足将.ttf文件按照设定unicode范围进行裁剪的需求。

(五)常见问题:

  1. “直”字、“将”字显示为另一种字形 imageimage 如上图,右边的为“直”和“将”的另一种写法,若显示右边的字形,请检查中文的ttf是否为arial unicode ms.ttf,因为该ttf含有的字模就是“直”和“将”的另一种字形,如下图所示:
    imageimage 对于这种情况可以直接更换ttf文件来解决,在Sun-ExtA.ttf的情况下预览这两个字符,如下所示:
    imageimage

  2. 输入字符不显示或者显示“_” 遇到这种情况先从以下几个步骤进行排查:
    a.打印font_lang_get(),查看当前设置语言是否支持当前字符显示,若不支持,则需用font_lang_set()切换到相应语言,也可直接设置为Unicode id(即font_lang_set(Unicode))支持显示所有语言的字符,先排除语言设置错误的问题;
    b.若确保了语言没有设置错误的情况下,仍然显示不出来,则把字符串编码putbuf出来,留意是否存在对应字符编码,若不存在对应编码则需排查传输过来的字符串在哪个环节缺失了字符,比如是app传过来时缺失了某个字符,还是存储阶段对字符串进行了处理导致丢失等;
    c.若存在对应编码但没有显示则需考虑是否是没有配置中没有包含对应编码,可以在.xml文件中查找是否包含了缺失字符的unicode码,或者是ttf文件里不包含对应字符,可以选择对应ttf后在FontTool.exe中输入对应字符unicode码在预览中查找,若查找不到则说明当前ttf不包含对应字符的字模,需要更换包含该字符的ttf文件。

  3. 如何查看unicode字库支持什么语言 unicode字库支持所有代码页显示,公版sdk中的language_list.h里面提供了一些基本的语言,但其实很多语言都是使用同一份驱动的,也就是说,这些语言用到的字符都是一样的,只是语法、语义存在差异,而字库仅仅是提供了支持这一类字符的显示功能,至于怎么排序,构成对应语言合法的语义,则是看用户如何去排列这些字符。举个例子,在英语里面,“你好”对应的是“hello”,法语里面则是“bonjour”,可见两者之间只是存在语法和语义上的差别,实际上用到的都是拉丁语系的字符,故切换到1252代码页即可显示,对应的English和Unicode这两个id都能满足当前需求。那么如何确定unicode字库是否支持某种特定语言呢?可以根据下面步骤进行判断:
    a.直接在Codepage.txt中查询该语言(简写和全称都查询一下),在字符映射表中能够找到的则是已支持的语言;
    image b.若无法在Codepage.txt中找到,则可以在百度中按照“目标语言 + 字母 / 字符 / 代码页”等关键词方式去查找,若目标语言所用代码页被Codepage.txt所包含,则支持该语言。如查询马来语,该语言在Codepage.txt中找不到,但可以了解到该语言采用的也是拉丁字母,初步确认采用1252可以显示马来语,后续可以进一步确认是否还有用到其他代码页,如有则继续添加上即可。
    image

  4. 为什么使用字库时俄语字符间隔比较大?如何缩小间隔 该问题可能是ttf中字模本身带有间隙导致,请更换1251的ttf后再次尝试。

  5. 为什么字模提取工具采集到一半突然闪退?字模文件也没有生成 以下面选择系统自带的黑体为默认字体为例:
    image 采集过程中闪退,一般是因为在一些编码范围内,当前选择的ttf并没有提供相应字模,导致工具“罢工”了,用ttf查看工具(开源ttf查看工具链接在文档顶部)可以看到,该simhei.ttf在9fa6后面开始就没有相应的字模了,没有相应字模,工具自然也无法采集出来。
    image 除此之外,在font.xml配置中,某个代码页配置了相应的ttf,但在对应路径下如果没有找到对应的ttf,也会出现找不到字模的情况。
    这个时候就需要确认Fonts文件夹下是否包含了font.xml中用到的所有ttf,以及对应ttf是否提供相应字模,如果没用提供相应字模,则需要更换ttf,确保ttf提供所选代码页包含的编码范围都有相应字模,这样字模提取工具才能够正常工作,又或者在charset路径下把ttf中没有字模的编码给去掉,让工具不采集这部分编码。

解决步骤:

  1. 确定卡死前的编码 image 假设卡死前停在“仿”字,这里会打印出“仿”字的unicode编码,即4eff,此时可以参考 fontforge根据字符查找编码(点击跳转)的方式查看ttf,检查ttf是否该字符后的字符大片空字符,以确定是否是该问题导致的死机。
    若在fonttool.exe中看不到“字模信息”这一栏目,可以调整电脑屏幕缩放比例:
    image 右键->显示设置->缩放和布局中缩放比例设置为150%,即可见到“字模信息”栏目。

  2. 若确定是ttf字模大片缺失引起,则可以参考 导出ttf非空字符的unicode编码(点击跳转) 的方式将ttf的unicode编码范围导出到.xml文件中,替换掉对应代码页的.xml,如ttf是中文简体-思源黑体的,生成出来的 思源黑体.xml,替换掉则用思源黑体.xml的内容替换gb2312.xml的内容,此时就不会按照原本gb2312.xml的内容进行提取,导致闪退,当然也可以找一个全一些的ttf文件,包含gb2312.xml中绝大部分的字模,也可以保证正常采集。

待补充

本文档包含以下子页面

Prev
点阵屏歌词字库相关(蓝牙歌词,普通歌词)
Next
音箱可视化彩屏-入门到进阶开发指导