← 字体里的隐藏开关 / 轮廓从哪来:位图描摹成矢量 待审核 16 / 18
加餐 · 栅格转矢量 / 描摹

轮廓从哪来:位图描摹成矢量

字体到底是什么讲到字形是一组控制点描出的贝塞尔轮廓——但这些点最初是谁放的?要么字体设计师在编辑器里手工放,要么从一张位图(扫描的旧字样、手写、点阵原稿)自动描摹(tracing)而来。描摹听起来只是「沿黑白边界画一圈」,通用描摹器(如 potrace)也确实只追求轮廓相似——可字体要的不止于此:它要的是结构合理的轮廓。控制点要最少、节点要落在极值点上(让手柄水平 / 垂直)、直线段要保持笔直、拐点处要打节点标记结构。这些约定对手工编辑、hinting,尤其可变字体的插值兼容至关重要。下面这块 demo 把同一个位图,分别交给「笨拙描摹」与「结构化描摹」,看两者的差距。

关键不是「点多点少」,而是「点放得对不对」:笨拙描摹的顶点数随分辨率线性膨胀,且永远是楼梯——放大必然暴露锯齿。结构化描摹把节点钉在字形的极值点(最上 / 下 / 左 / 右),那里切线恰好水平或垂直,手柄因此轴对齐;两段曲线之间若有拐点(曲率反号)也单独打一个节点。这样几个点就能精确复原整条曲线,且无级缩放都光滑。

1 · 为什么字体宁可少点也要放对:可变字体的插值

把同一个字形的体与体存进一个可变字体(variable font),中间任意字重靠浏览器逐控制点插值算出。前提是两端的控制点能一一对应。节点都钉在极值点上时,细 / 粗两端结构一致,插值平滑;一旦某个节点没落在极值(像笨拙描摹那样随手放),两端对应关系错位,中间字重就会鼓包 / 塌陷 / 出折痕。拖下面的滑块走一遍 0 → 1,再切「节点错位」对比同一段插值的差别。

2 · 通用描摹器 vs 字体级描摹

关注点 通用描摹(potrace 等) 字体级描摹(img2bez)
优化目标 轮廓视觉相似 轮廓相似 + 结构合理
控制点数 不限,常远超必要 最少,够还原即可
节点位置 沿曲线均匀 / 随边界 钉在极值点,手柄轴对齐
直线段 可能被拟合成微曲 保持笔直
拐点 不特别处理 单独打节点标记结构
输入精度 常先二值化再描 反走样灰度,亚像素边界
插值兼容 不保证 为可变字体而设计

这里的位图是为演示而由一条干净轮廓反向光栅化得到的;真实场景里输入是扫描件 / 旧字样,「结构化描摹」要做的正是从那堆像素里反推出这样一条轮廓。img2bez 的三段式:精确读边界 → 按转向定角点 / 直段 / 极值 / 拐点并强制极值处切线轴对齐 → 可选地照原始像素再精化。

这页接哪里:结构化轮廓画好后,怎么把它实时画到屏幕是另一端的工程;而轮廓里那些控制点本身长什么样、坐标怎么存,见字体到底是什么

3 · 相关链接

  • img2bez:为字体设计优化的栅格转矢量描摹——elih.net。本页蓝本。Rust 实现的描摹库,目标不是轮廓最像而是「像设计师那样画」:控制点最少、极值点放节点且切线轴对齐、直线保持直、拐点标记结构,并以可变字体插值兼容为重要约束;附自动化结构评分。
  • Potrace: Transforming bitmaps into vector graphics——potrace.sourceforge.net。经典通用位图描摹器与其算法论文:多边形逼近 → 平滑成曲线。优化轮廓相似度,不为字体结构而设,作为对照。
  • gvar — Glyph Variations Table——learn.microsoft.com。可变字体逐控制点存储「变化量」的表:正因为靠点的位移做插值,两端轮廓的点必须一一对应、结构一致,否则中间字重失真。
  • Bézier curve · MDN Glossary——developer.mozilla.org。on-curve 锚点 + off-curve 手柄如何定义一段曲线;描摹的产物就是一串首尾相接的贝塞尔段。