Символ TrueType Font сделан из квадратичного Безье. Почему в контуре глифа появляется несколько последовательных точек, не соответствующих кривой?
Я пишу синтаксический анализатор TTF. Для лучшего понимания формата TTF я использовал TTX для извлечения данных глифа ".notdef" из C:\Windows\calibri.ttf следующим образом.
<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 состоит из квадратичных кривых Безье, каждый из которых имеет две точки кривой (конечные точки) и только одну точку кривой (контрольная точка). Как интерпретировать эти последовательные не кривые точки?
1 ответ
Для синтаксического анализа TTF необходимо использовать http://www.microsoft.com/typography/otspec/glyf.htm а также технические документы о формате TTF с сайта Microsoft. Они говорят нам, что для кривой есть два типа точек: на кривой и вне кривой. Точки на кривой - это "реальные" точки, через которые проходит кривая, а точки на кривой - это контрольные точки, определяющие кривизну Безье.
Теперь то, что вы описываете как "кривая Безье", является правильным: одна кривая Безье идет от 1 реальной точки, направляемой 1 контрольной точкой, к 1 реальной точке. Тем не менее, квадратичные кривые, как правило, являются дерьмом для проектных работ, потому что они действительно плохо подходят для аппроксимации круговых дуг, но с ними гораздо дешевле работать, чем с кубическими кривыми, поэтому мы придерживаемся их для шрифтов с контурами истинного типа. Чтобы обойти это, контуры 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 немного глупа, но все же достаточно разборчива)
После нескольких летдальнейшего редактирования мне удалось найти документацию, которая фактически объясняет (или, по крайней мере, подразумевает) ее в документации Apple по TTF, по https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html, что на "рисунке 13" гласит, что:
В частности, точки на кривой, расположенные в средних точках касательных к кривой, не добавляют никакой дополнительной информации и могут быть опущены.
Еще больше редактировать ShreevatsaR указывает, что текст между рисунками 2 и 3 в документации Apple также имеет значение:
Также было бы возможно указать кривую, показанную на фиг.2, с одной меньшей точкой, удалив точку p2. Точка p2 не является строго необходимой для определения кривой, поскольку ее существование подразумевается, и ее местоположение может быть восстановлено на основе данных, предоставленных другими точками. После перенумерации оставшихся точек получаем [РИСУНОК 3].