GlyphWiki logo
ナビゲーション
ヘルプ
検索

ツールボックス
他の言語
解説ノート編集履歴

GlyphWiki:KAGEデータ仕様

出典: フリーグリフデータベース『グリフウィキ(GlyphWiki)』

前書き

この文書はKAGEシステムにおいて字形の中間記述形式として使われているKAGEデータ(字形中間記述データ)に関して、現時点(2022年2月18日(金) 16:50)での技術的詳細をまとめたものです。この文書を公開する目的は2つあります:

  • 1. KAGEデータ形式に関する整理された情報を広く一般に提供するため。
  • 2. KAGEエンジンの実装詳細 (implementation details) とKAGEデータ形式の仕様との境目を明確にするため。

まず1.に関して、(Googleで検索する限りでは)最新のKAGEデータ形式に関して詳細に記述された資料はみつからないという現状があります。そのためKAGEエンジンやグリフエディタなどの周辺ツールのソースコードを読んで多くを推測せざるをえず、KAGEデータを利用するソフトウェアの開発に高い障壁を生じさせています。この障壁を取り除くため、筆者(利用者:twe)がKAGEエンジンのソースコードを読むなどし推測した内容を言語化して残しておくものです。したがって、本来の仕様(上地さんの博士論文に初期の仕様があるそうです)とは用語や解釈が違っている可能性があります。誤りのある場合は修正を歓迎します。

2.に関して、グリフウィキでは専ら https://github.com/kamichikoichi/kage-engine/ で公開されているKAGEエンジン(以降 kamichikoichi/kage-engine と呼びます)が使われているので、特に非漢字グリフについて、このKAGEエンジンの実装詳細に大きく依存するデータが多くあります。これは「特定の実装が仕様になっている」状態といえます。そのようなデータが増えていけば、複数のKAGEエンジンの実装の間で「こっちのエンジンでは正しく出力されるが、あっちのエンジンでは正しく出力されない」といったケースが増えていき、新しいKAGEエンジンの開発を妨げてしまうほか、既存のKAGEエンジンの修正をも難しくしてしまいます。この状況を打開する第一歩として、個々のデータが特定の実装詳細に依存しているかしていないかの明確な基準をこの文書で定めることにします。

  • 例. vertical-short-bar@6のような細長い線を実現するために、頭形状(や尾形状)の欄を1000以上の値にする手法が広く使われています。kamichikoichi/kage-engine では、縦画の太さを密集度に応じて自動調整する機能が備わっていて、その自動調整で求まった値を後段の処理のために一時保存する場所として頭形状の欄の1000の位を利用しています。よって、vertical-short-bar@6のようにそこに予め9などの値を入れておくと、後段の処理に対して自動調整で求まった値が9であるように見せかけることができ、異常に細い縦画が出力されます。この挙動は、「自動調整で求まった値を頭形状の欄の1000の位に保存している」という kamichikoichi/kage-engine の実装詳細に依存するものであり、他のKAGEエンジンはこのデータを解釈しない可能性があります。

  • 注. どこまでが仕様でどこからが実装詳細なのか、はどうしても主観的な判断になってしまいます。議論の余地がありそう(と筆者が勝手に思う)な点はなるべく 論点. から始まる注釈を付けておきます。

この文書は字形中間記述形式の詳細を記述するものですので、KAGEエンジン(で出力される画像)やグリフウィキ(で管理される他のデータ)の詳細にはあえて立ち入りません。

それから、この文書はあくまでも現時点での詳細を「まとめたもの」ですので、この文書の内容に完全に従うソフトウェア以外を認めない、ということではありませんし、そのような態度がとられることは望みません。また、詳細が変わればこの文書も適宜修正されるべきであり、これで仕様を固定したいというつもりはありません。

用語の定義

この文章を通して使われる用語を以下の通り定義します。

部品名
[“:”、“$”、改行文字]をいずれも含まない文字列
  • 参考. グリフウィキでは、グリフ名(+ バージョン指定)のみが使えるので、正規表現 /([a-z][a-z0-9-]{1,59}_)?[a-z][a-z0-9-]{4,59}(@[1-9][0-9]*)?/ にマッチする文字列となります(参照:GlyphWiki:グリフを登録する)。
データ行
[整数または部品名]からなる配列を区切り文字“:”で連結した文字列であって、#「データ行」節の要件を満たすもの
  • 論点. 「整数」は「実数」としてもよいかもしれません。kamichikoichi/kage-engine ではパースの段階で整数に丸められます。
(データ行Lの)
データ行L(を区切り文字“:”で連結する前の配列)を構成する個々の[整数または部品名]
KAGEデータ
データ行からなる配列
  • 参考. グリフウィキでは、API等では区切り文字“$”で連結した1つの文字列として表現され、編集画面では改行文字で連結した1つの文字列として表示されます。ここでは配列として統一的に扱います。
部品データベース
部品名をKAGEデータに対応付けるもの
(点P)の 座標
2次元平面上にある点Pの位置を表す2つの実数( x座標 , y座標 )の組。画面の右方向をx軸正の向き、下方向をy軸正の向きとします。
(筆画Sを)描画 する
筆画Sをもとに図形を画面上に生成すること
筆画図形
筆画を画面に描画して生成された図形
  • 注. 1つの筆画から複数の筆画図形が生成されることがあります。
(KAGEデータA0を)描画 する
KAGEデータA0をもとに#「KAGEデータの描画」節で述べる方法で図形を画面上に生成すること
処理系
KAGEデータを取り扱うソフトウェアやシステム
  • 注. 「処理系」が指し示すものにはKAGEエンジンだけでなく、グリフウィキやその他KAGEデータを活用するシステムも含まれます。

データ行

データ行は、筆画行、部品引用行、特殊行のいずれかです。

筆画行

筆画行 は1つ目の欄が整数「1」「2」「3」「4」「6」「7」のいずれかであるようなデータ行です。 1つの筆画行は1つの 筆画 を表現します。1つの筆画が漢字を手書きする際の1画に対応することもありますが、2つ以上の筆画の組み合わせが手書きの1画に対応する場合もあります。(#「CJK筆画とKAGEデータの筆画の対応表」節も参照してください。)

  • 例. ㇋(u31cb) は手書きでは通常1画で書きますが、KAGEデータでは4つの筆画の組み合わせで表現されています。
  • 注. どの筆画の組み合わせが手書きの1画に対応するかをKAGEデータから直接知ることはできません。また、手書きの1画に対応する複数の筆画行が連続してKAGEデータ内に現れる保証はありません。

筆画行を構成する欄はすべて整数であり、部品名を含みません。1つ目の欄の整数は筆画の 線種 を示します。また、欄の個数は線種によって次の表のとおりに決まります。

1つ目の欄線種欄の個数
1直線7
2曲線9
3折れ9
4乙線9
6複曲線11
7縦払い11

いずれの線種においても、2つ目の欄の整数は 頭形状 を、3つ目の欄の整数は 尾形状 を表します。頭形状と尾形状として現れうる整数値とその意味は線種ごとに異なります。 4つ目以降の欄の整数はすべて、筆画を構成する 制御点 の座標を表します。偶数番目(4, 6, 8, 10番目)の欄はx座標を、奇数番目(5, 7, 9, 11番目)の欄はy座標を表します。

筆画は、線種、頭形状、尾形状、制御点の配列、の4つ組で表されます。筆画を構成する制御点の座標の数値は(処理系依存の精度の)実数です。

  • 注. データ行に現れうる数値は整数ですから、筆画行が直接表す筆画の制御点の座標の数値は整数になります。しかし部品を展開(後述)すると部品に含まれる筆画が変形され、制御点の座標の数値が非整数になることがあります(処理系が小数をサポートする場合)。

最初の制御点を筆画の 始点 、最後の制御点を筆画の 終点 と呼びます。

線種によっては筆画の始点や終点が他の筆画に 接続 することがあります。接続には、始点や終点の座標が、他の筆画の始点や終点の座標と一致するもの( カド接続 )と、始点や終点が、他の筆画の始点から終点までの中間点(の近く)に位置するものがあります。

  • 例. 曰(u66f0) の中央の横画は、始点は左の縦画の中間点に接続していますが、終点はどの筆画にも接続していません。一方で、上と下の2本の横画は、始点・終点ともに縦画の始点・終点と座標が一致する形でカド接続しています。
  • 例. u4ebb-01の縦画の始点は左払いの中間点には接続していません。一方u4ebb-01-var-001の縦画の始点は左払いの中間点の近くに位置する形で接続しています。

筆画の頭形状や尾形状には、それぞれ始点や終点が接続していることを前提とするものがあります。しかしながら、どの筆画のどこに接続しているのかという情報はKAGEデータに直接は含まれていません。それどころか、他の筆画に接続していることの保証すらありません。

カド接続には、「左上角」「右上角」「左下角」「右下角」を構成するものがあります。これらは、「口」の四隅にある形態の角(┌、┐、└、┘)を指しており、この4つの形態を「口」の字における位置で区別しているものです。したがって、角が字の中でどの位置にあるかは角の名称と関係がありません。

  • 例. 爿(u723f) の左上には左下角があります。

また、「八屋根の右上角」という角もあります。これは 八(u516b-j) や八屋根(u516b-03)などに固有の形状の角で、横画の終点と右払いの始点で構成されます。

直線

線種が「直線」である筆画は2つの制御点を持ち、これら2つの制御点を結ぶまっすぐな線分を中心線とする図形を表現します。 特に、明朝体において直線的な中心線に対して始筆から終筆までほぼ一定の太さで肉付けされるもの、グループ:CJK筆画でいうとu31d0u31d1u31daや、u31c6u31d5u31d7u31d8のそれぞれの前半と後半などを表現します。

直線の筆画には 縦画 を表現するものと 横画 を表現するものがあります。2つの制御点の位置関係によって、次の通りに縦画と横画の区別が行われます。

  • 論点. この条件分岐は実装詳細である可能性があります。

  • 2つの制御点のx座標の差の絶対値が、y座標の差の絶対値以下であれば、縦画です。
  • 2つの制御点のx座標が異なり、y座標が等しいならば、横画です。
  • 2つの制御点のy座標が異なり、1つ目の制御点のx座標が2つ目の制御点のx座標より大きければ、縦画です。
  • 上のいずれにも当てはまらなければ、横画です。

同じ内容を別の観点で言い直すと、次のようになります。1つ目の制御点から見た2つ目の制御点の向きを求めたとき、それが画面の右向きとなす角 θ が 0° ≦ θ < 45° または θ = 180° を満たす場合に横画であり、そうでない場合は縦画です。

  • 注. 縦画と横画の区別は部品を展開したあとに行われるので、直線の筆画行を含む部品を引用したとき、その筆画行が縦画とみなされるか横画とみなされるかが、部品矩形の縦横比によって変わることがありえます。
    • 論点. この挙動も実装詳細である可能性があります。

横画を表現する直線筆画に現れうる頭形状は次の表の通りです。

2つ目の欄頭形状説明
0開放他のどの筆画にも接続していません。 例. 一(u4e00) の始点
2接続(横)他の筆画(縦画、[折れ、乙線]の前半、曲線、複曲線、縦払い)に接続しています。 例. 日(u65e5) の3つの横画の始点

  • 参考. kamichikoichi/kage-engine はこの2つの頭形状について全く同一の図形を生成します。そのため、グリフウィキ上のKAGEデータではこの2つが頻繁に混同されています。

横画を表現する直線筆画に現れうる尾形状は次の表の通りです。

3つ目の欄尾形状説明
0開放他のどの筆画にも接続していません。 例. 一(u4e00) の終点
2接続(横)他の筆画(縦画、[折れ、乙線]の前半、曲線、複曲線、縦払い)に接続しています。 例. 日(u65e5) の3つの横画の終点

縦画を表現する直線筆画に現れうる頭形状は次の表の通りです。

2つ目の欄頭形状説明
0開放他のどの筆画にも接続していません。 例. 丨(u4e28) の始点
32接続(縦)他の筆画(横画、[折れ、乙線]の後半、曲線、複曲線)の中間に接続しています。 例. 丁(u4e01) の縦画の始点、 乑(u4e51-g@5) の中央の縦画の始点
12左上カド1. 他の横画の始点に接続して、この横画と左上角を構成します。 例. 口(u53e3) の左の縦画の始点
2. 他の筆画([曲線、複曲線]、尾形状 = 左払い)の終点に接続して、この筆画と左上角を構成します。 例. 臼(u81fc) の左の縦画の始点
22右上カド他の横画の終点に接続して、この横画と右上角を構成します。 例. 口(u53e3) の右の縦画の始点

縦画を表現する直線筆画に現れうる尾形状は次の表の通りです。

3つ目の欄尾形状説明
0開放他のどの筆画にも接続していません。 例. 丨(u4e28) の終点
32接続(縦)他の筆画(横画、[折れ、乙線]の後半、曲線、複曲線)の中間に接続しています。 例. 土(u571f) の縦画の終点、u571f-07@1の縦画の終点
13左下カド1. 他の横画の始点に接続して、この横画と左下角を構成します。 例. 口(u53e3) の左の縦画の終点
2. 他の筆画([曲線、複曲線]、頭形状 = 細入り、尾形状 = 止め)の始点に接続して、この筆画と左下角を構成します。 例. 女(u5973) の縦画の終点
23右下カド他の横画の終点に接続して、この横画と右下角を構成します。 例. 口(u53e3) の右の縦画の終点
4左ハネ左に跳ねます。他のどの筆画にも接続しません。 例. ㇚(u31da) の終点
313左下zh用旧他の横画の始点に接続して、この横画と左下角を構成します。台湾の国字標準字体などでは、手書きしたときに縦画と横画を一続きで書く左下角と、2画以上に分けて書く左下角とでデザインに差異を設けており、この差異を再現したい場合に、前者の左下角に使用されます。 例. u7259-tの左上の縦画の終点
413左下zh用新1. 他の横画の始点に接続して、この横画と左下角を構成します。中国大陸で使われる宋体では、手書きしたときに縦画と横画を一続きで書く左下角と、2画以上に分けて書く左下角とでデザインに差異を設けており、この差異を再現したい場合に、前者の左下角に使用されます。 例. u7259-gの左上の縦画の終点
2. 他の筆画([曲線、複曲線]、頭形状 = 接続、尾形状 = 左払い)の始点に接続して、この曲線と右上に跳ね上げる左下角を構成します。 例. u8ba0-01@9の縦画の終点
24右下H/T他の横画の終点に接続して、この横画と右下角を構成します。台湾の国字標準字体などでは、筆写体で横画が右に突き出る右下角と、縦画が下に突き出る右下角とでデザインに差異を設けており、この差異を再現したい場合に、前者の右下角に使用されます。 例. 回(u56de-t) の右から2つ目の縦画の終点

  • 参考. 「左下zh用旧」「左下zh用新」の名前はグリフエディタで用いられてきた用語で、元来「313: 左下GT用」が両方の役割を兼ねていましたが、この2つの尾形状を区別する必要が生じたため「413: 左下zh用新」が新設されると同時に「313: 左下GT用」が「313: 左下zh用旧」に改名されたことに由来します。

  • 論点. 「左下zh用新」尾形状は1.が本来の用法であり、2.の用法は本来想定されていない可能性がありますが、グリフウィキでは2.も広く使われています。

曲線

線種が「曲線」である筆画は3つの制御点を持ち、これら3つの制御点で定まる2次ベジエ曲線を中心線とする図形を表現します。 グループ:CJK筆画の中でいうと、u31c0u31c1u31c2u31c3u31cfu31d2u31d4や、u31c7u31c9u31cau31cbu31ccu31d6u31d9u31ddu31e1の末尾、u31dbの前半と後半を表現します。

  • 注. ベジエ曲線の性質により中心線は、両端の制御点を必ず通過しますが、中間の制御点は通過するとは限りません。

中心線がほぼ直線的になるものであっても、明朝体において始筆と終筆の間で太さが変化するものは「直線」筆画では表現できず、代わりに「曲線」筆画で表現されます。

  • 例. u91cd-01の最も上の「㇒」や最も下の「㇀」はほぼ直線的な中心線を持ちますが、どちらも「曲線」筆画で表現されます。

曲線筆画に現れうる頭形状は次の表の通りです。

2つ目の欄頭形状説明
0開放他のどの筆画にも接続していません。 例. 亻(u4ebb) の左払いの始点、 弋(u5f0b) の2画目の始点
32接続1. 他の筆画の中間に接続しています。 例. 丆(u4e06) の左払いの始点
2. 他の縦画(尾形状 = 左下zh用新)の終点に接続して、この縦画と右上に跳ね上げる左下角を構成します。 例. u8ba0-01@9の左下の始点
12左上カド他の横画の始点に接続して、この横画と左上角を構成します。 例. 望(u671b-j@2) の右上「月」部分の左払いの始点
22右上カド他の横画の終点に接続して、この横画と右上角を構成します。 例. ㇇(u31c7) 𠃌(u200cc-jv) u4e59-05の後半の始点
7細入り1. 他のどの筆画にも接続していないか、他の筆画の中間に接続しています。右払い、止め、左ハネのいずれかの尾形状と組み合わせます。 例. ㇏(u31cf) ㇔(u31d4) ㇁(u31c1) の始点
2. 他の縦画の終点に接続して、この縦画と左下角を構成します。止めの尾形状と組み合わせます。 例. 女(u5973) の止めの始点
27屋根付き細入り他の横画の終点に接続して、この横画と八屋根の右上角を構成します。 例. 乁(u4e41-j) の後半の始点

  • 注. 頭形状「開放」「接続」「左上カド」「右上カド」は明朝体において始筆が太くデザインされる箇所で使われます。一方で「細入り」「屋根付き細入り」は始筆が細くデザインされる箇所で使われます。

  • 論点. グリフウィキのデータには、2つ目の欄が整数「2」になっているものが比較的古くに登録されたものを中心に多くあります。ほとんどが整数「32」(頭形状 = 接続)と読み替えて問題がないと思われます。これについての歴史的経緯は不明です。

曲線筆画に現れうる尾形状は次の表の通りです。

3つ目の欄尾形状説明
7左払い1. 左下へまたは右上へ払う終筆です。他のどの筆画にも接続していません。 例. 亻(u4ebb) の左払いの終点、u571f-07@1の右下の終点
2. 他の縦画の始点に接続して、この縦画と左上角を構成します。 例. 臼(u81fc) の左上の左払いの終点
0右払い右下へ払う終筆です。他のどの筆画にも接続しません。 例. ㇏(u31cf) の終点
8止め止めの終筆です。他のどの筆画にも接続しません。 例. ㇔(u31d4) の終点
4左ハネ左に跳ねます。他のどの筆画にも接続しません。 例. ㇁(u31c1) の終点
5右ハネ右上に跳ねます。他のどの筆画にも接続しません。 例. ㇂(u31c2) の終点

  • 注. 尾形状「右払い」「止め」「左ハネ」「右ハネ」は明朝体において終筆が太くデザインされる箇所で使われます。一方で「左払い」は終筆が細くデザインされる箇所で使われます。したがって、 ㇀(u31c0) は左から右に書きますが、明朝体で終筆が細くデザインされるので、尾形状は「左払い」になります。

曲線筆画の頭形状と尾形状とその意味は、次の組み合わせでしか出現できません。

  • 注. この制約は明朝体において始筆と終筆のデザインの組み合わせが限られていることに由来します。

頭形状尾形状
0: 開放7: 左払い 亻(u4ebb) の左払い、u571f-07@1の下
0: 開放5: 右ハネ 弋(u5f0b) の2画目
32: 接続7: 左払い 丆(u4e06) の左払い、u8ba0-01@9の左下
32: 接続4: 左ハネu6210-04-var-001@1の内部
32: 接続5: 右ハネ 民(u6c11-j@4) の最後の画
12: 左上カド7: 左払い 望(u671b-j@2) の右上「月」部分の左払い
22: 右上カド7: 左払い ㇇(u31c7) の後半
22: 右上カド4: 左ハネ 𠃌(u200cc-jv) の後半
22: 右上カド5: 右ハネu4e59-05の後半
7: 細入り0: 右払い ㇏(u31cf)
7: 細入り8: 止め ㇔(u31d4)
7: 細入り4: 左ハネ ㇁(u31c1)
27: 屋根付き細入り0: 右払い 乁(u4e41-j) の後半

折れ

線種が「折れ」である筆画は3つの制御点を持ち、これら3つの制御点を順に結ぶ、2つの線分からなる折れ線を中心線とする図形を表現します。 典型的には、1つ目の制御点の下に2つ目の制御点が、2つ目の制御点の右に3つ目の制御点が並ぶことで、 ㇄(u31c4) ㇟(u31df) のような筆画を表現します。

直線の筆画2つが構成する左下角が、明朝体において太い縦棒と細い横棒の組み合わせでデザインされる図形 ㇗(u31d7) 匚(u531a) を表現するのに対して、折れの筆画は、縦棒と横棒が太さを大きく変えずカーブを描いてつながる図形 ㇄(u31c4) 匸(u5338) を表現します。

折れ筆画に現れうる頭形状とその意味は、縦画を表現する「直線」筆画と共通です。

折れ筆画に現れうる尾形状は次の表の通りです。

3つ目の欄尾形状説明
0開放他のどの筆画にも接続していません。 例. 匸(u5338) の右下の終点
5上ハネ右上に跳ねます。他のどの筆画にも接続しません。 例. 乚(u4e5a) の終点
32接続他の筆画(縦画、[折れ、乙線]の前半、曲線、複曲線、縦払い)に接続しています。 例. u56db-var-001の内部右側の終点

乙線

線種が「乙線」である筆画は3つの制御点を持ち、1つ目の制御点から出発して2つ目の制御点の方向へまっすぐ向かい、途中でなめらかなカーブを描きながら方向を変え、3つ目の制御点へ2つ目の制御点の方向からまっすぐ至る中心線をもつ図形を表現します。途中で描くカーブの形状は処理系依存です。 乙(u4e59)u6c17-05などで使われます。

  • 注. 折れ筆画と異なり、通常、中心線は2つ目の制御点を通りません。

乙線筆画に現れうる頭形状は次の表の通りです。

2つ目の欄頭形状説明
0開放他のどの筆画にも接続していません。
22右上カド他の横画の終点に接続して、この横画と右上角を構成します。 例. 乙(u4e59) の右上

乙線筆画に現れうる尾形状は次の表の通りです。

3つ目の欄尾形状説明
0開放他のどの筆画にも接続していません。
5上ハネ右上に跳ねます。他のどの筆画にも接続しません。 例. 乙(u4e59) の右下の終点

複曲線

線種が「複曲線」である筆画は4つの制御点を持ち、これら4つの制御点で定まる3次ベジエ曲線を中心線とする図形を表現します。制御点の少ない「曲線」筆画では表現しきれない場合に利用されます。

現れうる頭形状と尾形状とその組み合わせ、意味は「曲線」筆画と共通です。

縦払い

線種が「縦払い」である筆画は4つの制御点を持ち、1つ目と2つ目の制御点を結ぶまっすぐな線分に、2〜4つ目の制御点で定まる2次ベジエ曲線を続けた曲線を中心線とする図形を表現します。典型的には、1〜3つ目の制御点は縦一直線に並び、 ㇓(u31d3) のような筆画を表現します。

縦払い筆画に現れうる頭形状とその意味は、縦画を表現する「直線」筆画と共通です。

縦払い筆画に現れうる尾形状は次の表の通りです。

3つ目の欄尾形状説明
7左払い他のどの筆画にも接続していません。 例. 丿(u4e3f) の終点

部品引用行

部品引用行 は1つ目の欄が整数「99」であるようなデータ行です。 他の部品に含まれる筆画を、後述の「展開」操作で述べる変形を行って配置することを表します。

部品引用行には8個の欄で構成されるものと11個の欄で構成されるものがあります。いずれの場合も、8つ目の欄は部品名で、1つ目〜7つ目の欄はすべて整数です。11個の欄がある場合は、10個目と11個目の欄はどちらも整数です。

4つ目〜7つ目の欄は、展開操作のパラメータ 部品矩形 を指定します。4つ目と5つ目の欄が部品矩形の左上のx座標とy座標をそれぞれ表し、6つ目と7つ目の欄が部品矩形の右下のx座標とy座標をそれぞれ表します。

2つ目と3つ目の欄は、展開操作のパラメータ 点D のx座標とy座標を指定します。点Dのx座標が100より大きい場合は、この部品引用行に11個の欄がなければならず、その10個目と11個目の欄が展開操作のパラメータ 点S のx座標とy座標を指定します。点Dのx座標が100以下の場合は、点Sの座標は(0, 0)になります。

  • 注. 9つ目の欄の内容は規定されていません。

  • 参考. グリフウィキでは“99:0:0:0:0:200:200:[部品名]”の形式の単一の部品引用行のみからなるKAGEデータをもつグリフを「エイリアス」と呼び、特殊な取り扱いをしています。

部品の展開

部品を 展開 する、もしくは部品引用行を展開するとは、 部品名部品矩形点D点S をもつ部品引用行に対して次の操作を行い、[筆画または図形変形命令]からなる配列 A を得ることです。

  • 1. 空の配列を作り、これを A とおきます。
  • 2. 部品データベースを用いて 部品名 に対応するKAGEデータを取得して、これに含まれる各データ行 L について、順に次の操作を行います。
    • a. もし L が筆画行ならば、L が表す筆画を A の末尾に追加します。
    • b. そうでなくて、もし L が特殊行であって、L が図形変形命令を表すならば、L が表す図形変形命令を A の末尾に追加します。
    • c. そうでなくて、もし L が部品引用行であれば、[L を展開して得られた配列]を構成する各[筆画または図形変形命令]を順に A の末尾に追加します。
  • 注. ステップ3.から7.まではストレッチ機能とよばれる機能の説明です。点S と 点D の座標がともに(0, 0)である場合はこれらを飛ばしてステップ8.に進んでも影響がありません。
  • 3. A に含まれる[筆画または図形変形命令]のうち筆画だけを抽出し、それらのすべての制御点を含む最小の矩形を求め、これを 外接矩形 (bounding rectangle) と呼びます。
    • 論点. A に筆画が含まれない場合に外接矩形をどうするか、定義されていません。
  • 4. 点S を (+100, +100) だけ平行移動した点を 点S′ とおきます。
  • 5. もし、点D のx座標が100より大きいならば、点D を (−100, +100) だけ平行移動した点を 点D′ とおきます。
  • 6. そうでなければ、点D を (+100, +100) だけ平行移動した点を 点D′ とおきます。
  • 7. A に含まれる各[筆画または図形変形命令] E について、E の各制御点 P に次の操作を行います。
    • a. もし P のx座標が 点S′ のx座標より小さいならば、[[外接矩形の左端のx座標と P のx座標の差]と[点S′ のx座標と P のx座標の差]の比]が[[外接矩形の左端のx座標と x′ の差]と[点D′ のx座標と x′ の差]の比]と等しくなるような実数 x′ を求めます。
    • b. そうでなくて、もし P のx座標が 点S′ のx座標より大きいならば、[[外接矩形の右端のx座標と P のx座標の差]と[点S′ のx座標と P のx座標の差]の比]が[[外接矩形の右端のx座標と x′ の差]と[点D′ のx座標と x′ の差]の比]と等しくなるような実数 x′ を求めます。
    • c. そうでなければ、点D′ のx座標を x′ とおきます。
    • d. もし P のy座標が 点S′ のy座標より小さいならば、[[外接矩形の上端のy座標と P のy座標の差]と[点S′ のy座標と P のy座標の差]の比]が[[外接矩形の上端のy座標と y′ の差]と[点D′ のy座標と y′ の差]の比]と等しくなるような実数 y′ を求めます。
    • e. そうでなくて、もし P のy座標が 点S′ のy座標より大きいならば、[[外接矩形の下端のy座標と P のy座標の差]と[点S′ のy座標と P のy座標の差]の比]が[[外接矩形の下端のy座標と y′ の差]と[点D′ のy座標と y′ の差]の比]と等しくなるような実数 y′ を求めます。
    • f. そうでなければ、点D′ のy座標を y′ とおきます。
    • g. E の制御点 P を点 (x′, y′) に変更します。
    • 注. 点S′ と 点D′ が外接矩形の内側にあるとき、この操作は次のような内容を指しています。点S′ を通る垂直線で外接矩形を左右に分割します。左右を合わせた矩形(= 外接矩形)の位置や大きさを変えないように[左側を拡大し右側を縮小]または[左側を縮小し右側を拡大]すれば、垂直線を 点D′ を通る垂直線に移すことができます。左右それぞれにある制御点を、この拡縮によって移る点に移動します。上下に関しても同様で、点S′ を通る水平線で外接矩形を上下に分割し、この水平線を 点D′ を通る水平線に移すような上下それぞれの拡縮で制御点を移動します。
  • 8. A に含まれる各[筆画または図形変形命令] E について、E の各制御点 P に次の操作を行います。
    • a. P のx座標を x とするとき、実数 x′ を x′ = x / 200 ×[部品矩形 の横幅]+[部品矩形 の左端のx座標]で定義します。
    • b. P のy座標を y とするとき、実数 y′ を y′ = y / 200 ×[部品矩形 の縦幅]+[部品矩形 の上端のy座標]で定義します。
    • c. E の制御点 P を点 (x′, y′) に変更します。
  • 9. A を返します。

  • 注. 典型的には個々の漢字が点(0, 0)を左上、点(200, 200)を右下とする矩形全体を埋めるようにデザインされます。部品がそのようにデザインされていれば、引用された部品は部品矩形を埋めるように展開されます。

  • 注. ストレッチ機能は、組み合わせる相手によって内側の比率が変わるような部品を、1つの部品で効率よく管理するための機能です。
    • 例. ufa66は右上の部品が複雑になるにつれu48ab-var-001@10のように左側の比率が小さく、右側(= 右払いの部分)の比率が大きくなります。これはufa66を引用するときに 点S′ の左に 点D′ が来るように展開パラメータを設定することで実現されます。

特殊行

特殊行 は1つ目の欄が整数「0」であるようなデータ行です。

図形変形命令

特殊行は2つ目の欄が整数「97」「98」「99」のいずれかであるならば、 図形変形命令 を表します。図形変形命令は、それまでに画面上に描画された筆画図形のうち特定の矩形に含まれるものを変形することを指示します。

  • 注. 部品の展開が「筆画」を変形する(= 制御点の座標を変更する)のに対して、図形変形命令は「筆画図形」を変形します。
  • 注. 図形変形命令はobuso-1633-jv 𢨋(u22a0b) のような奇妙なグリフを実現するための機能であり、通常の漢字を表すKAGEデータには出現しません。

図形変形命令を表す特殊行は、7つの欄からなります。2つ目と3つ目の欄は次の表の通りに図形変形命令の 変形種類 を指定します。

2つ目の欄3つ目の欄変形種類
整数「99」整数「1」回転90°
整数「99」整数「2」回転180°
整数「99」整数「3」回転270°
整数「98」整数「0」左右反転
整数「97」整数「0」上下反転

4つ目〜7つ目の欄が図形変形命令の 変形矩形 を指定します。4つ目と5つ目の欄が変形矩形の左上のx座標とy座標をそれぞれ表し、6つ目と7つ目の欄が変形矩形の右下のx座標とy座標をそれぞれ表します。

図形変形命令は、変形種類と変形矩形の組で表されます。

図形変形命令の 制御点 とは、その図形変形命令の変形矩形の左上と右下の2つの点を指します。

その他の特殊行

図形変形命令を表さない特殊行をどのように扱うかは、処理系に任されています。

  • 参考. グリフウィキでは次のようなものが使われています。 kamichikoichi/kage-engine はいずれのデータ行も無視します。
    • “0:0:0:0”
      • 1. 偏を表すデータ行と旁を表すデータ行の間などに入れ、漢字の構成とデータ行の対応を分かりやすくします。
      • 2. この単独の特殊行からなるKAGEデータを登録し、グリフデータが無いことを表します。(「白紙化グリフ」と呼ばれます。)
    • “0:-1:-1:-1”
      • この単独の特殊行からなるKAGEデータを登録し、空白のグリフであることを表します。 例. u0020
    • “0:1:0:[Dx]:[Dy]:[Sx]:[Sy]”
      • グリフエディタ向けAPIが返す応答で部品データの1つ目のデータ行として含まれ、部品のメタ情報に設定された「ストレッチ境界」データをグリフエディタに伝達します。

KAGEデータの描画

処理系がKAGEデータをもとに図形を生成するとき、個々の筆画からどのような図形を描画するかは処理系に任されています。そのため同一の筆画を、ある処理系は明朝体で描画し、別の処理系はゴシック体、また別の処理系は丸ゴシック体で描画し、……といったことが考えられます。

個々の筆画を画面に描画する(処理系依存の)方法が与えられたとき、データ行の配列であるKAGEデータ A0描画 する方法を次の通り定めます。

  • 1. 空の配列を作り、これを A とおきます。
  • 2. KAGEデータ A0 に含まれる各データ行 L について、順に次の操作を行います。
    • a. もし L が筆画行ならば、L が表す筆画を A の末尾に追加します。
    • b. そうでなくて、もし L が特殊行であって、L が図形変形命令を表すならば、L が表す図形変形命令を A の末尾に追加します。
    • c. そうでなくて、もし L が部品引用行であれば、[L を展開して得られた配列]を構成する各[筆画または図形変形命令]を順に A の末尾に追加します。
  • 3. 配列 A に含まれる各[筆画または図形変形命令] E について、順に次の操作を行います。
    • a. もし E が筆画ならば、 E を処理系依存の方法で画面に描画します。
    • b. そうでなければ、これまで画面に描画された筆画図形のうち、 E の変形矩形に完全に収まるものすべてについて、E の変形種類に応じて次の変形を施します。
      • i. もし変形種類が「左右反転」ならば、変形矩形の中心を通るような垂直線に関して左右反転します。
      • ii. もし変形種類が「上下反転」ならば、変形矩形の中心を通るような水平線に関して上下反転します。
      • iii. もし変形種類が「回転90°」ならば、変形矩形の中心に関して反時計回りに90°回転します。
      • iv. もし変形種類が「回転180°」ならば、変形矩形の中心に関して反時計回りに180°回転します。
      • v. もし変形種類が「回転270°」ならば、変形矩形の中心に関して反時計回りに270°回転します。

  • 注. 図形変形命令はそれまでに描画された図形にのみ変形を施すので、データ行を入れ替える操作はKAGEデータを描画した結果の図形に影響する場合があります。
  • 注. 図形変形命令の変形種類が「回転90°」または「回転270°」で、変形矩形が正方形でない場合、回転した筆画図形が変形矩形に収まらない可能性があります。

CJK筆画とKAGEデータの筆画の対応表

Unicode仕様書のAppendix F: Documentation of CJK Strokesに記載されるStrokeと、KAGEデータで表される筆画との対応を表にしたものです。

  • 注. 実際にグリフウィキ上で登録されているデータも参照してください。

StrokeVariantAcronym筆画
u31d0H直線(横画)
u31c0T曲線、複曲線(頭形状 = 開放、尾形状 = 左払い)
u31d1S直線(縦画)
u31daSG直線(縦画、尾形状 = 左ハネ)
u31d2P曲線、複曲線(尾形状 = 左払い)
u31d3SP縦払い
u31d4u4e36-var-001D曲線、複曲線(頭形状 = 細入り、尾形状 = 止め)
u31cfN曲線、複曲線(頭形状 = 細入り、尾形状 = 右払い)
u4e40-j曲線、複曲線(頭形状 = 開放、尾形状 = 左払い) + 曲線、複曲線(頭形状 = 細入り、尾形状 = 右払い)T + N
u4e40-04-var-001u4e40-jTN曲線、複曲線(頭形状 = 開放、尾形状 = 左払い) + 曲線、複曲線(頭形状 = 細入り、尾形状 = 右払い)T + N
u4e41-j直線(横画、尾形状 = 接続(横)) + 曲線、複曲線(頭形状 = 屋根付き細入り、尾形状 = 右払い)H + N
u31d5HZ直線(横画、尾形状 = 接続(横)) + 直線(縦画、頭形状 = 右上カド)H + S
u31c7HP直線(横画、尾形状 = 接続(横)) + 曲線、複曲線(頭形状 = 右上カド、尾形状 = 左払い)H + P
u200cd-var-001直線(横画、尾形状 = 接続(横)) + 直線(縦画、頭形状 = 右上カド)H + S
u31d6HG直線(横画、尾形状 = 接続(横)) + 曲線、複曲線(頭形状 = 右上カド、尾形状 = 左払い)H + P
u31d7u200cb-jv@2SZ直線(縦画、尾形状 = 左下カドまたは左下zh用新または左下zh用旧) + 直線(横画、頭形状 = 接続(横))S + H
u31d8SWZ直線(縦画、尾形状 = 右下カド) + 直線(横画、尾形状 = 接続(横))
論点. 横画の始点でなく終点をカド接続させると、筆画が運筆と反対向きになります。
S + H
u31c4SW折れ(尾形状 = 止めまたは接続)
u31d9ST直線(縦画、尾形状 = 接続) + 曲線、複曲線(頭形状 = 開放、尾形状 = 左払い)S + T
u2010c-g直線(縦画、尾形状 = 左下zh用新) + 曲線、複曲線(頭形状 = 接続、尾形状 = 左払い)S + T
u200cb-var-003PZ曲線、複曲線(尾形状 = 左払い) + 曲線、複曲線(頭形状 = 開放、尾形状 = 左払い)P + T
u200cb-jv@2直線(縦画、尾形状 = 左下カドまたは左下zh用新または左下zh用旧) + 直線(横画、頭形状 = 接続(横))S + H
u31dbPD曲線、複曲線(尾形状 = 左払い) + 曲線、複曲線(頭形状 = 細入り、尾形状 = 止め)P + D
u5973の1画目)直線(縦画、尾形状 = 左下カド) + 曲線、複曲線(頭形状 = 細入り、尾形状 = 止め)S + D
u31e2PG
u31c1WG曲線、複曲線(頭形状 = 細入り、尾形状 = 左ハネ)
u31c2XG曲線、複曲線(頭形状 = 開放、尾形状 = 右ハネ)
u31c3BXG
u31df折れ(尾形状 = 上ハネ)SWG
u31c5HZZ直線(横画、尾形状 = 接続(横)) + 直線(縦画、頭形状 = 右上カド、尾形状 = 左下カドまたは左下zh用新または左下zh用旧) + 直線(横画、頭形状 = 接続(横))H + S + H
u31cdHZW直線(横画、尾形状 = 接続(横)) + 折れ(頭形状 = 右上カド、尾形状 = 止めまたは接続)H + SW
u31caHZT直線(横画、尾形状 = 接続(横)) + 直線(縦画、頭形状 = 右上カド、尾形状 = 接続) + 曲線、複曲線(頭形状 = 開放、尾形状 = 左払い)H + S + T
u31ca-g直線(横画、尾形状 = 接続(横)) + 直線(縦画、頭形状 = 右上カド、尾形状 = 左下zh用新) + 曲線、複曲線(頭形状 = 接続、尾形状 = 左払い)H + S + T
u200cc-jvHZG直線(横画、尾形状 = 接続(横)) + 曲線、複曲線(頭形状 = 右上カド、尾形状 = 左ハネ)H + (?)
u200cc-itaiji-001直線(横画、尾形状 = 接続(横)) + 直線(縦画、頭形状 = 右上カド、尾形状 = 左ハネ)H + SG
u31c8HZWG直線(横画、尾形状 = 接続(横)) + 折れ(頭形状 = 右上カド、尾形状 = 上ハネ)H + SWG
u4e59-05直線(横画、尾形状 = 接続(横)) + 曲線、複曲線(頭形状 = 右上カド、尾形状 = 右ハネ)H + XG
u31deSZZ直線(縦画、尾形状 = 左下カドまたは左下zh用新または左下zh用旧) + 直線(横画、頭形状 = 接続(横)、尾形状 = 接続(横)) + 直線(縦画、頭形状 = 右上カド)S + H + S
u200d1-var-003直線(縦画、尾形状 = 左下カドまたは左下zh用新または左下zh用旧) + 直線(横画、頭形状 = 接続(横)、尾形状 = 接続(横)) + 曲線、複曲線(頭形状 = 右上カド、尾形状 = 左払い)S + H + P
u31dfSWG折れ(尾形状 = 上ハネ)
u31ceHZZZ直線(横画、尾形状 = 接続(横)) + 直線(縦画、頭形状 = 右上カド、尾形状 = 左下カドまたは左下zh用新または左下zh用旧) + 直線(横画、頭形状 = 接続(横)、尾形状 = 接続(横)) + 直線(縦画、頭形状 = 右上カド)H + S + H + S
u31cbHZZP直線(横画、尾形状 = 接続(横)) + 直線(縦画、頭形状 = 右上カド、尾形状 = 左下カドまたは左下zh用新または左下zh用旧) + 直線(横画、頭形状 = 接続(横)、尾形状 = 接続(横)) + 曲線、複曲線(頭形状 = 右上カド、尾形状 = 左払い)H + S + H + P
u31e0HXWG直線(横画、尾形状 = 接続(横)) + 乙線(頭形状 = 右上カド、尾形状 = 上ハネ)H + (?)
u31ccHPWG直線(横画、尾形状 = 接続(横)) + 曲線、複曲線(頭形状 = 右上カド、尾形状 = 左払い) + 曲線、複曲線(頭形状 = 細入り、尾形状 = 左ハネ)H + P + WG
u31c9SZWG直線(縦画、尾形状 = 左下カドまたは左下zh用新または左下zh用旧) + 直線(横画、頭形状 = 接続(横)、尾形状 = 接続(横)) + 曲線、複曲線(頭形状 = 右上カド、尾形状 = 左ハネ)S + H + (?)
u31e1HZZZG直線(横画、尾形状 = 接続(横)) + 直線(縦画、頭形状 = 右上カド、尾形状 = 左下カドまたは左下zh用新または左下zh用旧) + 直線(横画、頭形状 = 接続(横)、尾形状 = 接続(横)) + 直線(縦画、頭形状 = 右上カド、尾形状 = 左ハネ)H + S + H + (?)
u31e3Q

その他特殊な例:

  • 注. これらは、明朝体に固有のデザインを、KAGEデータの筆画を組み合わせて実現したもので、他の書体(ゴシック体など)の図形の生成には向かないかもしれません。

  • 冫(u51ab) 氵(u6c35) の下: 曲線、複曲線(頭形状 = 細入り、尾形状 = 止め) + 曲線、複曲線(頭形状 = 接続、尾形状 = 左払い) (D + T)
  • 冖(u5196) : 曲線、複曲線(頭形状 = 細入り、尾形状 = 止め) + 直線(横画、頭形状 = 接続(横)、尾形状 = 接続(横)) + 曲線、複曲線(頭形状 = 右上カド、尾形状 = 左払い) (D + (HG) = D + H + P)

参考: 仕様に則らないグリフウィキ上の漢字グリフ

グリフウィキに登録された漢字のKAGEデータで広く使われている手法のうち、kamichikoichi/kage-engine の実装詳細に依存するものであり、他の処理系は同じようには解釈しない可能性があるものを列挙します。

  • 注. この節に挙げる手法は「バッドノウハウ」であり、グリフを作成する際は可能であれば避けるべきものです。
  • 注. 筆者の目についたものを挙げたものであり、これらがすべてではありません。

  • 筆画行の頭形状や尾形状の欄が100以上の整数であるもの(縦画の尾形状「313: 左下zh用旧」と「413: 左下zh用新」を除きます)。
    • 通常より細い線を実現するために使われています。 例. u32393-t@2の左ハネを含む筆画
    • 頭形状が本来「接続」である[曲線または複曲線]の始筆を水平にするためにも使われています。 例. u27c28-04@6の1画目
    • kamichikoichi/kage-engine では、太さなどの自動調節や接続判定の結果を頭形状や尾形状の欄の整数の100の位以上に保存しており、これを予め0以外の値に設定しておくことで細い線を出力したり水平な始筆を出力したりすることができます。
    • もし処理系が十分賢く、筆画が込み入るところを自動で細くしたり、近接する横画を検出して自動で水平にしたりしていれば、このような細工の大半は不要になります。
  • データ行の1つ目の欄が100以上の整数であるもの。
    • 太さの自動調節を免れ、手動で調節した太さ(または調節されていない状態の太さ)の線を実現するために使われています。 例. u98a8-02@2
    • kamichikoichi/kage-engine では太さなどの自動調節では1つ目の欄の整数を(そのまま)見て調節対象の筆画を選んでいますが、筆画の描画処理では1つ目の欄の整数の10の位以下のみを見て筆画の種類を決定しています。このため、100の位以上に0でない値を付け加えることで、自動調節の影響を受けない筆画が出力されます。
  • u53e3-v@4の右下など、カド接続を構成する縦画の頭形状や尾形状が「接続(縦)」であるもの。
  • u27c28-04@5のように、頭形状が「接続」である[曲線または複曲線]の始筆を水平にする目的でごく短い横画で「フタをする」もの。
    • kamichikoichi/kage-engine では、[曲線または複曲線]の頭形状が「接続」であって、その始点とy座標が等しい水平な横画に始点が接続しているならば、始筆の切り口が水平になります。しかし、u27c28-04@4のような形で部品化すると、部品引用行を展開したときに始点のy座標が非整数になってしまうことが多く、切り口が水平になる条件を満たせなくなります。そこで、部品の中に(見えない大きさの)水平な横画を含めることで確実に切り口を水平にすることができます。
    • 接続しているか(= 切り口を水平にするか)を処理系が判定する際に、y座標に多少の差(1未満など)があっても接続していると判定するようになれば「フタ」は不要になります。