IBM Plex Sans JP で ExtraLight, Thin ウェイトを使うと Bold ウェイトになる

  1. 開発お疲れさまです。

    先日、PlemolJP というフォントをリリースしまして (https://github.com/yuru7/PlemolJP) 、Meryもいつも通り大活躍でした。やはりFontsフォルダ直読み込みの機能はフォントデバッグにおいて最高です。ありがとうございます。

    その最中に気付いたのですが、IBMから先日リリースされた IBM Plex Sans JP、ならびに PlemolJP でも、ExtraLight, Thin ウェイトが正しく読み込まれない事象が見られたため、ご報告します。
    太さからして、Bold ウェイトが読み込まれている気がします。

    # 再現手順

    1. IBM Plex Sans JP (OR PlemolJP) の全ウェイトをインストール
    2. Mery のフォント設定から "IBM Plex Sans JP Thin" を選択する

     |  yuko  |  返信
  2. ご報告ありがとうございます。

    PlemolJP、先日、ツイッターのほうで拝見しました。さすが、目の付け所がクールですね。これも HackGen のようにヒットしそう!なるほど、見やすい。そしてフォントのウェイトの選択肢の多さ。

    そんな重要ポイントで Mery のバグ…😱

    いただいた条件で現象を再現することができました。

    …が、ほんとに謎。対策についてはまだ何も分かっていません。

    DirectWrite がオンの状態だと Thin でも太字のようになっているようですね。また、DirectWrite がオフの状態だと、一応、細いのですが本来の細さではなさそうです。

    調査してみましたところ、どうやら Delphi の仕様とフォントの仕様、そして Windows の仕様が重なって発生しているような気がします。

    (1) Delphi の仕様

    これが一番厄介な気もしますが、Delphi は仕様上、フォントのウェイトが「Regular (400)」と「Bold (700)」の 2 つの概念しかありません。

    なので通常 (Regular) は IBM Plex Sans JP Thin をウェイト 400 で呼び出します。

    (2) フォントの仕様

    IBM Plex Sans JP Thin はウェイト 100 が「Regular」として設定されているのだと思います。(フォントについては詳しくないもので、これは間違っているかもしれません)

    (3) Windows (DirectWrite?) の仕様

    Regular のウェイトが 100 で作成されているフォントに対して、ウェイト 400 で呼び出すとなぜか Bold (700) が発動してしまいます。謎…

    Regular (200) の IBM Plex Sans JP ExtLt でも同様に Bold (700) になってしまいます。

    Regular (300) の IBM Plex Sans JP Light など、ウェイトが 200 より大きいものは大丈夫。

    ちなみに、「源真ゴシック ExtraLight (100)」と「源真ゴシック Light (200)」も同様にダメで、Bold (700) になってしまいました。

    ということで、Windows (DirectWrite?) としてはフォントに Regular として設定されているウェイトから 200 以上離れた数値、400 を指定すると Bold フォントが適用されてしまうのではないかと考えています。

    Regular のウェイトが 100 や 200 のフォントに対して、Delphi は仕様で Regular (400) を使うので、Windows はウェイトがフォントの Regular の値から 200 以上離れているから親切に「太字フォント適用したろ!」ってなって Bold になってるのではないかと推測しています。

    …が、以上は想像です。情報がまったく見つからず、詳細な原因や対策については検討もついていない状態です。

    以上、とりあえず現状の調査結果のご報告ですが、引き続き調査して行きたいと思いますので、もしお気づきの点などがございましたらご協力いただけると助かります。

     |  Kuro  |  返信
  3. > そんな重要ポイントで Mery のバグ…😱

    あまりマルチウェイトなフォントをテキストエディタに設定するってケースは少ないと思うので、見つかりづらい部分ですよね。

    実のところ、私もOS側・アプリ側でフォントがどう呼ばれるかってメカニズムをあまり理解していないのですが(結構、見よう見まねで作っているので…😅)、フォントの仕様についてはいくつかお伝えしておきたいと思います。

    > IBM Plex Sans JP Thin はウェイト 100 が「Regular」として設定されているのだと思います。

    これはご推察の通りだと思います。
    IBM Plex Sans JP を模倣して、そういう作りにしました。

    ウェイトに関連しそうなフォント内のメタ情報の設定箇所っていくつかあるのですが、その中でも関係しているかなと思うのが OS/2 (*1) と TTF名 (*2) です。

    *1 参考: https://docs.microsoft.com/en-us/typography/opentype/spec/os2
         ※「usWeightClass」項にスタイルの数値 (Thin なら100) を格納する
    *2 参考: https://docs.microsoft.com/en-us/typography/opentype/spec/name
         ※「Name IDs」項の Code 2 にスタイル名称 (Regular や Bold) を格納する

    下図は実際の PlemolJP Thin の設定です。1枚目がOS/2のウェイト設定、2枚目がTTF名の設定です。
    https://imgur.com/a/brgygQl

    ちなみに Regular の場合は以下のようになっています。
    https://imgur.com/a/hpWYTYy

    的を射ない情報ですが、なにかの参考になれば…。

     |  yuko  |  返信
  4. そういえば PlemolJP の紹介記事に Mery についての紹介も少し掲載してみたのですが、大丈夫でしょうか?
    もしご迷惑になるようでしたら削除しますので、言っていただければと思います。
    https://qiita.com/tawara_/items/0a7b8c50a48ea86b2d91#%E8%A1%A8%E7%A4%BA%E6%A4%9C%E8%A8%BC%E3%81%AB%E4%BE%BF%E5%88%A9%E3%81%AA%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF

     |  yuko  |  返信
  5. > あまりマルチウェイトなフォントをテキストエディタに設定するってケースは少ないと思うので、見つかりづらい部分ですよね。

    それに加えて GDI (DirectWrite オフ) だと、一応、それっぽく描画できているので余計に見つかりづらい気もしますね。

    言い訳っぽくなりますが、Microsoft 純正のワードパッドでも Thin は本来の細さが発揮できないようです。

    ちょっと太くなってしまい、装飾で太字を指定しても変化なし。Mery の GDI の挙動とまったく同じです。

    > 実のところ、私もOS側・アプリ側でフォントがどう呼ばれるかってメカニズムをあまり理解していないのですが(結構、見よう見まねで作っているので…😅)、フォントの仕様についてはいくつかお伝えしておきたいと思います。

    私も似たような感じで、逆にフォント側の仕組みについては知識がなくて…

    当時とは時代も変わってしまい、結合文字やらリガチャやらバリアブルフォントやら、エディター開発にフォントの知識が必須な時代となってしまったようで、苦戦を強いられております😅

    情報ありがとうございます。

    なるほど、ウェイトの部分ってサブファミリーっていうんですね。いただいた情報のおかげでググるキーワードのヒントになり、対策への手がかりがつかめました。

    GDI のほうは Delphi の仕様に足を引っ張られるので開発が難航しそうですが、DirectWrite のほうは対策を仕込めそうです。

    > そういえば PlemolJP の紹介記事に Mery についての紹介も少し掲載してみたのですが、大丈夫でしょうか?

    はい、大丈夫です。ご紹介いただきありがとうございます。むしろ、Thin が描画できないという問題でご迷惑をおかけしてしまうかもしれません😱

    インストール不要な一時フォント機能ですね、すっかり忘れていました。

    DirectWrite 対応でこれができるエディターって他にないような気がしますね。たぶん、ほとんど使われていない機能だと思いますがw

    本件につきましては引き続き調査していきますので、また何かお気づきの点などございましたらご協力いただけると幸いです。

     |  Kuro  |  返信
  6. > インストール不要な一時フォント機能ですね、すっかり忘れていました。

    ええーっ!w
    Meryのキラーコンテンツ的なものの1つだと思っていたのに!(フォント合成職人だけ?)

    Windowsのフォント管理の排他の仕組みがあまりよろしくないようで、上書きインストールし続けていると時折レジストリからは消えるけど実ファイルが残ることがあるんですよね…それが起きないだけでかなり助かっています。

    > 結合文字やらリガチャやらバリアブルフォントやら

    フォントだけでもよく新しい技術が出てくるものだなって感心してしまいますね。HackGenなどはfontforgeという無料のフォントツールを使って合成や調査をするのですが、もうバリアブルフォントとかになってくると無料ツールじゃ太刀打ちできなくなってくる気がします。でも、有料じゃなくっても綺麗で多くのグリフが入ったフォントが使えるようになったのは良いことですね。

    > 言い訳っぽくなりますが、Microsoft 純正のワードパッドでも Thin は本来の細さが発揮できないようです。
    > ちょっと太くなってしまい、装飾で太字を指定しても変化なし。Mery の GDI の挙動とまったく同じです。

    MeryのGDI設定で確認するのを忘れていました…。確かにGDI設定とワードパッドではThinの表示具合が変わりますね。

    GDIで見ると、Thin~ExtraLight ⇔ Light~Bold では文字幅まで変わってしまっていますね。
    そして Thin~ExtraLight では太字指定も効かなくなっていて、謎です…。

    時間があるときに OS/2 などの中身を見たりしてみたいと思います~

     |  yuko  |  返信
  7. > Meryのキラーコンテンツ的なものの1つだと思っていたのに!(フォント合成職人だけ?)

    もともと、学校や職場などの PC でフォントのインストールが制限されている環境のために開発した機能だったものですから。

    フリーソフトという性質上、そういった環境で使われることは少ないということもあってか、この機能についての評判は一度も聞いたことがありませんでした😭

    お役に立てたということで大変うれしく思います。

    > MeryのGDI設定で確認するのを忘れていました…。確かにGDI設定とワードパッドではThinの表示具合が変わりますね。

    これは恐らく IBM Plex Sans JP Thin をウェイト 400 で呼び出しているためだと思います。

    > そして Thin~ExtraLight では太字指定も効かなくなっていて、謎です…。

    フォントの仕組みは分からないのですが、太字ってウェイトに +300 かな?と予想しています。

    もしそうであれば、IBM Plex Sans JP Thin は Regular のウェイトが 100 なので、太字にするとウェイトが 400 ということになります。

    でもワードパッドや Delphi の仕様では Regular はウェイト 400 という前提で呼び出すので、IBM Plex Sans JP Thin は常に太字が呼び出されているのではないかと…。

    > 時間があるときに OS/2 などの中身を見たりしてみたいと思います~

    ご協力ありがとうございます。

    上記の予想で記載した太字の概念について、フォント側でそういった決まりがあるのか、アプリ側の話なのかちょっとわからないもので、もしご存じであれば教えていただきたいのですが…

    Windows の API では以下のような定義になっているのですが、

    FW_THIN = 100;
    FW_EXTRALIGHT = 200;
    FW_LIGHT = 300;
    FW_NORMAL = 400;
    FW_MEDIUM = 500;
    FW_SEMIBOLD = 600;
    FW_BOLD = 700;
    FW_EXTRABOLD = 800;
    FW_HEAVY = 900;

    IBM Plex Sans JP Thin の場合、Regular が 100 (FW_THIN) なら、太字を指定した場合のウェイトって +300 して 400 (FW_NORMAL) になるのが正しいのでしょうか。それとも "BOLD" の文字どおり 700 (FW_BOLD) になるのが正しいのでしょうか。

    通常のウェイト 100 に対して太字のウェイトが 700 というのも変な気がします。かといって太字は +300 という情報も特に見当たりませんし…😥

    本件、非常に難航しています。もしかすると、フォント設定ダイアログに「ウェイト」なる項目を新たに設けて、ユーザー側でウェイトを選択していただくような仕様になるかもしれません。(秀〇エディタさんがそうなってました)

    …これはこれでバリアブルフォントだとウェイトを自由に変えられるようになるので、アリといえばアリなのかもしれませんがw

     |  Kuro  |  返信
  8. > フリーソフトという性質上、そういった環境で使われることは少ないということもあってか、この機能についての評判は一度も聞いたことがありませんでした😭

    新たなソフトのインストールが厳しい環境だと、フリーソフトも一度定番が決まってしまうとそれが覆らないですもんね。(フリーソフトを入れちゃダメだけど、Lhaplusとサクラエディタは必ず入っているみたいな)
    私はあまり詳しくない同僚などにMeryの布教活動(?)をするときに、設定ファイルごと渡すとフォント設定も必要になるので、フォントを同梱して展開したりしてましたね。これまた「手軽に展開できていいなー」と思っていました。

    > IBM Plex Sans JP Thin の場合、Regular が 100 (FW_THIN) なら、太字を指定した場合のウェイトって +300 して 400 (FW_NORMAL) になるのが正しいのでしょうか。それとも "BOLD" の文字どおり 700 (FW_BOLD) になるのが正しいのでしょうか。

    回答を持ち合わせていないのですが、関係するかもしれない情報は共有しておきたいと思います。

    本来、「このフォントファミリー内において、これがRegular、これがBoldのファイルだ」という情報は、OS/2テーブル内の「fsSelection」という項目のビット値で定められています。(ウェイトとはまた違う話なのが、ややこしいですね…😅)

    先日お見せしたOS/2情報 ( https://docs.microsoft.com/en-us/typography/opentype/spec/os2#fsselection ) から、fsSelectionのところを見ると、例えば bit 0 がイタリック、bit 5 が Bold、bit 6 が Regular などと書かれています。

    以下は、IBM Plex Monoと、IBM Plex Sans JPのfsSelectionを抽出した情報です。
    実際にこれらの情報を照らし合わせてみると、Rebular や Bold などのファイルで該当ビットが立っていることが見て取れます。

    こういった定義があることを鑑みると、BOLD指定の時は Bold ビット(bit 5)が立っているファイルを参照するというのが、機械的な選択である気がします。

    # IBM Plex Mono
    IBMPlexMono-Thin.ttx:    <fsSelection value="00000001 00000000"/>
    IBMPlexMono-ThinItalic.ttx:    <fsSelection value="00000001 00000001"/>
    IBMPlexMono-ExtraLight.ttx:    <fsSelection value="00000001 00000000"/>
    IBMPlexMono-ExtraLightItalic.ttx:    <fsSelection value="00000001 00000001"/>
    IBMPlexMono-Light.ttx:    <fsSelection value="00000001 00000000"/>
    IBMPlexMono-LightItalic.ttx:    <fsSelection value="00000001 00000001"/>
    IBMPlexMono-Regular.ttx:    <fsSelection value="00000001 01000000"/>
    IBMPlexMono-Italic.ttx:    <fsSelection value="00000001 00000001"/>
    IBMPlexMono-Text.ttx:    <fsSelection value="00000001 00000000"/>
    IBMPlexMono-TextItalic.ttx:    <fsSelection value="00000001 00000001"/>
    IBMPlexMono-Medium.ttx:    <fsSelection value="00000001 00000000"/>
    IBMPlexMono-MediumItalic.ttx:    <fsSelection value="00000001 00000001"/>
    IBMPlexMono-SemiBold.ttx:    <fsSelection value="00000001 00000000"/>
    IBMPlexMono-SemiBoldItalic.ttx:    <fsSelection value="00000001 00000001"/>
    IBMPlexMono-Bold.ttx:    <fsSelection value="00000001 00100000"/>
    IBMPlexMono-BoldItalic.ttx:    <fsSelection value="00000001 00100001"/>
    
    # IBM Plex Sans JP
    IBMPlexSansJP-Thin.ttx:    <fsSelection value="00000001 00000000"/>
    IBMPlexSansJP-ExtraLight.ttx:    <fsSelection value="00000001 00000000"/>
    IBMPlexSansJP-Light.ttx:    <fsSelection value="00000001 00000000"/>
    IBMPlexSansJP-Regular.ttx:    <fsSelection value="00000001 01000000"/>
    IBMPlexSansJP-Text.ttx:    <fsSelection value="00000001 00000000"/>
    IBMPlexSansJP-Medium.ttx:    <fsSelection value="00000001 00000000"/>
    IBMPlexSansJP-SemiBold.ttx:    <fsSelection value="00000001 00000000"/>
    IBMPlexSansJP-Bold.ttx:    <fsSelection value="00000001 00100000"/>

    ちなみにウェブだとウェイトの指定に lighter、bolder などの相対指定な考え方はあるようで、「元のウェイト300に bolder 指定すると400が選ばれる」などが定義されているようですね。
    https://developer.mozilla.org/ja/docs/Web/CSS/font-weight

    > 本件、非常に難航しています。もしかすると、フォント設定ダイアログに「ウェイト」なる項目を新たに設けて、ユーザー側でウェイトを選択していただくような仕様になるかもしれません。(秀〇エディタさんがそうなってました)

    サクラエディタでもそうなってました。
    たしかにマルチウェイトのフォントの場合、フォントリストで「xxx SemiBold」「xxx Medium」などとウェイト別にリストが増えてしまうので、それが1つにまとまって見えるのはスッキリして良さそうですね。

    PS:
    ちなみに IBM Plex Sans JP, PlemolJP のウェイトは以下のような構成になっています。Text というウェイト値が珍しいですね。

    - Thin: 100
    - ExtraLight: 200
    - Light: 300
    - Regular: 400
    - Text: 450
    - Medium: 500
    - SemiBold: 600
    - Bold: 700

     |  yuko  |  返信
  9. > サクラエディタでもそうなってました。

    秀○も見てみましたが、サクラとはまた違う方式でした。これだと、フォントリストがまとまったりすることはなさそうですね。

    秀○、「太さ: 自動」というのが、Windowsが取得した太さということなんですかね?
    例えばThinを選択して、太さを「自動」にすると、本件の「微妙にThinじゃない変な描画」になりますが、太さを「Regular(100)」を選択してあげると、ちゃんとThinの太さになります。

    手元ですぐ見られる環境ということで、IntelliJでも確認してみました。
    結果、これもダメでした。同じくThinとExtraLightで、以下のような描画でした。
    https://imgur.com/a/tuTgWqo

    ここまで来ると「そもそもWindowsでの取得方式が微妙なのかも」という話も出てきそうですが、複数のソフトで共通して表示に問題が出てきてしまうという事実には違いないので、フォント側で対策ができるなら対策した方がいいのかもしれませんね。

     |  yuko  |  返信
  10. PlemolJP Thin の OS/2 内の usWeight を100、200、300とそれぞれ変えたものを用意してみました。

    ※フォント設定での表示が「PlemolJP Console NF Thin」になっているのがこの実験用フォントです
    ※適当に生成したので、GDI表示での文字幅がおかしくっています。インストールせずにFontsフォルダで確認するのをオススメします。

    https://drive.google.com/drive/folders/1H7RyTjOu6g4w3XPNp_OphZWhApun1rfX?usp=sharing

    300のときに正規の表示結果が得られますが、100-200のときは例の荒れた表示になりますね。
    やはり usWeight が200以下のものは正しく表示されないと見て良さそうですね。
    ただ、例えば前述のサクラや秀○での太さ指定であったり、VSCodeで "editor.fontWeight": "100" と設定するなどすれば表示されるので、アプリケーション側の呼び出し方法で回避する術はあるのでしょうね(大変そうですけど…😅)

     |  yuko  |  返信
  11. ちょうど、今、前回の返信を書き終わったところでした。

    > PlemolJP Thin の OS/2 内の usWeight を100、200、300とそれぞれ変えたものを用意してみました。

    ありがとうございます!これは試させていただき、改めてご報告させていただきたいと思います。

    以下、前回の返信です😅

    情報ありがとうございます。

    なるほど、fsSelection は勉強になりました。どうやら私は勘違いをしていたようです。

    IBM Plex Sans JP Thin はウェイト 100 が Regular としてフォント側で設定されているのかと思っていましたが、Regular ビットが立っていないところを見るとそうでもなさそうですね。

    Mery のフォント設定ダイアログで IBM Plex Sans JP Regular と IBM Plex Sans JP Bold だけは 1 つにまとめられて "IBM Plex Sans JP" として表示されるのも、この Regular ビットと Bold ビットが立っているためなのでしょうね。

    そして IBM Plex Sans JP Thin には Regular も Bold もない、と。

    秀〇エディタさんのフォント設定ダイアログですと、IBM Plex Sans JP Thin を選択すると "太さ" の項目に "Regular (100)" と表示されるので、てっきりフォント側で Regular として設定されているものだと思っていました。

    > 秀○も見てみましたが、サクラとはまた違う方式でした。これだと、フォントリストがまとまったりすることはなさそうですね。

    そうなんですよね。サク〇エディタさんは Windows 標準のフォントダイアログを使われているのだと思います。メモ帳などでも同様です。

    秀〇エディタさんは独自のフォントダイアログになっていて、フォントリストは Mery のようにフォントスタイル?ごとに分かれて表示されますね。

    > 秀○、「太さ: 自動」というのが、Windowsが取得した太さということなんですかね?

    "自動" は恐らく FW_NORMAL (400) を Windows API に投げているのだと思います。

    でも、この方式だと "太さ" の項目、必要ある?と、ちょっと疑問に思うところもあります。

    一応、"IBM Plex Sans JP" を選択すると太さは Regular (400) と Bold (700) の 2 つが選べるようになりますが、では Bold を選択した場合って、標準のフォントが太字になるのは良いとして、強調表示とかで太字にする部分はどうなるの?

    と思ってしまいます。

    …が、実際のところは、秀〇エディタさんは強調表示とかの太字は 1 ピクセル右にずらして重ね書きすることで太字を作り出しているようなので、標準のフォントとして Bold (700) を選択した場合でも、強調表示とかではさらに太い太字が描画できるという仕組みになっているようです。

    というわけで秀〇エディタさんスゲー!と思うのと同時に、本件、どう対応するのが良いのか分からなくなって来ました。

    とりあえずひとつ言えることは、フォントに設定されているウェイトを自動で選択することはできないのでどうにかしてユーザー側で選択してもらう必要があるということです。

    一応、ウェイト FW_DONTCARE (0) を指定すれば自動でデフォルトのウェイトを使って呼び出すことができないことはないのですが、どのウェイトが選択されるか分からないのも不安です。

    > 例えばThinを選択して、太さを「自動」にすると、本件の「微妙にThinじゃない変な描画」になりますが、太さを「Regular(100)」を選択してあげると、ちゃんとThinの太さになります。

    そうそう。微妙に Thin じゃない変な描画、これは Mery の GDI と同じ感じですよね。

    そもそも IBM Plex Sans JP Thin の中にそんな微妙なフォントが含まれているわけでもないのに、どこからやってきたのでしょう?

    …と思って調べていたところ、GDI はフォントに Bold のスタイルが含まれていない場合、自動で Bold をエミュレート (1 ピクセル横に重ね書き) してグリフを作り出すという情報がありました。

    微妙に Thin じゃない変なフォントの正体は、フォント側でウェイトが 100 に設定されているフォントに対して、FW_NORMAL (400) を指定して呼び出してしまうことで、Windows はウェイトの数値を相対的に見て Bold だと勘違いした挙句、GDI がご丁寧に Bold をエミュレートしてしまった結果、出来上がったフォント。ということになるのかなと思います。

    > 手元ですぐ見られる環境ということで、IntelliJでも確認してみました。

    ご協力ありがとうございます。

    うーん、Mery の他にも同じ症状の仲間がいて良かったです (良くないけど😅)

    > フォント側で対策ができるなら対策した方がいいのかもしれませんね。

    きちんと描画できているアプリがある以上、アプリ側での対策は必要だと思います。

    いただいた情報を参考にさせていただき、もう少し検討してみたいと思います。

     |  Kuro  |  返信
  12. > PlemolJP Thin の OS/2 内の usWeight を100、200、300とそれぞれ変えたものを用意してみました。

    ありがとうございます。早速、検証してみました。

    > やはり usWeight が200以下のものは正しく表示されないと見て良さそうですね。

    これが根本的な問題と見て間違いなさそうですね。

    ワードパッドや IntelliJ などは恐らくウェイト 400 で呼び出してると思うので、フォント側で対応するとしたら usWeight を 400 にすると Thin に非対応なアプリでも正しく描画できるようになるんじゃないかと思います。

    …が、それはそれで気持ち悪いので、アプリ側での対応が好ましいですね。

    アプリ側でやるとしたら、やはりウェイトの設定項目を設けてユーザー側でウェイトを指定していただくかたちになりそうです。

    試しにウェイトの一覧を取得する機能を作っていたのですが、いただいたフォントのデータがとても役に立ちそうです。

    引き続き研究してみたいと思います。

     |  Kuro  |  返信
  13. おおっ、着々と糸口が見つかっているようで、さすがですっ!

    > ワードパッドや IntelliJ などは恐らくウェイト 400 で呼び出してると思うので、フォント側で対応するとしたら usWeight を 400 にすると Thin に非対応なアプリでも正しく描画できるようになるんじゃないかと思います。

    この方式、同じく考えていました。
    が、これをやってしまうとおそらく、ブラウザなどの「フォントファミリー名+ウェイト」で表示を制御するアプリで問題が出てくる気がしています。

    IBM Plex Sans JPやPlemolJPの設定では、Thin~Boldを同じフォントファミリーとして扱われる仕組みになっています。
    そうすることによって以下のCSSのように "PlemolJP Thin" などフォントファミリーのフルネームにせずとも、Thinなどのウェイトが適切に表示されるようになります。

    * {
      font-family: PlemolJP;
      font-weight: 100;
    }

    そのため、Thinの usWeight を400などにしてしまうと、こういった用途に対応できなくなるのではないかと考えてやめてしまいました。あちらを立てるとこちらが立たず…。

    ちなみに、前述の「Thin~Boldを同じフォントファミリーとして扱われる仕組み」ですが、以下の OS/2 テーブルに加え、name テーブルというものが関係しています。

    (1)OS/2 テーブル fsSelection でビット 8 (WWS) を立てる
    (2)name テーブル Name ID 16 (Typographic Family name) と Name ID 17 (Typographic Subfamily name) を設定する。
    - Name ID 16: 全ウェイトで共通する名前を指定する ("PlemolJP" など)
    - Name ID 17: ウェイト固有の名称を設定する ("Thin" など)
    name テーブルについて: https://docs.microsoft.com/en-us/typography/opentype/spec/name

    Meryや秀○で読まれているフォントフルネーム("PlemolJP Thin" など)は、name ID 1 (Font Family name) かと思います。

     |  yuko  |  返信
  14. Kuroさんの方での調査に役立つかもと思いまして、name, OS/2 テーブル情報の詰め合わせを用意しました。
    下記から「ttx詰め合わせ.zip」をダウンロードしてください。
    https://drive.google.com/drive/folders/1H7RyTjOu6g4w3XPNp_OphZWhApun1rfX

    ttx というのは、OS/2 を始めとしたフォント内のテーブル情報の抽出・編集ができるツールです。
    上記zipは、それを使って抽出したデータ(XMLファイル)となります。

    「ttf」と「ttx」フォルダに分けています。
    - 「ttx」フォルダ: name, OS/2 テーブル情報(XMLファイル)
    - 「ttf」フォルダ: 上記ttxファイルの抽出元になっているフォントファイル

    ttxファイルを見てみればなんとなく見れば分かるかと思いますが、データは以下のように「name」「OS_2」タグを使って表現されています。

      <name>
      ...
        <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
          IBM Plex Mono
        </namerecord>
    
        ⇒「namerecord」タグの nameID 属性は https://docs.microsoft.com/en-us/typography/opentype/spec/name の「Name IDs」章に定義されているコードと紐付く。上記の場合、nameID="1" (Font Family name) が、「IBM Plex Mono」という値で設定されている、という意味
      ...
      </name>
      
      <OS_2>
      ...
        <fsSelection value="00000001 01000000"/>
    
        ⇒例の「fsSelection」のビット値
      ...
      </OS_2>

    なお今回、詰め合わせ対象としたのは、以下のフォントたちです。

    - IBM Plex Mono
    - IBM Plex Sans JP
    - PlemolJP
    - 源真ゴシック

     |  yuko  |  返信
  15. > おおっ、着々と糸口が見つかっているようで、さすがですっ!

    Thin をウェイト 100 を指定して呼び出して、きちんと描画できるところまでは確認できました。

    その後、フォントダイアログに [ウェイト] の項目を設けるための開発をしているのですが、色々と問題が出てきまして苦戦しております。

    ・[ウェイト] で Bold (700) を選択したときの強調表示の太字の仕様
    → 通常の文字が Bold (700) になるため、それより太いフォントがない場合は強調表示で太字にできない
    → 秀○エディタさんのように重ね書きで無理やり太字にする方式にすると、今度は太いフォントがある場合にもそれを使わず重ね書きになってしまう
    → VS Code はそれより太いフォントがない場合は強調表示も太字にならないようなので、それで妥協する?

    ・[印刷] におけるウェイトの扱いをどうする?
    → 秀○エディタさんは印刷のときはウェイトの概念なし。Thin だと例の微妙な太いフォントが使われる
    → 印刷ダイアログにも [ウェイト] の項目を設ける?😅

    ・フォントの履歴におけるウェイトの扱いをどうする?
    → 最近使用したフォントの一覧にウェイトも保持するようにする?😭

    ・アウトラインなどのプラグインのフォントのウェイトはどうする?
    → プラグイン側にもウェイトの概念をもたせなければ対応できないため、プラグイン SDK およびプラグインのカスタマイズが必要となる😱

    などなど、これらすべてをきちんと実装するとなると非常に時間がかかるため、何か別のアプローチも検討してみる必要がありそうです。

    > が、これをやってしまうとおそらく、ブラウザなどの「フォントファミリー名+ウェイト」で表示を制御するアプリで問題が出てくる気がしています。

    なるほど、それは盲点でした。確かにおっしゃるとおりですね。

    > ちなみに、前述の「Thin~Boldを同じフォントファミリーとして扱われる仕組み」ですが、以下の OS/2 テーブルに加え、name テーブルというものが関係しています。

    メモ帳のフォントダイアログのように、同じフォントファミリーでまとめて表示される場合はこの仕組みが使われているのですね。

    Mery や秀○エディタさんで読んでいるフォントフルネーム一覧の場合ですが、Thin や Light などは別々に表示されるのに、Regular と Bold だけは 1 つになって表示されてしまうんですよね。

    Mery 側からするとフォントフルネームで呼び出したフォントの "デフォルトのウェイト" が知りたいだけなのですが、フォントフルネームに対してウェイトが 1 対 1 ではない場合もあるので困っています。

    デフォルトのウェイトさえ取得できれば、そのフォントに最適なウェイトを指定して呼び出せるので、そもそも [ウェイト] 設定の画面など必要なくなるのですが…。

    > Kuroさんの方での調査に役立つかもと思いまして、name, OS/2 テーブル情報の詰め合わせを用意しました。

    ご協力ありがとうございます。専用のツールなしでフォントの情報が見られるのはとても助かります!

    フォントファミリー名とかフォントフルネームなど、よく分かっていなかった部分も多いので、頂いたデータを見ながら勉強してみたいと思います。

     |  Kuro  |  返信
  16. なるほど…フォント設定の仕組みに手を入れてしまうと、表示関連の諸々に影響が出てくるわけですね。これは想像していたより影響範囲が広がってしまいますね…😓

    > Thin や Light などは別々に表示されるのに、Regular と Bold だけは 1 つになって表示されてしまうんですよね。

    Regular, Boldが1つにまとまってしまうのは、「nameID="1"」の設定に関係しています。

    お渡ししたttxファイルの中に以下のような記述があります。この「nameID="1"」が、フォントファミリー名です。※ここの値を本トピック上では便宜上、「フォントフルネーム」と表現していました。
    IBM Plex Sans JP(と、PlemolJP)では、Regular, Bold で同じ名前を使っているため、1つにまとまっているようです。

        <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
          PlemolJP
        </namerecord>

    それ以外のThinなどのウェイトでは、ウェイト名もくっつけた名前になっています。

        <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
          PlemolJP Thin
        </namerecord>

    nameID="1" をRegular,Boldで「PlemolJP Console NF」になっていた状態から、それぞれ「PlemolJP Console NF Regular」「PlemolJP Console NF Bold」とウェイト名を付加した名称に変更した実験用ファイルを用意してみました。
    下記に「Regular,Boldフォントファミリー名変更.zip」をアップしました。
    https://drive.google.com/drive/folders/1H7RyTjOu6g4w3XPNp_OphZWhApun1rfX

    これらをMeryで読み込むと、フォントが「PlemolJP Console NF Regular」「PlemolJP Console NF Bold」としてそれぞれのウェイト個別に選べるようになることが見て取れるかと思います。

    ちなみに源真ゴシックの場合、Regular, Bold の nameID="1" は元からこのRegular, Boldで分けた状態の命名になっているようで、MeryからRegular、Boldがそれぞれ選択できるようになっていますね。

    > Mery 側からするとフォントフルネームで呼び出したフォントの "デフォルトのウェイト" が知りたい

    なるほど、デフォルトのウェイトですかー。
    通常ならfsSelectionで Regular ビットが立っているものがデフォルト、ということにはなりそうですが、IBM Plex Sans JP では Regular 以外でそのビットが立っていないから取れない、ということでしょうか。

    標準でウェイト 400 をOSに要求するとのことですが、そのときに「ウェイト 400 のフォントは存在しない」という情報が受け取れるのなら、なんとかできそうなんですけどね。
    例えば、ブラウザでの「太さのフォールバック ( https://developer.mozilla.org/ja/docs/Web/CSS/font-weight#fallback_weights )」にならって、

    - 対象フォントのウェイト 400 を探す
    - 無ければ、対象フォントのウェイト 400 未満を降順で探す
    - 無ければ、対象フォントのウェイト 400 超を昇順で探す

    のような、太さのフォールバックの仕組みを実装できればいいのですが…

     |  yuko  |  返信
  17. 休日の貴重な時間にご協力いただきありがとうございます。

    > これは想像していたより影響範囲が広がってしまいますね…😓

    何か他に良い方法はないかと試行錯誤してみたのですが、どうにも…。

    VS Code にも fontWeight の項目があることですし、サク〇エディタさんや E〇Editor さんの設定ファイルを観察してみたら、やはりウェイトの値が保持されていました。やっぱりウェイトの設定画面、必要ですね…😭

    余談ですが、ずっと「ウェイト」と呼んでいましたが、フォントの世界では「ウエイト」(エが大きい) と表記するほうが一般的なようですね。

    > これらをMeryで読み込むと、フォントが「PlemolJP Console NF Regular」「PlemolJP Console NF Bold」としてそれぞれのウェイト個別に選べるようになることが見て取れるかと思います。

    ありがとうございます。確かに、それぞれのフォントが分かれて表示されるようになりました。

    すべてのフォントがウェイトごとにわかれて一覧表示されるなら、フォントとウェイトが 1 対 1 になるのでウェイトを自動設定できるかと思ったのですが、nameID="1" が同じケースを考えるとこの作戦は考えが甘かったようですね。

    > 通常ならfsSelectionで Regular ビットが立っているものがデフォルト、ということにはなりそうですが、IBM Plex Sans JP では Regular 以外でそのビットが立っていないから取れない、ということでしょうか。

    そうですね。フォントの作り方によっては、Regular ビットが立っているものがひとつもなくて、例えば Thin (100)、ExtraLight (200)、Light (300) の 3 つのウェイトがまとまったフォントファミリーといったケースもありうる、ということだと思いますので。

    そうなるとアプリ側でそのフォントを選択するときに、ユーザーにウェイトを選んでもらわないと、どのウェイトを採用すべきなのか判断できませんからね。

    > 太さのフォールバックの仕組みを実装できればいいのですが…

    これは私も考えてみたのですが、400 を基準に探すと Regular に当たる可能性は高いですが、Regular が 200 のものや 500 のものもあるので、走査する方向によっては Regular 以外に先にヒットしてしまう可能性もありますね。

    もっとも、Windows にはもともとそういう仕組みが備わっているので、Thin の場合だと 400 を基準にフォントを探しに行って Bold (700) が返って来ちゃってるのだと思いますが…😅

    走査する方向がウェイトが大きい方向に優先的に向かってる感じですね。

    自前で実装してウェイトが小さい方向に優先的に向かうようにしたとしても、今度は逆のパターンで不一致が発生するはずです。

    とりあえず、ウェイトの項目を追加してみました。まだこの路線で進めるかどうか悩ましいところですが、現状のご報告です。
    https://imgur.com/a/ZM7Tf24

    一応、エディターのウェイト対応、プラグインへのウェイト受け渡し、はなんとなく開発できました。今のところ印刷機能はウェイトに対応しない方向です。

    しかし、DirectWrite は不思議なもので Thin が含まれていない "IBM Plex Sans JP" などを選択してウェイトを 100 にするときちんと Thin が読み込まれるようです。その逆もアリで Thin なのにウェイト 900 とかにもできちゃうという…。(GDI のほうはそういうわけにはいきませんが)

    これはこれで面白そうなのでアリといえばアリでしょうか。

     |  Kuro  |  返信
  18. > 休日の貴重な時間にご協力いただきありがとうございます。

    いえいえ。こちらこそ軽い気持ちでご報告したら思いのほか深い沼だったようで、なんだかすみません😅

    > 余談ですが、ずっと「ウェイト」と呼んでいましたが、フォントの世界では「ウエイト」(エが大きい) と表記するほうが一般的なようですね。

    なるほど。キヤノンみたいな感じですね(?)

    > とりあえず、ウェイトの項目を追加してみました。まだこの路線で進めるかどうか悩ましいところですが、現状のご報告です。

    おお、仕事が早い…!
    ウェイトの直指定で 100, 200 とか入れるのに対応しているんですね。
    ただ何やら、ウェイト 900 で「PlemolJP」「PlemolJP Thin」を交互に選択している場面で「aA」の表示幅が微妙に変わるのが気になりました。

    > そうですね。フォントの作り方によっては、Regular ビットが立っているものがひとつもなくて、例えば Thin (100)、ExtraLight (200)、Light (300) の 3 つのウェイトがまとまったフォントファミリーといったケースもありうる、ということだと思いますので。
    > そうなるとアプリ側でそのフォントを選択するときに、ユーザーにウェイトを選んでもらわないと、どのウェイトを採用すべきなのか判断できませんからね。
    > 自前で実装してウェイトが小さい方向に優先的に向かうようにしたとしても、今度は逆のパターンで不一致が発生するはずです。

    なるほど…段々と、秀○があの仕様になっているワケが見えてきたような気がしてきます。
    自動選択はベターだけどベストではない。だから「自動」とその他ウェイトの選択肢を用意してユーザーに適宜選んでもらう、としたのかもしれませんね。

    > しかし、DirectWrite は不思議なもので Thin が含まれていない "IBM Plex Sans JP" などを選択してウェイトを 100 にするときちんと Thin が読み込まれるようです。その逆もアリで Thin なのにウェイト 900 とかにもできちゃうという…。(GDI のほうはそういうわけにはいきませんが)

    DirectWriteだとブラウザっぽい挙動をしてくれるんですかね。
    このへんは、nameID="16" を見ているから、というのが理由になってくると思います。

    nameID="16" は、「優先ファミリー名」や「タイポグラフィックファミリー名」と呼ばれるもので、 nameID="1" が異なっているファミリー同士を同じファミリーとして扱うための値のようです。
    IBM Plex Sans JPのようにウェイトごとに nameID="1" が「IBM Plex Sans JP」「IBM Plex Sans JP Thin」などと別々に設定されていても、nameID="16" さえ同じ「IBM Plex Sans JP」となっていれば、1つのファミリーとして扱う。そんな仕組みです。

    PlemolJPでも当初 nameID="16" の存在をしらず、nameID="16" を未設定で生成したときは、Windowsにインストールしたフォントが C:\Windows\Fonts フォルダ上で見たときに「Regular & Boldと、それ以外のウェイト」という2つのフォルダに分かれてしまったのを確認しています。
    全ウェイトの nameID="16" に「PlemolJP」という値を設定したことで、 C:\Windows\Fonts 上でも「PlemolJP」という1つのフォルダに収まるようになったのです。

    GDIでも上記のように nameID="16" の値が考慮されるようになるのがベストだとは思いますが、DirectWriteでそのように扱えるだけでも十分助かると思います。

     |  yuko  |  返信
  19. > ただ何やら、ウェイト 900 で「PlemolJP」「PlemolJP Thin」を交互に選択している場面で「aA」の表示幅が微妙に変わるのが気になりました。

    間違えました。映像で見えているのは PlemolJP ではなくて IBM Plex Sans JP でしたね。

     |  yuko  |  返信
  20. > いえいえ。こちらこそ軽い気持ちでご報告したら思いのほか深い沼だったようで、なんだかすみません😅

    いえいえ。趣味でやっているものですから😅 お付き合いいただきありがたい限りです。

    > ただ何やら、ウェイト 900 で「PlemolJP」「PlemolJP Thin」を交互に選択している場面で「aA」の表示幅が微妙に変わるのが気になりました。

    ほんとですね、これは気付いてなかったので助かりました。

    調査してみましたところ、どうやら存在しないウェイトを指定したときの挙動が DirectWrite の API によって異なるようで、描画に使っている API と文字幅の取得に使っている API で差が生じてしまっているようです。

    > なるほど…段々と、秀○があの仕様になっているワケが見えてきたような気がしてきます。
    > 自動選択はベターだけどベストではない。だから「自動」とその他ウェイトの選択肢を用意してユーザーに適宜選んでもらう、としたのかもしれませんね。

    私もそう思いました。「自動」の挙動については疑問が残るところはありますが…😅

    > IBM Plex Sans JPのようにウェイトごとに nameID="1" が「IBM Plex Sans JP」「IBM Plex Sans JP Thin」などと別々に設定されていても、nameID="16" さえ同じ「IBM Plex Sans JP」となっていれば、1つのファミリーとして扱う。そんな仕組みです。

    うはぁ…、複雑すぎますね。

    DirectWrite の不思議な挙動ということでたまたま nameID="16" が読まれていたようですが、ご指摘いただいた「表示幅が微妙に変わる」件を調査しました結果、DirectWrite の実装を大きく変えなければならなくなりそうで、これはレベルダウンのバグにつながる可能性があります。

    そういうわけで、[ウェイト] の項目追加案につきましては一旦、白紙に戻しまして、フォントの研究をしつつ、対策についてはゼロから再検討させていただきたいと思います。

    手探り状態なもので、進んだり戻ったりして申し訳ございませんが、進捗がありましたらまたご報告させていただきますね😉

     |  Kuro  |  返信
  21. 追伸: FontForge をインストールしましたので、私のほうでもフォント情報を確認したり、変更して実験が出来るようになりました。

    使い方はまだ勉強中ですが、これである程度は私の環境でも調査が出来るようになると思います。本当に、色々とご協力ありがとうございます。

     |  Kuro  |  返信
  22. DirectWriteも表示幅が1:2になるように、など色々と最適化を進めていただいてましたもんね…その辺のツジツマ合わせが大変、みたいな話もありそうですね。

    > 手探り状態なもので、進んだり戻ったりして申し訳ございませんが、進捗がありましたらまたご報告させていただきますね😉

    試行錯誤にお時間割いていただいて、ありがとうございました。
    喫緊で困っているわけでもありませんから、思い立ったときに試してみていただくくらいで大丈夫ですので!

    > 追伸: FontForge をインストールしましたので、私のほうでもフォント情報を確認したり、変更して実験が出来るようになりました。

    おおっ、これでKuroさんも合成フォント作成に乗り出せるわけですね(違う)

    Windows版のFontForgeだとちょっと不安定だったりするので、本格的にいじるときはやはりLinux上でやるのがいいのですが、OS/2やTTF名 (name テーブル) をいじる程度であれば、多分耐えうると思います。

    不明点あれば、できる限りご協力しますのでお声がけください。(Kuroさんの方が私より深掘りしてしまう可能性がありますがw)

    引き続き、よろしくお願いします🙇‍♂️

     |  yuko  |  返信
スポンサーリンク