LaTeX2e 2020/02/02のNFSS2の仕様変更(1)―Font series defaults per document family

# はじめに

2020/02/02にLaTeX2eの更新がありました．それに伴ってほぼ同時にpLaTeX2eも更新されました．これまでぐだぐだとmweights.styの中身を見ていましたが，やっとこLaTeX2eの本体に入ります．

ありがたいことにほぼ同時に日本語対応も更新されたので，日本語対応の内容と仕様変更も含めて，mweights.styが提案した「familyごとのデフォルトのseries」を定めるという考え方のLaTeX2eでの表現を見ていこうと思います．今回は内部の実装までは触れません．

なお，texjp.orgのpLaTeXリポジトリの[Issue88](https://github.com/texjporg/platex/issues/88)も参照してください．また，本稿はpLaTeX2e <2020-02-02>+1 (based on LaTeX2e <2020-02-02> patch level 1)を前提としています．

（追記：2020/03/01）結局，patch level 5が2020/02/29で入って，TeX Live 2019はfrozenとなりました．ただ，特別措置でplatex/luatexjpはfrozen後に更新が入っています．tlmgrしてpLaTeX <2020-02-02>+3が出てくればOKです．patch level 5への追随のコードを書かれたaminophenさん，ありがとうございます．


（注意）混とんとしてきました．patch level 4でちょっと怪しくなってます．\DeclareFontShapeに手が入っているようです．2020/02/27追記

（注意）LaTeX2e <2020-02-02> patch level 3が出ます．ちょっと大きな不具合修正です．不具合の詳細は

- [TeX forum 2775](https://oku.edu.mie-u.ac.jp/tex/mod/forum/discuss.php?d=2775)
- [LaTeX2e issue277](https://github.com/latex3/latex2e/issues/277)

を参照してください．おおざっぱに言うと，`\fontfamily`で直接familyを変更した状況下で，`\sffamily`などの「高レベル」なフォント変更コマンドを使うと，`\fontfamily`での値ではなく`\sfdefalut`などの値がfamilyとして使われてしまうということのようです．


（注意）mweights.styを`\usepackage`や`\RequirePackage`で読み込むことはLaTeX2e 2020/02/02ではできません．`\usepackage`で読み込みを指定してもエラーも出さずに無視されます．したがって`mweights.styのコードを前提としたマクロを使っている場合には注意が必要です．

# familyごとのseriesのデフォルトを定める`\DeclareFontSeriesDefault`

familiyごとのデフォルトのseriesを定めるに際して，mweights.styは指定を直接的に行う，パッケージ開発者向けの実装です．一方，LaTeX2eではそのためのインタフェースである`\DeclareFontSeriesDefault`というそのままの名前のマクロが新設されています．


## `\DeclareFontSeriesDefault`の書式と機能

（注意）よく見るとLaTeX2e <2020/02/02>の`\DeclareFontSeriesDefault`のコードにスペルミスがありました．すでに[LaTeX2e issue264](https://github.com/latex3/latex2e/issues/264)で修正されており，LaTeX2e <2020/02/02> patch level 1として公開されています．修正箇所は

```tex:latex.ltx<2020-02-02>
\newcommand\DeclareFontSeriesDefault[3][]{%
  \def\@reserveda{#1}%
  \ifx\@resereda\@empty %!!! ここ v がない
```
です．<2020/02/02> patch level 1では`\reserved@a`に統一されています．他にも`\reserved@b`と`\@reservedb`が混同（？）されていたようなところが修正されていてフォント関連のエラーが解消されています．

###書式

```tex
\DeclareFontSeriesDefault[<family>]{<series>}{<value>}

<family>：オプション
   rm，sf，tt，mc，gtのどれかをとる．
   mc，gtは日本語の明朝，ゴシックのことなので(u)pLaTeX2eのときのみである．
<series>：必須
   mdまたはbf．
<value>：必須
   seriesの値として使用できるものを与える．

<value>として推奨されている値は以下のweightとwidthの組み合わせの45通りで，mは誤解を招かない限り省略される．
   weight: ul el l sl m sb b eb ub 
   width : ec c sc  m  x
例：ulはulmのこと，ecはmecのこと，mはmmのこと
```

この`<value>`の値は`\DeclareFontShape`で自由に決めることができる値です．そして，従来はその値によるフォントの変更や実際の使用方法はユーザ側，もしくはパッケージ開発者が定めることが事実上要求されていました．

それに対して今回の更新では，LaTeX2eのカーネル側に十分と思われる45種類のseriesの値が与えられ，さらにその遷移のルールも規定されました（[ltnews31](https://www.latex-project.org/news/latex2e-news/ltnews31.pdf)[^1]の「Extending the font series management in NFSS」）[^2]．これによって，seriesの値がある程度は標準化され，より簡単に多様なフォントに対応できるようにするという意図があるようです．

したがって，seriesの値<value>はこの45種類の値から選ぶようにします．実際問題としてこの45種類で不足するようなことはほとんどないとは思います．

[^1]: texdoc ltnews31でも見ることができます．

[^2]: これらの値は，latex.ltxから`\DeclareFontSeriesChangeRule`かgrepで抽出してから重複を排除して整理したものです。texjp.orgのpLaTeXレポジトリの[issue88](https://github.com/texjporg/platex/issues/88)のzrさんのまとめに記載されたものと同じです．

### 使い方

```tex
\DeclareFontSeriesDefault{AA}{XX}     %% (1)
\DeclareFontSeriesDefault[FF]{AA}{XX} %% (2)
```
オプションの引数をとらない(1)の書式では，`\AAseries`が定義されているという前提の下で，

```tex
\def\AAdefault{XX}
```
と同等の定義がなされます．`\AAseries`が定義されている「AA」は，md，bfですので，「AA」に与えられる値の制限はここでの前提に由来します．

次に，オプションが与えられる(2)の書式では，`\AAseries@FF`が定義されているという前提の下で，

```tex
\edef\AAseries@FF{XX}
```
と同等の定義がなされます．`\AAseries@FF`が定義されている「AA」はmd，bf，「FF」はrm，sf，tt，mc，gt（mc，gtはpLaTeX2eの場合）ですので，「AA」と「FF」に与えられる値の制限はここでの前提に由来します[^3]．

[^3]: `\DeclareFontSeriesDefault`がだすエラーにはmc，gtについての言及はありませんが，それは機能的に問題がないためにpLaTeX2eでは`DeclareFontSeriesDefault`そのものには手を入れていないからです．

実は`\DeclareFontSeriesDefault`が本質的に行っていることは，`\AAdefault`，`\AAseries@FF`をXXに定義することだけです[^4]．実際のフォント変更に関するもろもろは，`\rmfamily`や`\bfseries`といったフォント変更のマクロの方で処置されます．このあたりの流れは[前稿](https://qiita.com/kbhonda/items/2bf281dea035810f9af8)のmweights.styの挙動とそっくりでまさに取り込んだという感じです．

[^4]: 厳密には，mweights.styが`\AtBeginDocument`にコードを追加していたように，フォントの初期化へのフラグの設定も行ってはいます．

### サンプル1

### サンプル1：素直に使ってみる

```tex
\documentclass{jarticle}
\begin{document}
\sffamily\mdseries ABC123あいうえお

\DeclareFontSeriesDefault[sf]{md}{bx}
\DeclareFontSeriesDefault[mc]{md}{bx}

\sffamily\mdseries ABC123あいうえお
\end{document}
```
![sfbx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550932/73ea6dcb-f7c0-f938-428d-65b19fe6daf6.png)

`\sffamily\mdseries`は欧文をSansSerifの普通の太さにするだけです（和文も明朝のまま）．これが出力の最初の行です．

`\DeclareFontSeriesDefault`でsf（SansSerif）とmc（明朝）のmd（Medium）をbx（BoldExtended）に切り替えます．`\DeclareFontSeriesDefault`はプリアンブル限定ではないのでこういう使い方が許されます．


切り替えた結果，ボールドとゴシックになっていることが分かります．`\mdseries@sf`と`\mdseries@mc`がbxになってそれが`\sffamily\mdseries`で使われたことによります．


### サンプル2：\XXdefaultの動き

```tex
\documentclass{jarticle}

\DeclareFontSeriesDefault{md}{bx}
\DeclareFontSeriesDefault{bf}{m}

\DeclareFontFamily{JY1}{test}{}
\DeclareFontShape{JY1}{test}{m}{n}{<-> jis}{}
\DeclareFontShape{JY1}{test}{bx}{n}{<-> jisg}{}

\begin{document}
\romanfamily{ptm}\kanjifamily{test}
\mdseries mdseriesだけど太い\par
\bfseries bfseriesだけども細い

\end{document}
```
![bfmd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550932/b393f9ad-deaa-6703-b930-5b51fc08bad5.png)

このサンプルでは`\DeclareFontSeriesDefault`をオプションなしで使うことで`\mddefault`，`\bfdefault`を逆にしています．従来は`\mdseries`，`\bfseries`はseriesをそれぞれ`\mddefault`，`\bfdefault`に変更するものでした．それが今回の更新では，現在のfamilyが`\rmdefault`，`\sfdefault`，`\ttdefault`，`\mcdefault`，`\gtdefault`（mcとgtはpLaTeX2eの場合）のどれでもないときに使われる値になりました．そこで`\romanfamily`と`\kanjifamily`で`\rmdefault`などは変えずにfamilyだけを別のものに変えることで，`\mddefault`と`\bfdefault`が使われていることが確認できます．

従来でも`\fontfamily`や`\usefont`を直接使用するような場合は，ある意味で自己責任というかカーネルの用意している枠組みから外れるという意識が必要でしたがそれは変わりません．今回の更新でカーネルが扱える範囲が広がったので，その枠組みにうまく乗ることができるようにフォントの設定を作る方がいいのかもしれません．



### `\bfdefault`の初期値の変更と注意

以前は`\bfdefault`の値は「bx」（bold extend）でしたが，今回からは`\bfdefault`の値は「b」になっています．日本語に関しても同様なのですが，この辺りはデフォルトのフォント（Computer ModernやLatin Modern，日本語の場合は標準の明朝とゴシック）を使っている限りは何も変わらないようになっています．`\textbf{AB}`でcmbxのフォントだったのがcmbのフォントになることはありません．

ただし，いろいろなパッケージの組み合わせや何らかのタイミングの問題でいきなり日本語のゴシックが明朝に変わってしまうことが起こるかもしれません．cmbxがcmbになるかもしれません．今まで出ていなかったフォントの代替の警告が出るかもしれません．要注意です[^5]．

[^5]: LaTeXに詳しい人が作成して，フォント周りに手が入っていて，安定しているのであまりメンテナンスされていないというようなパッケージやclassファイルは要注意だと思っています．

## フォント変更マクロはどう作ればいいのか？

今回の更新でフォント変更周りの仕組みのインターフェースよりの部分に大きな変更が入りました．~~根本的な部分に大変動があるわけではないので楽観はしています．~~事態が混沌としてきました．patch level 4まできて，奥地の書き替えが起こってきています．今後，フォントの変更マクロはどのように作るのが便利かつ安定なのでしょうか．

まず，文書全体のフォントを一気に変えるタイプのフォント変更があります．古くはtimesパッケージ，最近ではnewtxtextパッケージのようなものです．このタイプの場合は，今回の更新を取り込んでベースになる部分を定義して，`\bfseries`などのユーザ側のマクロが期待通りの動きになるようにするのがいいように思います．LaTeX teamの意図はこれなのではと思います．

一方で，スポット的にフォントを多彩に切り替えるケースがあります．たいていの商業出版物のためにはこちらのケースが必要です．従来は`\usefont`/`\usekanji`/`\useroman`を使ったり，`\bfseries`などではなく専用の切り替えマクロを用いたりすることが多かったはずです．この従来の方法が今回の更新で破綻するようなことはまずないとは思っています．

ただこの方法は，下手に作ると「このときはそれ，あのときはこれ，そのときはどれ？」が発生します．自動判別すればいいのに人間が一個一個入力を変えるという状態です．これを排除するために今回の更新内容をうまく使えるようにすればいいのかもしれません．

今後CTANにいろいろなパッケージがあがって実際に使う機会が増えれば，このあたりの知見が蓄積されることになるとは思います．私自身，どのように使えば便利なのか，使わないほうがよいのか判断しかねています．

（実装に関してはまた次回・・・）