什么是 .mfp
一句话
MediaFontsPacked(缩写 .mfp,即 Media Fonts Packed)是一个开放的字体包容器格式规范, 用来把一批字体连同它们的元数据、预览图、许可证文本打包成单个文件, 并且支持在不重写整个文件的前提下做增量更新。
它的定位可以概括为一句话:
一个能被通用压缩工具直接打开的字体包格式。
它不是什么
理解一个格式,先划清边界通常比列功能更有效。
| 它不是 | 说明 |
|---|---|
| 不是字体格式 | .mfp 不定义字形、也不改变字体本身的编码。包内的字体仍是 TTF / OTF / TTC 等既有格式 |
| 不是加密容器 | 内容完整性由逐条目 SHA-256 与可选的签名条目承担,而不是靠"不让别人解压" |
| 不是客户端程序 | 本规范只定义字节布局与语义;增量更新算法、预览渲染、字体安装都留给客户端决定 |
| 不是"重新发明压缩" | 压缩沿用 ZIP 既有的 deflate / store,没有自定义压缩算法 |
为什么要在 ZIP64 之上做
.mfp 物理上就是一个带自定义头尾的标准 ZIP64 归档。整个格式只在标准 ZIP 之上加了两样东西:
| 扩展项 | 大小 | 作用 |
|---|---|---|
MFP Header | 固定 32 字节 | 格式识别(magic)、版本、标志位、manifestOffset |
manifest.json | 变长 | 唯一索引,描述包内全部字体、模板、校验与冲突信息 |
其余全部是普通 ZIP 条目。这是一个刻意的设计选择,不是技术上的妥协,它换来三件事:
- 生态互操作性 —— 用户可以用任何熟悉的工具查看、备份、迁移包内资源,不被单一客户端绑定
- 可排障性 —— 出问题时能直接用通用工具定位是容器结构问题还是客户端逻辑问题
- 零成本迁移 —— 已有 ZIP 工具链的团队可直接复用现有流程生成与校验容器
换句话说:如果哪天维护者不在了,你的字体包依然是你能打开的东西。
设计目标与取舍
| 目标 | 采用的做法 | 代价 |
|---|---|---|
| 单文件承载多字体 | 一个 ZIP64 归档装全部条目 | 单包体积随字体数量增长 |
| 内容可校验 | 逐条目 SHA-256(checksum 结构) | 打包时多一遍哈希计算 |
| 支持超大容器 | 强制 ZIP64 | 对极小文件有一定冗余开销 |
| 高频增量更新 | revision 链 + ZIP 追加语义 | 需维护 revision 历史 |
| 向后兼容 | 新增字段均为可选,缺失时分级降级 | 读取端需实现降级逻辑 |
现存实现的兼容性边界
设计前提里有一条需要标注清楚:通用压缩工具可以打开它,但有一个尺寸边界。
- 前置的 32 字节 Header 不影响通用工具打开(7-Zip、bsdtar、Python
zipfile实测均可正常列出与解压) - 真正的风险在文件末尾:恢复记录位于 EOCD 之后,一旦超过约 64 KB, 部分严格实现(bsdtar、Python
zipfile)会因只回扫文件末尾 64 KB 而找不到 EOCD
完整的实测数据、原理分析与修复建议见 通用工具兼容性。