规范中 TTF 字体构建的缺失部分

Missing pieces for TTF font building from Spec

我无法解决这些与 TTF 规范相关的问题。

  1. "Computing the checksum" 在 "head".
  2. "xMin"、"yMin"、等 "head"
  3. maxPoints、maxContours、maxComponentPoints、maxComponentContours、maxTwilightPoints "maxp"
  4. uint8 flags[variable] Array of flags 在 "glyf"

我想知道是否有人可以澄清这些片段。

1

对于 (1) it says 这个:

checkSumAdjustment To compute: set it to 0, calculate the checksum for the 'head' table and put it in the table directory, sum the entire font as a uint32_t, then store 0xB1B0AFBA - sum. (The checksum for the 'head' table will be wrong as a result. That is OK; do not reset it.),

我找到了他们引用的两个校验和实现:

// https://docs.microsoft.com/en-us/typography/opentype/spec/otff

uint32
CalcTableChecksum(uint32 *Table, uint32 Length)
{
uint32 Sum = 0L;
uint32 *Endptr = Table+((Length+3) & ~3) / sizeof(uint32);
while (Table < EndPtr)
    Sum += *Table++;
return Sum;
}

uint32 CalcTableChecksum(uint32 *table, uint32 numberOfBytesInTable)
    {
    uint32 sum = 0;
    uint32 nLongs = (numberOfBytesInTable + 3) / 4;
    while (nLongs-- > 0)
        sum += *table++;
    return sum;
    }

这是简单的实现。我的问题是,什么进入校验和 value。所以看起来是这样的:

  1. 计算头部校验和 table。
  2. "sum the entire font as a" 不知道什么意思.
  3. 也不知道这意味着什么("then store 0xB1B0AFBA - sum. (The checksum for the 'head' table will be wrong as a result. That is OK; do not reset it.),")

2

对于 (2),我不确定如何计算。似乎我只是将所有字形捆绑成一个 spritemap,然后计算最终大小。但是我认为它说不要考虑字形的边界框,所以 不完全 确定它的意思。

3

对于 (3),未找到有关这些变量含义的任何文档。

4

对于(4),我不知道这是什么意思"uint8 flags[variable] Array of flags"。他们在下面有 table,但我不确定它是 per contour 还是 per glyphper点.

我还有一个关于理解复合字形的相关问题here 如果你知道的话。

一般来说,您可能会发现 current OpenType specification 很有用,因为它包含许多 Apple 版本中没有的更新、说明和更正。

关于您的具体问题:

1head.checksumAdj计算

说明相当清楚,虽然有隐含的 "step zero" of assemble 所有字体数据(tables、目录等)进入最终版本表格和顺序。一旦你拥有了:

  1. head table 中的 checkSumAdj 的值设置为零

  2. 计算 head table 的校验和并将其存储在字体的 table 目录(其中 tag/checksum/offset/length 是为字体中包含的所有 table 存储)

  3. 计算整个字体的总和(所有uint32的总和,就像table校验和),包括步骤1和2的修改。

  4. 0xB1B0AFBA 减去步骤 3 中的值存储在 head.checkSumAdj 中。就这样!关于头部校验和出现不正确的措辞意味着如果你要 运行 在 head table 之后 存储最终值的校验和计算,这看起来是错误的。但这没关系,因为它是这样定义的:本质上是 head table 的校验和,您必须首先忽略(设置为 0)checkSumAdj 值。

2 head xMin, xMax, yMin, yMax

这就是所有字形的 xMin、xMax、yMin 和 yMax。每个 字形 xMin、xMax 等都非常简单 "the minimum (maximum) X (Y) coordinate" 所有点(对于复合字形,你会在 after组成字形,即在复合字形定义中应用任何移位、缩放或其他转换之后)。在 head table 和字形数据中,边界框都是一个 16 位有符号整数数组。所以通常的过程是遍历每个字形,得到计算出的边界框,当你这样做的时候,跟踪 X/Y min/max (独立)。完成循环后,您将获得 head table 的值,它本质上是一个矩形,包含字体中每个字形的每个坐标。

3 maxp

这些在 maxp table definition 中有相当明确的定义:

  • maxPoints是任意单个非复合("simple")字形的最大点数

  • maxContours 同样是任何单个非复合 字形

  • 的最大轮廓数
  • maxComponentPoints复合字形中的最大点数(即所有组成字形的点数之和)

  • maxComponentContours 同样是 composite glyph

  • 中的最大轮廓数
  • maxTwilightPoints是指TrueType指令0区使用的最大"twilight"点数。如果您的字体不使用 TrueType 指令,则可以将此(以及其他与指令相关的字段)设置为零。如果您不熟悉 TrueType 指令(通常称为 "hints")以及它们如何存储在字形数据中,您可能需要查看 OpenType 规范的“Instructing TrueType Glyphs" and "TrueType Instruction Set”部分。

4 glyf table 简单字形标志

uint8 flags[variable]表示flags数组长度可变。其原因在 specification ("Simple Glyph Flags"):

中讨论

In logical terms, there is one flag byte element, one x-coordinate, and one y-coordinate for each point. Note, however, that the flag byte elements and coordinate arrays used packed representations. In particular if a logical sequence of flag elements or sequence of x- or y- coordinates is repeated, then the actual flag byte element or coordinate value can be given in a single entry, with special flags used to indicate that this value is repeated for subsequent logical entries.

换句话说,flags数组的元素,展开后是每个坐标,但实际存储 作为 uint8 数组不一定(与坐标数据本身的存储一样)。很大程度上取决于每个字形中的坐标排列。