stb_truetype.h:把 TTF 文件读进内存,就能渲染字体位图
【免费下载链接】stbstb single-file public domain libraries for C/C++项目地址: https://gitcode.com/GitHub_Trending/st/stb
stb_truetype.h 是一个单文件、零依赖的 C 语言库,职责很窄:把 TTF 字体文件解析成 TrueType 字形位图。你做游戏 UI、终端字符渲染、工具类画文本,都不必再引一套重字体引擎。值得看的点在于:它把"字节流怎么变成屏幕上的像素"这条链路摊开给你看,没有黑盒。
它凭什么只靠一个 .h 就能干活?
- 单文件交付:一个头文件拷进工程即可编译
- 零依赖:纯 C,C/C++ 工程都吃
- 内存直读:字体读进缓冲区就解析,不落盘
- 多渲染模式:普通位图、亚像素定位、SDF 距离场
上面的渲染图来自仓库自带测试tests/sdf/sdf_test.c,同一字体从小字号拉到 104px,边缘依然干净。
三行代码出第一个字形
库不碰文件系统,你先把 TTF 读进内存:
unsigned char *buf = 读你的 .ttf 到 buf,得 len;接着建字体信息并定字号——scale 是"1 个 EM 单位等于几 px"的换算系数,直接给像素高度最省事:
stbtt_fontinfo f; stbtt_InitFont(&f, buf, 0); float scale = stbtt_ScaleForPixelHeight(&f, 24);最后一步才碰到像素。位图尺寸和落点偏移都是输出参数,算完直接画:
unsigned char *m = stbtt_GetCodepointBitmap( &f, scale, scale, 'A', &w, &h, &ox, &oy);数据走向只有两段:
整像素还是亚像素?普通位图还是 SDF?
第一个开关是定位精度。整像素版只吃整数坐标,字符排出来边缘偶发发虚;亚像素版多收一个 0–1 之间的小数位移,边缘立刻顺:
stbtt_MakeCodepointBitmapSubpixel(&f, out, w, h, w, scale, scale, 0.3f, 0.0f, cp); // 0.3f 是 x 方向亚像素偏移需要逐字符对齐到小数坐标时就用它,UI 排版尤其有感。
第二个开关是输出形态。普通位图画多大就烘焙多大,放大后锯齿明显;SDF(有向距离场,本质是"每个像素离字形边缘多远"的灰度图)可以一份贴多档尺寸,放大不糊:
unsigned char *sdf = stbtt_GetCodepointSDF(&f, scale, cp, 8, 255, 7.0f, &w, &h, &ox, &oy); // padding=8, 缩放系数 7.0固定尺寸的 HUD、控制台日志选普通位图;要在运行时缩放或做描边特效,选 SDF。
一次画 96 个字符,draw call 怎么降?
逐字符现生成位图,每帧都重复劳动。换个思路:把整组字形一次烤进一张纹理图集(font atlas),之后每画一个字只是提交一个四边形,draw call 立刻降下来。
stbtt_BakeFontBitmap(buf, 0, // 字体字节流与偏移 24.0f, // 像素高度 atlas, W, H, // 目标图集缓冲 32, 95, // 起始码点、字符数 chardata); // 每字符的 UV 与度量图集大小要够塞下全部字符,字符多就换stbtt_PackFontRanges按 Unicode 区间分批打包——中文这种上万字符的字体,逐字符烘焙不现实。
三个容易栽的坑
⚠️显存悄悄涨:stbtt_GetCodepointBitmap内部会分配缓冲。根因是你只拿到了指针,忘了它归你管。解法:配对调用stbtt_FreeBitmap(m, 0),userdata 要和分配时一致。
⚠️TTC 字体显示乱码:TTC 是字体集合文件,一个文件装好几款字体。根因是 offset 写死 0,拿到的是集合里第一款而非你要的那款。解法:用stbtt_GetFontOffsetForIndex(buf, index)查偏移再传给stbtt_InitFont。
⚠️小字号边缘发虚:根因是字形轮廓落在像素格线之间,硬取舍就出现锯齿。解法:定位走亚像素接口,或烘焙时开过采样再降采样。
什么时候别用它?
- 段落级排版(换行、对齐、字距调整):它只给字形,不给排版引擎
- 双向文字与复杂文本特性:需要 FreeType 这类引擎级支持
- 纯 GPU 原生管线:字形数据要绕道 CPU 内存,不如引擎自带方案顺
如果你的需求只是 UI 标签或游戏 HUD 上的单行文字,CPU 侧生成加图集方案,性能完全够用。下一步建议:挑一个现有 UI 元素,把它的位图路径换成 SDF 版本,对比 12px 下的边缘质量——差异比想象中大。
| 我想做的事 | 调哪个函数 |
|---|---|
| 从内存读 TTF 并解析 | stbtt_GetFontOffsetForIndex+stbtt_InitFont |
| 按像素高度定字号 | stbtt_ScaleForPixelHeight |
| 生成单个码点的字形位图 | stbtt_GetCodepointBitmap |
| 亚像素精确定位字形 | stbtt_MakeCodepointBitmapSubpixel |
| 烘焙整套字体图集 | stbtt_BakeFontBitmap |
【免费下载链接】stbstb single-file public domain libraries for C/C++项目地址: https://gitcode.com/GitHub_Trending/st/stb
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考