Inter 仓库 fontsample 工具实战指南:macOS 下用 CoreText 生成字体 PDF/PNG 文本样张
【免费下载链接】interThe Inter font family项目地址: https://gitcode.com/gh_mirrors/in/inter
本文基于 Inter 开源字体仓库(gh_mirrors/in/inter)内的misc/tools/fontsample工具,完整讲解其构建方式、命令行用法与底层实现原理。fontsample是一个 macOS 专用的 Objective-C++ 命令行程序,用于将任意 macOS 可读取的字体文件渲染成居中的文本样张并输出为 PDF(或 PNG),是字体开发与质量检查流程中快速查验字形渲染效果的实用小工具。读完本文,你将掌握该工具的编译、参数配置、输出格式控制,以及其基于 CoreText / CoreGraphics / ImageIO 的完整渲染管线。
工具定位:为字体开发服务的 macOS 样张生成器
fontsample位于 misc/tools/fontsample/README.md,其定位非常明确:一个 macOS 专用程序,用于为某个具体字体文件生成带文本样式的 PDF。它面向的典型场景是字体开发者/设计师在构建出新的字形后,快速把字体文件丢给工具,得到一张可直接查看排版效果的样张,例如用于检查 Inter 各字重、斜体或可变字体的字形渲染是否正常。
工具本身只依赖 macOS 系统框架(Foundation、CoreText、CoreGraphics、CoreServices、ImageIO),不依赖任何第三方字体渲染库,因此构建极简:一条make即可完成编译。
构建与基本使用
编译
在 misc/tools/fontsample/ 目录下直接执行:
$ makeMakefile 中定义了完整的编译规则:使用clang作为编译器,源文件为 fontsample.mm(Objective-C++,故用clang的 C++ 模式编译,并开启-fobjc-arc自动引用计数),链接阶段引入-lobjc以及 Foundation、CoreText、CoreServices、CoreGraphics、ImageIO 五个系统框架。默认编译标志包含-Wall -g -fno-common,若需要调试构建可传DEBUG=1(此时关闭-O0优化),否则默认不额外优化。清理产物执行make clean。
编译成功后,运行./fontsample -h查看完整用法:
$ ./fontsample -h usage: ./fontsample [options] <fontfile> options: -h, -help Show usage and exit. -z, -size <size> Font size to render. Defaults to 96. -t, -text <text> Text line to render. Defaults to "Rags78 **A**". -o <file> Write output to <file> instead of default filename. Defaults to <fontfile>.pdf. If the provided filename ends with ".png" a PNG is written instead of a PDF. <fontfile> Any font file that macOS can read.注:
-h输出中未列出-width与-height,但源码 fontsample.mm 的usagetemplate及参数解析逻辑实际支持这两个选项(详见下文“参数说明”),这是源码与 README 的一个细微差异,使用时以实际行为为准。
最小示例
# 为 Inter-Regular.woff2 生成默认样张 PDF $ ./fontsample Inter-Regular.woff2 # 指定字号与文本,输出到自定义文件 $ ./fontsample -z 128 -t "The quick brown fox" -o sample.pdf Inter-Regular.woff2 # 输出 PNG 格式 $ ./fontsample -t "Hello Inter" -o sample.png Inter-Regular.woff2输出文件名缺省时取输入字体文件去掉扩展名后加.pdf(例如Inter-Regular.woff2→Inter-Regular.pdf);若-o指定的文件名以.png结尾(不区分大小写),则输出 PNG,否则一律输出 PDF。
命令行参数详解
fontsample支持的所有选项汇总如下:
| 参数 | 别名 | 取值 | 默认值 | 说明 |
|---|---|---|---|---|
-h | -help | 无 | — | 打印用法并退出 |
-z | -size | 数值 | 96 | 渲染字号(pt),必须>= 1且为合法数字 |
-t | -text | 字符串 | "Rags78 **A**" | 渲染的单行文本 |
-o | — | 文件路径 | <fontfile>.pdf | 输出文件;以.png结尾则输出 PNG |
-width | — | 像素整数 | 自动 | PNG 输出时强制图像宽度(源码支持,README 未列出) |
-height | — | 像素整数 | 自动 | PNG 输出时强制图像高度(源码支持,README 未列出) |
参数解析逻辑(源码级)
参数解析由 fontsample.mm 的parseargs完成,要点如下:
- 所有选项必须以
-开头且长度大于 1;-h/-help打印用法后以退出码 0 退出。 -z/-size通过atof解析为浮点数,若结果为 NaN 或小于 1,则通过badarg报错并退出;-width/-height使用strtoull解析为无符号整数。getargval负责取选项的下一个参数值,若缺失、为空或以-开头,会报 “missing value for argument” 错误。- 未知标志一律报
unknown flag;非选项参数被收集为位置参数,main中要求恰好一个<fontfile>——少于一个报missing <fontfile>,多于一个报extraneous argument after <fontfile>。
渲染管线:从字体文件到 PDF/PNG
整个渲染流程可以从main → pdfmake这条调用链拆解,核心步骤依次为:加载字体、构建文本行、计算排版度量、绘制输出。
1. 加载字体:loadFont
loadFont 接收字体文件路径与字号,按以下顺序创建字体对象:
CFURLCreateWithFileSystemPath将路径转为 POSIX 风格 URL;CGDataProviderCreateWithURL创建数据提供者(读取失败则报failed to read file退出);CGFontCreateWithDataProvider解析字体数据(解析失败报failed to parse font退出);CTFontCreateWithGraphicsFont以指定size创建 CoreText 字体对象(失败报CTFontCreateWithGraphicsFont failed退出),并在返回前释放cgf、dataProvider、url。
注意:调用方必须对返回值执行CFRelease(函数注释已明确要求),pdfmake在渲染完成后确实释放了font与textLine。
2. 构建文本行:createTextLine
createTextLine 将文本与字体封装为带kCTFontAttributeName属性的NSAttributedString,再调用CTLineCreateWithAttributedString得到可绘制的排版行CTLineRef。若文本无效(例如无法排版),pdfmake会报invalid sample text并退出。
3. 计算度量:CTLineGetTypographicBounds
pdfmake中通过:
CGFloat width = CTLineGetTypographicBounds(textLine, &ascent, &descent, &leading); CGFloat height = ascent + descent + leading;获得文本行的排版宽度与高度,作为后续页面/画布的自动尺寸。draw函数据此把文本在画布内水平、垂直居中:水平位置x = ceilf((width - textWidth) / 2),垂直位置y = descent + ceilf((height - textHeight) / 2)(descent用于保证文本基线定位正确)。
4. 输出 PDF:makePDF
makePDF 使用CGPDFContextCreate创建 PDF 上下文,页尺寸mediaBox取文本行的排版宽高;流程为CGPDFContextBeginPage → draw → CGPDFContextEndPage → CGPDFContextClose,最终把生成的 PDF 数据写入输出文件。源码中draw的白色背景填充代码被注释掉(见 fontsample.mm),即默认输出透明背景、仅含居中文本的 PDF 页面。
5. 输出 PNG:makePNG
makePNG 走另一条路径:
- 画布尺寸默认取
width × height * 1.2(高度放大 120% 防止裁剪);若指定了-width/-height则覆盖对应维度。 - 分配
width * height * 4字节的位图缓冲区,用CGBitmapContextCreate创建 RGBA 位图上下文(kCGImageAlphaPremultipliedLast,8 位每通道)。 draw绘制文本后,CGBitmapContextCreateImage生成CGImageRef,再由writePNG借助 ImageIO 的CGImageDestinationCreateWithURL(kUTTypePNG)写入 PNG 文件,失败时返回 NO 并在 stderr 记录日志。
应用场景与注意事项
- 使用前提:本工具是 macOS 专用程序,依赖 Objective-C 运行时与系统框架,无法在 Linux/Windows 上直接编译运行;构建机器需具备 Xcode 命令行工具(提供
clang与系统 SDK)。 - 字体格式:
<fontfile>接受任何 macOS 能读取的字体文件,理论上涵盖 OTF、TTF、WOFF2、TTC/OTC 等;Inter 仓库构建产物(如 docs/font-files/Inter-Regular.woff2、docs/font-files/InterVariable.ttf)均可直接作为输入,用于快速查验样张。 - 与仓库其他工具的配合:
fontsample是 Inter 工具链中偏“人工目检”的一环;自动化质量检查另有make test驱动的 fontbakery 报告(见仓库根 Makefile)。若需要批量生成字距(kerning)样张,可参考同为工具链的 misc/tools/kernsample.py。 - 已知限制:源码中
makePDF留有 “TODO: read and use options.width and options.height” 注释(fontsample.mm),即-width/-height目前仅对 PNG 输出生效,PDF 页面尺寸始终由文本度量自动决定。
小结
fontsample是一个小而完整的 macOS 字体渲染工具:约 300 行 Objective-C++ 源码,串联起 CoreText 文本排版、CoreGraphics 绘制、ImageIO 图片输出三大系统框架,提供了字号、文本、输出格式、画布尺寸等实用控制项。对于 Inter 这类需要高频验证字形渲染效果的字体项目,它是一条低成本、可复现的目检途径;其实现同时也是一个学习 macOS 系统级字体渲染 API 的简洁范本。相关文件可按以下路径深入阅读:README(misc/tools/fontsample/README.md)、构建配置(misc/tools/fontsample/Makefile)、完整实现(misc/tools/fontsample/fontsample.mm)。
【免费下载链接】interThe Inter font family项目地址: https://gitcode.com/gh_mirrors/in/inter
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考