グリフが全角かどうかの見極め (was Re: 明日のミーティング

ちょっとテクニカルになりそうなので、スレッド分けます。

On Tue, Apr 27, 2021 at 9:53 AM 木田泰夫 <kida@me.com> wrote:

> 結局、そのグリフが全角かどうか高速に見分ける方法があるか、にかかって来ますね。石井さん、ご存知ですか?
>

短い版:残念ながらありません。実装者観点から行くと、クラス分けとグリフ判別はフェーズが違うので
1.クラス分けフェーズでは、「全角『かも』しれない」文字コードは「調整可能」クラスに入れておく
2.調整段階で「ただし全角でなければ調整しない」 例外を入れる
と分かれている方が仕様どおりに実装しやすくなりますし、多様な実装方法に対応した仕様にもなりやすいかと思います。


長い版:
文字コードと書式(フォント、縦書きなど)の組み合わせから、グリフと幅を計算する作業を「shaping」「シェーピング」と呼びます。ここ10年ほどで使われるようになった、わりと新しめ(?)の言葉です。

今どきのOpenTypeはかなり多機能なので、これは結構重い作業で、文字中心のページであれば、ページ全体のレイアウトの20~30%程度をシェーピングで費やすため、ここを効率的に行うことは速度面からはとても大事なことになります。

コードポイントと設定言語から決め打ちで調整を計算するアプリのおおまかな手順としては
1.Unicodeからクラスを計算して、調整可能箇所を決める
2.シェーピングする
3.調整可能箇所のうち、 全角グリフのものを選んで、調整箇所を決める
4.決め打ちのテーブルに従って調整する
となります。1を2の後にやると、日本語以外の言語に影響が出ない、幅によってクラスを分けられる、などのポイントはありますが、そこは後で触れるので、一旦置いておいて。

しかし、フォントが調整用の情報を持っていて、調整時にそれを使うとなると、話が難しくなってきます。フォントの情報を使って幅を計算・調整するのは、それこそが「シェーピング」作業なので、シェーピングが終わった後に、シェーピングと同じことをする、ということになってしまいます。上のステップを書き直すと
4a.調整箇所にOpenType機能をオンにするよう指示して、2.シェーピングをやり直す
あるいは
4b.シェーピングに頼らず自分でフォント情報を読み込んで調整する

このうち、1と4aが重い作業です。2も重いですが、これは調整しない場合にも一回は必要なので割愛。また、4bも重いですが、シェーピングと同じことの一部を自前で計算するので、自前コードはある程度の局所最適化努力が可能です。4bの難しさは、どちらかというと、シェーピングでやれば数行で済む作業と同じことをするコードを書いて、速度最適化を施す、ということ、を大きな観点やメンテナンス上から「よし」とするかどうか、という点になるかと思います。うちのような、組版が製品の主軸でなく、グローバル対応が前提になるアプリでは、なかなか難しい条件であることは、木田さんならおわかりいただけるかと思います。

このため、1と4aをいかにうまく実行するかが速度面からは鍵になってきます。上にも少し書いたように、クラス分けを3で行えば、グリフ幅によって別クラスを割り振ることは可能ですが、1と3が分かれている方が実装の自由度が上がるため、工夫の余地が増えて、ありがたいです。

先日お話したフォントの中で調整をやらせるcontextual
spacingが速いのは、1、3、4aをフォント作成時に事前に計算しておいて、その計算結果をフォントに埋め込み、2.シェーピングが一度ですむようにしているからですが、この事前計算をする時に、やはり1、2、3のステップを踏みます。こういった工夫も含めて、実装の自由度を許すには、文字クラスと「全角かどうか」は分かれている方がありがたいと思います。

Received on Wednesday, 28 April 2021 05:28:00 UTC