フォント

2011年2月20日 (日)

もう1度だけT2FAnalyzer

T2FAnalyzerの最新版V1.4.1をリリースしました。

埋め込みビットマップの表示に対応しました。こんな感じです。

T2f141_0


埋め込みビットマップは実際はEBDTテーブルに格納されているのですが、EBLCテーブルのタブの内部に表示されます。

GPOSテーブルのルックアップタイプ8のChaining Contexual Positioningのフォーマット3の表示にも対応しました。

後は主にバグフィックスです。

2011年2月12日 (土)

T2FAnalyzer1.4.0リリース

ちょっとだけやる気がでたので、T2FAnalyzerの最新版をリリースします。

GPOSテーブルの以下のルックアップサブテーブルの表示に対応しました。

  • ルップアップタイプ1のSingle Adjustment
  • ルックアップタイプ2のPair Adjustment
  • ルックアップタイプ3のCursive Adjustment
  • ルックアップタイプ4のMarkToBase Attachment
  • ルックアップタイプ6のMarkToMark Attachment

一応内部では、全ルックアップタイプの解析コードだけは走るようになってます。
画面を用意してないだけで・・・・・dash

Windows7付属の全フォントといくつかの無料フォントでは、とりあえず
問題なく解析できてるようです・・

それにしても、もう技術ネタかく気力は全くねぇな俺sweat02

2010年4月15日 (木)

T2FAnalyzer V1.3.0リリース

一応予定通り?惰性でT2FAnalyzer V1.3.0をリリースしました。

新たに

  • BASEテーブル
  • JSTFテーブル(一部)

に対応しました。埋め込みビットマップのEBDTやるとか言ってましたが、画面を色々考えなきゃいけないのでキャンセルしましたdash。ということで機械的にできそうなJSTFテーブルに一部対応しました。

V1_3_0sc

BASEテーブルの画面分かりづらいかも・・bearing

また、ネットワーク絡みの作業に戻るぞhappy02

2010年4月 6日 (火)

モチベーション下降中というよりゼロ。

この2ヶ月間は趣向を変えてネットワーク絡みのプログラミングと実験・調査をやってたのだがまた燃え尽きたdash。一気にやると燃え尽きるな。頑張ったgoodHTTPプロトコルURIの仕様書を読んでたり、ヘッダを移植したようにWinHttp Servicesと戯れてた。楽しかったhappy02

で、ここ1週間はやる気メーターがzeroになってしまったので全くプログラミングから離れてたのだが、このままだと前みたく数ヶ月は遊びほうけてしまいそうな予感なので、無理やりにでも波に乗らんとと思い、とりあえず、T2FAnalyzerの残りでもやってみようかなと思いソースを見てたdash

とりあえず、画面が作りかけのBASEテーブルを終わらしたいんだが、どこまでが作りかけか完全に忘れたsweat02。いてて。後一息だったはずなんだが、また、仕様書読むはめになるのは嫌だ。

後は、埋め込みビットマップのEBDTテーブル辺りだなと思い仕様書を読んで、どんな画面イメージがいいか考え中。

というより、最新の開発環境を購入してあるので、T2FAnalyzerのUnicode化(現状のT2FAnalyzerは古い開発環境でビルドしてるのでAnsiアプリ)と正式にVista以降に対応させたいと前々から思っているのだが、ワケあって保留中。まぁ、これは別にT2FAnalyzerが使いやすくなるとかとは全く関係ないが・・(文字化けとか発生したりUnicodeでないと困るような部分ほとんどないので)。

まぁ、順調にモチベーションがあがらなければ放置だけどdashdash

そういえば、T2FAnalyzerはメニューとかすべて英語だが、、どうも英語圏の人に全く使われていないので、前に作ってあった英語の紹介ページへのリンクを張ってみた。公開はしてあったのだが、リンクはらんとGoogleでヒットしないな。ははは。

2010年1月18日 (月)

T2FAnalyzer V1.2.2リリース

TrueType/OpenType Font解析ツールT2FAnalyzerの最新版V1.2.2をリリースしました。

主な変更は要望のあったGSUBテーブルのLookupタイプ7の拡張置換の対応です。後は、高速化と最適化です。起動時間が大幅に短縮し、色々リソース(USERSやGDIリソース)の使用量を大幅に削減しましたsweat01

ということで、ちょっとまだ実装されていない機能を調べてみました。

  • GSUBテーブルのLookupタイプ8の逆順連鎖型文脈依存単独置換
  • GPOSテーブルのすべてのタイプのLookupサブテーブル
  • BASEテーブル(V1.3.0で対応)
  • JSTFテーブル(V1.3.0で一部対応)
  • VORGテーブル
  • EBDTテーブル
  • cmapテーブルのフォーマット14のUnicode Variation Sequences

こんな感じかな。

GSUBテーブルに関しては今回のリリースでLookupタイプ8以外のLookupサブテーブルはすべて対応した事になります。8は内部では確かずっと前から解析自体はされているのですが、画面が・・dash

GPOSテーブルのLookupサブテーブルは全滅ですdash。解析自体も画面もまだ作ってない(というより仕様書も読んでない)。

BASEテーブルは解析自体は終わっていて画面も途中まで作ってて挫折sweat02

まぁ、残ったのはなんか自分的にあんまおもしろくなさそうなものばっかdashdash

ということもあり残りは要望の都度、追加していこうかなと思います。

 

というか、これらや今回のLookupタイプ7の拡張置換を含めて、そのようなフォントを持ってないのでこちらで動作確認できませんのであしからずsweat01sweat02

2009年11月12日 (木)

OpenTypeフォントの続き(12)・・・PostScriptアウトラインの更に続き

前回は位置が固定であるHeaderからGlobal Subr INDEXまで見たので残りのいくつかのデータをとっとと見て行こう。

残りのデータはオフセット経由でアクセスされる。

まずは、CharStrings INDEX。

Cff3_1_2

肝となるデータである。CharStrings INDEXにはフォントに含まれる各グリフのアウトラインを記述するプログラムが格納される。前回も述べたがこのプログラムはCharstringと呼ばれ、そのフォーマットはTop DICTのCharstringTypeキーによって指定される。MinionPro-Itの場合、Top DICTにCharstringTypeキーが含まれていないので、デフォルト値2のType2 Charstringとなる。

CharStrings INDEXのcountフィールドはフォントに含まれるグリフの数を表す。上の画像より1851個のグリフが含まれている事が分かる。また、CFFにおいて各グリフはGID(Glyph Identifier)によって識別されるが、CharStrings INDEX内の先頭のグリフから順にGIDが0、1、2・・となる。上の画像ではGIDが265のグリフが表示されている。厳密にはCFFのGIDとOpenTypeフォントの文字コードからcmapテーブルによって変換されるグリフインデックスは別物であるが、PostScriptアウトラインのOpenTypeフォントの場合、OpenTypeフォントのグリフインデックス=CFFのGIDとなる。ちなみに、CharStrings INDEXへのオフセットはフォントのTop DICTのcharstringキーの値として指定される(このオフセットはCFFフォーマットの先頭からのオフセット)。

Charset。

Cff3_2

Charsetにはグリフ(GID)と名前(SID)のマッピング情報が格納される。詳細は省略するが、例えば、先ほどのCharStrings INDEXの画像でGIDが256のグリフが表示されていたが、このグリフのSIDは上の画像より1465であることがわかる(GID 0のグリフの名前は省略されているので、[Index]列が256-1=255のエントリ)。また、String INDEXよりSIDが1465の文字列はc_kであるから、GIDが256のグリフの名前はc_kであるdashdash

Encoding。

Encodingを持ったフォントが見つからんdash。たぶん、文字コードとSIDかGIDのマッピング情報が格納される(SIDかGIDのどっちかは仕様書読んでも理解できませんsad)。

Private DICT。

Cff3_3

そのまんまであるが、Private DICTにはフォントにプライベートな情報が格納されるsweat02sweat02。Subrキーはこのフォントだけからアクセスできるサブルーチンが格納されたLocal Subr INDEXへのオフセットを表す。

Local Subr INDEX。

Cff3_4

はやくも燃え尽き気味sweat02sweat01

とりあえず、バージョンを1.2として最新版をアップロードしておきました。Type2 Charstringの解析はまだですが、とりあえず、グリフの形状が分かるようになったのでこれでいいかなと・・・

2009年11月 7日 (土)

OpenTypeフォントの続き(11)・・・PostScriptアウトラインの続き

準備ができたので今回は実際にPostScriptアウトライン形式のOpenTypeフォントを解析してみるのだが、PostScriptアウトライン形式のOpenTypeフォントってどこで無料で手に入るんだdashdash??と思ってたら、いいものが既にインストールされていた。

たいていの人が既にインストールしてあるであろう無償のPDFビューアのAdobe ReaderをインストールするといくつかPostScriptアウトライン形式のOpenTypeフォントがインストールされるのでこれを解析してみる。ということでここでは、<Adobe Readerのインストールフォルダ>\Resource\Fontフォルダにある欧文用のMinonPro-It(ファイル名MinionPro-It.otf)というOpenTypeフォントを使って話を進める(別のフォルダCIDFontに小塚明朝、小塚ゴシックという日本語用のPostScriptアウトライン形式のOpenTypeフォントがあるのだが、これらのフォントは脇においておく)。

実際に解析結果を示しながら話を進めるが、最初にAdobeというかPostScript系のフォントはある程度、歴史を知らないとなぜこういう構造や仕組みになっているかなど理解に苦しむかも知れないbearing。実際、CFFフォーマットを理解するために、その前身?のType1やCID-Keyedフォントの仕様書や更にはPostScriptの言語リファレンスまで自分はかいつまんで読むはめになったsweat02sweat01

ということで、まずは前回示したCFFフォーマットのレイアウトにおける位置が固定であるHeaderからGlobal Subr INDEXまでの解析結果を順に見ていく。

まずは、Header。

Cff2_1

文字通りヘッダ情報が格納される。Major、Minorは順にCFFフォマーットのメジャーバジョーン番号、マイナーバージョン番号を表す。

Name INDEX。

Cff2_2

Name INDEXには含まれるフォントの名前が前回説明したINDEXデータとして格納される。含まれるフォントの数はこのName INDEXのcountフィールドによって決定される。上の画像より1個のフォントが含まれていることがわかる。ちなみに、他のデータはそのままにしてこのフォントの名前の先頭文字をヌル文字(0x00)にすることで、フォントを論理削除できる。

Top DICT INDEX。

Cff2_3_2

Top DICT INDEXには、含まれるフォントのトップレベルの情報が前回説明したDICTデータとして格納される。もちろん、フォントの各情報はキー・値のペアとして表されるが、定義済みのTop DICTキーには例えば次のようなものがある。

Top DICTキー
キー
version(0) SID
Notice(1) SID
Copyright(12 0) SID
FullName(2) SID
FamilyName(3) SID
省略
FontBBox(5) 配列
省略
charset(15) 数値
Encoding(15) 数値
CharStrings(15) 数値
省略

1列目はキーの名前で、括弧内はキー自身の値つまりキー値である。例えば、フォントの完全名を指定するFullNameキーの値はSIDを表すので、このSIDを使い次のString INDEXの対応するエントリを見れば、フォントの完全名がわかる。また、フォントのバウンディングボックス(境界矩形)を指定するFontBBoxキーの値は4つの要素を持つ配列(順に矩形の左端のx座標、下端のy座標、右端のx座標、上端のy座標)である。charset、Encoding、CharStringsへのCFFフォーマットの先頭からのオフセットをそれぞれ指定するcharset、Encoding、CharStringsキーの値は単純な数値である。定義されているすべてのキーとその詳細は仕様書を参照ということでdashdash・・・・ちなみに、上の画像では、計10個のキーが定義されてるが、デフォルト値を持つキーは省略できる。

String INDEX。

Cff2_4

String INDEXには含まれるフォント間で共通のフォント名以外の文字列が格納される。ちなみに、これらの文字列はSID(String Identifier)と呼ばれる2バイトの符号無し整数によって参照される。また、一般的な文字列は標準文字列として計391個(SID::0-390まで)定義済みであるので、String INDEXに含まれる各文字列のSIDは先頭の文字列から順に、391、392、393・・・となる。上の画像より1616個の文字列が格納されていることが分かる。

Global Subr INDEX。

Cff2_5

Global Subr INDEXには各フォント間で共有されるサブルーチンが格納される。CFFフォーマットでは各グリフのアウトラインが単純なデータというより一種のプログラム(Type2 Charstringなどと呼ばれる)によって定義されるが、サブルーチンとはこのプログラムから呼び出されるサブプログラムの事である(通常のコンピュータプログラム言語におけるサブルーチンと同一の概念)。上の画像より1024個のグローバルなサブルーチンが格納されている事が分かる。各サブルーチンの中身についてはまだ解析してないので表示してない・・・

と長くなったので今回はここまでdash。残りの解析に手間取ってるsweat02ので、とりあえず、ここまでの解析に対応したT2FAnalyzerの最新版をアップロードしておきました。ダウンロードは脇のいつものリンクから。

2009年11月 4日 (水)

OpenTypeフォントの続き(10)・・・PostScriptアウトライン

一連のOpenTypeフォントのシリーズでOpenTypeフォントは、グリフデータとしてTrueType形式のアウトラインまたはPostScript形式のアウトラインを含むことができると書いたが、今回はPostScriptアウトラインについて。

PostScriptアウトラインに関するグリフデータは第2回で述べたようにCFFテーブルに格納され、このテーブルはCFF(Compact Font Format)と呼ばれる形式のフォーマットになっているが、このCFFフォーマットについて書いてみる。

CFFフォーマットは複数のフォントを格納でき、Type1、CID-Keyedフォントよりコンパクトなバイナリ表現のフォーマットである。CFFフォーマットがコンパクトな理由は、バイナリ表現を使用したり、フォント間で共通のデータを共有したり、また、頻繁に出現するデータに対してデフォルト値を与えたりしているためである。(Type1やCID-Keyedフォントって何?って話はここでは触れない。)

ということで、まずは、CFFフォーマットで使われるデータ型から。

CFFデータ型
名前 範囲 説明
Card8 0-255 1バイト符号無し整数
Card16 0-65536 2バイト符号無し整数
OffSize 1-4 オフセットのサイズを指定する1バイト符号無し整数
Offset 可変 1,2,3または4バイトオフセット
SID 0-64999 2バイトストリングID

Card8、Card16はそれぞれ1、2バイトの符号無し整数を表すデータ型である。OffSizeは対応するOffsetで表されるデータ型のフィールドのサイズを表し、1-4の範囲の値を取る。例えば、この値が1なら対応するOffset型のフィールドのサイズは1バイトになる。順に2なら2バイト、3なら3バイト、4なら4バイトである。

CFFフォーマットのレイアウトの概要は次のようになる。

CFFレイアウト
名前 説明
Header -
Name INDEX -
Top DICT INDEX -
String INDEX -
Global Subr INDEX -
Encodings -
Charsets -
FDSelect -
CharStrings INDEX -
Font DICT INDEX -
Private DICT -
Local Subr INDEX -
Copyright and Trademark Notices -

上の表のようにCFFフォーマットはいくつかのデータの集合として定義されている。また、上の表を見てわかるようにINDEXやDICTと共通の名前を持ったデータがあるが、最初にこれらについて説明する。

ちなみに、HeaderからGlobal Subr INDEXまでの最初の5つの位置は固定であり、残りはオフセット経由でアクセスされる。

まずはINDEXデータについて。

INDEXデータは可変サイズのオブジェクトの配列であり、次のような構造になる。

INDEXデータ
名前 説明
Card16 count INDEXデータ内のオブジェクトの数
OffSize offSize オフセット配列の要素のサイズ
Offset offsets[count+1] オフセット配列(オフセット配列の直前のバイトからのオフセット)
Card8 data[varies] オブジェクトデータ

countフィールドはINDEXデータ内に含まれるオブジェクトの数を表す。offSizeフィールドは続くオフセット配列の要素のサイズを表す。offsetsフィールドは各オブジェクトへのオフセットの配列であり、INDEXデータ内の各オブジェクトへはこのオフセットを使ってアクセスする。また、このオフセット配列の要素数はINDEXデータ内に含まれるオブジェクトの数+1つまりcount+1であり、i番目のオブジェクトのサイズは

i番目のオブジェクトのサイズ=offsets[i+1] - offsets[i]

で一様に求まる。このオフセットはオフセット配列の直前のバイトからのオフセットつまりoffSizeフィールドからのオフセットを表すので、オフセット配列の最初の要素offsets[0]は常に1になる。ちなみに、countフィールドが0の空のINDEXの場合、残りのフィールドは存在しない。

例えば、各フォント間で共有される文字列はString INDEXに上記の構造においてオブジェクトとして格納されている。同様に、フォント毎の情報は次に説明するDICTデータとして表現されるが、これらの情報はTop DICT INDEXに上記の構造においてオブジェクトとして格納されている(ややこしいが、Top DICT INDEX全体は上記のINDEXデータでINDEXデータ内に含まれる各オブジェクトが次に説明するDICTデータである)。

次はDICTデータについて。

DICT(DICTionary)データはキー・値のペアのコレクションであり、キーは1または2バイトのデータ、値は可変長の整数または実数を表すデータである(ちなみに、値には複数個の整数や実数の配列としても格納できる)。

DICTデータの各キー・値のペアは特別なルールでエンコードされていて、ここでは、詳細については省略するが、簡単に説明すると

値を表すバイトデータ、キーを表すバイトデータ、値を表すバイトデータ、キーを表すバイトデータ・・・・・

のようにエンコードされる。キー・値のペアの値のデータが先にくる。また、(先頭の)バイトデータによって値とキーが区別できるようになっているので、DICTデータの先頭から1バイトずつ処理すればデコードできるようになっている。例えば、DICTデータをデコードするプログラムは次のようになる。

具体的には先頭バイトが0-21ならキー、28、29、247-254なら整数の値、30なら実数の値という具合になっているdash。上記のプログラムは1つのキー・値ペアをデコードするプログラムであるが、通常、DICTデータへのオフセットと共にDICTデータ全体のサイズが与えられるので、与えられたサイズに達するまでデコードすれば、DICTデータに含まれるすべてのキー・値のペアをデコードできる。

と、抽象的なことばかりだとイメージが掴みにくいかもしれないので、次回以降具体的にこれらの中身を見ていこうと思う。また、次回でCFFの解析に対応したT2FAnalzyerの最新版も同時にアップロードしようと思うhappy02

2009年10月26日 (月)

CFF/Type2 Charstring

データベース絡みの事をやっていたのであるが、行き詰まったdashので、気分転換にちょっと本格的にT2FAnalyzerで要望のあったCFF(Compact Font Format)/Type2 Charstringの解析に向けて、仕様書を読み始めた。

Type2 Charstringというものがグリフのアウトラインを記述してるようであるが、TrueTypeアウトラインのglyfテーブルと違って、CFFアウトラインは一種のプログラムじゃんbearing。このプログラムの実行環境であるType2 Charstringインタプリタもどきみたいなの作らんとアウトラインの形状をラスタライズできそうにもないな(TrueTypeインストラクションほど複雑そうではないが・・)wobbly

うーん。

漠然とCFF/Type2の全体のイメージが掴めたので、CFF/Type2の解析部分のプログラミングを開始しましたhappy02

Cfftype2_2

2009年1月20日 (火)

OpenTypeフォントの続き(9)・・・インストラクション

久しぶりにOpenTypeフォントの続き。今回はインストラクション

インストラクションは特定のグリフに、または、フォント全体に関連付けることができる。特定のグリフに関連付けられたインストラクションはグリフプログラム(Glyph Program)と呼ばれ、glyfテーブルに格納され、そのグリフが要求される度に実行される。フォントプログラム(Font Program)はfpgmテーブルに格納されるインストラクションで、フォントにアクセスされる最初に一度だけ実行される。コントロール値プログラム(Control Value Program)はprepテーブルに格納されるインストラクションで、フォントのポイントサイズが変わるたびに実行される。

ところで、インストラクションを実行するプログラムはTrueTypeインタプリタと呼ばれるが、TrueTypeインタプリタは主に

  • インストラクションストリーム
  • インタプリタスタック
  • グラフィックスステート

で構成される。インストラクションのオプコードとデータは順序付けれた一連のバイト値として格納されるが、この一連のバイト値はインストラクションストリームと呼ばれ、インストラクションポインタ(IP)が次に実行するインストラクションを指し示す。

Opentype9_ip_2

また、TrueTypeインタプリタはインストラクションに必要なデータとインストラクションによって生成された結果をスタックに格納するが、このスタックはインタプリタスタックと呼ばれる。ほとんどのインストラクションはこのスタックに対して操作を行うが、PUSH命令と呼ばれるインストラクションはインストラクションストリームからその引数を取り、それをスタックに転送する。

PUSH命令
インストラクション 説明
NPUSHB[] PUSH N Bytes
NPUSHW[] PUSH N Words
PUSHB[abc] PUSH Bytes
PUSHW[abc] PUSH Words

ところで、インタプリタスタックの各要素は32ビットの固定長であるので、PUSH命令でインストラクションストリームから取り出したデータはゼロ拡張や符号拡張を行い32ビット長にしてからスタックにPOPする必要がある。

と、いろいろ省略してるが、まぁ、TrueTypeインタプリタを作る人以外は、これ以上、深入りしてもしょうがないような気がするので、実際にインストラクションを解析してみる。まずは、Tahomaフォントのフォントプログラムから。

Opentype9_1

フォントプログラムでは主に他で使用される関数やインストラクションが定義されるのだが、そのためのFDEF(Function DEFinition)命令が見てとれる。次は、コントロール値プログラム。

Opentype9_2

PUSH命令だらけである。先ほども書いたが、PUSH命令は引数がインストラクションストリームから取られるので、PUSH命令の次の命令のオフセットが引数のサイズだけ飛んでいるのである。最後はグリフプログラム。

Opentype9_3

とこんな感じ。

ちなみに、TrueTypeインタプリタの実行環境のメモリ要件など関する情報はmaxpテーブルに格納されている。

Opentype9_4_2

上の画像はTahomaフォントのmaxpテーブルの内容であるが、例えば、定義されている関数の数(MaxFunctionDefs)は57個、定義されているインストラクションの数は(MaxInstructionDefs)は0個、グリフプログラムの最大バイト数(MaxSizeOfInstructions)は1406バイトであるので、グリフプログラムの実行のために1406バイト以上のメモリを確保しておけばよい・・・・

というかT2FAnalyzerのプログラムが巨大になり手に負えなくなってきたwobbly・・・リファクタリングしないとだめだなぁ・・・

自作ソフトウェア

無料ブログはココログ

メモ