D言語的なフォントを作ってみた

D言語くん初心者です。よろしくおねがいします。

さて本題です。D言語くんマニアの皆さんなら、きっと[Go言語]のことはよくご存じだと思います。

[Go言語]: https://golang.org/

聞くところでは、先月、Go言語の“公式”のフォントがリリースされたようです。

  * [Go fonts](https://blog.golang.org/go-fonts) ― The Go Blog

これは一大事です。「Go言語のフォント」があるのに「D言語のフォント」がない、なんて状態では不安で夜も眠れないですね。

というわけで、**作りました。**

  * [Demando](https://github.com/zr-tex8r/Demando) ― GitHub:zr-tex8r

Demando.otf をOSにインストールします。
その上で、次のHTML文書を、**FirefoxまたはWindows10のIE／Edge／Chromeで**開きましょう[^color]。

[^color]: このフォントはMicrosoftの方式（Segoe UI Emojiと同じ）のカラー絵文字フォントです。現状ではWindows以外のOSは非対応ですが、Firefoxは自力でカラーグリフをレンダリングしているため、どのOSでもカラーグリフが表示されます。非対応の環境で見た場合はモノクロのグリフが代わりに表示されます。

```html
<!DOCTYPE html>
<html><head><title>Demando</title><style>
body { font: 36pt "Demando", sans-serif; }
</style></head><body>
<p>DEAR MY OLDEST FRIEND.<br>
I’M ADDICTED TO D.</p>
</body></html>
```

![sample-demando.png](https://qiita-image-store.s3.amazonaws.com/0/14550/a068421a-72bb-97ad-8c26-f9b6046c4cb4.png)


これで安心して眠れますね！

以上！ ありがとうございました。



---

# 補足篇：「D言語なフォント」の作り方

![demando-101.png](https://qiita-image-store.s3.amazonaws.com/0/14550/a5797e70-56a6-8403-ea1e-bf1ef7e49b72.png)

Demandoのような「Microsoft方式のカラー絵文字OpenTypeフォント」の作成方法について解説します。ただし、「普通の（カラーでない）OpenTypeフォントの作り方」については全く触れないことにし、説明の対象を**「普通のフォントを改造してカラー絵文字フォントにする」**過程に限定します。

## 前提知識

  * 普通の（カラーでない）OpenTypeフォントを作成することができる。
  * コマンドシェルの扱いに慣れている。

※Pythonの知識は不要です。

## TTXのインストール

Pythonで作られたフォント操作ツールである「TTX」の**2.5版以上**が必要なので、入っていない場合は以下の手順でインストールします。[^ttx]

  * TTXの実行にはPythonの3.4版以上／2.7版以上を要するので、必要に応じてPythonをインストール／アップデートします。

  * Pythonの「fonttools パッケージ」をインストール／アップデートします。

    ```console
    $ pip install fonttools -U
    ```

    これにより`ttx`コマンドもインストールされます。

  * 念のためTTXのバージョンを確認します。

    ```console
    $ ttx --version
    3.15.1
    ```

[^ttx]: TTXは単体の実行ファイル（Python無しで動く）でも配布されています。2.5版以上であれば単体実行版でも構いません。もし古い単体実行版がインストールされている場合はアンインストールしてください。


## Demandoの作り方

以下ではDemando（`Demando.otf`）を例にして手順を説明します。先述の通り、Demandoでは〈D〉(U+0044)の文字に対してカラーの（D言語くんの）グリフ（字形）が割り当てられています。残りの文字はモノクロです。

![demando-102.png](https://qiita-image-store.s3.amazonaws.com/0/14550/d86757a6-2180-8e04-f1f6-2987c333d960.png)

## ①普通のOpenTypeフォントを作成する

まずは、「Demandoの元」となる、普通の（カラーでない）OpenTypeフォント`Demando0.otf`を作成します[^fontname]。この「元フォント」では、Demandoの〈D〉に対応するグリフとして、以下のものを含めておきます。

[^fontname]: フォントファイルに含まれるフォント名のデータをTTXで編集するのは面倒なので、この`Demando0.otf`を作るときには、フォント名は「Demando」にしておきましょう。

![demando-103.png](https://qiita-image-store.s3.amazonaws.com/0/14550/40565314-372e-c5a9-9b50-bbdc42bd76fb.png)

  * `Demando0.otf`の〈D〉(U+0044)には「Demandoの〈D〉をカラー絵文字非対応の環境で使った時に表示されるグリフ」（フォールバック用のグリフ）を割り当てます。ここではモノクロのD言語くんを入れています。

  * U+E100～U+E102（Unicodeの外字領域）にはカラーのD言語くんの「部品」を入れています。これらのグリフは「適当な色を付けて重ねて出力するとカラーのD言語くんになる」ように作られています。HTMLで再現すると以下のようになります。

    ```html
<!DOCTYPE html>
<html><head><title>Example</title>
<style>
.layer { font: 24pt Demando, sans-serif; margin: 10px;
         position: absolute; top: 0; left: 0; }
</style></head>
<body><!-- U+E100, U+E101, U+E102 を重ね書きする -->
<div class="layer" style="color:#FF0000">&#xE100;</div>
<div class="layer" style="color:#000000">&#xE101;</div>
<div class="layer" style="color:#FFFFFF">&#xE102;</div>
</body></html>
```

〈D〉以外の文字については、Demandoで使われるべきグリフをそのまま入れておきます。

![demando-104.png](https://qiita-image-store.s3.amazonaws.com/0/14550/a25bbad5-936c-3731-8a92-4cb760565922.png)

## ②TTXが使うグリフ名を調べる

これから`Demando0.otf`をTTXで加工して本物のDemando（`Demando.otf`）を作るわけですが、そのために、U+0044、U+E100～E102のグリフに対する（TTXが使う[^glyphname-1]）「グリフ名」を知る必要があります。このグリフ名はTTXを使って調べられます。

[^glyphname-1]: フォント自体がグリフ名を規定している場合（TrueTypeグリフのフォントは大抵がそう）はTTXはその名前を利用しますが、そうではない場合はTTXが便宜的にグリフ名を付けます。

```console
$ ttx -t cmap Demando0.otf
Dumping "Demando0.otf" to "Demando0.ttx"...
Dumping 'cmap' table...
```

生成された`Demando0.ttx`の中身は以下のようなXMLファイルになっています。

```xml:Demando0.ttx
<?xml version="1.0" encoding="UTF-8"?>
<ttFont sfntVersion="OTTO" ttLibVersion="3.15">

  <cmap>
    <tableVersion version="0"/>
    <cmap_format_4 platformID="0" platEncID="3" language="0">
      <map code="0x20" name="space"/><!-- SPACE -->
      <map code="0x21" name="exclam"/><!-- EXCLAMATION MARK -->
      <map code="0x22" name="quotedbl"/><!-- QUOTATION MARK -->
……(以下省略)……
```

この中の`<map code="0x20" name="space"/>`という記述は「U+0020の文字に対するグリフ名は`space`である」ことを表しています[^cmaptable]。なので、code属性が`0x44`、`0xe100`、`0xe101`、`0xe102`であるmap要素を探してそのname属性の値を見ればグリフ名がわかります。CFFグリフのOpenTypeフォントの場合は以下のようになっているはずです[^fontname-2]。

  * 文字U+0044 → グリフ名`D`
  * 文字U+E100 → グリフ名`uniE100`
  * 文字U+E101 → グリフ名`uniE101`
  * 文字U+E102 → グリフ名`uniE102`

[^cmaptable]: 大抵の場合、上記の`.ttx`ファイルの中に「codeが`0x20`のmap要素」は複数あります。これはファイルの中に複数の“cmap_何々”要素があり、その要素の各々の中に`0x20`のmap要素がある、という格好になっているからです。しかし、それらのmap要素のnameの値はどれも同じになっているはずです。

[^fontname-2]: CFFグリフのOpenTypeの場合、フォントはグリフ名を規定しないため、グリフ名は文字コード値から機械的に決められます。

## ③カラーグリフの情報を記したTTXファイルを作成する

「赤のU+E100、黒のU+E101、白のU+E102を順に重ね書きするとカラーの〈D〉(U+0044)になる」という情報をXMLで記述した、以下のようなTTXファイル`Demando.ttx`を作成します。

```xml:Demando.ttx
<?xml version="1.0" encoding="UTF-8"?>
<!-- ↓この行はDemando0.ttxの2行目と同じにする -->
<ttFont sfntVersion="OTTO" ttLibVersion="3.15">

  <COLR>
    <version value="0"/>
    <!-- ↓カラーの'D'(U+0044)のグリフの定義 -->
    <ColorGlyph name="D">
      <!-- ↓色0でU+E100を書く -->
      <layer colorID="0" name="uniE100"/>
      <!-- ↓色1でU+E101を重ね書き -->
      <layer colorID="1" name="uniE101"/>
      <!-- ↓色2でU+E102を重ね書きすれば完成 -->
      <layer colorID="2" name="uniE102"/>
    </ColorGlyph>
  </COLR>

  <CPAL>
    <version value="0"/>
    <!-- ↓3色からなるパレットの定義 -->
    <numPaletteEntries value="3"/>
    <palette index="0">
      <!-- ↓色0は赤(valueはRGBAで指定) -->
      <color index="0" value="#FF0000FF"/>
      <!-- ↓色1は黒 -->
      <color index="1" value="#000000FF"/>
      <!-- ↓色2は白 -->
      <color index="2" value="#FFFFFFFF"/>
    </palette>
  </CPAL>

</ttFont>
```

## ④TTXファイルと元フォントを結合する

最後に、TTXを用いて、`Demando.ttx`の情報をフォント`Demando0.otf`に“マージ”します。

```console
$ ttx -m Demando0.otf Demando.ttx
Compiling "Demando.ttx" to "Demando#1.otf"...
Parsing 'COLR' table...
Parsing 'CPAL' table...
```

これで「カラーのD言語くん」入りのフォント`Demando.otf`が**完成しました！**

![demando-105.png](https://qiita-image-store.s3.amazonaws.com/0/14550/2a976586-6b7b-5e66-bd55-f53ffa698471.png)