我正在写一个TTF解析器。为了更好地理解TTF格式,我使用TTX提取C:\ Windows \ calibri.ttf的“.notdef”字形数据,如下所示。
<TTGlyph name=".notdef" xMin="0" yMin="-397" xMax="978" yMax="1294">
<contour>
<pt x="978" y="1294" on="1"/>
<pt x="978" y="0" on="1"/>
<pt x="44" y="0" on="1"/>
<pt x="44" y="1294" on="1"/>
</contour>
<contour>
<pt x="891" y="81" on="1"/>
<pt x="891" y="1213" on="1"/>
<pt x="129" y="1213" on="1"/>
<pt x="129" y="81" on="1"/>
</contour>
<contour>
<pt x="767" y="855" on="1"/>
<pt x="767" y="796" on="0"/>
<pt x="732" y="704" on="0"/>
<pt x="669" y="641" on="0"/>
<pt x="583" y="605" on="0"/>
<pt x="532" y="602" on="1"/>
<pt x="527" y="450" on="1"/>
many more points
</contour>
...some other xml
</TTGlyph>
您可以在一行中看到多个曲线外控制点。但我了解到,TrueType字体由Quadratic Beziers组成,每个Beziers都有两个曲线上的点(终点)和一个曲线外点(控制点)。如何解释这些连续的曲线外点?
答案 0 :(得分:23)
TTF解析需要从microsoft站点应用http://www.microsoft.com/typography/otspec/glyf.htm以及有关TTF格式的技术文档。这些告诉我们曲线有两种类型的点:曲线上和曲线外点。曲线上的点是曲线通过的“实际”点,而曲线外曲线点是引导贝塞尔曲率的控制点。
现在,您所描述的“贝塞尔曲线”是正确的:单个贝塞尔曲线从1个实际点(由1个控制点引导)变为1个实际点。然而,二次曲线通常是设计工作的废话,因为它们在逼近圆弧方面非常糟糕,但它们也比使用三次曲线便宜得多,因此对于具有truetype轮廓的字体我们坚持使用它们。为了解决这个问题,TTF概述通常使用贝塞尔曲线序列来获得看起来不错的均匀曲线,并且这些序列往往具有良好的性质:曲线上和曲线外的点以非常特殊的模式间隔。
考虑这个贝塞尔序列:
P1 - C1 - P2 - C2 - P3 - C3 - P4
如果我们添加on
信息,我们会将其编码为TTF:
P1 - C1 - P2 - C2 - P3 - C3 - P4
1 - 0 - 1 - 0 - 1 - 0 - 1
现在的技巧:如果每个Pn是一个曲线上的点,并且每个Cn是一个控制点,和 P2恰好位于C1和C2之间,P3位于C2和C3之间,等等,那么这是一个可压缩的曲线:如果我们知道C1和C2,我们就知道P2,所以我们不必明确地列出它,我们可以把它留给任何解析字形轮廓的东西。
因此,TTF将编码长贝塞尔序列以获得均匀曲线:
P1 - C1 - C2 - C3 - P4
1 - 0 - 0 - 0 - 1
节省可观的空间,而不会损失精度。如果您查看TTX转储,您会在每个点的on
值中看到这一点。要获得P2,P3等,我们所做的就是:
foreach(array as point):
// do we have an implied on-curve point?
if(mask_for_point == 0 && mask_for_previous_point === 0):
missing_point = midpoint(point, previous_point)
points.push(missing_point)
// add the explicitly encoded point
points.push(point)
运行此程序后,points
数组将具有交替的曲线上和曲线外点,并且贝塞尔曲线构造为
for(i=0, i<arr.length, i+=2):
curve(array[i], array[i+1], array[i+2])
经过一些搜索后, 编辑,http://chanae.walon.org/pub/ttf/ttf_glyphs.htm涵盖了如何以非常好的细节处理glyf
表数据(ascii图形有点傻,但仍然足够清晰)
进一步编辑我设法在https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html#necessary上找到了实际上解释(或者至少暗示)在TTF上的Apple文档中的文档。 13“表示:
特别是位于曲线切线中点的曲线上的点不会增加额外的信息,可能会被省略。
进一步编辑 ShreevatsaR指出苹果文档中图2和图3之间的文字也是相关的:
通过去除点p2,还可以通过少一点来指定图2中所示的曲线。不需要点p2来定义曲线,因为它的存在暗示并且其位置可以从其他点给出的数据重建。在重新编号剩余的点之后,我们有[图3]。