负的unsigned int?

时间:2014-04-21 20:20:49

标签: unsigned true-type-fonts

我试图绕过truetype规范。在this page上的' cmap'部分格式4 ,参数 idDelta 被列为无符号16位整数(UInt16)。然而,更进一步,给出了几个例子,这里给idDelta赋值-9,-18,-27和1.这怎么可能?

2 个答案:

答案 0 :(得分:0)

该页面上idDelta的定义和使用不一致。在struct subheader中,它被定义为int16,而稍早一点的同一个子标题被列为UInt16*4

这可能是规范中的一个错误。

如果你看一下实际的实现,like this one from perl Tk,你会发现idDelta通常是签名的:

typedef struct SUBHEADER {
    USHORT firstCode;       /* First valid low byte for subHeader. */
    USHORT entryCount;      /* Number valid low bytes for subHeader. */
    SHORT idDelta;      /* Constant adder to get base glyph index. */
    USHORT idRangeOffset;   /* Byte offset from here to appropriate
                 * glyphIndexArray. */
} SUBHEADER;

或者查看libpdfxx的实施:

struct SubHeader
{
USHORT firstCode;
USHORT entryCount;
SHORT idDelta;
USHORT idRangeOffset;
};

答案 1 :(得分:0)

这不是规范中的错误。对于示例,它们在idDelta行中显示负数的原因是All idDelta[i] arithmetic is modulo 65536.(引自上一节)。这是这样的。

获取字形索引的公式为

glyphIndex = idDelta[i] + c

其中c是字符代码。由于此表达式必须是模数65536,因此如果您使用大于2个字节的整数,则该表达式等于以下表达式:

glyphIndex = (idDelta[i] + c) % 65536

idDelta是u16,所以假设它的最大值为65535(0xFFFF),则glyphIndex等于c - 1,因为:

0xFFFF + 2 = 0x10001 0x10001 % 0x10000 = 1

您可以将其视为发生溢出时环绕0的16个整数。

现在请记住,模是重复除法的,保留余数。好吧,在这种情况下,由于idDelta仅16位,所以模将需要做的最大除法数量是1,因为从两个16位整数相加中可以得到的最大值是0x1FFFE,小于0x100000。这意味着快捷方式是减去65536(0x10000)而不是执行模。

glyphIndex = (idDelta[i] - 0x10000) + c

这就是示例在表中显示的值。这是我解码的.ttf文件的一个实际示例:enter image description here

我想要字符代码97(小写的“ a”)的索引。

  1. 97大于32且小于126,因此我们使用映射的索引2。
  2. idDelta[2] == 65507
  3. glyphIndex = (65507 + 97) % 65536 === 68(65507 - 65536) + 97 === 68