テーブル一覧を読み込むプログラム
では、実際にここまでの情報を読み込んで、フォントのテーブル一覧を表示してみます。
引数でフォントファイル (複数可) を指定すると、テーブルの情報を表示します。
03_tables.c
引数でフォントファイル (複数可) を指定すると、テーブルの情報を表示します。
03_tables.c
/******************************* * テーブル一覧表示 * * [usage] exe <files> *******************************/ #include <stdio.h> #include <stdlib.h> #include <stdint.h> /* 2byte 読み込み */ uint16_t read16(FILE *fp) { uint8_t b[2]; fread(b, 1, 2, fp); return (b[0] << 8) | b[1]; } /* 4byte 読み込み */ uint32_t read32(FILE *fp) { uint8_t b[4]; fread(b, 1, 4, fp); return ((uint32_t)b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; } /* Tag を表示 */ void put_tag(uint32_t t) { printf("'%c%c%c%c' (0x%08X)", t >> 24, (t >> 16) & 255, (t >> 8) & 255, t & 255, t); } /* オフセットテーブル */ void read_offset_table(FILE *fp) { uint32_t ver,name,cksum,offset,len; uint16_t num,srange,esel,rshi; //バージョン ver = read32(fp); //テーブル数 num = read16(fp); //searchRange srange = read16(fp); //entrySelector esel = read16(fp); //rangeShift rshi = read16(fp); printf("\n==== offset table ====\n"); printf("version: 0x%08X | numTables: %d\n", ver, num); printf("searchRange: %d | entrySelector: %d | rangeShift: %d\n\n", srange, esel, rshi); printf(" tag | checksum | offset | len\n"); printf("-----------------------------------------------------------\n"); //TableRecord for(; num > 0; num--) { //識別子 name = read32(fp); //チェックサム cksum = read32(fp); //オフセット位置 offset = read32(fp); //長さ len = read32(fp); put_tag(name); printf(" | 0x%08X | 0x%08X | %u\n", cksum, offset, len); } } /* TTC ヘッダ */ void read_ttc_header(FILE *fp) { uint32_t i,htag,num,dsig_tag,dsig_len,dsig_offset; uint32_t *pfont_offset; uint16_t majver,minver; //ヘッダ htag = read32(fp); //メジャーバージョン majver = read16(fp); //マイナーバージョン minver = read16(fp); //フォント数 num = read32(fp); printf("\n---- TTC header ----\n"); printf("tag:"); put_tag(htag); printf(" | version: %d.%d | font nums: %u\n", majver, minver, num); //各フォントのオフセット位置 pfont_offset = (uint32_t *)malloc(4 * num); if(!pfont_offset) return; for(i = 0; i < num; i++) pfont_offset[i] = read32(fp); //ver 2.0 if(majver == 2 && minver == 0) { //タグ dsig_tag = read32(fp); //長さ dsig_len = read32(fp); //オフセット dsig_offset = read32(fp); printf("[DSIG] tag:"); put_tag(dsig_tag); printf(" | len: %u | offset: %u\n", dsig_len, dsig_offset); } //各フォント for(i = 0; i < num; i++) { fseek(fp, pfont_offset[i], SEEK_SET); read_offset_table(fp); } free(pfont_offset); } /* ファイル読み込み */ void read_file(char *filename) { FILE *fp; uint32_t ver; printf("\n<<<< %s >>>>\n", filename); fp = fopen(filename, "rb"); if(!fp) { printf("can't open '%s'\n", filename); return; } //先頭4byteで判定 ver = read32(fp); rewind(fp); if(ver == 0x74746366) read_ttc_header(fp); else read_offset_table(fp); fclose(fp); } /* main */ int main(int argc,char **argv) { int i; for(i = 1; i < argc; i++) read_file(argv[i]); return 0; }
OTF ファイルの場合
==== offset table ==== version: 0x4F54544F | numTables: 17 searchRange: 256 | entrySelector: 4 | rangeShift: 16 tag | checksum | offset | len ----------------------------------------------------------- 'BASE' (0x42415345) | 0xEDFAF516 | 0x00FBEF00 | 240 'CFF ' (0x43464620) | 0x696BDA8A | 0x0003F7BC | 16250689 'DSIG' (0x44534947) | 0x00000001 | 0x00FFECFC | 8 'GDEF' (0x47444546) | 0x020E0201 | 0x00FFED04 | 28 'GPOS' (0x47504F53) | 0x0EB8AF1A | 0x00FFED20 | 47386 'GSUB' (0x47535542) | 0xD0728B36 | 0x0100A63C | 177698 'OS/2' (0x4F532F32) | 0x92B910B0 | 0x00000180 | 96 'VORG' (0x564F5247) | 0xB042CD0A | 0x01035C60 | 876 'cmap' (0x636D6170) | 0x96E15049 | 0x00000B1C | 257151 'head' (0x68656164) | 0x1837A009 | 0x0000011C | 54 'hhea' (0x68686561) | 0x0C140872 | 0x00000154 | 36 'hmtx' (0x686D7478) | 0x1B0CBDAC | 0x01035FCC | 262132 'maxp' (0x6D617870) | 0xFFFF5000 | 0x00000178 | 6 'name' (0x6E616D65) | 0xCE24457C | 0x000001E0 | 2362 'post' (0x706F7374) | 0xFF860032 | 0x0003F79C | 32 'vhea' (0x76686561) | 0x0CA815AA | 0x01075FC0 | 36 'vmtx' (0x766D7478) | 0x98EC06F2 | 0x00FBEFF0 | 261386
version が 0x4F54544F で、'CFF ' テーブルがあるので、PostScript アウトラインです。
テーブルレコードは、タグの数値の昇順に並んでいます。
TTF ファイルの場合
==== offset table ==== version: 0x00010000 | numTables: 20 searchRange: 256 | entrySelector: 4 | rangeShift: 64 tag | checksum | offset | len ----------------------------------------------------------- 'BASE' (0x42415345) | 0x858F93E0 | 0x0000014C | 216 'GDEF' (0x47444546) | 0x00262FBF | 0x00000224 | 30 'GPOS' (0x47504F53) | 0x43C70945 | 0x00000244 | 4784 'GSUB' (0x47535542) | 0xAA360E49 | 0x000014F4 | 16590 'OS/2' (0x4F532F32) | 0x555687CD | 0x000055C4 | 96 'cmap' (0x636D6170) | 0x229F0A2A | 0x00005624 | 245775 'cvt ' (0x63767420) | 0x1E3D1ACC | 0x00041634 | 146 'fpgm' (0x6670676D) | 0xE27402A5 | 0x000416C8 | 116 'gasp' (0x67617370) | 0x00170009 | 0x0004173C | 16 'glyf' (0x676C7966) | 0x79D230F9 | 0x0004174C | 5593490 'head' (0x68656164) | 0x05F2BF62 | 0x005970E0 | 54 'hhea' (0x68686561) | 0x0CE4349E | 0x00597118 | 36 'hmtx' (0x686D7478) | 0x8F8CC666 | 0x0059713C | 48914 'loca' (0x6C6F6361) | 0x6B2586E6 | 0x005A3050 | 48960 'maxp' (0x6D617870) | 0x402D0343 | 0x005AEF90 | 32 'name' (0x6E616D65) | 0x2E48568C | 0x005AEFB0 | 2264 'post' (0x706F7374) | 0x0266A8C3 | 0x005AF888 | 113505 'prep' (0x70726570) | 0x3F711A3D | 0x005CB3EC | 10 'vhea' (0x76686561) | 0x0FEB07B2 | 0x005CB3F8 | 36 'vmtx' (0x766D7478) | 0xACAB56A6 | 0x005CB41C | 24480
version が 0x00010000 なので、TrueType アウトラインです。
TTC ファイルの場合
---- TTC header ---- tag:'ttcf' (0x74746366) | version: 1.0 | font nums: 2 ==== offset table ==== version: 0x00010000 | numTables: 18 searchRange: 256 | entrySelector: 4 | rangeShift: 32 tag | checksum | offset | len ----------------------------------------------------------- 'GDEF' (0x47444546) | 0x002631BD | 0x0000026C | 30 'GSUB' (0x47535542) | 0x318E856A | 0x0000028C | 3518 'OS/2' (0x4F532F32) | 0x55B86FF6 | 0x0000104C | 96 'cmap' (0x636D6170) | 0x38F73E61 | 0x000010AC | 236166 'cvt ' (0x63767420) | 0x20CC21DC | 0x0003AB34 | 204 'fpgm' (0x6670676D) | 0x0F5DE35E | 0x0003AC00 | 113 'gasp' (0x67617370) | 0x00170009 | 0x0003AC74 | 16 'glyf' (0x676C7966) | 0xCBC0EEED | 0x0003AC84 | 7530768 'head' (0x68656164) | 0xF47D3A3D | 0x00769594 | 54 'hhea' (0x68686561) | 0x0BA737D7 | 0x007695CC | 36 'hmtx' (0x686D7478) | 0x3E38E58A | 0x007695F0 | 50600 'loca' (0x6C6F6361) | 0xD896AD5C | 0x00775B98 | 50916 'maxp' (0x6D617870) | 0x41E90549 | 0x0078227C | 32 'name' (0x6E616D65) | 0x89601DAF | 0x0078229C | 2438 'post' (0x706F7374) | 0xE54080A5 | 0x00782C24 | 120451 'prep' (0x70726570) | 0x3F71193D | 0x007A02A8 | 10 'vhea' (0x76686561) | 0x10083968 | 0x007A02B4 | 36 'vmtx' (0x766D7478) | 0xD3EFC50D | 0x007A02D8 | 50910 ==== offset table ==== version: 0x00010000 | numTables: 18 searchRange: 256 | entrySelector: 4 | rangeShift: 32 tag | checksum | offset | len ----------------------------------------------------------- 'GDEF' (0x47444546) | 0x002631BD | 0x0000026C | 30 'GSUB' (0x47535542) | 0x9DCCFA49 | 0x007AC9B8 | 3546 'OS/2' (0x4F532F32) | 0x55706F79 | 0x007AD794 | 96 'cmap' (0x636D6170) | 0x817507EC | 0x007AD7F4 | 235446 'cvt ' (0x63767420) | 0x20CC21DC | 0x0003AB34 | 204 'fpgm' (0x6670676D) | 0x0F5DE35E | 0x0003AC00 | 113 'gasp' (0x67617370) | 0x00170009 | 0x0003AC74 | 16 'glyf' (0x676C7966) | 0xCBC0EEED | 0x0003AC84 | 7530768 'head' (0x68656164) | 0xF47D3775 | 0x007E6FAC | 54 'hhea' (0x68686561) | 0x0BA737D7 | 0x007695CC | 36 'hmtx' (0x686D7478) | 0x3E38E58A | 0x007695F0 | 50600 'loca' (0x6C6F6361) | 0xD896AD5C | 0x00775B98 | 50916 'maxp' (0x6D617870) | 0x41E90549 | 0x0078227C | 32 'name' (0x6E616D65) | 0x07271158 | 0x007E6FE4 | 2466 'post' (0x706F7374) | 0xE54080A5 | 0x00782C24 | 120451 'prep' (0x70726570) | 0x3F71193D | 0x007A02A8 | 10 'vhea' (0x76686561) | 0x10083968 | 0x007A02B4 | 36 'vmtx' (0x766D7478) | 0xD3EFC50D | 0x007A02D8 | 50910
各フォントごとに、オフセットテーブルがあります。
なお、1番目と2番目のフォントで、いくつかテーブルデータのオフセット位置が同じものがあります。
('GDEF' や 'cvt ' など)
テーブルデータが全く同じであれば、複数のフォントで同じデータを使うことができます。