必须先用 FT_New_Memory_Face 创建 FT_Face,再调 FT_Load_Glyph 加载字形,才能安全访问 glyph->outline;直接传内存流给 FT_Outline_Decompose 错误。

如何用 FreeType 从内存加载字体并提取轮廓(FT_Outline)
FreeType 不支持直接“从纯内存字节流”提取轮廓,必须先调用 FT_New_Memory_Face 创建 FT_Face,再用 FT_Load_Glyph 加载字形后,才能访问其 glyph->outline。关键点是:不能跳过 face 初始化和 glyph 加载两步。
常见错误是把字体数据指针直接传给 FT_Outline_Decompose —— 它只接受已解析好的 FT_Outline*,不认原始内存。
-
FT_New_Memory_Face的第 2 个参数必须是字体数据起始地址(const FT_Byte*),第 3 个参数是总字节数,不能为 0 或溢出 - 加载前务必检查
face->num_glyphs是否 > 0,否则FT_Load_Glyph可能静默失败 - 调用
FT_Load_Glyph时推荐用FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE,避免自动栅格化干扰轮廓获取
怎么安全地访问和遍历 FT_Outline 中的点与轮廓段
FT_Outline 是一个结构体,包含点坐标数组 points、标志数组 tags 和轮廓起始索引数组 contours。它的内存由 FreeType 内部管理,不可 free,也不可长期持有指针——下次 FT_Load_Glyph 调用可能复用或重分配。
-
outline.n_points和outline.n_contours是当前字形真实数量,不是容量;遍历时必须用它们做上界,不能硬写 1024 -
outline.tags[i]每个字节含控制信息:FT_CURVE_TAG_ON(普通点)、FT_CURVE_TAG_CUBIC(三次贝塞尔控制点)、FT_CURVE_TAG_CONIC(二次)——注意宏定义在freetype/ftoutln.h,需显式包含 - 轮廓闭合靠
contours数组:第i个轮廓从contours[i-1] + 1到contours[i](contours[-1]视为 -1),不是按点顺序连续排列
如何用 FT_Outline_Render 在自定义位图上栅格化(非 FT_Load_Char 自动流程)
如果已有自己的 FT_Bitmap(比如 32-bit BGRA 内存缓冲区),想把轮廓画进去,不能直接调 FT_Load_Char——它会覆盖 bitmap 结构并强制用 FreeType 内部格式。正确路径是:手动构造 FT_Bitmap → 调 FT_Outline_Render → 用 FT_Raster_Params 指定渲染器和回调。
立即学习“C++免费学习笔记(深入)”;
-
FT_Bitmap的buffer必须由你 malloc,且按pitch × rows分配;pitch要对齐(通常为 4 字节倍数),FreeType 不帮你补齐 -
FT_Outline_Render需要先调FT_Get_Renderer获取FT_Renderer,再填FT_Raster_Params:设params.source = &outline,params.target = &bitmap,params.flags = FT_RASTER_FLAG_AA(开启抗锯齿) - 若目标格式非 8-bit 灰度(如 RGBA),必须自己实现
FT_Raster_RenderFunc回调,FreeType 默认只写灰度值到bitmap.buffer
为什么 FT_Load_Glyph 后 glyph->outline 有时为空或点数为 0
这不是 bug,而是字体本身不含矢量轮廓。有些字体(尤其是某些 .ttf 的 symbol 子集、.fon、或被压缩/损坏的文件)只提供位图 glyph(glyph->format == FT_GLYPH_FORMAT_BITMAP),此时 outline 字段无效。
- 务必在
FT_Load_Glyph后检查glyph->format == FT_GLYPH_FORMAT_OUTLINE,否则访问outline是未定义行为 - 某些字体用复合字形(
FT_LOAD_COMPUTE_METRICS不影响此判断),需递归展开(调FT_Get_SubGlyph_Info),但 FreeType 2.10+ 默认已自动处理简单合成 - Windows 上从 GDI 获取的字体句柄转成内存流时,可能丢失 CFF/TrueType 表,导致加载后无轮廓——建议优先用原始 .ttf/.otf 文件测试
实际中最容易被忽略的是:FreeType 的坐标系 Y 轴向上,而多数光栅化目标(如 OpenGL 纹理、DirectX surface)Y 向下,不做 y = height - y 反转会得到上下颠倒的轮廓。这个翻转必须在点坐标读取后、送入渲染器前完成,而不是指望 FT_Outline_Transform。


















