负的unsigned int?

问题描述 投票:0回答:2

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

unsigned true-type-fonts
2个回答
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;
};

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

当发生溢出时,您可以将此视为一个16整数,大约为0。

现在请记住,模数是重复除法,保留余数。那么在这种情况下,因为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相同
© www.soinside.com 2019 - 2024. All rights reserved.