0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Noto Sans のサブセットが CJK を含んでいなかったので、エクスポートを画像 PDF に切り替えた

0
Posted at

背景

私は LiveSuggest という会議アシスタントを作っています。画面上に表示しておくタイプのツールで、通話に bot は参加しません。この記事では、会議セッションを PDF に書き出す機能で多言語対応がうまくいかなかった件と、その対処をまとめます。

もともとの構成

セッションのエクスポートでは、テキストを選択できる PDF を生成しています。生成には pdf-lib を使い、フォントには Noto Sans のサブセットを埋め込んでいます。

ラテン文字のセッションでは、この構成で問題は出ていませんでした。

原因

埋め込んでいるサブセットが対応している文字体系は、ラテン文字、キリル文字、ギリシャ文字です。CJK、ハングル、アラビア文字、タイ文字、デーヴァナーガリーは入っていません。

フォントに含まれていない文字は、そのフォントでは描画できません。そのため、日本語、韓国語、中国語のセッションは、テキスト PDF の経路では正しく書き出せない状態になっていました。

対処として、Unicode 判定で経路を分けた

エクスポートのときに本文の文字を Unicode で判定して、どちらの経路を使うか決めるようにしました。

日本語、韓国語、中国語が含まれていれば、html2pdf で画像 PDF を生成します。この分岐にはユニットテストを書いてあります。

トルコ語とポーランド語はラテン文字系なので、テキスト PDF のまま出力します。キリル文字とギリシャ文字もサブセットに含まれているので、同じくテキスト PDF です。テキストを選択できる出力を残せる言語では、そちらを優先しています。

レンダラーが失敗したときのフォールバック

テキストレンダラーが失敗した場合も、同じ画像 PDF のフォールバックに切り替えます。判定とは別にもう一つ逃げ道を用意しておいて、テキスト経路で何か起きてもエクスポート自体は完了するようにしています。

フォールバック先を一つにまとめたので、画像 PDF の経路は CJK の分岐とレンダラー失敗時の両方から使われます。

トレードオフ

画像 PDF にすると、文字の選択ができなくなります。日本語、韓国語、中国語のセッションについては、テキストとして選択できることより、とにかく文字が表示されることを優先しました。

アラビア文字、タイ文字、デーヴァナーガリーもサブセットには入っていません。これらの扱いは今回の CJK の分岐とは分けて考える必要があり、この記事では結論を書いていません。

振り返り

フォントをサブセット化するときは、どの文字体系が残るのかを最初に把握しておくべきでした。サブセットの範囲がわかっていれば、範囲外の言語を判定で振り分ける設計は最初から組めます。

もう一つは、分岐の判定ロジックにテストを付けておくことです。どの言語がどちらの経路に行くかは、コードを読むだけでは見落としやすいので、テストで固定しておくと安心できます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?