LaTeX で組文字したい

<!-- # LaTeX でも組文字したい -->

しばしば使われる組文字 [^kumimoji] ですが、Unicode やフォントから提供される組文字だけで欲しい組文字がすべて揃っているわけではありません。

[^kumimoji]: [Wikipedia][wiki-kumimoji] によれば、以下のように説明されています。

    > 組文字（くみもじ）は、1 行の文字列中内に複数行記述する組版のことを言う。一般には、「㍍」「㍿」のように、全角サイズ 1 文字の領域に複数文字を入れる場合が多い。

    例えば、[Unicode][unicode-kumimoji] には 4 文字の「㍍」や「㍿」の他にも、2 文字「㌔」や 3 文字「㌘」等もあり、最大で 6 文字「㌖」があります。

[wiki-kumimoji]: https://ja.wikipedia.org/wiki/%E7%B5%84%E6%96%87%E5%AD%97 "組文字 - Wikipedia"

[unicode-kumimoji]: https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5Cp%7Bsubhead%3DSquared+Katakana+words%7D%0D%0A%5Cp%7Bsubhead%3DSquared+hiragana+from+ARIB+STD+B24%7D%0D%0A%5Cp%7Bsubhead%3DJapanese+corporation%7D&g=&i= "組文字 | Unicode Utilities: UnicodeSet"

もっと自由に組文字したい人もいることでしょう。

本記事では、組文字を自由に作成できる kumimoji パッケージを作って対応してみようという試みです。

## 基本的な考え方

1 行の高さの中に 2 行分を入れる必要があるので、次のように `\hbox` の中に文字を入れて `\vbox` で重ねれば組文字ができます。

```latex
\vbox{
  \hbox to 2\zw { 組文 }
  \hbox to 2\zw { 字 \hfill }
}
```

これを 1×1 zw の大きさにリスケールすれば組文字になります。

## 実装

expl3 で実装し、LuaLaTeX＋luatexja を前提とします。

基本的な文字配置は次のようになっています。

![image-image-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590705/96ad9164-7409-843b-5d47-5ed7ecf4b550.png)

これを実現するために、以下のような処理の流れになりました。

1. 文字を上部と下部の 2 つに分ける
    - 文字数が奇数の場合、上部の文字数が $\lfloor \frac{N}{2}\rfloor$、下部の文字数が $\lfloor \frac{N}{2}\rfloor+1$ にする
1. 上部・下部の文字数が 1 文字のとき `\hfill` を挿入
    - 全体が 2 文字：
        - 上部の右側、下部の左側
    - 全体が 3 文字：
        - 下部の右側
1. 文字を配置
1. 1×1 zw の大きさに調整

ただし、組文字を作成するにあたって次の 2 点について考慮する必要がありました。

- 文字数が奇数のとき、上部と下部のどちらを多くするか
- 異体字セレクタのような文字数とカウントされるが見えない文字への対応

文字数が奇数のとき、上部と下部を分ける区切り位置は `|` で手動で明示できるようにしました。これはルビ振りのためのパッケージから着想を得ています。
実装内では `\seq_set_split:Nnn` を使うと、指定した文字を区切り文字として簡単に sequence に変更できます。ここからトークンを取り出します。

異体字セレクタを含む場合は上部と下部に実際に見える文字が何文字配置されるかを明示して指定するようにしました。これによって、自動カウントをせずに済みます。
実装内では clist として受け取って、それを int になるようにしています。

ただし、上部と下部のどちらに異体字セレクタを含む文字があるか分からないので、区切り位置も明示する必要があります。

## できたもの

https://github.com/yarakos95/kumimoji

使い方は、プリアンブルで `\usepackage{kumimoji}` して、組文字したい文字を `\kumimoji` の中に入れるだけです。

```latex
\documentclass{jlreq}
\usepackage{kumimoji}
\begin{document}

これが\kumimoji{組文字}です！

\end{document}
```

この他、いくつかのオプションを提供しています。kumimoji パッケージで遊んでみましょう。

### kumimoji で遊んでみる

ここでは次の 4 つのオプションで遊んでみましょう。

- フォント命令
- 文字色
- 区切り位置の調整
- 揃え位置の調整

デフォルトでは本文フォントを利用するため明朝体ですが、`font` オプションを利用すればゴシック体等に変更できます。

```latex
脊椎動物は\kumimoji[font = \gtfamily]{魚類}、\kumimoji[font = \gtfamily]{両生類}、\kumimoji[font = \gtfamily]{は虫類}、\kumimoji[font = \gtfamily]{鳥類}、\kumimoji[font = \gtfamily]{哺乳類}に大別されます。
```

![image-image-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590705/5aa0adc7-a9a0-b28e-8616-e6644d91d0e6.png)

また、`color` オプションでは `black`、`white`、`red`、`green`、`blue`、`cyan`、`magenta`、`yellow` のいずれかを指定できます。

```latex
三大宝石とは\kumimoji[color = magenta]{ルビー}・\kumimoji[color = cyan]{サファイア}・\kumimoji[color = green]{エメラルド}の3つを指します。
```

![image-image-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590705/7db03058-d48b-4c1e-53bd-8385a0891522.png)

また、5 文字の組文字について Unicode の組文字を見てみると、「㌕」のように 2--3 のように分かれているものが大半ですが、1 つだけ「㌙」は 3--2 で分かれています。

kumimoji パッケージでは 2--3 で分けることをデフォルト動作としていますが、これを 3--2 の変更も可能です。`|` で区切り位置を指定します。

```latex
1\kumimoji{グラム|トン}は1000\kumimoji{キログラム}です。
```

![image-image-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590705/1dd924e5-c457-766c-caca-f8e956c1239a.png)

加えて、上部と下部の揃え位置を調整可能です。例えば `top = center` とすれば、上部を中央揃えにできます。

```latex
木が3本集まって\kumimoji[top = center]{木|木木}になる。
```

![image-image-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590705/51f7da24-7fec-1e69-f410-401e57b6623d.png)

### 長〜い組文字

組文字は長くても 6 文字程度になっていますが、世の中にはこれよりも長い組文字が存在します。このような長い組文字を作成するには、2 つの組文字を並べて疑似的に対応した [^angstrom] り、2 文字幅の組文字を作成して対応する [^sievert] ようです。

[^angstrom]: [朝日新聞デジタルの 2012 年 8 月 6 日の記事][asahi-2012073100006] によれば、「オングストローム」を組文字として利用していたことがあるようです。ここでは「オントロ」と「グスーム」に分割することで 2 文字幅 8 文字の組文字を構成したそうです。

[^sievert]: [朝日新聞デジタルの 2012 年 7 月 15 日の記事][asahi-2012071500002] によれば、「ミリシーベルト」や「マイクロシーベルト」の組文字が 2 文字幅で作成されたそうです。ここでは、接頭辞の「ミリ」や「マイクロ」と単位の「シーベルト」を上下で分けたとされています。

[asahi-2012073100006]: http://www.asahi.com/special/kotoba/archive2015/moji/2012073100006.html "オントロ・グスームの記憶 - ことばマガジン：朝日新聞デジタル"
[asahi-2012071500002]: http://www.asahi.com/special/kotoba/archive2015/moji/2012071500002.html "原発事故で生まれた外字 - ことばマガジン：朝日新聞デジタル"

このような長い組文字も kumimoji パッケージで作成できます。

例えば、2 文字分の長さの組文字を作成したいときは、`width` オプションで幅を指定します。

```latex
\kumimoji[width = 2\zw]{オングストローム}
```

実際に試してみると、次のようになります。

```latex
1\kumimoji[width = 2\zw]{オングストローム}は1\kumimoji{メートル}の\kumimoji{百億分|の一}です。
```

![image-image-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590705/b21e60ae-638c-fbfc-12bb-1dce1c038c59.png)

また、区切り位置を調整したいときは `|` を使います。

```latex
%% デフォルトは「ミリシー」「ベルト」に分割される
\kumimoji[width = 2\zw]{ミリ|シーベルト}
%% デフォルトは「マイクロシ」「ーベルト」に分割される
\kumimoji[width = 2\zw]{マイクロ|シーベルト}
```

実際に試してみると、次のようになります。

```latex
1\kumimoji[width = 2\zw]{ミリ|シーベルト}は1\kumimoji{シーベルト}の\kumimoji{千分の一}、
1\kumimoji[width = 2\zw]{マイクロ|シーベルト}はそのまた\kumimoji{千分の一}です。
```

![image-image-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590705/b3506c2c-e6d6-ed43-84e5-f80e2f69b867.png)


そのため、これまでに示したオプションと組み合わせれば次のような組文字も作成できます。（文字を詰めているので、幅は 0.1zw だけ小さいです）

```latex
%% https://x.com/fishemicco/status/1874344188793504077
幸福が増して嬉い事が
\kumimoji[width = 1.4\zw, top = left, bottom = right]{あります}
```

![image-image-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590705/31de2a30-2d14-9b97-8e91-3fba00e61f3f.png)

明記していませんでしたが、kumimoji パッケージは縦書きにもとりあえず対応しています。

### 異体字セレクタへの対応

異体字セレクタ（見えないけどそこにあると文字の形を変える文字）を含んだ組文字を作成する場合は、少しだけ注意が必要です。

例えば、辻と言う文字にはシンニョウの点が 2 つのもの（辻 (U+98F4)）と 1 つのもの（辻󠄀 (U+98F4, U+E0100)）があります。

そのため「辻󠄀野さん」を組文字する場合、奇妙な結果を得ることになります。

```latex
\kumimoji{辻野さん} %% 点 2 つ
\kumimoji{辻󠄀野さん} %% 点 1 つ
```

![image-image-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590705/0980faa0-f09a-732a-f59d-2fdfe65804ab.png)

これは、` 辻󠄀 ` に含まれる異体字セレクタが 1 文字と数え上げられることで、全体が 5 文字であると認識され、上段が 2 文字、下段が 3 文字に分割されたためです。

これを上手く処理するには、区切り位置と上段・下段の文字数を手動で指定します。
すなわち、以下のようにします。

```latex
\kumimoji{辻野さん} %% 点 2 つ
\kumimoji{辻󠄀野|さん}[2, 2] %% 点 1 つ
```


![image-image-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590705/72da2257-a361-925f-458b-cf73c558f6db.png)

### 合字

組文字ではないですが、「㍻」のような合字もあります。Unicode には、年号の合字がいくつか含まれています。（[参考][unicode-gohji]）

[unicode-gohji]: https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%0D%0A%5Cp%7Bsubhead%3DJapanese+era+names%7D&g=&i= "合字 | Unicode Utilities: UnicodeSet"

kumimoji パッケージでは、これもついでに作成できるようにしてみました。方法は `\kumimoji` に `*` オプションを課すだけです。

```latex
元号は\kumimoji*{昭和}、\kumimoji*{平成}と続き、
2019年5月1日から\kumimoji*[font=\gtfamily]{令和}になりました。
```

![image-image-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590705/c4ab5dc5-549e-fdf9-30d2-60cce50dde96.png)

## 余談

組文字を自由に作成できる kumimoji パッケージを作ってみました。

世の中には [組文字の下段で文章を作るジェネレータ][koizuka-kumimoji] がありますが、kumimoji パッケージで組文字を作ればもっと自由度の高い文章が作れそうですね（ちょっとズルい？）

[koizuka-kumimoji]: https://www.koizuka.jp/kumimoji "組文字変換さん(仮)"

### expl3 メモ

expl3 の l3box には graphicx パッケージにおける `\scalebox` や `\rotatebox` に相当する関数が用意されています。そのため、graphicx パッケージを利用しなくてもボックスの拡大・縮小、回転が可能になっています。