フォント TrueType 構造解析のソースを表示
新しいページはコチラ
移動:
案内
,
検索
[[フォント]]に戻る。 == 概要 == 仕様書はAppleのホームページに掲載されています。この記事で頑張って読みこみたいと思います。 [https://developer.apple.com/fonts/TrueType-Reference-Manual/ https://developer.apple.com/fonts/TrueType-Reference-Manual/] オープンタイプはこちら [https://docs.microsoft.com/en-us/typography/opentype/spec/ https://docs.microsoft.com/en-us/typography/opentype/spec/] OpenTypeとTrueTypeの違いってあるんですけど、ほとんどは同じです。何にも変わらないことだらけ。でも侮っていると、全然違う部分に迷い込んでたりする。注意は必要。ずっと解析してると。どっち見ても同じなので、普通にOpenTypeの仕様書を読みながらTrueTypeを解析してたりする。あぶねぇわな。 手動で読み解いてもすぐ忘れてしまうし、プログラムを使ってフォント構造をなんらかの方法で処理して理解を助けるようなものを作りたいと思います。できればPDFでグリフ番号も取得しつつ、フォントが埋め込めるくらいまではいきたい。 まずは、FreeTypeが動かせる環境を構築します。そうすると、カラー絵文字処理用のlibpngもいるんだそうな。ということはその圧縮メカニズムを司るzlibもいるんだって。というわけで [[FreeTypeをコンパイル]]にその道中どんなこと作業が必要なのかをまとめます。 [[FreeTypeを使う]]で基本的な操作から、ちょっとした使い方くらいをやってみます。 だいぶと逸れましたが、目的を達成しようと思うと、やっぱりFontファイルの構造を理解しないと駄目ですね。アップルのページを見ながら考えてみます。せっかくなので、C++でフォントのImpact.ttfのバイナリファイルを読み込んで、プログラムによって分解しながら解析してみようと思います。まずはヘッダー情報とテーブルの配置情報が上の方に詰まってるみたいなので、読み込んでみようと思います。理解した情報をテキストに吐き出すということをやってみます。途中、簡易freetypeみたいなことをして遊ぶことを目的にやっていけば、自分でフォントを描画するsvgファイルを作ってみたりできて楽しそう。サブセットを作るための礎を築くことが出来そうな気がしています。ちょっと時間かかりそうだな。もっと若い時に頑張ってみればよかったかも。 力技のプログラムで分解します。カッコいいクラスとかは作る気が無いです。よっぽど繰り返し同じようなプログラムを書いてるなこれって思ったら、なんかやるかもしれないですけど。例外処理とかやる気なし。エラーが出始めても見返せないくらいの奴にしてやりますよ。 === '''構造''' === ttfファイルの構造を以下に示します。 全体としては、ヘッダ部 12byte と TAGと呼ばれる4文字のコードに意味付けがされていて、TAGとその内容という構成が可変長でファイル全体のほとんどを占めます。とくに文字の形に関する情報を持つglyfというタグが容量が大きくなります。ヘッダ部につづいて、それぞれのTAGテーブルがどこに配置されているかを示した情報が1つのTAGあたり16Byteで位置情報を記載しています。これをTAGテーブル部と呼びます。そのあとにそれぞれのタグの値に対応するテーブル部とよばれる大きい容量の領域が続きます。TAGには、フォントファイル内で必ず定義されるべきものと、オプションのものがあります。またフォントファイルの形式毎にも必須となるTAGの違いがあります。OpenTypeフォントのotfやそのコレクションファイルである。otcファイルも一部のTAG情報が独立しているもののほとんど同じような構造になっています。TrueTypeと同じ意味を持っているTAGもあります。TrueTypeのコレクションであるttcもttcだけが扱うTAGがあります。 '''■ヘッダ部(ファイル先頭から12Byte固定 アドレス0x0000 0000 ~ 0x0000000b)''' <table style="width: 100%; text-align: left; border-collapse: collapse; border-spacing: 0;"> <tr style=" background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff;"> <th style="width: 50px;">バイト数</th> <th style="width: 140px;">型</th> <th style="width: 150px;">名前</th> <th>説明</th> </tr> <tr> <td>4</td> <td>unsigned int</td> <td>sfntVersion</td> <td>ttf outline 0x00010000</td> </tr> <tr style=" background: #eeeeee;"> <td>2</td> <td>unsigned short</td> <td>numTables</td> <td>TAGテーブル数</td> </tr> <tr> <td>2</td> <td>unsigned short</td> <td>searchRange</td> <td>TAGテーブル数から決定</td> </tr> <tr style=" background: #eeeeee;"> <td>2</td> <td>unsigned short</td> <td>entrySelector</td> <td>TAGテーブル数から決定</td> </tr> <tr> <td>2</td> <td>unsigned short</td> <td>rangeShift</td> <td>TAGテーブル数から決定</td> </tr> </table> entrySelectorはTAG テーブル数が 16(0x10) 以下なら 3。17(0x11) 以上 32(0x20)以下なら4。33(0x21) 以上 64((0x40))以下なら5。の、ように2^n<=TAGテーブル数となるようなnの最大値がentrySelectorです。 searchRangeは 16 * 2^(entrySelector)という値です。 rangeShiftは16 * TAGテーブル数 - entrySelector という値です。 TAGテーブル数から計算できるこれらの値は、よくわからない意味不明の操作をしているように感じますが、TAGテーブルの範囲を計算するために必要となるような値になっています。無くても原理がわかっていれば、再度計算できますけど、また計算するという時間を減らすために備わっていると考えてよいでしょう。なんどもなんども、読み込むかもしれませんので、計算量の節約に役立つのかもしれません。上記の値にヘッダ部自体が使う12byteをふくめると最初のテーブルへのoffsetが求まります。 '''■TAGテーブル部 (TAG数*16Byteの可変長)''' この部分にフォントファイルで使われるTAGとそのテーブルの位置とテーブルの長さとチェックサムと呼ばれる誤り検知のための符号が記述されます。 <table style="width: 100%; text-align: left; border-collapse: collapse; border-spacing: 0;"> <tr style=" background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff;"> <th style="width: 50px;">バイト数</th> <th style="width: 140px;">型</th> <th style="width: 150px;">名前</th> <th>説明</th> </tr> <tr> <td>4</td> <td>char array[4]</td> <td>tag</td> <td>ASCII code4文字からなるtag名</td> </tr> <tr style=" background: #eeeeee;"> <td>4</td> <td>unsigned int</td> <td>checkSum</td> <td>誤り検出符号</td> </tr> <tr> <td>4</td> <td>unsigned int</td> <td>offset</td> <td>当該tagの始まるポジション</td> </tr> <tr style=" background: #eeeeee;"> <td>4</td> <td>unsigned int</td> <td>length</td> <td>長さ</td> </tr> </table> 例えばWindowsのImpactというフォントだと以下のようなTAGテーブルになっています。見やすいようにTAGテーブルのポジションの値で昇順にしました。あとCheckSumは実際に計算した値も記載しています。もちろんtableに書かれていた値と計算した値は一致しています。 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 100px; ">TAG code</th> <th style = "width: 100px; ">Check sum</th> <th style = "width: 100px; ">Check sum(calc)</th> <th style = "width: 100px; ">Offset</th> <th>Length</th> <tr > <td>head</td> <td>e4e92bf5</td> <td>e4e92bf5</td> <td>0000017c</td> <td>00000036</td> </tr> <tr style=" background: #eeeeee;"> <td>hhea</td> <td>125a0ce1</td> <td>125a0ce1</td> <td>000001b4</td> <td>00000024</td> </tr> <tr > <td>maxp</td> <td>0837030e</td> <td>0837030e</td> <td>000001d8</td> <td>00000020</td> </tr> <tr style=" background: #eeeeee;"> <td>OS/2</td> <td>785c754a</td> <td>785c754a</td> <td>000001f8</td> <td>00000060</td> </tr> <tr > <td>hmtx</td> <td>fea2e775</td> <td>fea2e775</td> <td>00000258</td> <td>00000fec</td> </tr> <tr style=" background: #eeeeee;"> <td>LTSH</td> <td>f1306fc0</td> <td>f1306fc0</td> <td>00001244</td> <td>000003ff</td> </tr> <tr > <td>VDMX</td> <td>6959818c</td> <td>6959818c</td> <td>00001644</td> <td>00001194</td> </tr> <tr style=" background: #eeeeee;"> <td>hdmx</td> <td>1dd7c845</td> <td>1dd7c845</td> <td>000027d8</td> <td>00005408</td> </tr> <tr > <td>cmap</td> <td>089aa4b6</td> <td>089aa4b6</td> <td>00007be0</td> <td>00000672</td> </tr> <tr style=" background: #eeeeee;"> <td>fpgm</td> <td>c7712c46</td> <td>c7712c46</td> <td>00008254</td> <td>00000764</td> </tr> <tr > <td>prep</td> <td>32e8b0c7</td> <td>32e8b0c7</td> <td>000089b8</td> <td>00000855</td> </tr> <tr style=" background: #eeeeee;"> <td>cvt </td> <td>d595b7a9</td> <td>d595b7a9</td> <td>00009210</td> <td>00000620</td> </tr> <tr > <td>loca</td> <td>03dc4364</td> <td>03dc4364</td> <td>00009830</td> <td>00000ff0</td> </tr> <tr style=" background: #eeeeee;"> <td>glyf</td> <td>550e4c1b</td> <td>550e4c1b</td> <td>0000a820</td> <td>00022720</td> </tr> <tr > <td>kern</td> <td>bfcec4b5</td> <td>bfcec4b5</td> <td>0002cf40</td> <td>00000b8e</td> </tr> <tr style=" background: #eeeeee;"> <td>name</td> <td>28de000e</td> <td>28de000e</td> <td>0002dad0</td> <td>00000ba1</td> </tr> <tr > <td>post</td> <td>ff360066</td> <td>ff360066</td> <td>0002e674</td> <td>00000020</td> </tr> <tr style=" background: #eeeeee;"> <td>gasp</td> <td>001d0021</td> <td>001d0021</td> <td>0002e694</td> <td>00000010</td> </tr> <tr > <td>DSIG</td> <td>771dbaee</td> <td>771dbaee</td> <td>0002e6a4</td> <td>00001dc4</td> </tr> <tr style=" background: #eeeeee;"> <td>GDEF</td> <td>00260400</td> <td>00260400</td> <td>00030468</td> <td>0000001e</td> </tr> <tr > <td>GPOS</td> <td>662a22e1</td> <td>662a22e1</td> <td>00030488</td> <td>00000f12</td> </tr> <tr style=" background: #eeeeee;"> <td>GSUB</td> <td>35d8e622</td> <td>35d8e622</td> <td>0003139c</td> <td>000013da</td> </tr> <tr > <td>meta</td> <td>1aa59251</td> <td>1aa59251</td> <td>00032778</td> <td>00000048</td> </tr> </table> 各tagテーブルの本体テーブルは4の倍数のバイト数の長さになるように調整されていて、実際の長さがLengthですが、Lengthが4の倍数になっていない場合は、そうなるように各byte値が00値で埋められます。 このような構造なので、フォントファイル自体は4の倍数のバイト数になっています。ファイルの先頭から4byteづつ読み込んで、4byteをunsigned int値として、足し算を繰り返す操作によって、チェックサムが計算できます。フォントファイル自体のチェックサムは全てのフォントファイルで0xB1B0AFBAになります。これは必須tagのheadのadjustment CheckSumという値で0xB1B0AFBAになるように調整されています。adjustment CheckSumはheadの3番目の4byteの値です。したがって(adjustment CheckSumを除いたフォントファイル全てのCheckSum)+(必須tagのheadのadjustment CheckSum) = 0xB1B0AFBA となります。テーブルごとのチェックサムはテーブルのオフセットポジションから、次のテーブルまでを足し算をした値です。チェックサムの計算を繰り返すと、unsigned intの4byteという容量からはなんども桁あふれが発生しますが、どんどん切り捨てて計算を繰り返します。tag名がheadのテーブルだけはadjustment CheckSumを無視したチェックサムを求めます。 adjustment CheckSumはフォントファイルに変更が発生した場合は計算しなおす必要がある値です。変更が発生したテーブルのチェックサムも変更が必要です。 '''■テーブル部 (可変長)''' ==== head ==== headテーブルは固定長(0x36 Byte)です。朱色のアンダーラインは、他のテーブルでも利用する値です。 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>説明</th> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>MajorVersion</td> <td>メジャーバージョン</td> </tr> <tr> <td>unsigned short</td> <td>MinorVersion</td> <td>マイナーバージョン</td> </tr> <tr style = " background: #eeeeee;"> <td>FixPoint16.16</td> <td>FixedfontRevision</td> <td>16.16固定小数点</td> </tr> <tr> <td>unsigned int</td> <td><span style = "background:linear-gradient(transparent 75%, #ff9393 75%); font-weight:bold; ">checkSumAdjustment</span></td> <td>前の項目で説明したとおり</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned int</td> <td>magicNumber</td> <td>0x5f0f3cf5で固定</td> </tr> <tr> <td>unsigned short</td> <td>flags</td> <td>※1</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>unitsPerEm</td> <td>1文字(EM)あたりのピクセル数</td> </tr> <tr> <td>unsigned long long</td> <td>CreateDate</td> <td>作成日</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned long long</td> <td>ModifyDate</td> <td>編集日</td> </tr> <tr> <td>unsigned short</td> <td>xMin</td> <td>水平方向有効最小座標値</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>yMin</td> <td>垂直方向有効最小座標値</td> </tr> <tr> <td>unsigned short</td> <td>xMax</td> <td>水平方向有効最大座標値</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>yMax</td> <td>垂直方向有効最大座標値</td> </tr> <tr> <td>unsigned short</td> <td>macStyle</td> <td>mac向けスタイルフラグ。OS/2 テーブルの fsSelection ビットと一致させる。※2</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>lowestRecPPEM</td> <td>文字が可読となる最小の1EMあたりのピクセル表現値</td> </tr> <tr> <td>short</td> <td>fontDirectionHint</td> <td>フォント記述方向 0:両方、1 : 左から右、2:左から右と移動無し、-1 : 右から左、-2:右から左と移動無し</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td><span style = "background:linear-gradient(transparent 75%, #ff9393 75%); font-weight:bold; ">indexToLocFormat</span></td> <td>タグ名loca1のテーブルにおけるOffset形式 0 : unsigned short16、 1 : unsigned int32</td> </tr> <tr> <td>unsigned short</td> <td>glyphDataFormat</td> <td>グリフ記述形式 現時点では0のみ</td> </tr> </table> ※1. flagは各ビット毎に以下のような意味になります。 bit 0:y=0がベースラインなら1 bit 1 : 左端の黒がLSB(Left Side Bearing) bit 2 : スケーリングされたポイントサイズと実際のポイントサイズで字形が異なる。 bit 3 : 分数スケールが含まれる場合に整数スケールを利用する。 bit 4 : マイクロソフトが提供するTrueTypeスケーラを利用する。 bit 5 : 垂直方向にレイアウトされ、x 座標 0 が目的の垂直ベースラインに対応するようにグリフが描画されたフォントに設定する必要がある。 bit 6 : このビットはゼロで固定。 bit 7 : フォントが正しい言語レンダリング(アラビア語フォントなど)の合字レイアウトを必要とする場合に設定する。 bit 8 : 規定値で発生していると指定されている1つ以上の特異効果 Apple Advanced Typographyを持つ場合に設定が必要。 bit 9 : フォントに右から左への強いグリフが含まれている場合に設定する必要がある。 bit 10 : フォントにインド風の並べ替え効果が含まれている場合に設定する必要がある。 bit11~13 : Adobeによって定義されている。 bit 14 : フォント内のグリフが、 last resort font(豆腐文字の先進的なモノ)など、コードポイント範囲の単なる汎用シンボルがある場合に、このビットを設定する必要がある。 ※2.macfontStyleは以下のようなフラグです。 bit 0 : 太字 bit 1 : 斜体 bit 2 : 下線 bit 3 : アウトライン bit 4 : シャドウ bit 5 : 凝縮 (狭) bit 6 : 拡張 IMPACT.ttfの例は以下のとおりです。 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 100px; ">Name</th> <th>Value</th> </tr> <tr style = " background: #eeeeee;"> <td>MajorVersion</td> <td>1</td> </tr> <tr> <td>MinorVersion</td> <td>0</td> </tr> <tr style = " background: #eeeeee;"> <td>FixedfontRevision</td> <td>5.11</td> </tr> <tr> <td>checkSumAdjustment</td> <td>0x9932de9a</td> </tr> <tr style = " background: #eeeeee;"> <td>magicNumber</td> <td>0x5f0f3cf5</td> </tr> <tr> <td>flags</td> <td>0x001b ※0001_1011 bit4,3,1,0 </td> </tr> <tr style = " background: #eeeeee;"> <td>unitsPerEm</td> <td>2048</td> </tr> <tr> <td>CreateDate</td> <td>1992/07/22 17:04:10</td> </tr> <tr style = " background: #eeeeee;"> <td>ModifyDate</td> <td>2017/03/03 19:59:44</td> </tr> <tr> <td>xMin</td> <td>-265</td> </tr> <tr style = " background: #eeeeee;"> <td>yMin</td> <td>-677</td> </tr> <tr> <td>xMax</td> <td>2894</td> </tr> <tr style = " background: #eeeeee;"> <td>yMax</td> <td>2392</td> </tr> <tr> <td>macStyle</td> <td>0</td> </tr> <tr style = " background: #eeeeee;"> <td>lowestRecPPEM</td> <td>9</td> </tr> <tr> <td>fontDirectionHint</td> <td>1</td> </tr> <tr style = " background: #eeeeee;"> <td>indexToLocFormat</td> <td>1</td> </tr> <tr> <td>glyphDataFormat</td> <td>0</td> </tr> </table> ==== maxp ==== maxpテーブルは固定長(0x20 Byte)です。主にグリフ全体における各要素の最大値を示しています。メモリをどれくらい確保していればグリフが確実に読み込めるかといった目安にもなります。基本的には動的にメモリを確保すると思いますが、メモリ不足を事前に察知することができます。総グリフ数は他のテーブルでも利用します。 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>Value</th> </tr> <tr style = " background: #eeeeee;"> <td>Fixed 16.16</td> <td>Fixedversion</td> <td>0b0000000100000000 1.00=TrueTypeアウトラインフォント<br/>0b0000000101010000 0.3125=PostScriptアウトライン</td> </tr> <tr> <td>unsigned short</td> <td><span style = "background:linear-gradient(transparent 75%, #ff9393 75%); font-weight:bold; ">numGlyphs</span></td> <td>グリフ数</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>maxPoints</td> <td>単一グリフの最大ポイント数</td> </tr> <tr> <td>unsigned short</td> <td>maxContours</td> <td>単一グリフの最大輪郭(りんかく)数</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>maxCompositePoints</td> <td>複合グリフの最大ポイント数 複合グリフに使う単一グリフのポイント数の足し算なので、どのグリフが複合で使われるかによって決まるため、上記項目の単一グリフの最大値とはあまり関連はないものです。</td> </tr> <tr> <td>unsigned short</td> <td>maxCompsiteContours</td> <td>複合グリフの最大輪郭数。上記に同じく</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>maxZones</td> <td>1 : Z0命令を使う。2 : Z0命令を使わない。</td> </tr> <tr> <td>unsigned short</td> <td>maxTwilightPoints</td> <td>最大Z0命令使用数。</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>maxStorage</td> <td>ストレージエリア最大数</td> </tr> <tr> <td>unsigned short</td> <td>maxFunctionDefs</td> <td>最大FDEF数</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>maxInstructionDefs</td> <td>最大IDEF数</td> </tr> <tr> <td>unsigned short</td> <td>maxStackElements</td> <td>最大スタック深さ</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>maxSizeOfInstructions</td> <td>最大命令数</td> </tr> <tr> <td>unsigned short</td> <td>maxComponentElements</td> <td>最大複合グリフ要素利用数</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>maxComponentDepth</td> <td>最大複合グリフ再帰深度</td> </tr> </table> グリフ数は以下のテーブルに影響を与えます。 *グリフ位置テーブル ('loca') *グリフデータテーブル ('glyf') *'Zapf' テーブル さらに、一部のテーブルにはグリフインデックスが含まれており、フォントからグリフを削除した場合に更新が必要になる場合があります。このようなテーブルの部分的なリストは次のとおりです。 *文字グリフマッピングテーブル ('cmap') *妥当性テーブル ('just') *カーニングテーブル ('kern') *拡張グリフ変態テーブル ('morx') これらの整合性を保って、編集すれば、不要なグリフを削除するといったサブセット化はできそうですね。 でも、ここに来て、今まで知らなかった技術のいくつかを知る。それが、<span style = "background:linear-gradient(transparent 75%, #7fbfff 75%); font-weight:bold; ">フォントヒンティング</span>、<span style = "background:linear-gradient(transparent 75%, #7fbfff 75%); font-weight:bold; ">命令スタック</span>、<span style = "background:linear-gradient(transparent 75%, #7fbfff 75%); font-weight:bold; ">再帰</span>、<span style = "background:linear-gradient(transparent 75%, #7fbfff 75%); font-weight:bold; ">トワイライトポイント</span>、<span style = "background:linear-gradient(transparent 75%, #7fbfff 75%); font-weight:bold; ">ストレージ</span>といったあたり。 いやはや、これは深い。そりゃこんだけ沢山タグがあるわけだな。フォントは深い。知り尽くせぬほど深そうだ。もうちょっと仕様書とか文献を読み込みます。日本でフォントに詳しい文書書いてる人はGoogleでは10人くらいな感じがする。グラフ用紙に「ねこ」という2文字をプロットしてる深いサイトとopnetypeのタグの半分くらいにふれているサイト。凄すぎる。あっちこちいったりきたりして勉強だな。 フォントヒンティングはwikipediaによると文字が小さくなったときに頂点の位置を変更する場所みたいな説明だった。参考画像をみると確かにフォントヒンティングがあるほうが小さい文字を読み取りやすい。優れた技術だ。ちなみにfontforgeでさえもフォントヒンティングは読み込まないらしい。fontforgeでは編集できないそうな。コピーしたり自動生成?したりするらしい。説明によるとユーザインターフェースを提供しにくいそうだ。あれだけのものを作る人が諦めるってことは、ヒント関連ってむずかしそうだな。 この時代になってなお、無料ではまだ、フォントの奥深いところは素人には簡単に手出しできない状態になっているようだ。有料版とか企業がつかってるフォントエディタってすごいんかな。気になる。企業だけしか持ててないから、優秀なフォントは生まれにくいのかもしれない。個人でもきっかけさえあればすごいことやってのける時代だけど、環境がなければ、たやすくは生まれないんだな。 ともかく、 以下がIMPACT.ttfの例です <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 100px; ">Name</th> <th>Value</th> </tr> <tr style = " background: #eeeeee;"> <td>Fixedversion</td> <td style = "text-align: right;">1.00</td> </tr> <tr> <td>numGlyphs</td> <td style = "text-align: right;">1019</td> </tr> <tr style = " background: #eeeeee;"> <td>maxPoints</td> <td style = "text-align: right;">242</td> </tr> <tr> <td>maxContours</td> <td style = "text-align: right;">60</td> </tr> <tr style = " background: #eeeeee;"> <td>maxCompositePoints</td> <td style = "text-align: right;">82</td> </tr> <tr> <td>maxCompsiteContours</td> <td style = "text-align: right;">5</td> </tr> <tr style = " background: #eeeeee;"> <td>maxZones</td> <td style = "text-align: right;">2</td> </tr> <tr> <td>maxTwilightPoints</td> <td style = "text-align: right;">16</td> </tr> <tr style = " background: #eeeeee;"> <td>maxStorage</td> <td style = "text-align: right;">47</td> </tr> <tr> <td>maxFunctionDefs</td> <td style = "text-align: right;">86</td> </tr> <tr style = " background: #eeeeee;"> <td>maxInstructionDefs</td> <td style = "text-align: right;">0</td> </tr> <tr> <td>maxStackElements</td> <td style = "text-align: right;">913</td> </tr> <tr style = " background: #eeeeee;"> <td>maxSizeOfInstructions</td> <td style = "text-align: right;">408</td> </tr> <tr> <td>maxComponentElements</td> <td style = "text-align: right;">3</td> </tr> <tr style = " background: #eeeeee;"> <td>maxComponentDepth</td> <td style = "text-align: right;">1</td> </tr> </table> 英語フォントの癖にスタックが913とかマジか。トワイライトポイントが16ってことはあんまり沢山せっていするものではないんだな。なんだろこれ。あとストレージエリアの47は多い奴は結構あるんだなっていう印象。なんかわかったら、追記します。追記がないあいだは、こいつ、いろいろ書いてるくせに理解できていないと思って下さい。 ==== hhea、hmtx ==== hheaテーブルは固定長(0x24 Byte)です。水平レイアウト情報です。hmtxテーブルはグリフ数で決まる可変長です。各グリフの横送り幅と送り幅の左側を起点として、文字の黒色がある一番左の位置の情報をもっています。LSBと呼びます。Left Side Bearingです。このときのBearingは位置認識という意味を持ちます。挙動という意味もありますが、こちらが、軸受けなんかに使われるボールベアリングの意味だと思われです。 水平方向にフォントを並べていくとき使われる情報です。'''h'''orizontal '''hea'''dで、hheaだと思われます。 各グリフの情報をもつという意味で'''h'''orizontal '''m'''a'''t'''ri'''x'''で、hmtxだと思われます。確度が高いとは思いますが、推測情報ばかりで申し訳ないです。 <big>'''■hhea'''</big> <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>説明</th> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>MajorVersion</td> <td>メジャーバージョン</td> </tr> <tr> <td>unsigned short</td> <td>MinorVersion</td> <td>マイナーバージョン</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>Ascent</td> <td>高さ</td> </tr> <tr> <td>unsigned short</td> <td>Descender</td> <td>ベースラインの下</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>LineGap</td> <td>行間</td> </tr> <tr> <td>unsigned short</td> <td>AdvanceWidthMax</td> <td>最大文字の送り幅</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>MinLeftSideBearing</td> <td>送り幅枠左基準の最小の左側黒色部の座標</td> </tr> <tr> <td>short</td> <td>MinRightSideBearing</td> <td>送り幅枠右基準の最小の右側黒色部の座標</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>XMaxExtent</td> <td>左下原点から右黒色部の最大値</td> </tr> <tr> <td>short</td> <td>CaretSlopeRise</td> <td>斜体角度垂直ならtan90度でCaretSlopeRise:1/CaretSlopeRun:0。</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>CaretSlopeRun</td> <td>上記説明のとおり</td> </tr> <tr> <td>short</td> <td>CaretOffset</td> <td>斜体分のカーソル移動量</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>MetricDataFormat</td> <td>hmtx テーブルのデータフォーマット。現時点で0のみ</td> </tr> <tr> <td>unsigned short</td> <td><span style = "background:linear-gradient(transparent 75%, #ff9393 75%); font-weight:bold; ">NumberOfMetrics</span></td> <td>各グリフのAdvanceWidth、LSB定義数</td> </tr> </table> IMPACT.ttfでは以下のようになります。 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 100px; ">Name</th> <th>Value</th> </tr> <tr style = " background: #eeeeee;"> <td>MajorVersion</td> <td style = "text-align: right;">1</td> </tr> <tr> <td>MinorVersion</td> <td style = "text-align: right;">0</td> </tr> <tr style = " background: #eeeeee;"> <td>Ascent</td> <td style = "text-align: right;">2066</td> </tr> <tr> <td>numGlyphs</td> <td style = "text-align: right;">-432</td> </tr> <tr style = " background: #eeeeee;"> <td>LineGap</td> <td style = "text-align: right;">0</td> </tr> <tr> <td>AdvanceWidthMax</td> <td style = "text-align: right;">2974</td> </tr> <tr style = " background: #eeeeee;"> <td>MinLeftSideBearing</td> <td style = "text-align: right;">-265</td> </tr> <tr> <td>MinRightSideBearing</td> <td style = "text-align: right;">-265</td> </tr> <tr style = " background: #eeeeee;"> <td>XMaxExtent</td> <td style = "text-align: right;">2894</td> </tr> <tr> <td>CaretSlopeRise</td> <td style = "text-align: right;">1</td> </tr> <tr style = " background: #eeeeee;"> <td>CaretSlopeRun</td> <td style = "text-align: right;">0</td> </tr> <tr> <td>CaretOffset</td> <td style = "text-align: right;">0</td> </tr> <tr style = " background: #eeeeee;"> <td>MetricDataFormat</td> <td style = "text-align: right;">0</td> </tr> <tr> <td>NumberOfMetrics</td> <td style = "text-align: right;">1019</td> </tr> </table> hmtx の IMPACTの結果は以下の通りです。各グリフ毎にある値なので1019行を超えるため、テキストへのリンクを貼り付けておきます。これだけの値を手作業でまとめることは無謀すぎます。ようやっとでプログラムで動かしてるんだなって思ってもらえると思います。 [[メディア:IMPACT TAG hmtx TebleInfo.txt|IMPACT_TAG_hmtx_TebleInfo.txt]] つかっているプログラムは、もし完成することがあるならば有用なものになるかもしれないので、Qtのライセンスに触れない形式でアップロードするかもしれません。商用の扱いはダメですからね。 <big>'''■hmtx'''</big> <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>説明</th> </tr> <tr style = " background: #eeeeee;"> <td>longHorMetric</td> <td>hMetrics[GlyphID]</td> <td>グリフID毎のAdvaceWidthとLSB longHorMetric構造体は後述</td> </tr> <tr> <td>short</td> <td>leftSideBearing[GlyphID]</td> <td>hMetricsで記述されなかった残りのグリフID毎のLSB</td> </tr> </table> '''※longHorMetric構造体''' <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>説明</th> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>advaceWidth</td> <td>グリフの送り幅</td> </tr> <tr> <td>short</td> <td>leftSideBearing</td> <td>グリフのLSB</td> </tr> </table> hmtxでは、グリフの送り幅とLSBを構造体の形式とみなしてGlyphID順に読み込んでいきます。hheaのNumberOfMetricsで定義された分だけ構造体が配列のように読み取ることができるようになっています。maxpで定義されたNumGlyphsの値よりNumberOfMetricsが少ない場合は、残りのadvanceWidthは配列の最後の値がすべてに適用されます。残りのLSBは別途、グリフ毎に定義することが必要になっています。 ==== OS/2 ==== OS/2テーブルはフォントのコンピュータが取り扱うために必要な基本的な数値情報が格納されています。OS/2はIBMやMicrosoftのオペレーティングシステムの名前でどちらもOS/2の愛称がありました。一番流行っていたオペレーティングシステムとやりとりする主な値なのでこのような後世に残るようなテーブル名をつけてしまったのだと思います。OS/2自体は、みかけなくなりましたが、このワードは今も生きています。OS/2テーブルのバージョン毎に長さが変わります。Version0なら0x4cByte Version1では、0x54Byte。Version2、3および4だと0x60Byteです。Version5なら0x68Byteになります。 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>説明</th> </tr> <tr> <td>unsigned short</td> <td>UsVersion</td> <td>テーブルバージョン番号 0~5</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>SXAvgCharWidth</td> <td>フォント平均文字幅</td> </tr> <tr> <td>unsigned short</td> <td>UsWeightClass</td> <td>フォント太さ指標 ※1</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>UsWidthClass</td> <td>フォント文字幅指標 ※2</td> </tr> <tr> <td>unsigned short</td> <td>usType</td> <td>フォント取り扱い各種フラグ ※3</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>SSubscriptXSize</td> <td>下付き文字の横幅</td> </tr> <tr> <td>short</td> <td>SSubscriptYSize</td> <td>下付き文字の高さ</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>SSubscriptXOffset</td> <td>下付き文字の横位置</td> </tr> <tr> <td>short</td> <td>SSubscriptYOffset</td> <td>下付き文字の縦位置</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>SSuperscriptXSize</td> <td>上付き文字の横幅</td> </tr> <tr> <td>short</td> <td>SSuperscriptYSize</td> <td>上付き文字の縦幅</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>SSuperscriptXOffset</td> <td>上付き文字の横位置</td> </tr> <tr> <td>short</td> <td>SSuperscriptYOffset</td> <td>上付き文字の縦位置</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>SStrikeoutSize</td> <td>取り消し線の太さ</td> </tr> <tr> <td>short</td> <td>SStrikeoutPosition</td> <td>取り消し線のベースラインからの縦位置</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>SFamilyClass</td> <td>上位バイト=ファミリークラス、下位バイト=サブクラス ※4</td> </tr> <tr> <td>unsigned char</td> <td>ucPanose[0]</td> <td>書体特性 ※5</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned char</td> <td>ucPanose[1]</td> <td></td> </tr> <tr> <td>unsigned char</td> <td>ucPanose[2]</td> <td></td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned char</td> <td>ucPanose[3]</td> <td></td> </tr> <tr> <td>unsigned char</td> <td>ucPanose[4]</td> <td></td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned char</td> <td>ucPanose[5]</td> <td></td> </tr> <tr> <td>unsigned char</td> <td>ucPanose[6]</td> <td></td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned char</td> <td>ucPanose[7]</td> <td></td> </tr> <tr> <td>unsigned char</td> <td>ucPanose[8]</td> <td></td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned char</td> <td>ucPanose[9]</td> <td></td> </tr> <tr> <td>unsigned int</td> <td>UiUnicodeRange1</td> <td>1~4まで128バイトのフラグ ※6</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned int</td> <td>UiUnicodeRange2</td> <td></td> </tr> <tr> <td>unsigned int</td> <td>UiUnicodeRange3</td> <td></td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned int</td> <td>UiUnicodeRange4</td> <td></td> </tr> <tr> <td>unsigned char[4]</td> <td>ucAchVendID</td> <td>ASCIIコード4文字のフォントベンダーID</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>FsSelection</td> <td>フォントパターンフラグ ※7</td> </tr> <tr> <td>unsigned short</td> <td>UsFirstCharIndex</td> <td>最小ユニコード番号32</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>UsLastCharIndex</td> <td>最大ユニコード番号32</td> </tr> <tr> <td>unsigned short</td> <td>STypoAscender</td> <td>印刷するときのグリフ高さ</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>STypoDescender</td> <td>-印刷するときのグリフ深さ</td> </tr> <tr> <td>unsigned short</td> <td>STypoLineGap</td> <td>印刷するときの行間</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>UsWinAscent</td> <td>Windowsでのグリフ高さ</td> </tr> <tr> <td>unsigned short</td> <td>UsWinDescent</td> <td>Windowsでのグリフ深さ</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned int</td> <td>UiCodePageRange1</td> <td>1~2の64bitの含まれるコードページ言語のフラグ</td> </tr> <tr> <td>unsigned int</td> <td>UiCodePageRange2</td> <td>UiUnicodeRangeと同じような仕組みです。</td> </tr> <tr style = " background: #eeeeee;"> <td>short</td> <td>SXHeight</td> <td>ベースラインと小文字xの高さ</td> </tr> <tr> <td>short</td> <td>SCapHeight</td> <td>ベースラインと大文字Hの高さ</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>UsDefaultChar</td> <td>フォントが無い場合に参照されるグリフ番号 0 になることが多い。</td> </tr> <tr> <td>unsigned short</td> <td>UsBreakChar</td> <td>ブレーク文字の規定値 ほとんどが0x20半角空白スペース</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>UsMaxContext</td> <td>合字で扱う最大グリフ数</td> </tr> <tr> <td>unsigned short</td> <td>UsLowerOpticalPointSize</td> <td>フォントが使われる最小サイズ</td> </tr> <tr style = " background: #eeeeee;"> <td>unsigned short</td> <td>UsUpperOpticalPointSize</td> <td>フォントが使われる最大サイズ</td> </tr> </table> *xAvgCharWidth : 小文字26文字すべてがないと0になります。小文字のみの、advanceWidth送り幅の平均ですが、単純な値ではないです。使用頻度に応じた重みづけ係数表を使った計算をします。(a送り幅x係数+…z送り幅 + 空白送り幅x係数)/1000の値です。この値は文字数 x 送り幅で1行の文字長さを推測できるもだそうです。 <table border=1> <tr> <th style = " background: #778ca3;">字</th><th>係数</th><th style = " background: #778ca3;">字</th><th>係数</th><th style = " background: #778ca3;">字</th><th>係数</th><th style = " background: #778ca3;">字</th><th>係数</th><th style = " background: #778ca3;">字</th><th>係数</th> </tr> <tr> <td style = " background: #778ca3;">a</td><td>64</td><td style = " background: #778ca3;">b</td><td>14</td><td style = " background: #778ca3;">c</td><td>27</td><td style = " background: #778ca3;">d</td><td>35</td><td style = " background: #778ca3;">e</td><td>100</td> </tr> <tr> <td style = " background: #778ca3;">f</td><td>20</td><td style = " background: #778ca3;">g</td><td>14</td><td style = " background: #778ca3;">h</td><td>42</td><td style = " background: #778ca3;">i</td><td>63</td><td style = " background: #778ca3;">j</td><td>3</td> </tr> <tr> <td style = " background: #778ca3;">k</td><td>6</td><td style = " background: #778ca3;">l</td><td>35</td><td style = " background: #778ca3;">m</td><td>20</td><td style = " background: #778ca3;">n</td><td>56</td><td style = " background: #778ca3;">o</td><td>56</td> </tr> <tr> <td style = " background: #778ca3;">p</td><td>17</td><td style = " background: #778ca3;">q</td><td>4</td><td style = " background: #778ca3;">r</td><td>49</td><td style = " background: #778ca3;">s</td><td>56</td><td style = " background: #778ca3;">t</td><td>71</td> </tr> <tr> <td style = " background: #778ca3;">u</td><td>31</td><td style = " background: #778ca3;">v</td><td>10</td><td style = " background: #778ca3;">w</td><td>18</td><td style = " background: #778ca3;">x</td><td>3</td><td style = " background: #778ca3;">y</td><td>18</td> </tr> <tr> <td style = " background: #778ca3;">z</td><td>2</td><td style = " background: #778ca3;">sp</td><td>166</td><td></td><td></td><td></td><td></td><td></td><td></td> </tr> </table> ※1usWeightClassは100~900の100の倍数で指定される指標です。 100 Ultra-light 200 Extra-light 300 Light 400 Semi-light 500 Medium 600 Semi-Bold 700 Bold 800 Extra-Bold 900 Ultra-Bold ※2usWidthClassは文字幅の指標です。 1 Ultra-condensed 50% 2 Extra-condensed 63.5% 3 condensed 75% 4 semi-condensed 87.5% 5 Medium 100% 6 Semi-Expanded 112.5% 7 Expanded 125% 8 Extra-expanded 150% 9 Ultra-expanded 200% ※3 フォント取り扱いフラグ Bit 0 : 予約 = 0 Bit 1 : Bit2あるいは3が1のときは1であってはならないフラグです。所有者に許可なく埋め込み、編集、ファイル交換してはならないです。 Bit 2 : Bit1あるいは3が1のときは1であってはならないフラグです。そのまま埋め込みしてもよいですが、リモートでフォントが表示されるドキュメントは読み取り専用になっていないといけない。 Bit 3 : フォントファイルを編集しての埋め込みが許されています。 Bit 4-7 : 予約 = 0 Bit 8 : サブセット化しようとする文書の出力の仕組みを許可しないです。 Bit 9 :ビットマップによる埋め込みのみ許可 Bit 10-15 : 予約 = 0 ※4 SFamilyClass 文字のデザイン分類をするものです。作ってる人も分類むずかしいでしょうね。 ファミリークラス分類 Bit 0 : 分類なし Bit 1 : オールドスタイルセリフ 15世紀から17世紀のセリフスタイルです。 Bit 2 : 過度なセリフ 18世紀から19世紀のセリフスタイルです。 Bit 3 : モダンセリフ 20世紀。 Bit 4 : クラレンドンセリフ Bit 5 : スラブセリフ Bit 6 : 予約済 = 0 Bit 7 : フリーフォームセリフ。セリフはあるけど自由なものです。 Bit 8 : サンセリフ。セリフがないゴシック体のような文字 Bit 9 : 装飾。豪華な装飾がほどこされた字体です。 Bit 10 : スクリプト。手書きをシミュレートするような設計がされています。 Bit 11 : 予約済 = 0 Bit 12 : シンボリック。記号とか Bit 13-14 : 予約済 = 0 オールドスタイルセリフのサブクラスといったように上位バイトで決まる下位バイトの意味付け分類が存在します。1、2、3、4、5、7、8、9、10、12の10種類ある。 以下はオールドスタイルの例です。全部の分類を記述するのは大変なので、リンクを貼っておきます。 Bit 0 : 分類無し Bit 1 : 丸みを帯びている Bit 2 : ガラルデ Bit 3 : ベネチアン Bit 4 : モディファイベネチアン Bit 5 : 現代オランダ Bit 6 : 伝統オランダ Bit 7 : コンテンポラリ Bit 8 : カリグラフィ Bit 9-14 : 予約済 = 0 Bit 15 : 種々雑多な といったように上位バイトに基づいた分類がある。 ※5 PANOSE 1バイトの数値で以下0~9の10種類の様々なフラグがあります。 PANOSE[0] : bFamilyType : :0 : Any :1 : No Fit :2 : Text and Display :3 : Script :4 : Decorative :5 : Pictorial PANOSE[1] : bSerifStyle : :0 : Any :1 : No Fit :2 : Cove :3 : Obtuse Cove :4 : Square Cove :5 : Obutuse Square Cove :6 : Square :7 : Thin :8 : Bone :9 : Exaggerated :10 : Triangle :11 : Normal Sans :12 : Obtuse Sans :13 : Perp Sans :14 : Fiared :15 : Rounded PANOSE[2] : bWeight : :0 : Any :1 : No Fit :2 : Very Light :3 : Light :4 : Thin :5 : Book :6 : Medium :7 : Demi :8 : Bold :9 : Heavy :10 : Black :11 : Nord PANOSE[3] : bProportion : :0 : Any :1 : No Fit :2 : Old Style :3 : Modern :4 : Even Width :5 : Expanded :6 : Condensed :7 : Very Expanded :8 : Very Condensed :9 : MonoSpace PANOSE[4] : bContrast : :0 : Any :1 : No Fit :2 : None :3 : Very Low :4 : Low :5 : Medium Low :6 : Medium :7 : Medium High :8 : High :9 : Very High PANOSE[5] : bStrokeVariation : :0 : Any :1 : No Fit :2 : Gradual/Diagonal :3 : Gradual/Transitional :4 : Gradual/Vertical :5 : Gradual/Horizontal :6 : Rapid/Vertical :7 : Rapid/Horizontal :8 : Instant/Vertical PANOSE[6] : bArmStyle : :0 : Any :1 : No Fit :2 : Straight Arm/Horizontal :3 : Straight Arm/Wedge :4 : Straight Arm/Vertical :5 : Straight Arm/Single Serif :6 : Straight Arm/Double Serif :7 : Non-Straight Arm/Horizontal :8 : Non-Straight Arm/Wedge :9 : Non-Straight Arm/Vertical :10 : Non-Straight Arm/Single Serif :11 : Non-Straight Arm/Double Serif PANOSE[7] : bLetterform : :0 : Any :1 : No Fit :2 : Normal/Contact :3 : Normal/Weighted :4 : Normal/Boxed :5 : Normal/Flattened :6 : Normal/Rounded :7 : Normal/Off Centter :8 : Normal/Square :9 : Obliqui/Contact :10 : Obliqui/Weighted :11 : Obliqui/Boxed :12 : Obliqui/Flattened :13 : Obliqui/Rounded :14 : Obliqui/Off Centter :15 : Obliqui/Square PANOSE[8] : bSerifStyle : :0 : Any :1 : No Fit :2 : Standard/Trimmed :3 : Standard/Pointed :4 : Standard/Serifed :5 : High/Trimmed :6 : High/Pointed :7 : High/Serifed :8 : Constant/Trimmed :9 : Constant/Pointed :10 : Constant/Serifed :11 : Low/Trimmed :12 : Low/Pointer :13 : Low/Serifed PANOSE[9] : bXHeight : :0 : Any :1 : No Fit :2 : Constant/Small :3 : Constant/Standard :4 : Constant/Large :5 : Ducking/Small :6 : Ducking/Standart :7 : Ducking/Large ※6 uiUnicodeRange ユニコード使用範囲を指定する部分です。0~127のそれぞれのbitフラグがUnicodeの一定の範囲を指し示します。範囲についてはMicrosoftのOpentype仕様書に記述があります。 achVendID[4] 4文字のベンダーIDをMicrosoftが管理しています。 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 100px; ">VenderID</th> <th>名前</th> </tr> <tr style = " background: #eeeeee;"> <td>ACG </td> <td style = "text-align: right;">AGFA コンピュグラフィック</td> </tr>Adbe <tr> <td>Adbe</td> <td style = "text-align: right;">Adobe Systems</td> </tr> <tr style = " background: #eeeeee;"> <td>Appl</td> <td style = "text-align: right;">Apple</td> </tr>Adbe <tr> <td>Alts</td> <td style = "text-align: right;">AltSys</td> </tr> <tr style = " background: #eeeeee;"> <td>B? </td> <td style = "text-align: right;">Bigelow&Holmemes</td> </tr> <tr> <td>Bert</td> <td style = "text-align: right;">Berthold</td> </tr> <tr style = " background: #eeeeee;"> <td>Bits</td> <td style = "text-align: right;">BitStream</td> </tr> <tr> <td>DTC </td> <td style = "text-align: right;">ディジタルタイプフェイス Corp.</td> </tr> <tr style = " background: #eeeeee;"> <td>HP </td> <td style = "text-align: right;">ヒューレットパッカード</td> </tr> <tr> <td>IBM </td> <td style = "text-align: right;">IBM</td> </tr> <tr style = " background: #eeeeee;"> <td>KATF</td> <td style = "text-align: right;">Kingsley/ATF</td> </tr> <tr> <td>Lans</td> <td style = "text-align: right;">有限会社 Lanston タイプ</td> </tr> <tr style = " background: #eeeeee;"> <td>LETR</td> <td style = "text-align: right;">Letraset</td> </tr> <tr> <td>Lino</td> <td style = "text-align: right;">Linotype</td> </tr> <tr style = " background: #eeeeee;"> <td>MONO</td> <td style = "text-align: right;">モノタイプ</td> </tr> <tr> <td>MS </td> <td style = "text-align: right;">マイクロソフト</td> </tr> <tr style = " background: #eeeeee;"> <td>QMSI</td> <td style = "text-align: right;">QMS/Imagen</td> </tr> <tr> <td>URW</td> <td style = "text-align: right;">URW</td> </tr> <tr style = " background: #eeeeee;"> <td>ZSFT</td> <td style = "text-align: right;">ZSoft</td> </tr> </table> ※7 fsSelection フォントスタイルを選択するフラグ部分です。 Bit 0 : ITALIC 斜体 Bit 1 : UNDERSCORE 下線 Bit 2 : NEGATIVE 反転 Bit 3 : OUTLINED 輪郭 Bit 4 : STRIKEOUT 打消し線 Bit 5 : BOLD 太字 IMPACT.ttfの値は以下のとおりでした。 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 100px; ">Name</th> <th>Value</th> </tr> <tr style = " background: #eeeeee;"> <td>UsVersion</td> <td style = "text-align: right;">3</td> </tr> <tr> <td>SXAvgCharWidth</td> <td style = "text-align: right;">1222</td> </tr> <tr style = " background: #eeeeee;"> <td>UsWeightClass</td> <td style = "text-align: right;">400</td> </tr> <tr> <td>UsWidthClass</td> <td style = "text-align: right;">3</td> </tr> <tr style = " background: #eeeeee;"> <td>sFsType</td> <td style = "text-align: right;">8</td> </tr> <tr> <td>SSubscriptXSize</td> <td style = "text-align: right;">1184</td> </tr> <tr style = " background: #eeeeee;"> <td>SSubscriptYSize</td> <td style = "text-align: right;">1081</td> </tr> <tr> <td>SSubscriptXOffset</td> <td style = "text-align: right;">0</td> </tr> <tr style = " background: #eeeeee;"> <td>SSubscriptYOffset</td> <td style = "text-align: right;">0</td> </tr> <tr> <td>SSuperscriptXSize</td> <td style = "text-align: right;">1184</td> </tr> <tr style = " background: #eeeeee;"> <td>SSuperscriptYSize</td> <td style = "text-align: right;">1081</td> </tr> <tr> <td>SSuperscriptXOffset</td> <td style = "text-align: right;">0</td> </tr> <tr style = " background: #eeeeee;"> <td>SSuperscriptYOffset</td> <td style = "text-align: right;">800</td> </tr> <tr> <td>SStrikeoutSize</td> <td style = "text-align: right;">102</td> </tr> <tr style = " background: #eeeeee;"> <td>SStrikeoutPosition</td> <td style = "text-align: right;">690</td> </tr> <tr> <td>SFamilyClass</td> <td style = "text-align: right;">2053</td> </tr> <tr style = " background: #eeeeee;"> <td>ucPanose[0]</td> <td style = "text-align: right;">2</td> </tr> <tr> <td>ucPanose[1]</td> <td style = "text-align: right;">11</td> </tr> <tr style = " background: #eeeeee;"> <td>ucPanose[2]</td> <td style = "text-align: right;">8</td> </tr> <tr> <td>ucPanose[3]</td> <td style = "text-align: right;">6</td> </tr> <tr style = " background: #eeeeee;"> <td>ucPanose[4]</td> <td style = "text-align: right;">3</td> </tr> <tr> <td>ucPanose[5]</td> <td style = "text-align: right;">9</td> </tr> <tr style = " background: #eeeeee;"> <td>ucPanose[6]</td> <td style = "text-align: right;">2</td> </tr> <tr> <td>ucPanose[7]</td> <td style = "text-align: right;">5</td> </tr> <tr style = " background: #eeeeee;"> <td>ucPanose[8]</td> <td style = "text-align: right;">2</td> </tr> <tr> <td>ucPanose[9]</td> <td style = "text-align: right;">4</td> </tr> <tr style = " background: #eeeeee;"> <td>UiUnicodeRange1</td> <td style = "text-align: right;">0x00000287</td> </tr> <tr> <td>UiUnicodeRange2</td> <td style = "text-align: right;">0x00000000</td> </tr> <tr style = " background: #eeeeee;"> <td>UiUnicodeRange3</td> <td style = "text-align: right;">0x00000000</td> </tr> <tr> <td>UiUnicodeRange4</td> <td style = "text-align: right;">0x00000000</td> </tr> <tr style = " background: #eeeeee;"> <td>ucAchVendID</td> <td style = "text-align: right;">MONO</td> </tr> <tr> <td>FsSelection</td> <td style = "text-align: right;">64</td> </tr> <tr style = " background: #eeeeee;"> <td>UsFirstCharIndex</td> <td style = "text-align: right;">32</td> </tr> <tr> <td>UsLastCharIndex</td> <td style = "text-align: right;">64260</td> </tr> <tr style = " background: #eeeeee;"> <td>STypoAscender</td> <td style = "text-align: right;">1619</td> </tr> <tr> <td>STypoDescender</td> <td style = "text-align: right;">-229</td> </tr> <tr style = " background: #eeeeee;"> <td>STypoLineGap</td> <td style = "text-align: right;">343</td> </tr> <tr> <td>UsWinAscent</td> <td style = "text-align: right;">2066</td> </tr> <tr style = " background: #eeeeee;"> <td>UsWinDescent</td> <td style = "text-align: right;">432</td> </tr> <tr> <td>UiCodePageRange1</td> <td style = "text-align: right;">0x2000009f</td> </tr> <tr style = " background: #eeeeee;"> <td>UiCodePageRange2</td> <td style = "text-align: right;">0xdfd70000</td> </tr> <tr> <td>SXHeight</td> <td style = "text-align: right;">1327</td> </tr> <tr style = " background: #eeeeee;"> <td>SCapHeight</td> <td style = "text-align: right;">1619</td> </tr> <tr> <td>UsDefaultChar</td> <td style = "text-align: right;">0</td> </tr> <tr style = " background: #eeeeee;"> <td>UsBreakChar</td> <td style = "text-align: right;">32</td> </tr> <tr> <td>UsMaxContext</td> <td style = "text-align: right;">5</td> </tr> <tr style = " background: #eeeeee;"> <td>UsLowerOpticalPointSize</td> <td style = "text-align: right;">0</td> </tr> <tr> <td>UsUpperOpticalPointSize</td> <td style = "text-align: right;">64565</td> </tr> </table> ==== LTSH スケール系==== グリフの数だけ unsigned char 型の配列をもつ可変長のテーブルです。サイドベアリングが無い場合は常に線形であることを意味する1とする必要がある値で、LinearThreSHoldの意です。headテーブルのflag値のbit4:マイクロソフトのスケーラを使うを有効にしたときにだけLTSH指定するのが一般的な使い方です。0~255の値でグリフを線形にスケーリングできる垂直骨の高さを1emあたりの数値として指定します。0~255ピクセルの大きさにスケールしたときに線形しはじめるのはどこからかというテーブルだと思います。小さい文字にはヒントにしたがったリニアスケールではない値という意味です。1だと、とにかくリニアスケール(単純な拡大・縮小)っていう感じなのかな。もうちょっと確信をもてるような文献にであえたら続報あるかもしれません。 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>説明</th> </tr> <tr> <td>unsigned short</td> <td>UsVersion</td> <td>テーブルバージョン番号 0</td> </tr> <tr style = " background: #eeeeee;" > <td>unsigned short</td> <td><span style = "background:linear-gradient(transparent 75%, #ff9393 75%); font-weight:bold; ">UsNumGlyphs</span></td> <td>グリフ数</td> </tr> <tr> <td>unsigned char</td> <td>UcPels[NumGlyphs]</td> <td>各グリフのスケール垂直骨高さ</td> </tr> </table> IMPACT.ttfの設定内容は以下の通りでした。グリフの数だけある線形スケーリング垂直骨高さなので、テキストファイルのリンクを示します。 [[メディア:IMPACT TAG LTSH TebleInfo.txt|IMPACT_TAG_LTSH_TebleInfo.txt]] ==== VDMX スケール系 ==== VDMXはVertical Device Metric の意味でOS/2テーブルのusWinAscentとusWinDescentの値から任意のサイズのフォントにおける最大の黒色部分高さを決定します。スケーリングによる高さと丸め込み量による高さとで異なるフォント高さになるため、yMaxやyMinから飛び出ることがないように定義されます。VDMXヘッダーにアスペクト比ごとにグループ化したときの総数だけratRange構造体を保有する可変量と総数だけテーブル開始位置からの記載ポジションを設定する可変量を保有しています。ratRange構造体が4バイトです。そしてVDMXレコードが続きます。高さレコードの数だけ1レコード12byteのvTable構造体を持ちます。VDMXタグテーブルは大きな配列になります。アスペクト比ごとのグループ?なんそれって感じでマイクロソフトの仕様書のページにいくと分類が乗ってました。なるほどxとyの比率を検出して、どのテーブルを使うべきかを検出するそうな。それで、ratRagneのxRatio、yStartRatio、yEndRatioが0,0,0になっているのが全ての比率に対応するグループのテーブルなのでこれが見つかると検索を終了するので、0,0,0は配列の最後に配置するべきだそうです。いやー、これは深い。ratRagneのbCharSetの意味はテーブルバージョンによって変わることになっています。Version 0 の bCharset 1のみすべてのグリフに適用せずANSIコードのみに適用されることになります。Version 1の利用が推奨されているようです。bCharset 0 は既存のフォントに追加する場合、1 は全く新しいフォント用に使うことになっています。 ■VDMX Header <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>説明</th> </tr> <tr> <td>unsigned short</td> <td>UsVersion</td> <td>テーブルバージョン番号 0 or 1</td> </tr> <tr style = " background: #eeeeee;" > <td>unsigned short</td> <td>UsNumRecs</td> <td>VDMXグループ数</td> </tr> <tr> <td>unsigned short</td> <td>UsNumRatios</td> <td>アスペクト比ごとのグループ数</td> </tr> <tr style = " background: #eeeeee;" > <td>ratioRange構造体</td> <td>ratRange[UsNumRatios]</td> <td>numRatioの数の配列のratRage構造体</td> </tr> <tr> <td>unsigned int</td> <td>vdmxGroupOffsets[UsNumRatios]</td> <td>numRatioの数の配列のテーブル先頭からのアドレス位置</td> </tr> </table> ■ratRagne構造体 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>説明</th> </tr> <tr> <td>unsigned char</td> <td>bCharSet</td> <td>文字セット</td> </tr> <tr style = " background: #eeeeee;" > <td>unsigned char</td> <td>xRatio</td> <td>x-Ratioのために使う値</td> </tr> <tr> <td>unsigned char</td> <td>yStartRatio</td> <td>y-Ratioの開始値</td> </tr> <tr style = " background: #eeeeee;" > <td>unsigned char</td> <td>yEndRatio</td> <td>y-Ratioの終了値</td> </tr> </table> ■VDMX Record <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>説明</th> </tr> <tr> <td>unsigned short</td> <td>UsRecs</td> <td>高さレコード数</td> </tr> <tr style = " background: #eeeeee;" > <td>unsigned char</td> <td>ucStartsz</td> <td>y垂直骨高さ開始値</td> </tr> <tr> <td>unsigned char</td> <td>ucEndsz</td> <td>y垂直骨高さ終了値</td> </tr> <tr style = " background: #eeeeee;" > <td>vTable構造体</td> <td>vTable_Entry[usRecs]</td> <td>numRatioの数の配列のratRage構造体</td> </tr> </table> ■vTable構造体 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>説明</th> </tr> <tr> <td>unsigned short</td> <td>yPelHeight</td> <td>適用するyPel値</td> </tr> <tr style = " background: #eeeeee;" > <td>short</td> <td>yMax</td> <td>yPelのための最大値</td> </tr> <tr> <td>short</td> <td>yMin</td> <td>yPelのための最小値</td> </tr> </table> IMPACT.ttfの場合は以下のようになっていました。ものすごい細かく設定されてるんですね。フォントファイル制作ってやっぱスゴイな。 [[メディア:IMPACT TAG VDMX TebleInfo.txt|IMPACT_TAG_VDMX_TebleInfo.txt]] ==== hdmx スケール系 ==== hdmxはHorizontal Device Metricの意味でVDMXは大文字でしたが、水平方向についての定義です。このテーブルもheadテーブルのflag値のbit 4 が 1 である場合にのみ使われることが推奨されています。 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>説明</th> </tr> <tr> <td>unsigned short</td> <td>UsVersion</td> <td>テーブルバージョン番号 0 </td> </tr> <tr style = " background: #eeeeee;" > <td>unsigned short</td> <td>usNumRecord</td> <td>レコード数</td> </tr> <tr> <td>unsigned int</td> <td>UiSizeDeviceRecord</td> <td>DeviceRecordテーブルの大きさ。NumGlyph+2より大きい値</td> </tr> <tr style = " background: #eeeeee;" > <td>DeviceRecords</td> <td>Record[NumRecord]</td> <td>DeviceRecords構造体</td> </tr> </table> ■DeviceRecord構造体 <table style = "width: 100 ; text-align: left; border-collapse: collapse; border-spacing: 0; "> <tr style = " background: #778ca3; border-right: solid 1px #778ca3; color: #ffffff; "> <th style = "width: 200px; ">型</th> <th style = "width: 200px; ">Name</th> <th>説明</th> </tr> <tr> <td>unsigned char</td> <td>ucPixelSize</td> <td>ピクセルサイズ </td> </tr> <tr style = " background: #eeeeee;" > <td>unsigned char</td> <td>ucMaxWidth</td> <td>最大幅</td> </tr> <tr> <td>unsigned char</td> <td>ucWidths[numGlyph]</td> <td>各グリフごとの送り幅</td> </tr> </table> 全部がツメツメに格納されているわけではなく、1つのRecord番号のDeviceRecord構造体を記述するときにUiSizeDeviceRecordの長さになっていることは注意するべきところで、2+numGlyph数からUiSizeDeviceRecord Byteの分までを0x00でPaddingをしないといけません。 IMPACT.ttfの内容は以下のファイルリンクの通りになります。割かし長いテーブル内容です。 [[メディア:IMPACT TAG hdmx TebleInfo.txt|IMPACT_TAG_hdmx_TebleInfo.txt]] ==== cmap ==== 文字コードをうけとって、グリフIDに変換して、必要なグリフ表示を行うための対応表です。最近はUnicodeを受け取る方式のフォントファイルcmapが準備されていることが多いそうです。他の方法もあるのは手ごわい。あんまり使われない方法も知らないといけないんだなぁ。やだな。 中規模の可変長のテーブルになることが多いです。ややこしさはglypの実体テーブルの次くらいだという感じです。理解できるかどうかわかりませんが、仕様書をひも解いていきます。仕様書読んだらわかるだろ?そうなん?あれだけで瞬時に理解しきれるとか頭良すぎるでしょ。あーた。 == '''関連記事''' == :[[フォント OpenType 構造解析]] : [[FreeTypeをコンパイル]] :[[FreeTypeを使う]] [[フォント]]に戻る。
フォント TrueType 構造解析
に戻る。
個人用ツール
ログイン
名前空間
ページ
議論
変種
表示
閲覧
ソースを表示
履歴表示
操作
検索
案内
メインページ
コミュニティ・ポータル
最近の出来事
最近の更新
おまかせ表示
ヘルプ
ツールボックス
リンク元
関連ページの更新状況
特別ページ