南宁一站网网络技术有限公司,wordpress enter,wordpress中国话插件,社群营销的具体方法fontTools库来检测字体文件中是否包含某字符
如何判断一个汉字是否在TTF字体中有定义
字库#xff1a;cmap 表 fontTools库来检测字体文件中是否包含某字符
https://blog.csdn.net/alxe_made/article/details/121619497 如何判断一个汉字是否在TTF字体中有定义
https://z…
fontTools库来检测字体文件中是否包含某字符
如何判断一个汉字是否在TTF字体中有定义
字库cmap 表 fontTools库来检测字体文件中是否包含某字符
https://blog.csdn.net/alxe_made/article/details/121619497 如何判断一个汉字是否在TTF字体中有定义
https://zhidao.baidu.com/question/2142595170230591988.html 字库cmap 表
原文地址 https://developer.apple.com/fonts/ttrefman/rm06/chap6cmap.html#Surrogates
总表
cmap表将字符编码映射为 glyph 即字符点阵图)的索引。对于某种字体选择什么编码依赖于目标平台的默认行为。要想字体运行在使用不同编码的多个平台需要多个编码表。因此cmap表会包含多个“子表”每个子表支持一种编码方案。
如果该字符的编码在字体文件中找不到任何glyph与之相对应则其glyph索引指向0。在字体文件中这个位置是一个代表“字符缺失”的glyph通常是一个空白方块。
如果字符编码根本不存在则映射为glyph索引-1这是保留给glyph流中被删除的glyph。
cmap表开头是cmap表版本和子表数目。然后是“子表”。
最初cmap表只能映射传统字符集标准即每字符编码使用8位8位16位混合或16位。随着ISOIEC10646-1的引入以及在Unicode2.0以后surrogates替代保留区的使用字体文件中的字符需要考虑16位/32位混合编码或32位编码。
最初对于编码子表类型只使用06的cmap版本号建议设置为0。如果cmap表中包含类型8以上的子表版本号设置为1——这些类型的子表使用了surrogates提供了对Unicode更好的支持。
目前这个建议不再适用所有的cmap表都应该将版本号设置为0。 Table6: cmap表头 Type Name Description UInt16 version Version number (Set to zero) UInt16 numberSubtables Number of encoding subtables 子表
每个cmap子表以platformID开始用于指定编码所使用的环境。然后是platformSpecificID用于标识在该platform下的某种编码。例如MacRomman是MacOS下几个标准的编码方案之一。在name表一节中有一个platformID和platformSpecificID的列表。最后是子表真实的偏移地址。 Table7: cmap子表 Type Name Description UInt16 platformID Platform identifier UInt16 platformSpecificID Platform-specific encoding identifier UInt32 offset Offset of the mapping table cmap子表应按照先platformID后platformSpecificID的顺序排序升序。
每个cmap子表可能是7种格式之一
format 0, format 2, format 4, format 6,format 8.0, format 10.0, and format 12.0 。 cmap格式 将Macintosh标准字符映射为glyph使用format0。format2则支持8位/16混合编码包含日、中、韩的字符到glyph的映射。format4用于16位映射。format6用于压缩的16位映射。
Formats 8, 10, and 12(properly 8.0, 10.0, and 12.0) 用于混合16位/32位以及纯32位映射。
译注utf-16是一种16位/32位混合编码。
这些编码都支持Unicode2.0以后的surrogates替代。 format 0 Format 0 适用于编码和glyph索引在单字节范围内的字符。这是标准的苹果字符到glyph的映射方式。
Table8: cmapformat 0 Type Name Description UInt16 format Set to 0 UInt16 length Length in bytes of the subtable (set to 262 for format 0) UInt16 language Language code for this encoding subtable, or zero if language-independent UInt8 glyphIndexArray[256] An array that maps character codes to glyph index values format 2 Format 2 适用于包含日、中、韩字符的字体。这种编码通常用于支持亚洲语言的Macintosh系统。这些字体包含8位/16位混合编码这种编码把2个byte中的第一个byte划出一段范围保留不用而在第2个byte中这些值却是可用的。
表9显示format2子表记录的数据结构。subHeaderKeys数组把高字节第1个byte的可能值映射到subHeaders数组的成员。这就能够判断是否使用了第2个字节2字节编码。另外这也会用来在glyphIndesArray数组中查找glyph索引。过程如下
设高字节为i取值0-255。先取subHeaderKeys[i]的值再除以8得到subHeader数组索引k。
如果k等于0说明i是一个单字节编码没有第2个字节了。如果k0则i是一个双字节编码的高字节那么他应该还有一个低字节j。
译注如果k0直接返回glyphIndexArray[i]作为glyph索引。 Table9: cmapformat 2 Type Name Description UInt16 format Set to 2 UInt16 length Total table length in bytes UInt16 language Language code for this encoding subtable, or zero if language-independent UInt16 subHeaderKeys[256] Array that maps high bytes to subHeaders: value is index * 8 UInt16 * 4 subHeaders[variable] Variable length array of subHeader structures UInt16 glyphIndexArray[variable] Variable length array containing subarrays subHeader的数据类型4个word的结构体其c语言定义为 typedef struct {
UInt16 firstCode;
UInt16 entryCount;
int16 idDelta;
UInt16 idRangeOffset;
} subheader; 如果k0subHeader[k]中的firstCode和entryCount被用于定义第2个字节j的取值范围 firstCode j (firstCode entryCount) 如果j不在范围之内返回glyph索引0缺失的字符。否则idRangeOffset会被用于指出glyphIndexArray数组的对应范围。glyphIndexArray紧跟在subHeaders数组之后并且可以简单地把它看作是subHeaders的一个扩充。首先需要计算出低字节字符映射数组的首地址 subArraysubHeader.idRangOffset(subHeader.idRangeOffset) 然后用低字节减去firstCode去索引subArray得到glyph索引初值p。idDelta为索引调整量。如果p0直接返回p。如果p!0那么ppidDelta。在必要的情况下需要对结果数用65535取模。
译注这段不好翻译或者原文描述有问题我采用了意译。
对于单字节k0的情况subHeaders[0]的firstCode0entryCount256idDelta0。正如前面所说的idRangeOffset指向glyphIndexArray首地址。i值被直接用于索引glyphIndex数组 p glyphIndexArray[i] 最后p被返回。 format 4 Format 4 是双字节编码。这种格式用于字体文件中的编码分布与几个连续的区域在区域之间可能有一些保留的空白。而有一些编码可能并不会与字体中的glyph对应。2字节的压缩编码则使用format6。
表头开始是格式编号format、子表长度length及语言language。紧接着是format数据。它分为3个部分 4 word(UInt16)的头部指定用于加快分段表查找的参数。4个数组用于描述段段是一个连续的编码范围。glyphID数组 Table10: Format 4 Type Name Description UInt16 format Format number is set to 4 UInt16 length Length of subtable in bytes UInt16 language Language code for this encoding subtable, or zero if language-independent UInt16 segCountX2 2 * segCount UInt16 searchRange 2 * (2**FLOOR(log2(segCount))) UInt16 entrySelector log2(searchRange/2) UInt16 rangeShift (2 * segCount) - searchRange UInt16 endCode[segCount] Ending character code for each segment, last 0xFFFF. UInt16 reservedPad This value should be zero UInt16 startCode[segCount] Starting character code for each segment UInt16 idDelta[segCount] Delta for all character codes in segment UInt16 idRangeOffset[segCount] Offset in bytes to glyph indexArray, or 0 UInt16 glyphIndexArray[variable] Glyph index array segCount指定了有多少段。在format4表中没有直接指定这个参数但所有的表参数中都间接的用到了segCount。segCount是指字体中连续编码区块的数目。searchRange是小于等于segCount的最大的2的n次方的2倍。 示例 Format 4 子表值计算方式: segCount 39 不计算segCount39 searchRange 64 (2 * (largest power of 2 39)) 2 * 32 entrySelector 5 (log2(the largest power of 2 segCount)) log2 (32) log2 (25)5 rangeShift 14 (2 * segCount) - searchRange (2 * 39) - 64
每个段都有一个statrCode、endCode、idDelta和idRangeOffset用于描述该段的字符映射。段以endCode值进行排序升序。
字符编码进行映射时首先查找到第1个endCode大于或等于它的段。如果该字符码大于该段的startCode将使用idDelta和idRangeOffset去查找glyph索引否则返回“丢失的字符”。为了标志段表结束最后一个段的endCode必需设置为0xffff。这个段不需要包含任何映射。它简单地将字符码0xffff映射为“丢失的字符”即glyph0。
如果idRangeOffset值不为0该字符编码的映射依赖于glyphIndexArray。字符编码到
startCode的偏移的量被用于加在idRangeOffset值中。最终这个数字用于表示从idRangeOffset自身地址到正确的glyphIdArray索引的偏移量。使用这种方法是因为在字体文件中glyphIdArray是紧跟在idRangeOffset地址之后。下面的公式列出glyph索引地址的计算 glyphIndexAddress idRangeOffset[i] 2 * (c - startCode[i]) (Ptr) idRangeOffset[i] 公式中乘以2的原因是需要把值转换成字节数。
当然也可以使用下列公式 glyphIndex *( idRangeOffset[i] idRangeOffset[i] / 2 (c - startCode[i]) ) 这种方式是由于idRangeOffset是一个Uint16数组。
如果 idRangeOffset为0idDelta加上字符编码即glyph索引。 glyphIndex idDelta[i] c 注意所有的idDelta[i]都是65535的模数。 以下表为例演示了字符编码102030990100153的glyph索引映射过程。这里segCount被指定为4。这是一个format4子表映射变量的示例演示从字符到glyph索引是如何计算的。假设段表的segCountX2是8searchRange是8entrySelector是2rangeShift是0。 Name Segment 1 Chars 10-20 Segment 2 Chars 30-90 Segment 3 Chars 100-153 Segment 4 Missing Glyph endCode 20 90 153 0xFFFF startCode 10 30 100 0xFFFF idDelta -9 -18 -27 1 idRangeOffset 0 0 0 0 下面是映射过程
10被映射为109120 被映射为2091130被映射为30181290被映射为901872等等。 format 6 Format 6 用于映射16位2字节的字符为glyph索引。有时称之为精简表映射。这种格式用于字符编码在一个连续范围的字体文件。非压缩的2字节编码映射应采用format4。format6格式如下表所示 Table11: cmapformat 6 Type Name Description UInt16 format Format number is set to 6 UInt16 length Length in bytes UInt16 language Language code for this encoding subtable, or zero if language-independent UInt16 firstCode First character code of subrange UInt16 entryCount Number of character codes in subrange UInt16 glyphIndexArray[entryCount] Array of glyph index values for character codes in the range 子表中的firstCode和entryCount指定了字符编码的可能范围。这个范围从firstCode开始长度等于entryCount。在这个范围之外的编码被映射为“丢失的字符”或者glyph索引0。在这个范围内的编码用编码减去firstCode将直接作为glphyIndexArray的下标从而得到glyph索引。 format 8.0–混合 16-位 and 32-位 Format 8.0 有点像format 2字符编码是可变长度的。如果字体中包含Unicdoe“替代”那么它也会包含16位unicode的其它规则。就像format2 允许混合8位/16位编码一样也需要一种16位/32位混合编码的映射。这种混合编码假设在32位字符编码中的高16位使用了和任何16位编码都不一样。这意味着要么有一部分字符编码是16位数要么32位数的前端由固定编码构成不代表任何意义。
下表位format 8子表格式 Type Name Description Fixed32 format Subtable format; set to 8.0 UInt32 length Byte length of this subtable (including the header) UInt32 language Language code for this encoding subtable, or zero if language-independent UInt8 is32[65536] Tightly packed array of bits (8K bytes total) indicating whether the particular 16-bit (index) value is the start of a 32-bit character code UInt32 nGroups Number of groupings which follow 接下来是分组。每个分组由下列结构构成 Type Name Description UInt32 startCharCode First character code in this group; note that if this group is for one or more 16-bit character codes (which is determined from the is32 array), this 32-bit value will have the high 16-bits set to zero UInt32 endCharCode Last character code in this group; same condition as listed above for the startCharCode UInt32 startGlyphCode Glyph index corresponding to the starting character code 请注意endCharCode并不是编码个数因为比照不同组时通常使用一个已有的字符编码进行的使用endCharCode就不用在组的基础上进行加法运算。
压缩的bit数组is32[]用于判断哪些16位数被保留给32位字符编码作为高字节以及哪些特定16位数开头的编码能在字体文件中映射到glyph。
因为系统软件需要知道还有多少字节才到下一个字符尤其是当前字符映射到“缺失的字符”时。
Format 8.0非常适合作为使用surrogates的Unicode文本其他字符集编码也很容易使用这种格式。
要判断某个16位cp是否是32位编码的高字节可以使用公式 is32[cp / 8 ] ( 1 ( cp % 8 ) ) ) 如果得到的不是0该16位数是一个32位编码的前半部分。0则反之。一个字体文件可以既没有编码为0x0000的glyph也可以没有高16位为0x0000的glyph。 format 10.0–Trimmed array Format 10.0 有点像format 6里面定义了一个trimmed数组去掉了数组中的空值用于表示32位字符编码的范围
: Type Name Description Fixed32 format Subtable format; set to 10.0 UInt32 length Byte length of this subtable (including the header) UInt32 language 0 if dont care UInt32 startCharCode First character code covered UInt32 numChars Number of character codes covered UInt16 glyphs[] Array of glyph indices for the character codes covered format 12.0–Segmented coverage Format 12.0 有点像format 4, 但它使用32位整数定义段结构这是子表结构 Type Name Description Fixed32 format Subtable format; set to 12.0 UInt32 length Byte length of this subtable (including the header) UInt32 language 0 if dont care UInt32 nGroups Number of groupings which follow 分组的结构定义 Type Name Description UInt32 startCharCode First character code in this group UInt32 endCharCode Last character code in this group UInt32 startGlyphCode Glyph index corresponding to the starting character code 这里再一次使用了endCharCode而不是Code的个数原因同format8.0中所述。 Mac OS兼容信息 所有的子表格式Mac 0SX10.2及以后都支持。对于任何特定的cmap子表MacOS不针对某种特定格式。
Newton-兼容信息
Newton 字体使用较老的format 0,2,4,6子表格式不支持format 8.010.012.0。 依赖 cmap表指向glyph索引。因此glyph索引对某种字体而言必需是有效的而且不能超过glyphs的大小glypns大小在maximumpfoile表中描述 maximumprofile table。 工具 对cmap表进行编辑主要使用ftxdumperfuser进行。注意ftxdumperfuser支持全部的7种子表格式以及使用统一码标量值的增补Unidcode字符。 附: Unicode 和Surrogates
最初的Unicode标准允许所有字符都使用16个bit进行编码。这最多能包括65354个字符Unicode编码规定UFFFE和UFFFF保留不能用于字符编码更多细节请参考Unicode标准。Unicode字符集与其它字符集编码不同有一些编码其所有字符都使用8位编码另一些则部分字符使用8位部分字符使用16位。
在Unicode 2.0研发过程中发现一个明显的事实——没有足够的编码来覆盖人类所有字符。为解决这个问题使用了一个扩展机制——surrogates。surrogates替代指一些特殊的Unicode编码它们是成对的包括高位替代UD800到UDBFF和低位替代UDC00到UDFFF。将一对替代映射为单个的32位整数称作单值代表单个字符。
Unicode 2.0 and 3.0 并没有哪个字符使用替代但2001年3月发表的Unicode3.1包含了40000个字符就用到了替代。之后更多的字符使用替代进行编码。
Unicode字符使用16位编码并且在UTF-16引入了替代。cmapformat 8.0适用于UTF-16编码。注意0x0000总是一个单独的编码它后面永远不会出现32位中的另外一半。
Unicode技术委员会已经采用了32位Unicode编码每个字符将用32位编码代表即UTF-32。format10.0和12.0适用于UTF-32。
还有8位编码的实现如UTF-8。UTF-8常用于C字符串的交换协议通常以0字节作为结尾。没有哪种格式适用于UTF-8。 https://blog.csdn.net/iteye_10993/article/details/82340061