のねのBlog

パソコンやソフト開発で起きた問題など書きます。よろしくお願いします。

TrueType OpenType ファイル構造 その1

$ xxd arial.ttf  | head
00000000: 0001 0000 0019 0100 0004 0090 4453 4947  ............DSIG
00000010: b77e 536a 000d dc30 0000 1adc 4744 4546  .~Sj...0....GDEF
00000020: b13f b3a1 000c 4b24 0000 0334 4750 4f53  .?....K$...4GPOS
00000030: 83c6 e844 000c 4e58 0001 20f8 4753 5542  ...D..NX.. .GSUB
00000040: fe0f 144b 000d 6f50 0000 6c5a 4a53 5446  ...K..oP..lZJSTF
00000050: 6d2a 6906 000d dbac 0000 001e 4c54 5348  m*i.........LTSH
00000060: 7b10 38c6 0000 44ac 0000 1091 4f53 2f32  {.8...D.....OS/2
00000070: 1432 5d84 0000 0218 0000 0060 5043 4c54  .2]........`PCLT
00000080: fd7b 3e43 000c 4aec 0000 0036 5644 4d58  .{>C..J....6VDMX
00000090: 5092 6af5 0000 5540 0000 1194 636d 6170  P.j...U@....cmap
Offset Table
Type Name Description
Fixed sfnt version 0x00010000 for version 1.0 or 'OTTO'.
USHORT numTables Number of tables.
USHORT searchRange (Maximum power of 2 <= numTables) x 16.
USHORT entrySelector Log2(maximum power of 2 <= numTables).
USHORT rangeShift NumTables x 16-searchRange.
_0 _1 _2 _3
0000000: 00 01 00 00 sfnt version
_4 05
0000004: 00 19 numTables 0x19=0d25
_6 _7
0000006: 01 00 searchRange
_8 _9
0000008: 00 04 entrySelector
_A _B
000000A: 00 90 rangeShift
searchRange
◯0x02= 02 <= numTables(0x19=0d25)
◯0x04= 04 <=
◯0x08= 08 <=
◯0x10 = 16 <= 
X0x20=32 <=

0x10*0x10=0x100
entrySelector

 Log2(0d16 = 0x10)
=Log2(2^4=0d16 = 0x10)
=4
rangeShift
0x19*(0d16=0x10)=0x190
0x190 - 0x100 = 0x0090

The offset subtable
The offset subtable, documented in Table 4, begins with the scaler type of the font. The number of tagged tables in the ”sfnt”; follows.The table directory itself and any subtables are not included in this count. The entries for searchRange, entrySelector and rangeShift are used to facilitate quick binary searches of the table directory that follows. Unless a font has a large number of tables, a sequential search will be fast enough.

If a faster search is necessary, a binary search is most easily done on a number of entries that is a power of two. This makes it possible to cut the number of items to search in half by shifting. The remaining offset subtable entries should be set as follows:

searchRange is the largest power of two less than or equal to the number of items in the table,
 i.e. the largest number of items that can be easily searched.
rangeShift is the number of items minus searchRange;
 i.e. the number of items that will not get looked at if you only look at searchRange items.

Before the search loop starts, compare the target item to the item with number rangeShift.
サーチのループを始める前に、ターゲットとrangeShiftの数を比較する。
 If the target item is less than rangeShift, search from the beginning of the table.
target itemがrangeShiftより少ない場合、テーブルの開始の位置からサーチを開始する。
 If it is greater, search starting at the item with number rangeShift.
rangeShiftより大きい場合、rangeShiftの位置からサーチを開始する。
entrySelector is log2(searchRange). 
It tells how many iterations of the search loop are needed. (i.e. how many times to cut the range in half)

Note that the searchRange, the entrySelector and the rangeShift are all multiplied by 16 which represents the size of a directory entry.