character rendering

文字のレンダリング

[6] 文字レンダリングは、 単純に文字を並べていくだけに思えますが、 実は考えなければならないことがたくさんあって、 非常に複雑で難解な処理なのです。

文字とレンダリング

[16] 文字の連続のレンダリングが個別の文字 (グリフ) のレンダリングの連続とは異なることがあります。

[10] 文字と表現の記述
[8] 文字のレンダリング
[12] 文字の周辺

フォント依存文字

[1] フォント依存文字

OpenType の処理モデル

[35] cmap を参照する時点では、 文字列の転送・保管等に使う符号化方式 (いわゆる外部コード) ではなくフォント符号化を知っている必要があります。 Unicode の場合、 UTF-8 バイト列UTF-16 サロゲートペア等ではなく、 Unicode符号点の列です。

[36] cmap文字コード(列)からグリフIDへの写像です。 ほとんどの場合は1つの文字 (符号点) が入力ですが、 異体列は1つの異体列が入力となります。 従って cmap を引くには、 入力の文字列を (異体列とそれ以外の文字) の列に分解する必要があります。

[37] また、異体列から cmap を引いた出力は 「基底文字と同じグリフ」 という回答かもしれませんから、 基底文字符号点cmap をもう一度引かなければなりません。 (普通は同じフォントcmap基底文字を引けば適切なグリフIDが返ってくるはずですが、 データ構造的に保証はされていませんから、エラー処理が必要となります。)

[32] Windowsサロゲートペア, bidi, 用字系依存の shaping (文字前処理を含む。) を Uniscribe で実装し、 OpenType Layout によるグリフの置換と位置決定を OTLS で実装する、 という2段階構造になっているようです。

[30] Uniscribeアラビア文字, ヘブライ文字, タイ文字については、 古い OS が対応していた OpenType Layout 以前のフォントにも対応しています。 >>31

[34] 鏡像化cmap を参照する時点でも処理が必要です。 書字方向依存グリフ

[33] vert を使ったレンダリング縦書き対応していないフォントレンダリングには、 取得したグリフデータの回転が必要となります。 縦書きグリフ

[38] グリフ位置決定

[42] 機能については、 justification のために適当な長を実現すべく、 グリフの置き換えや位置調整を適用し直すことがあります。 JSTF

[51] SVG による SVG 字形データがあれば、それへの置き換えを行います。 これはグリフIDの列が決定した後で、 advance widthadvance height は変化しないはずとされています。 SVG 具体的にどのタイミングかまでは明らかではありませんが、 アンチエイリアス関係の処理よりは前でしょうか。 あるいは SVGグリフにはアンチエイリアス処理が適用できないとか、 通常グリフと同時処理はできないとか制約があったりするのでしょうか。

[56] 色フォント/絵文字グリフ選択と SVG の関係
  1. [53] variable font の処理
  2. [54] hinting
  3. [44] MERG の指定に従いグリフ列を併合します。
  4. [45] アンチエイリアシングの処理を適用します。

[52] SVGグリフへの置き換えやアニメーションによって bounding box が変化する可能性があります。 これが配置に影響するときは、再配置が必要になります。 SVG

[55] SVGグリフアニメーションすることがあります。 印刷時などのため、アニメーション有効、無効の2状態の入力が必要です。

OpenType Layout の処理モデル

[14] OpenType Layout フォントを使って文字を表示する文章処理クライアント (text-processing client) は、 次のようにして文字列からグリフ列を得るとされています。 >>13

  1. [15] フォントcmap に基づき、 文字符号列をグリフ索引 (glyph index) 列に変換します。
  2. [17] フォントGSUB に基づき、 グリフ列を編集します。
  3. [18] フォントGPOS BASE に基づき、 グリフ位置 (position) を決定します。
  4. [19] 設計座標 (design coordinates) (高解像度で装置非依存) で装置非依存改行 (line break) を決定します。
  5. [20] 利用者の指定がある場合、 フォントJSTF に基づき、 行揃え (justifies the lines) をします。
  6. [21] グリフラスター化し、 装置座標 (device coordinates) (出力装置の解像度に対応するもの) にグリフ群をレンダリングします。

[22] OpenType 仕様書ではこのうち最後の出力だけを OS の処理とし、他を文章処理クライアントの処理としています。 >>13 装置依存の処理かどうかで区分しているのでしょうか。 Windows の場合他の処理も OTLS を使って実装でき、 広い意味では全体が OS の範疇であります。 逆に出力がハードウェアでなく画像ファイル等なら全体が応用レベルで実装されていることもありそうです。

レンダリング処理と文字性の維持

[23] 文字列グリフ列に変換しレンダリングする一連の処理により、 異なる文字が同じグリフで表現されたり、 複数の文字合字グリフに置き換えられたり、 表示順論理順文字列の位置関係から入れ替わっていたりしますが、 多くの場合に元の文字との対応関係を保持し続ける必要があります。

[24] 例えば文字列の選択からのコピーを実現するためには、 選択したグリフ列から元の文字列が復元できる必要があります。

[25] 異なる文字列が同じグリフになったり、 文字コードがあっても表示には直接反映されなかったりもするので、 グリフの列だけを使って文字列を生成するのは困難で、 入力の文字と出力のグリフの対応関係を保持するのが一般的みたいです。
[29] PDF が作り方により、 または表示ソフトウェアの品質により、 コピペでおかしな文字列が生成されることがある、 というのはよく知られた問題です。

[27] bidishaping の処理では文字の順序が入れ替わって表示の順序が作られます。 関係性は相当複雑になるものの、元の文字との対応付けはできます。

[26] OpenType Layout では文章処理クライアントが文字グリフの関係を追跡し続けることになっています。 >>13 合字グリフに置き換えられて複数文字が1グリフにまとめられたりすることはあるものの、 対応付けを維持したままの GSUB による置換は容易に実現できます。

[28] OpenType フォント合字におけるキャレット位置の情報を持つことが出来ます。 複数の文字が1つのグリフにまとめられていても、 文字単位で選択範囲を指定することができます。 キャレット ただしそのような情報が欠けていることもありますし、 グリフが図形的に文字単位に分割できない場合もあります。 そのときは不自然な挙動になってしまいます。

[40] OpenType GPOS lookupType 5 (Mark-to-Ligature Attachment Positioning, MarkLigPos) は合字グリフ上の anchor point をいくつか指定できます。 マークグリフ配置に当たっては、 そのいずれかの anchor point を選ばなければなりません。 グリフ位置決定

[41] shaping engine による文字前処理や GSUB によるグリフの置き換えがあると、 合字グリフマークグリフの元になった基底文字結合文字の関係 (など) はグリフ列から読み取れなくなってしまうかもしれません。 しかし実装はその関係性を追跡しておかなければなりません (must) >>39基底文字合字グリフのどの部分に変化したかに応じて、 結合文字に由来するマークグリフをどの anchor point を使って配置するかを決定します。

動的なフォント変更

font-display, CSSアニメーション

セキュリティー

[4] 文字のセキュリティー参照。

[3] あるUNICODE文字がAppleデバイス上でアプリを破壊する――iOS、Mac、Watchの主要ソフトすべてに影響 | TechCrunch Japan (Taylor Hatmaker著, ) http://jp.techcrunch.com/2018/02/16/2018-02-15-iphone-text-bomb-ios-mac-crash-apple/

[5] #PS4 特定の文字列のメッセージを受け取るとクラッシュする事案が多数発生しているらしい…対処法はあるようなのでやってみて - Togetter () https://togetter.com/li/1276875

[7] AppleのOSをクラッシュさせる文字列がまた見つかる | スラド IT () https://it.srad.jp/story/20/04/25/2016238/

[49] Mac OS XとiOSで特定のアラビア語文字列を表示させるとクラッシュする問題が見つかる | スラド アップル, https://apple.srad.jp/story/13/09/03/0824238/

テスト

[2] unicode-org/text-rendering-tests: Test suite for text rendering () https://github.com/unicode-org/text-rendering-tests

関連

[9] レタリングとは違います。

メモ

[11] Text Rendering Hates You, , https://gankra.github.io/blah/text-hates-you/

[43] ケケモコソカメニハさんはTwitterを使っています: 「Qtさんフォールバックフォントを選ぶときに隣接する文字を考慮するらしく、こういうことが起きます。 スクリーンショットの状況はUbuntu Monoが◆を持っていないため。左の◆はDejaVu Sans Mono、aはUbuntu Mono、「あ」と右の◆はNoto Sans Mono CJK JP。 https://t.co/AKD9HfhYiJ」 / Twitter, , https://twitter.com/ytomino/status/1590051393716768768

[46] クメール文字が書けない - Helpfeel社のScrapboxを一部公開, https://scrapbox.io/nota-private-sample/%E3%82%AF%E3%83%A1%E3%83%BC%E3%83%AB%E6%96%87%E5%AD%97%E3%81%8C%E6%9B%B8%E3%81%91%E3%81%AA%E3%81%84

[47] 文字 (の情報システム上での表現) の知識がない技術者が設計すると >>46 のようなことが起きる。 欧米の技術者がシステムを設計するとアジア人が使えないものができるのと同じ原理。

[48] 書記素クラスターにうまく分割できればいいみたいな話になってるけど、それで語頭形とかの表示ちゃんとできてるんだろうか?

[50] Unicode はサービス拒否攻撃のリスク有り (#2767675) | iOSベータ版に「肌の色を指定できる」絵文字が登場 | スラド, https://srad.jp/comment/2767675