从活字到字体源码
我喜欢 Inconsolata 的字母、大括号和整行代码的阅读节奏,也希望常见操作符能像 Fira Code 那样连起来。直接换字体,会连同这些习惯一起换掉,于是有了 Ligconsolata Next。
Inconsolata 源码已经带有 !==、===、->、=>、>=、<-、<= 这组编程连字,但它们放在 dlig 这个可选特性里。编辑器的普通连字开关未必启用它,所以「字体里有」和「打开连字就能看到」之间隔了一层设置。早期 Ligconsolata 把这些替换暴露到 liga,Next 继续这个方向,并接上 Inconsolata v3 的可变字体源码。
后面的改动逐渐超出了 feature 开关。== 和 != 需要补出清楚的两横线形态,长箭头需要随字符数量延展,注释连字还得避开 URL 和路径。参考 Fira Code 时,我希望学的是覆盖面、上下文规则和验证方法,新增轮廓仍从 Inconsolata 自己的笔画派生。
一开始想做的只是补连字,却会不断遇到字体基础问题。两个字符合成一个字形后为什么还得占两格?同一个轮廓为什么在小字号里变了样?.ttf 能安装,为什么项目还要维护 .glyphs?这些问题牵涉字形复用、印刷工艺、屏幕像素和排版引擎,值得单独整理。
由于篇幅问题,全文分成 11 部分来讲。前八篇建立基础,第九篇回到这次 fork,最后两篇讨论 AI 参与实现和开发者怎样验收。
第一篇《字形怎样学会复用》从书写和字模开始,区分书法风格、雕版与活字,解释一套字形怎样进入可重复的排印流程。
第二篇《中文字体走进现代出版》关注报纸、画报、教材和工具书怎样提出不同的字形要求,并沿上海印刷字体设计与王选的汉字激光照排工作,理解中文字库的生产变化。
第三篇《西文字体穿过机器时代》从金属活字走到机械排版、照排和桌面出版,也解释代码字体为什么继承了打字机与终端的等宽约束。
第四篇《那些熟悉的字体从哪里来》用宋一体、Times New Roman、Arial、Comic Sans、微软雅黑、苹方和思源系列看具体任务与分发渠道。字体类别、具体字库和授权范围在这一篇分别说明。
第五篇《字体从像素格走向轮廓》解释点阵、贝塞尔曲线、栅格化和 hinting,回答「可缩放轮廓为什么仍会在小字号里发糊」。
第六篇《可变字体把变化装进一个文件》用真实字体的字重与字宽矩阵解释设计轴、master 和插值,以及等宽可变字体需要保持的宽度关系。
第七篇《连字让源码换一种读法》以 !== 为例,追踪字符到 glyph 的替换,区分 liga、dlig 和 calt,说明连字怎样保留原始文本与总宽度。
第八篇《字体源码藏在哪些文件里》打开项目里的 .glyphs、.nam 和 config.yaml,把设计数据、生成脚本、构建字体与验证工具对应起来。
第九篇《Ligconsolata Next 的连字改造》集中记录这次改造的取舍,包括两横线与三横线、长箭头片段、注释与路径冲突,以及真实字体样张。
第十篇《AI 改字体时到底在做什么》区分候选研究、重复生成和验收判断,解释脚本可以自动化到哪里,以及错误怎样从图片反推回源码。
第十一篇《不会字体设计,也能看懂字体改动》给出可操作的 review 方法,用 glyph 输出、宽度数据、上下文反例和字号矩阵判断一次改动是否具备继续使用的条件。
Ligconsolata Next 是采用新 family name 的派生字体,沿用项目中的 OFL 许可,与上游官方发行分别维护。文章里的机制图是教学示意,标为字体样张的图片则来自实际字体轮廓;两种图片分别用来解释机制和检查实现。