最近发现某个家伙又开始说梦话。先说明一下,iOS 27 beta 2 的苹方 VF 与 iOS 26 的内容完全一致,只是刷了个版本号。(这么一来,我在之前就已经完成了 iOS 27 苹方 VF 提取件的「全球首发」。)


既然内容完全没有变化,我们可以直接使用先前发布的 iOS 26 苹方 VF 字体文件,获取方式见文末,也可以去上一篇 iOS 26 苹方 VF 发布页;之前已经下载过的朋友直接就能享受 iOS 27 的体验。:-)
iOS 26.4.1 / 27.0 beta 2 苹方 VF(含苹方-日)
抢着搞噱头是不好的,不能连最基本的事实核查都不做。
鉴于 2026 年 AI 的编程能力发展情况,大家都可以试试用 Alpha Argon 在 2024 年发布的 iOS 18 苹方提取思路分析进行 vibe coding、从而自行提取截至目前任意版本的苹方 VF。技术分析在iOS 18 苹方 VF 发布推文里早已放送,也可以来他的原始发布页:
https://zhuanlan.zhihu.com/p/703335162
可惜我看了看某个东西的所谓提取教程,开头就是事实性错误,还弄出「中国日本」这样的操作,你的脑袋是豆包生的吗?提取的门道是有的,门槛是客观存在的,只有一句话某个东西说对了,就是必须有一台 Mac;但说实在的,如果没有一颗正常的智人大脑,给了 Mac 也白搭。

最重要的事实错误:macOS、iOS 等自带的 PingFangUI.ttc 拿到原文件也不能正常读取,只有待在原本私有库下的路径时才能被 CoreText 读取。
import Foundationimport CoreTextlet copiedFileURL = URL("...")let data = Data(contentsOf: copiedFileURL)assert(data != nil)assert(CTFontManagerCreateFontDescriptorsFromData(data as CFData) == nil)assert(CTFontManagerCreateFontDescriptorsFromURL(copiedFileURL as CFURL) == nil)
系统给 PingFang UI 开了后门;将它复制到其他任何位置,都不能按普通字体文件正常读取。所以从 iOS 固件提取原文件来读取是不可能的。如果真的要通过 CoreText(更准确地说是 CoreGraphics)提取苹方,只能在最新的 macOS/iOS 实体机或 Xcode Simulator 上跑代码。

如果有幸确实拿到了 CTFont 实例,也不需要考虑 LSB 的值,CTFontCreatePathForGlyph 只返回规范后的轮廓。
let font = CTFontCreateWithFontDescriptor(..., ...)var gid = 4635 as CGGlyphvar width = 0 as CGFloatCTFontGetAdvancesForGlyphs(font, .horizontal, &gid, &width, 1)let path = CTFontCreatePathForGlyph(font, gid, nil)!
这里所谓规范化指将字形的 LSB point 定为 x = 0,然后按照字号/UPM 缩放。如果一定要说,LSB 在这里就等于实际字面的最小横坐标;但既然记录了整个路径,为什么还要再单独强调 LSB 呢?
特意在这里列出需要提取 UPM 值也显得非常可疑。PingFang UI 的原始 UPM 没有多大意义,因为系统为了跟西文匹配,放大了 UPM 来缩小字身。要确定正常的 UPM,一般要把汉字字身宽定为 1em,因此对于苹方来说,正好是 1000。然而 hvgl 支持浮点坐标,UPM 选用 1000 并不能完全准确地反映 PingFang UI 带小数的坐标值。说「unitsPerEm=1000 :这是中文字形的标准设计单位,确保字形精度」就是不对了。

fontTools 没有从 JSON 生成 TTF 的功能,fontmake 也没有。
真正会大量使用 JSON 作为中间格式的是 OTFCC 和 FontLab (VFJ)。这里说「导出为 JSON 格式」,再「使用 fontTools 库生成标准 TTF 文件」,中间缺了真正关键的构建逻辑。
如果只是把 Swift 读出来的路径转存成 JSON,再在 Python 里读 JSON,那这几个 4 GB 大的文件很像是 AI 作出的决定。以及人类编写 Swift 或 Objective-C 时,CGPathElementType 是枚举类型,会直接使用具名成员,不会在意它的 raw value 是多少。要特意写出「type=0 → moveTo……」这种废话,就是 AI 最喜欢的掉书袋了。
另外,PingFang 和 SF 确实用的是二次曲线。但根本原因是 TT VF 处理起来更高效一些;CFF2 VF 太凌乱了。「二次贝塞尔曲线(qCurveTo) :苹果字体内部使用二次曲线而非三次曲线」显得没头没脑的;二次曲线没有三次曲线有表现力,结合前文关于 UPM 的表述,这个时候又不说「确保字形精度」了。AI 掉书袋 +1。

为五地字形分别扒了一遍数据,完全不懂 ttc 表共用机制。
五地字形共用了 hvgl 表,只通过不同的 cmap 来启用不同的字形映射。理论上五地扒出来的 JSON 文件大小不应该有明显差异,因为共用的轮廓数据占大头。
我自己扒出来的五地 7 采样 VFJ 只有 470 MB。当然,我在扒的过程中做了轮廓合并和简化无用锚点,所以体积小一些。如果自己参与了代码编写的过程的话,显然不乐意几乎相同的文件,每个 4 GB 的要重复五次。
看下来最后还有两处疑点:
- 不知道为什么要省去 wght = 200 的 thin 和 wght = 900 的 black。即使 black 可以说是新的粗体可以忽略,但旧的静态苹方有的 thin 要删去就很不可思议了。
- 为什么要相信说出「中国日本」的人能干出正常的事呢?
https://wwbsh.lanzout.com/i0ug13pf0vvg
夜雨聆风