一、创建项目目录

fonttools/
│
├─ font_subset_core.py
├─ build.bat
└─ venv/

进入目录:

cd /d F:\tools\fonttools

二、创建虚拟环境

创建:

python -m venv venv

激活:

venv\Scripts\activate

成功后命令行会出现:

(venv)

验证:

where python

输出应类似:

F:\tools\fonttools\venv\Scripts\python.exe

三、安装依赖

安装 FontTools:

python -m pip install fonttools

安装 PyInstaller:

python -m pip install pyinstaller

验证 FontTools:

python -c "from fontTools.subset import main;print('OK')"

输出:

OK

说明环境正常。


四、核心脚本 font_subset_core.py

import sys
from pathlib import Path
from fontTools.subset import main as pyftsubset_main

FONT_EXTS = {".ttf", ".otf"}


def read_text_auto(path):
    data = Path(path).read_bytes()

    for enc in ("utf-8-sig", "utf-8", "gbk", "gb18030"):
        try:
            return data.decode(enc), enc
        except UnicodeDecodeError:
            pass

    return data.decode("gb18030", errors="ignore"), "gb18030-ignore"


def sort_key(c):
    code = ord(c)

    if '0' <= c <= '9':
        return (0, code)

    if 'A' <= c <= 'Z':
        return (1, code)

    if 'a' <= c <= 'z':
        return (2, code)

    if 0x4E00 <= code <= 0x9FFF:
        return (4, code)

    return (3, code)


def make_unique_chars(text):
    chars = {
        c
        for c in text
        if not c.isspace()
        and ord(c) >= 32
    }

    return "".join(sorted(chars, key=sort_key))


def build_subset(font_path, chars_path, out_font_path):
    pyftsubset_main([
        str(font_path),
        f"--text-file={chars_path}",
        f"--output-file={out_font_path}",
        "--layout-features=*",
        "--glyph-names",
        "--symbol-cmap",
        "--legacy-cmap",
        "--notdef-glyph",
        "--notdef-outline",`
        "--recommended-glyphs",
    ])


def main():
    if len(sys.argv) < 3:
        print("用法: font_subset_core.exe 字体.ttf 文本.txt")
        return

    font_path = Path(sys.argv[1])
    text_path = Path(sys.argv[2])

    if not font_path.exists():
        print("字体文件不存在:", font_path)
        return

    if not text_path.exists():
        print("文本文件不存在:", text_path)
        return

    if font_path.suffix.lower() not in FONT_EXTS:
        print("第一个参数必须是字体文件:", font_path)
        return

    text, enc = read_text_auto(text_path)
    chars = make_unique_chars(text)

    chars_path = text_path.with_name(text_path.stem + "_chars.txt")
    chars_path.write_text(chars, encoding="utf-8")

    out_font_path = font_path.with_name(font_path.stem + "_subset" + font_path.suffix)

    build_subset(font_path, chars_path, out_font_path)

    print("处理完成")
    print("识别编码 :", enc)
    print("字符数量 :", len(chars))
    print("字符文件 :", chars_path)
    print("子集字体 :", out_font_path)


if __name__ == "__main__":
    main()

命令格式:

python font_subset_core.py 字体.ttf 文本.txt

测试:

python font_subset_core.py test.ttf test.txt
处理完成
识别编码 : utf-8-sig
字符数量 : 247
字符文件 : test_chars.txt
子集字体 : test_subset.ttf
  • 自动完成
读取文本
↓
去重
↓
排序
↓
生成 chars.txt
↓
调用 pyftsubset
↓
生成 subset.ttf

六、打包 EXE

使用 PyInstaller:

python -m PyInstaller -F --clean --collect-all fontTools --name FontSubset font_subset_core.py

参数说明:

-F               单文件
--clean          清理缓存
--collect-all    打包 FontTools 全部依赖
--name           EXE名称

打包完成:

dist/
└─ FontSubset.exe

FontSubset.exe 用于根据游戏文本自动生成字体子集。第一个参数为原始字体文件(支持 .ttf.otf),第二个参数为文本文件(.txt)。程序会自动读取文本内容、提取所有可见字符、去重排序、生成字符集文件,并调用内置的 pyftsubset 生成子集字体。

使用方式:

FontSubset.exe FZBWKS.ttf all_text.txt

执行后会生成:

all_text_chars.txt     // 去重后的字符集
FZBWKS_subset.ttf      // 生成的子集字体

适用于传奇游戏、手游项目、UI字体优化等场景,可大幅缩小字体体积,同时保留项目实际使用到的全部字符。


无需安装:

Python
FontTools
PyInstaller

用户机器直接运行即可。


七、 字体加粗

安装 FontForge

下载地址
然后打开上面生成的字体子集。勾选如下红框可紧凑显示(忽略空格只显示有的字符)
在这里插入图片描述

设置

Ctrl + A 全选,然后调整字体实现加粗。中文选 CJK 字中空隙保留选 Retain
我用 6 em units 这个要自己调看效果
在这里插入图片描述

导出

将选中字符导出为字体文件(警告什么的,反正也不会处理,直接跳过)
在这里插入图片描述

八、智能字体子集.bat

FontSubset.exe 辅助脚本
FontSubset.exe 所有目录创建文本文件,复制粘贴如下内容,然后文件改名为 智能字体子集.bat

@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion

title FontSubset 智能拖拽脚本
mode con cols=120 lines=32
color 07

goto main
:fail
color 0C
title [ERROR] FontSubset 智能拖拽脚本
::echo %~1
for %%i in (%*) do echo %%i
echo ===============================================
exit /b 1

:main

echo.
echo ===============================================
echo           FontSubset 智能拖拽脚本
echo ===============================================
echo 用法: 将此脚本与 FontSubset.exe 放在同一目录下 
echo   1. 拖入一个 .ttf 文件:		自动查找同目录同名 .txt 文件
echo   2. 拖入一个 .txt 文件:		自动查找同目录同名 .ttf 文件
echo   3. 同时拖入一个 .ttf + 一个 .txt:	直接使用这两个文件执行(文件名无需相同)
echo.
echo 例如:
echo   拖入: game.ttf 自动查找 game.txt
echo   执行: FontSubset.exe game.ttf game.txt
echo -----------------------------------------------
echo   拖入: 楷书.ttf + game.txt
echo   执行: FontSubset.exe 楷书.ttf game.txt
echo ===============================================
echo.

set "EXE=%~dp0FontSubset.exe"

if not exist "%EXE%" (
    call :fail "【错误】 找不到 FontSubset.exe"
    pause
    exit /b
)

if "%~1"=="" (
    call :fail "【错误】 请拖入 .ttf 或 .txt 文件"
    pause
    exit /b
)

set "TTF="
set "TXT="
set "BASE_DIR="
set "BASE_NAME="

:loop
if "%~1"=="" goto check

set "FILE=%~1"
set "EXT=%~x1"

if /i "%EXT%"==".ttf" (
    set "TTF=%FILE%"
    if not defined BASE_DIR set "BASE_DIR=%~dp1"
    if not defined BASE_NAME set "BASE_NAME=%~n1"
) else if /i "%EXT%"==".txt" (
    set "TXT=%FILE%"
    if not defined BASE_DIR set "BASE_DIR=%~dp1"
    if not defined BASE_NAME set "BASE_NAME=%~n1"
)

shift
goto loop

:check

if defined TTF if not defined TXT (
    for %%A in ("%TTF%") do (
        set "TXT=%%~dpnA.txt"
    )

    if not exist "!TXT!" (
        call :fail 【错误】找不到同名【txt】: !TXT!
        pause
        exit /b
    )
)

if defined TXT if not defined TTF (
    for %%A in ("%TXT%") do (
        set "TTF=%%~dpnA.ttf"
    )

    if not exist "!TTF!" (
        call :fail 【错误】找不到同名【ttf】: !TTF!
        pause
        exit /b
    )
)

if not defined TTF (
    call :fail "【错误】 没有找到 .ttf 文件"
    pause
    exit /b
)

if not defined TXT (
    call :fail "【错误】 没有找到 .txt 文件"
    pause
    exit /b
)

echo 当前字体文件: %TTF%
echo 当前字符文件: %TXT%
echo ===============================================
echo.

"%EXE%" "%TTF%" "%TXT%"

echo.
echo 执行完毕
pause

参考资料

https://github.com/fontforge/fontforge
Glyphr Studio(浏览器离线开源,轻量 AI 辅助)
yeungchenwa / FontDiffuser (本地开源 AI 模型,批量生成风格变体)

字体家 AI 在线字体编辑器(最推荐新手)
Lipi.ai Font Studio(海外在线,AI 批量变体专业)

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐