今天照例是设计古琴字体。在设计过程中,我注意到一个问题,就是 svg 的显示正常,但是导出为字体轮廓后,填充变得异常。例如下面这个“口”字:
原来是因为这个“口”字的路径是由两个闭合路径组成的,但其填充规则是 even-odd,字体轮廓的填充规则是 non-zero,也就是说默认外圈轮廓是顺时针方向,而内圈轮廓是逆时针方向。然而 even-odd 与轮廓方向无关,而是用射线法则来判断点是否在路径内。因此需要将 even-odd 的 fill rule 转换为 non-zero 的 fill rule,例如下面这个“口”字:
二者的源代码区别如下:
html
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" fill="#3498db" d="
M 10 10
L 190 10
L 190 190
L 10 190
Z
M 50 50
L 150 50
L 150 150
L 50 150
Z
"/>
</svg>html
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="nonzero" fill="#e74c3c" d="
M 10 10
L 190 10
L 190 190
L 10 190
Z
M 50 50
L 50 150
L 150 150
L 150 50
Z
"/>
</svg>注意到改动了 fill rule 和内圈路径的方向(由顺时针改为逆时针)。但在 svg 层面上的改动,很难从源码中直观的找到需要修改的路径,于是可以借助 脚本工具 进行修复。
或者在设计路径时就注意路径的方向。在 figma 中,如果需要在矢量图中挖洞,则需要把内圈路径置于外圈路径上方,然后使用布尔运算中的“减法”(subtract)操作,然后将路径拼合(outline stroke)后导出为 svg,这样就可以保证路径的方向正确。而之前我仅仅是用油漆桶工具填充两个闭合路径之间的区域,导致内圈路径的方向是默认的顺时针,而此时使用的是 even-odd 填充规则,导出为字体轮廓后使得填充异常。