このファイルは 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 名です。