X11 の PCF ビットマップフォントファイルのフォーマット

このファイルは X11 のソースに基づいています。ソースに書かれている内容と何らかの食い違いがあれば、私の記述が間違っています。ソースが定義です。

PCF (portable compile format) ファイルフォーマットは X サーバが使用するビットマップフォントの倍なり表現です。ファイルヘッダに続き一連のテーブルと、すべてのテーブルにへのポインタを含むヘッダが続きます。

ファイルヘッダ

ファイルヘッダは最下位バイトを先頭置いた 32 ビットの整数値の並びからなります。

char header[4];			/* 常に "\1fcp" */
lsbint32 table_count;
struct toc_entry {
    lsbint32 type;		/* 下記参照, どのテーブルかを指定 */
    lsbint32 format;		/* 下記参照, データがテーブル内にどんなフォーマットで格納されるかを指定 */
    lsbint32 size;		/* バイト数 */
    lsbint32 offset;		/* ファイルの先頭から */
} tables[table_count];

type フィールドは以下のどれか 1 つです:

#define PCF_PROPERTIES		    (1<<0)
#define PCF_ACCELERATORS	    (1<<1)
#define PCF_METRICS		    (1<<2)
#define PCF_BITMAPS		    (1<<3)
#define PCF_INK_METRICS		    (1<<4)
#define	PCF_BDF_ENCODINGS	    (1<<5)
#define PCF_SWIDTHS		    (1<<6)
#define PCF_GLYPH_NAMES		    (1<<7)
#define PCF_BDF_ACCELERATORS	    (1<<8)

format フィールドは以下のどれか 1 つです:

#define PCF_DEFAULT_FORMAT	0x00000000
#define PCF_INKBOUNDS		0x00000200
#define PCF_ACCEL_W_INKBOUNDS	0x00000100
#define PCF_COMPRESSED_METRICS	0x00000100

format フィールドは以下のフラグで修飾可能です:

#define PCF_GLYPH_PAD_MASK	(3<<0)		/* 説明はビットマップテーブルの項を参照 */
#define PCF_BYTE_MASK		(1<<2)		/* 上位バイトが先か */
#define PCF_BIT_MASK		(1<<3)		/* 上位ビットが先か */
#define PCF_SCAN_UNIT_MASK	(3<<4)		/* 説明はビットマップテーブルの項を参照 */

format フィールドは、各テーブルの最初のワードとして繰り返されます。ほとんどのテーブルは 1 種類のフォーマット (デフォルト) しか含んでいませんが、フォントによっては異なるフォーマットを使用しています。format の上位の 3 バイトが、全体のフォーマットを記述します。整数とビットが格納される方式は、上のマスクビットの 1 つを加えることによって変更することができます。

すべてのテーブルは 32 ビット境界から始まります (端数は 0 でパディングされます)。

属性テーブル

lsbint32 format; 		/* 常に最下位ビットが最初に格納される! */
int32 nprops;			/* format で指定されたバイトオーダで格納される */
struct props {
    int32 name_offset;		/* 以下の文字列テーブルへのオフセット */
    int8 isStringProp;
    int32 value;		/* 整数属性の即値, 文字列属性のオフセット */
} props[nprops];
char padding[(nprops&3)==0?0:(4-(nprops&3))];	/* 次の int32 境界まで埋める */
int string_size;		/* 文字列の総サイズ (末尾の NUL を含む) */
char strings[string_size];
char padding2[];

これらの属性は、X がユーザに提供するフォントアトムです。これらの多くは xc/doc/specs/XLFD/xlfd.tbl.ms またはこの文書で解説されています。 (X プロトコルはこれらのアトムに制限を加えていないので、第三者が何らかのフォントの定義を行うことができます)

属性の名前は、strings + props[i].name_offset に書かれています。

メトリックのデータ

いくつかのテーブル (PCF_METRICS, PCF_INK_METRICS およびアクセラレータテーブルの内部) には、圧縮フォーマット (PCF_COMPRESSED_METRICS) または非圧縮フォーマット (DEFAULT) のどちらかでメトリックデータが格納されています。圧縮フォーマットは、値を格納するのに byte 型を使用するのに対し、非圧縮フォーマットは short 型を使用します。(圧縮された) バイト値は符号なし byte 値で、0x80 のオフセットが加えられています (よって、実際の値は (getc(pcf_file)-0x80) になります)。データは以下のように格納されています:
圧縮フォーマット

uint8 left_sided_bearing;
uint8 right_side_bearing;
uint8 character_width;
uint8 character_ascent;
uint8 character_descent;
 /* 暗黙の文字属性フィールド = 0 */

非圧縮フォーマット:

int16 left_sided_bearing;
int16 right_side_bearing;
int16 character_width;
int16 character_ascent;
int16 character_descent;
uint16 character_attributes;

これは、XCharStruct で必要とされるデータを提供します。

アクセラレータテーブル

これらのデータは、フォントの全体に関わる多数の細々とした情報を提供します。個のデータ構造は PCF_ACCELERATORS と PCF_BDF_ACCELERATORS の 2 個のテーブルで使用されます。テーブルは DEFAULT か PCF_ACCEL_W_INKBOUNDS のいずれかのフォーマットを使用することができます (後者の場合、最後にいくつかの拡張メトリックデータが追加されます)。

アクセラレータテーブルは以下のような形をしています: 両方のテーブルが存在する場合、BDF アクセラレータのほうが標準アクセラレータよりも優先されます。BDF アクセラレータはフォント内の符号化された文字を参照するデータのみを含みます (それに対し、単純アクセラレータテーブルは全てのグリフを含むので、BDF アクセラレータの方がより正確なのです)。

メトリックテーブル

メトリックテーブルには PCF_METRICS と PCF_INK_METRICS の異なる 2 種類のテーブルが存在します。前者には、格納されたビットマップのサイズを含んでいるのに対し、後者は最小バウンディングボックスを含みます。両者は同じデータを含むことができますが、多くの CJK フォントはビットマップにパディングをしているため、すべてのビットマップは同じサイズです。テーブルフォーマットは DEFAULT または PCF_CONPRESSED_METRICS のどちらかが使用可能です (これの説明は、メトリックデータ に関するセクションを参照してください)。

lsbint32 format; 		/* 常に最下位ビットが最初に格納される! */
/* フォーマットが compressed の場合 */
    int16 metrics_count;
    Compressed_Metrics metrics[metrics_count];
/* それ以外で、フォーマットがデフォルト (uncompressed) の場合 */
    int32 metrics_count;
    Uncompressed_Metrics metrics[metrics_count];
/* endif */

ビットマップテーブル

ビットマップテーブルのタイプは PCF_BITMAPS です。フォーマットは PCF_DEFAULT でなければなりません。

lsbint32 format; 		/* 常に最下位ビットが最初に格納される! */
int32 glyph_count;		/* バイトオーダは format に依存する。メトリックの個数と同じになるべき */
int32 offsets[glyph_count];	/* ビットマップデータへのバイトオフセット */
int32 bitmapSizes[4];		/* 各種パディングオプションに依存するビットマップデータのサイズ */
				/*  どのオプションが使われているかは (format&3) で指定している */
char bitmap_data[bitmapsizes[format&3]];	/* ビットマップデータ。format は以下のフラグを含む: */
				/* バイトオーダ (format&4 => 最上位バイトが先頭)*/
				/* ビットオーダ (format&8 => 最上位ビットが先頭) */
				/* 各グリフのビットマップの各列をどうパディングするか (format&3) */
				/*  0=>byte毎, 1=>short毎, 2=>int毎 */
				/* ビットが (byte, short, int の)どの単位で格納されるか  (format>>4)&3 */
				/*  0=>byte単位, 1=>short単位, 2=>int単位 */

エンコーディングテーブル

エンコーディングテーブルは PCF_BDF_ENCODINGS 型です。フォーマットは PCF_DEFAULT でなければなりません。

lsbint32 format; 		/* 常に最下位ビットが最初に格納される! */
int16 min_char_or_byte2;	/* XFontStruct のとおり */
int16 max_char_or_byte2;	/* XFontStruct のとおり */
int16 min_byte1;		/* XFontStruct のとおり */
int16 max_byte1;		/* XFontStruct のとおり */
int16 default_char;		/* XFontStruct のとおり */
int16 glyphindeces[(max_char_or_byte2-min_char_or_byte2+1)*(max_byte1-min_byte1+1)];
				/* 各符号位置に対応するグリフインデックス */
				/* 値 0xffff は、その符号位置にグリフが存在しないことを表す */

1 バイトエンコーディングでは min_byte1==max_byte1==0 であり、符号位置の値は [min_char_or_byte2,max_char_or_byte2] の範囲に収まります。ある符号位置が値 encoding であるとき、対応するグリフインデックスは glyphindex[encoding-min_char_or_byte2] になります。

それ以外の場合、[min_byte1,max_byte1] は、2 バイトエンコーディングの 1 バイト目 (上位バイト) の取ることのできる値の範囲を指定し、一方 [min_char_or_byte2,max_char_or_byte2] が 2 バイト目の範囲を指定します。2 バイトエンコーディング (enc1, enc2) に対応するグリフインデックスは、glyph_index[(enc1-min_byte1)*(max_char_or_byte2-min_char_or_byte2+1)+enc2-min_char_or_byte2] になります。

すべてのグリフに文字符号を割り当てる必要はありません。すべての符号位置にグリフを割り当てる必要はありません。

スケーラブルな幅のテーブル

スケーラブルな幅のテーブルは PCF_SWIDTH です。フォーマットは PCF_DEFAULT でなければなりません。

lsbint32 format; 		/* 常に最下位ビットが最初に格納される! */
int32 glyph_count;		/* バイトオーダは format に依存する。メトリックの個数と同じになるべき */
int32 swidths[glyph_count];	/* ビットマップデータへのバイトオフセット */

スケーラブルな文字幅は、em ユニットで表した対応する PostScript 文字の幅 (em の 1/1000) です。

グリフ名テーブル

グリフ名テーブルは PCF_GLYPH_NAMES 型です。フォーマットは PCF_DEFAULT でなければなりません。

lsbint32 format; 		/* 常に最下位ビットが最初に格納される! */
int32 glyph_count;		/* バイトオーダは format に依存する。メトリックの個数と同じになるべき */
int32 offsets[glyph_count];	/* 文字列データへのバイトオフセット */
int32 string_size;
char string[string_size];

各文字につけられた PostScript 名です。


その他の情報源: