Closed13

SDL で地道に…… (→ 縦書きを断念)

toyboot4etoyboot4e

縺ゥ縺薙↓霎ソ繧顔捩縺上%縺ィ繧ゅ↑縺� ノートです。

toyboot4etoyboot4e

SDL の TextInput で 1 文字ずつ打てるようにしてみた:

  • 変換確定直後のアルファベット入力を弾く?
  • IME 変換候補の表示位置変更

出だしから敗北プラン……

toyboot4etoyboot4e

fontdue をフォークして縦書き表示:

advance_height を使うように修正できたものの、縦書き用のグリフが必要みたいで圧倒的難題感……

  • 一部記号類や半角アルファベットは 90 度回転して表示する必要がある (レイアウトと UV)
  • 『へ』の位置が妙なのは計算ミス?
  • 句読点などは 縦書きのグリフが分かれている 気がする
toyboot4etoyboot4e

読んだ。縦書きのグリフを引っ張ってくればあっさり解決するかも?:

  • FreeType Tutorial / II
    TTF フォントは複数のテーブルデータを持っており、 vert などの GSUB テーブルに縦書きのグリフが入っている。アルファベットを横に倒したグリフも入っているらしいので気が楽!

  • 縦書きについて | Fontorge 講座
    グリフには字送りのデータが入っており、大まかな文字のレイアウトができる。

より正確に文字を描くためには字詰め (kerning) を考える必要があるが、 fontdue::layout は字詰めを考慮していない。さらに綺麗に文字を描くには hinting やサブピクセル?を考えるとか。

上図の『へ』の位置は、単に字送りの大きさが間違っている気がする……なぜ……

toyboot4etoyboot4e

縦書きの使い道にはカットシーンに添えるというのがあって、確か小島監督がやっていた?

日本語が読める人には意味が通じるし、他国の人にもちょっとカッコいいと思ってもらえる可能性はある。演出手段の 1 つとしても縦書きは欲しい!

toyboot4etoyboot4e

GSUB テーブル

フォントファイルの中身は複数のテーブルに分かれている。たとえば fontdue::layoutGlyphPosition::advanece_height は、 vmtx (縦書きメトリクス) テーブルの advance 値だった。

GSUB (グリフ置換) テーブルや GPOS (グリフ配置) テーブルも使えば、真の縦書きに近づけるかも。まずは GSUB テーブルの最も簡単な使い方を試したい。

LookupType 1: Single Substitution Subtable (specs)

GSUB テーブルは『かな』などの文字セット毎に? LookupList を持つ。この LookupList は 8 つのサブテーブルを持ち、 1 つ目のテーブルは単純なグリフの置換を行う。

たとえば三点リーダ … を縦書きのグリフに置き換えたら ︙ になる。そもそも unicode に縦書きグリフがあったのか……。このような置換が可能な GSUB テーブルを、 vert 機能を実装した GSUB テーブルであると言う (はず) 。

参考

試しに ttf-parserexamples/font-infomplus-1p-regular.ttf のメタデータを覗いてみた:

クリックで開閉
Family name: Some("Mplus 1p")
PostScript name: Some("Mplus1p-Regular")
Units per EM: 1000
Ascender: 1075
Descender: -320
Line gap: 90
Global bbox: Rect { x_min: -115, y_min: -343, x_max: 1403, y_max: 1075 }
Number of glyphs: 8662
Underline: Some(LineMetrics { position: -125, thickness: 50 })
X height: None
Weight: Normal
Width: Normal
Regular: true
Italic: false
Bold: false
Oblique: false
Strikeout: Some(LineMetrics { position: 258, thickness: 49 })
Subscript: Some(ScriptMetrics { x_size: 650, y_size: 700, x_offset: 0, y_offset: 140 })
Superscript: Some(ScriptMetrics { x_size: 650, y_size: 700, x_offset: 0, y_offset: 480 })
Variable: false
OpenType positioning:
  Scripts:
    DFLT
      No languages
    cyrl
      No languages
    grek
      No languages
    latn
      No languages
  Features:
    kern
    mark
    mkmk
OpenType substitution:
  Scripts:
    DFLT
      No languages
    cyrl
      No languages
    grek
      No languages
    hani
      No languages
    kana
      Languages:
        JAN
    latn
      No languages
  Features:
    ccmp
    liga
    vert
Elapsed: 271us

GSUB テーブルが vert フィーチャを持っていることが確認できた。 TODO: Script って何だろう……

天下の FreeType も GSUB テーブルには対応していないらしく、 ttf-parser / rustybuzz 様様という感じ。

備考: 手動レイアウトが必要なものは?

  • アルファベットを 90 度倒す?
    もしもフォントの GSUB テーブルにアルファベット用の縦書きグリフが無かった場合、手動でグリフを回転する必要があるかもしれない。

  • 縦書きの中に半角数字の横書きを混ぜる?


stone のスクリーンショット

ここで Apple の TextView か何かが IME 表示すら縦書きにする ことに気づいてしまった。 SDL のソースを読めば、 IME 関連のネイティブの API に当たりがつくかもしれないけれど、大変そう……。たとえエディタは作れなくても、縦書き表示さえできればゲーム制作に転用できると予防線を張っておく。

toyboot4etoyboot4e
  • GSUB から LookupType1 サブテーブル?を回収
  • 置換先の縦書きグリフをラスタライズ

縦を向こうとする感じはあるので、何かのミスかな

→ そういえば縦書きのグリフをラスタライズしていなかったので、横書きのグリフを縦書き文字の縦書きメトリクスで描いていたみたい。

toyboot4etoyboot4e

召還〜〜

この程度なら、 GSUB テーブルを見るのではなく codepoint のマッピングで十分だったかもしれない。。

要修正:

  • グリフ漏れ
    • () のラスタライズ
    • <> の縦書きグリフはそもそも存在しない?
  • 縦書きのメトリクス修正? (原点修正?)
toyboot4etoyboot4e

() の縦書きグリフが空欄として表示される件について。 mplus-1p-regular.ttfglyph-inspector で調べたところ、 () の縦書きグリフは存在しない (存在したとしても空のグリフ) であることが分かった。

空欄へのグリフ置換は罠では……それとも、僕が置換を間違えている?

別フォントでは () の縦書きグリフはあるが <> の縦書きグリフは無かった。こういった対照なグリフは、縦書きグリフが用意されていない場合が多く、 自分で縦書きにする必要がある 気がする。

縦書きのレイアウトはリッチテキストのレイアウトに通じるところがあるかもしれない。

toyboot4etoyboot4e
  • GSUB テーブルの最も簡単な使い方が分かった。
  • 縦書き表示は自力でグリフの回転等を扱う必要があり、リッチテキストに通じる所がある気がする。
  • 縦書きエディタは諦めた。結局 Firefox の textarea を使うのが現実的だと思う。 Chromium もダメだった (Web 入門スクラップの通り) 。

結局、 IME とか入力・変換中文字の扱いが 1 番難しいんじゃないかな。縦書き表示はリッチテキストに近いと思えばなんとかなりそうなので、人心地ついた気分。

それじゃあゲームに戻って、簡易リッチテキスト表示から始めようかな。

このスクラップは2022/03/15にクローズされました