しろもじメモランダム

文字についてあれこれと。

『[改訂新版] プログラマのための文字コード技術入門』を読んだ

年末に発売されていたので読みました。

[改訂新版]プログラマのための文字コード技術入門 (WEB+DB PRESS plusシリーズ)

[改訂新版]プログラマのための文字コード技術入門 (WEB+DB PRESS plusシリーズ)

どんな感じの本だかざくっと

タイトルに「プログラマのための」あるように、プログラミング経験者がターゲットになっています。ビット・バイト、2進数・16進数、ファイル、プロトコルのような「常識」についてはさらっとした説明で済まされているので、その分、文字コードの本質的な部分・実践的な部分の密度が高くなっています。文章が平易なので、読み進めやすいかと思います。

さらに内容をはっきりさせるのであれば、『「現代日本プログラマのための」文字コード技術入門』といったところでしょうか。この本は、日本で現在使われている文字コードの話が中心です。世界各地の文字コードだったり、歴史的な文字の符号化などにもおもしろい話はたくさんあるのですが、そこには深入りせず、実用的なテーマに絞って解説されています。国内での業務にすぐ役立ちそうな内容です。

第7章「プログラミング言語文字コード」では JavaRuby が題材になっていますが、他の言語でも基本的な概念は共通しています。それ以外の章では JavaRuby の知識はまったく要求されませんので、馴染みがなくても大丈夫です。その前の第6章が Web の話だということもあり、個人的には JavaScript も取り上げてほしいところですが。

初版との比較

この本(改訂新版)は第2版にあたります。初版は2010年2月に発行されています。

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

初版と改訂新版、左右に並べて目で diff をとりながら読みました。Unicode をはじめ、各規格・ツールの更新に合わせた細かな対応がなされていますが、こうして見比べてみると、文字コードの本質的な部分についてはほとんど変わらないことが分かります。Unicode 絵文字(2010年〜)についての記述も増えていますが、ここ数年の世界的な普及を見ると、第3版ではもっともっとページ数が割かれるもしれません(笑)

この期間における最大の変化は、UTF-8 の圧倒的な普及でしょうか。初版では、著者の「JIS X 0213 推し」な雰囲気が端々から伝わってきましたが、UTF-8 の普及がそれを取り込む・呑み込むかたちになりました。Web ブラウジングで文字化けに遭遇するようなこともめっきり減り、たまに出会うと懐かしさすら感じます。Shift_JISEUC-JP や ISO-2022-JP を知らずに、UTF-8 一本で暮らしていける世代がすでに出てきているはずです。「レガシー」文字コードから解放される一方で、Unicode の孕んだ複雑さと向き合う場面が増えそうですが……

ただし、「UTF-8 の圧倒的な普及」という印象は、自分が仕事で新しめの Web アプリケーションを触っているから、というのもあるかもしれません。大企業や役所の業務システムはいまどんな感じなんでしょうか。

メモと補足

p. 9 図 1.2

亜 哀 愛 悪 握 圧 扱 安 … 惑 枠 湾 腕

となっていますが、これは「旧」常用漢字の先頭部分と末尾部分ですね。2010年の常用漢字改定によって、「亜 哀 悪 握 圧 … 惑 枠 湾 腕」という並びになりました。

p. 193

IANA の登録簿には、……実際に使われている JIS X 0213 の符号化方式が登録されていないという問題もあります。

登録されていなかったんですね、知りませんでした。

https://www.iana.org/assignments/character-sets/character-sets.xhtml

需要がなかったのでしょうか……;;

p. 206

HTML のDTD において、「copy という名前は © を表す」という定義がなされているため、……

このあたりは HTML 4.01 の話です。HTML5DTD は存在しません。

p. 208

Shift_JIS を用いる場合はリスト 6.1 の例の「UTF-8」の部分を「Shift_JIS」に、EUC-JP の場合は「EUC-JP」にします。

HTML の <meta charset="hogehoge"> を説明している箇所です。ただし、この本が参照している HTML 5.2 には

Authors should use UTF-8. Conformance checkers may advise authors against using legacy encodings.

という説明があり、「UTF-8 を使用すべき」となっています。一方、HTML Living Standard ではさらに進んで

The Encoding standard requires use of the UTF-8 character encoding and requires use of the "utf-8" encoding label to identify it. Those requirements necessitate that the document's character encoding declaration, if it exists, specifies an encoding label using an ASCII case-insensitive match for "utf-8". Regardless of whether a character encoding declaration is present or not, the actual character encoding used to encode the document must be UTF-8.

という記述になっており、「UTF-8 を使用しなければならない」ことになりました。

p. 216

URL の中に、予約されている記号や、ASCII で表現できない文字を書きたいときには、URL 符号化という方法が使われます。

この本では触れられていませんが、ドメイン名部分は Punycode によって符号化されます。例えば、https://日本語.jphttps://xn--wgv71a119e.jp になります。

p. 222

クライアントからの送信に使われる文字コードは、HTML の form 要素の accept-charset 属性で明示的に指定することもできます。accept-charset="Shift_JIS" と指定すれば Shift_JIS で送信するということです。

HTML 5.2 では

[...] each token must be an ASCII case-insensitive match for one of the labels of an ASCII-compatible encoding.

となっています。一方、HTML Living Standard では

If specified, the value must be an ASCII case-insensitive match for "UTF-8".

と規定されており、こちらも UTF-8 固定になりました。

p. 226

最後に、これからの日本語メールの符号化がどうあるべきかを考察しました。

初版の名残です。初版では今後についての考察があったのですが、UTF-8 の普及により、改訂新版ではこれが削除されています。

p. 293 表 8.1

表のタイトルが「ベンダー依存の変換の問題の発生する代表的な文字」になっていますが、おそらく表 8.2からの編集ミスです。


[改訂新版]プログラマのための文字コード技術入門 (WEB+DB PRESS plusシリーズ)

[改訂新版]プログラマのための文字コード技術入門 (WEB+DB PRESS plusシリーズ)

type の話

はじめに

この記事は、Feedforce Advent Calendar 2018 の 23 日目の記事です。前日は、あおいさんによる「平成の終わりに非ヲタに聴いてほしいハロプロソング5選」でした。ハロプロ……自分が音楽に疎すぎて話が広げられないのですが、あれですよね、℃-ute が話題になって来たころ、こう文字コード的にチャレンジングなユニット名だな、などと考えていたのが記憶に残っています。

さて、ここから本題で、今回はとりとめもなく type について書いてみます。

type

type とはそのまま「型」なんですが、文字界隈のみなさんはご存じのとおり、活字だったり、その書体だったり、そのへんのものをざっくり type と呼びます。もう少しきっちり言うと、活字(スタンプみたいなあれです)は movable type で、いろいろ並べ替えて使える文字の型、といった感じでしょうか。活字を組む(並べる)ことは組版 typesetting ですし、活字の表面に凸状に浮かび上がっている文字の形は書体 typeface といいます。まんまですね。

活字を組んできれいな版面を作る技術がタイポグラフィ typography で、誤植の typo は typographic error の略らしいです。会社名や商品名の「ロゴ」はロゴタイプ logotype の略ですね。活字で文書を書く機械はタイプライター typewriter ですし、タイプライターを打つことはタイピング typing です。タイプライターを電信(電気通信)と組み合わせたシステムがテレタイプ teletype で、そこから来た TTY という略称・概念は、今でも Unix 系のシステムで目にします*1

あ、ちなみに金属活字は、母型(ぼけい)という鋳型に鉛合金を流し込んで鋳造するんですが、母といっても英語では matrix ですね。

f:id:mashabow:20181223233559j:plain
金属活字とその母型*2

現代のデジタルフォントはデータ以外に実体がありませんが、そのフォントフォーマットには TrueType や OpenType という名前がつけられています。フォントのデザイナーは type designer ですし、フォントを制作している会社は type foundry(つまり活字鋳造所)と今でも呼ばれます。わたしは前職、タイププロジェクトという会社でフォントのエンジニアをしていました*3

さてさて。

7月にそのタイププロジェクトを退職し、現在フィードフォースでフロントエンドエンジニア修行中です。自分が所属しているプロダクトで、TypeScript を導入しようということになり*4、ここしばらく TypeScript と格闘しています。

TypeScript。Microsoft が TypeScript を公開した2012年にこんなことをつぶやいていたのですが、

結局今年の夏まで勉強せずに来てしまったため、上記の type 好きとしては若干引け目を感じておりました。ちなみに文字界隈で script といえば「用字系」の意味ですね。

導入時の設定(tsconfig.json, TSLint, Babel, Webpack, …)に慣れていなくて苦労しましたが、文法や概念自体は比較的すんなり飲み込めた感触です。昔ちょっと触った C#ActionScript をふわっと思い出しました。入門者向けのガイドだと、ES201x 側の機能の説明にページが割かれているものが多かったんですが、その点、@vvakame さんの以下のサイトはコンパクトで、手っ取り早く学ぶにはちょうどよい感じでした。

入門レベルを脱した後も、Qiita 上の TypeScript x.y.z 変更点 記事にはいつもお世話になっています。

で、静的型付けや型推論、やっていることや仕組みはなんとなくわかるのですが、ちゃんとした仕組みについてはそういえば理解していませんでした。また、社内の関数型プログラミングに強いエンジニアから関数型プログラミング圧を感じることもあり、いい加減そのへん勉強しようかと、適当に検索して出てきた筑波大の講義資料でも読んでみました。

そしたら、なかなかおもしろいんです。型なしラムダ計算のあたりは自分も学部時代に講義でやって、おもしろいー!と思っていたんですが、その自然な延長で型付け・型推論ができるんですね。この次は何を読めばいいのかな、と思って「おすすめの(わかりやすい)本などあったら教えてください 🙏」と社内のフロントエンドミーティングで聞いてみたところ、以下のふたつをおすすめされました。

前者はちょうど読み終えたところなんですが、演習問題があって回答を自動で採点してくれるところがおもしろいですね。JavaScript は分かっている人向けです。英語の言い回しがちょっと難しい気がしますが、関数型プログラミングに対する苦手感(昔 Lisp を触ろうとしてどうも馴染めなかった)はだいぶ解消されました。この調子で、後者のすごいH本もこれから読もうかと思います。

おわりに

というわけで、近況報告も兼ねて、とりとめのない type の話でした。そのうち、「どちらの type にも詳しいです!!!」と言えるようになりたいですね。

明日の Feedforce Advent Calendar 2018@meihong さんです。なにやら、なにかしらハートフルな内容を書いてくださるようです。それでは良い休日を!

*1:テレタイプは文字コードの歴史的にもおもしろいので、興味のある方は『文字符号の歴史―欧米と日本編』あたりをどうぞ。

*2:2017年3月11日に開催された《タイポグラフィの世界5 戦後日本の金属活字》で展示されていたものです。

*3:NHK 美の壺 取材こぼれ話 のページの《2018年6月22日放送 「心を伝える フォント」こぼれ話》という項に、タイププロジェクトの職場の様子(と自分の顔面)がちらっと載っています。

*4:正確に言うと、Flow から TypeScript への移行です。

フォントまわりのツールの探し方

Twitter 上でとある鍵アカ氏が「このツール知らなかった! 使ってみたらべんり! 楽しい!」的なことをつぶやいていました。フォントの世界にはお役立ちツールがいろいろとあるのですが、日本語での情報が少ないこともあり、とっかかりが難しいかもしれません。そこでこの記事では、「ツールを探すならまずはここから」という定番の情報源を3つ紹介しておきます。

1. awesome-typography

github.com

フォント関連のさまざまなツールがリストアップされたリンク集です。ツールだけでなく、オープンソースのフォントや、フォント関連のドキュメントなども一緒に挙げられています。

プログラミング言語別に並んでおり、ごく簡単な説明もついていますので、「この言語でうまいことあれをやってくれるツールないかなー?」というときには真っ先にチェックすべきページです。

2. 技術カンファレンスの動画

フォント関係のカンファレンスというと ATypI が有名ですが、TYPO LabsRobothon のように、技術的側面に特化したカンファレンスも開催されています。定番ツールから尖ったツールまで、作者の解説や実演デモをじっくり見ることができます。以下のように動画が公開されており、カンファレンスに行かずとも視聴できるのが嬉しいところです。

3. TypeDrawers

TypeDrawers は、書体制作やレタリング、タイポグラフィに関する掲示板です。プロの書体デザイナーや開発者が多く、活発な議論がなされています。いくつかのカテゴリーに分かれていますが、ツールの話題を探すのであれば、下の2つがメインになるでしょう。

いろいろなスレッドが立ちますので、全部追いかけようとすると大変かもしれませんが、最新の動向や界隈の評判などをチェックすることができます。フォント界の Stack Overflow のような存在です。アカウント登録をして、やりとりに参加するのも良いかもしれません。

その先へ

以上、3つのソースをさらっと紹介しました。気になるツールや愛用のツールが出てきたら、そのツールのリポジトリ/フォーラムを覗いたり、作者の Twitter をフォローしたりすると、芋づる式に世界が広がっていきます。巨人の肩の上に乗って満喫しましょう。

追記:OpenType の仕様に興味が出てきたら以下の記事もどうぞ。

タイププロジェクト株式会社を退職しました

2018年7月10日付けでタイププロジェクト株式会社を退職しました。

大学在学中の2012年8月からタイププロジェクトの仕事をするようになり、その後タイプエンジニア(フォントエンジニア)として2015年4月に入社しました。あわせると、6年近くにわたってお世話になったことになります。

タイププロジェクトがコンパクトなチームだったこともあり、製品版フォントのプロダクション、フォーマット変換やカスタマイズ、内製ツールの開発、制作ワークフローの自動化・省力化、イントラの管理などなど、とにかくいろいろなことに携わることができました。仕事を始めた当初はほとんど何もわかっていなかったのですが*1、おかげさまで随分いろいろなことができるようになり、自信もつきました。フォントへの興味がますます深まったのは、言うまでもありません。

タイププロジェクトに参加するまであまり想像していなかったのですが、実際の仕事では、タイプデザイナーなど他のメンバーとのコミュニケーションが頻繁に発生します。「こういう機能がほしい」「こんな感じならできるけど」とやりとりしながら開発を進めていく過程は、なかなか楽しいものでした。まわりの方が協力的で、この点において恵まれた環境だったと感じます。

ちなみに、明日からは別の会社にフロントエンドエンジニアとして入社します。文字関係の仕事ではありません。エンジニアとしてあらためて基礎固めを行い、実践的なチーム開発のスキルを身につけることができれば、と考えています。

仕事としては文字から離れることになりますが、あいかわらず興味は尽きませんので、これからもこのまま趣味として続けていきたいと思います。今後ともどうぞよろしくお願いいたします。

*1:Python を身に着けたのも実はこのときです。

Python パッケージとして再構成された AFDKO 2.7 がリリース

AFDKO の新バージョン 2.7.0 が先週リリースされました。AFDKO は、フォント開発のための Adobeコマンドラインツール集です。

github.com

Python パッケージ化

今回の大きな変更点は、AFDKO の中身がひとつの Python パッケージへと、がらっと再構成された点です。

The AFDKO has been restructured so that it can be installed as a Python package. It now depends on the user's Python interpreter, and no longer contains its own Python interpreter.

https://github.com/adobe-type-tools/afdko/tree/2.7.0#major-changes

すでに PyPIafdko パッケージがアップロードされていますので、普段の Python パッケージと同じく、以下のコマンドでインストールすることができます。

$ pip install afdko

従来(2.5 まで)の AFDKO は、スクリプトやバイナリ等が Python インタプリタとともに ZIP で固められて配布されており、AFDKO 中の Python スクリプトは、必ずこのインタプリタを使って実行されるようになっていました。また、これを実現するためにインストール方法やパスの管理が独自のものになっており、少々扱いづらい面がありました。

Python パッケージへの再構成作業は2017年末ごろからスタートし、ベータ期間(2.6 がこれに相当)を経て、今回の 2.7.0 をもってめでたく正式リリースとなったようです。この Python パッケージ化によって、以下のようなメリットが享受できそうです。

  • インストール/アンインストール/更新が、おなじみの pip で行えるようになる
  • バージョンの固定や切り替えが容易になる
  • 他の Python パッケージと組み合わせて使いやすくなる
  • パッケージのビルド方法やテスト方法が整備・明文化される

AFDKO 開発の盛り上がり

AFDKO の開発は、Adobe のエンジニアが中心となって進められていますが、昨年まではあまり活発には見えませんでした。バリアブルフォントへの対応などは進められていたようですが、発展著しい fontTools などと比べてしまうと、地味な印象がありました。また、AFDKO には

  • コードの可読性が低い
  • テストがほどんどない
  • 古い C のコードが多い
  • バグ報告やプルリクエストがなかなか対応されない
  • バグがあっても自分では直しにくい
  • Python 2

などのつらい面も多々あり、個人的にはここ数年、fontTools の方を利用する機会が圧倒的に多くなっていました。

しかしながら、昨秋ごろから開発が加速し、現在に至るまで活発な状態が続いています。

内容としては、コードのリファクタリングやテスト・CIの整備といった基礎的な部分の改善が大きくなっており、前述の Python パッケージ化も、その流れの中で実施されたように見えます。Python 3 をサポートするための作業も始まり、明るい未来が見えてきた感じがします。

期待を込めつつ、これからも引き続き AFDKO の動きに注目していこうと思います。

fontTools のペンを使ってグリフのアウトラインを取得する

先日 Twitter で、「グリフのアウトラインの座標列を取りたいんだけど」「それ pen protocol でできるよ!」というやりとりをしました。この記事では、pen protocol に対応したペンでアウトラインを取得する方法について、具体的に解説してみます。

pen protocol とペン

さて、そもそも pen protocol とは何でしょう? 今回はプロトコルの詳細には触れず、概観だけ説明します。

フォント界隈では Python が共通言語になっています。しかし、グリフを表すためのオブジェクトは、フォントエディタ(Glyphs, RoboFont, FontLab, ...)やライブラリ(fontTools, ufoLib, defcon, fontParts, ...)ごとにそれぞれ独自に定義されています。ざっくり言ってしまうと、「どんなグリフオブジェクトであれ、共通のインターフェイスでアウトラインを読み書きできると楽だよね」「SVG や PDF やいろんな描画 API にも対応したいよね」というのが pen protocol の発想です。pen protocol によってグリフからアウトラインを得たり、アウトラインを描いたりするためのオブジェクトをペン(pen)と呼びます。

pen protocol が広まった結果、現在までにいろいろなペンが実装されてきました。以下にいくつか例を挙げますが、これ以外にも存在しています。

なお、pen protocol には segment pen protocolpoint pen protocol の2系統があり、前者に対応したペンは HogePen、後者は HogePointPen のようなクラス名になっているのが通例です。この記事では、前者 segment pen protocol のペンをとり上げます*1

フォントを読み込んでグリフを準備する

以下、環境は Python 3.6.3, fontTools 3.20.1 です。fontTools は $ pip install fonttools でインストールできます。

ペンのことは一旦あと回しにして、まずはフォントファイルを読み込みます。今回は例として、源ノ角ゴシック Regular SourceHanSans-Regular.otf を使いました。

from fontTools.ttLib import TTFont
font = TTFont('SourceHanSans-Regular.otf')

次に、glyphSet と呼ばれる辞書様オブジェクトと、cmap(文字コードとグリフ名の対応)を取得しておきます。後者に関しては、従来 cmap テーブル font['cmap'] からサブテーブルを選んで辿っていく必要がありましたが、最近追加されたお手軽便利メソッド getBestCmap() でいい感じに取得できます。

glyph_set = font.getGlyphSet()  # {グリフ名: グリフ} っぽいオブジェクト
cmap = font.getBestCmap()       # {Unicode: グリフ名}

これらを使って、文字 char に対応したグリフオブジェクトを返す関数を作ります。

def get_glyph(glyph_set, cmap, char):
    glyph_name = cmap[ord(char)]
    return glyph_set[glyph_name]

例として、文字 "L" に対応するグリフオブジェクトを、 L としておきましょう。

L = get_glyph(glyph_set, cmap, 'L')

これでグリフの準備はできました。

RecordingPen でアウトラインの内容を得る

さて、アウトラインの内容を取得するためには、fontTools に同梱されている RecordingPen というペンを使います。まずはペンのインスタンスを作成します。

from fontTools.pens.recordingPen import RecordingPen
recording_pen = RecordingPen()

次に、このペンをグリフ上で動かします。pen protocol に対応したグリフオブジェクトは draw() メソッドを持っていますので、これにペンを渡して実行します。先ほどの "L" のグリフ L を使ってみましょう。

L.draw(recording_pen)

ペンで "draw" と言われると、どこかに描く・書き込むのかと思ってしまいがちですが、ここではグリフのアウトラインを「なぞる」行為のことだと捉えてください。この RecordingPen では value 属性になぞった結果が入っていますので、見てみましょう。

print(recording_pen.value)
[('moveTo', ((100, 0),)),
 ('lineTo', ((513, 0),)),
 ('lineTo', ((513, 79),)),
 ('lineTo', ((193, 79),)),
 ('lineTo', ((193, 733),)),
 ('lineTo', ((100, 733),)),
 ('closePath', ())]

目的どおりアウトラインの内容が出てきました。"L" の左下の点からスタートし、反時計回りにパスが構成されているのが分かります。

もうひとつ、"い" のグリフで試してみるとこうなります。

い = get_glyph(glyph_set, cmap, 'い')
recording_pen = RecordingPen()
い.draw(recording_pen)
print(recording_pen.value)
[('moveTo', ((226, 696),)),
 ('lineTo', ((130, 698),)),
 ('curveTo', ((135, 674), (136, 633), (136, 610))),
 ('curveTo', ((136, 552), (137, 432), (147, 346))),
 ('curveTo', ((174, 89), (264, -4), (357, -4))),
 ('curveTo', ((425, -4), (486, 53), (545, 221))),
 ('lineTo', ((482, 293),)),
 ('curveTo', ((456, 193), (410, 91), (359, 91))),
 ('curveTo', ((289, 91), (241, 200), (225, 366))),
 ('curveTo', ((218, 447), (217, 538), (218, 600))),
 ('curveTo', ((219, 626), (222, 672), (226, 696))),
 ('closePath', ()),
 ('moveTo', ((742, 669),)),
 ('lineTo', ((664, 642),)),
 ('curveTo', ((758, 526), (818, 330), (835, 152))),
 ('lineTo', ((916, 184),)),
 ('curveTo', ((902, 351), (831, 554), (742, 669))),
 ('closePath', ())]

曲線を中心とした、2つのパスで構成されています。

SVGPathPen を利用してSVGを作成する

今度は応用として、SVGPathPen というペンを使ってみましょう。このペンは、SVGパスデータ文字列を組み立ててくれます。SVGPathPen のコンストラクタは引数に glyphSet をとりますので、最初の方で用意した glyph_set を渡します。

from fontTools.pens.svgPathPen import SVGPathPen
svg_path_pen = SVGPathPen(glyph_set)

グリフ L をなぞった後、getCommands() メソッドでパスデータ文字列を取得します。

L.draw(svg_path_pen)
print(svg_path_pen.getCommands())
M100 0H513V79H193V733H100Z

パスデータ文字列が表示されました。左下の点 100 0 からスタートし、水平線 H と垂直線 V でパスが構成されています。

以下のようにガワを手書きして、独立したSVGファイルを作ります。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
    <path d="M100 0H513V79H193V733H100Z"/>
</svg>

このSVGファイルをブラウザで表示してみると、こんな感じです。

一応「L」のグリフが表示できました。が、上下逆さです。OpenType の座標系では y 軸が上方向に延びていますが、SVG では下方向に延びているため、そのままだと上下がひっくり返ってしまいます。transform 属性で上下を逆にし、viewBox 属性も調整しましょう。

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -1000 1000 1000">
    <path d="M100 0H513V79H193V733H100Z" transform="scale(1, -1)"/>
</svg>

これで正立しました。

最後に、もうちょっといい感じのSVGファイルを生成する関数を定義してみます。

from textwrap import dedent

def save_as_svg(font, char, output_path):
    '''TTFont オブジェクトを受け取り、指定した文字のグリフを SVG として保存する'''
    
    glyph_set = font.getGlyphSet()
    cmap = font.getBestCmap()
    
    # グリフのアウトラインを SVGPathPen でなぞる
    glyph = get_glyph(glyph_set, cmap, char)
    svg_path_pen = SVGPathPen(glyph_set)
    glyph.draw(svg_path_pen)

    # メトリクスを取得
    ascender = font['OS/2'].sTypoAscender
    descender = font['OS/2'].sTypoDescender
    width = glyph.width
    height = ascender - descender
    
    content = dedent(f'''\
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 {-ascender} {width} {height}">
            <g transform="scale(1, -1)">
                <!-- ボディの枠 -->
                <rect x="0" y="{descender}" width="{width}" height="{height}"
                    stroke="cyan" fill="none"/>
                <!-- グリフ座標系の原点 -->
                <circle cx="0" cy="0" r="5" fill="blue"/>
                <!-- グリフのアウトライン -->
                <path d="{svg_path_pen.getCommands()}"/>
            </g>
        </svg>
    ''')
    
    with open(output_path, 'w') as f:
        f.write(content)

"L" と "い" で実行してみます。

save_as_svg(font, 'L', 'L.svg')
save_as_svg(font, 'い', 'い.svg')

こんな感じの SVG ファイルができました。めでたしめでたし。

おわりに

この記事では pen protocol の概要を説明し、ペンを使ってアウトラインを取得したり、SVG として表示する方法について見てきました。一方、今回触れなかった話題としては、

  • pen protocol の詳細とペンの定義方法
  • グリフへの書き込み
  • ペンを利用したアウトラインの加工
  • さまざまなペンの紹介

などがあります。これらに関しては、またいずれ気が向いたときに記事を書くかもしれません。

なお、今回のファイルは以下のリポジトリにまとめておきました。どうぞご利用ください。

github.com

*1:若干紛らわしいのですが、segment pen protocol は単に pen protocol と呼ばれることがあります。

TTXによるフォントのチラ見をちょっといい感じにする設定

github.com

仕事場/プライベート問わずに大活躍の fontTools ですが、その中でも頻出なのが「フォントファイルを TTX でダンプして中身をチラ見したい」という場面です。

$ ttx -o out.ttx [オプション] font.otf
$ less out.ttx

つい最近まで、上のようにしてごく普通に中身を見ていたのですが、何度もやっているといい加減めんどくさくなってきます。そこで、.zshrc(適宜 .bashrc などに読み替えてください)に簡単なシェル関数を定義してみました。

tl() {
    ttx -q -o - $* | source-highlight -s xml -f esc | less
}

関数名はなんでもいいのですが、ttxless なので短く tl にしておきました。途中の source-highlightGNU Source-highlight というシンタックスハイライトの定番ツールです。こうしておけば、

$ tl [オプション] font.otf

とするだけでちょっといい感じに中身がチラ見できるようになります。べんり。

f:id:mashabow:20170111232302g:plain