Jim's QR Font は OpenType 機能を使用してテキストから直接 QR コードを生成する

Jim's QR Font は OpenType 機能を使用してテキストから直接 QR コードを生成する

概要

Jim's QR Font は、括弧で囲まれた ASCII 文字列を QR コードのグリフに変換し、それ以外のテキストを通常通りにレンダリングする実験的な TrueType/OpenType フォントです。この手法は OpenType GSUB 機能に依存しており、テキストのレイアウトエンジン内で直接 QR コードの生成を可能にします。


フォントの仕組み

  • [] で囲まれたテキストを QR コードのペイロードとして解析します。
  • 表示可能な ASCII 文字のみが受け入れられます。ペイロードの長さはフォントのバリエーションによって制限されます(17、32、または 53 文字)。
  • ジェネレーターは、バイトモード、固定マスクパターン (0)、および Reed‑Solomon 誤り訂正を使用して QR コードを構築します。
  • QR モジュールのグリフアウトラインはプログラムによって出力されます。周囲の表示可能な ASCII グリフは Liberation Sans Regular からコピーされ、フォントの em square に合わせてスケーリングされます。
  • 元の Liberation フォントとの命名衝突を避けるため、生成されたフォントファミリーは QR Font 1‑LQR Font 2‑L、および QR Font 3‑L と命名されています。

"All fonts use: Byte mode, Printable ASCII input, Fixed mask pattern 0, [ and ] as delimiters" – project README.


利用可能なフォントのバリエーション

バリエーション モジュールグリッド 最大文字数
qrfont-1L.ttf 21 × 21 17
qrfont-2L.ttf 25 × 25 32
qrfont-3L.ttf 29 × 29 53

各バリエーションは GitHub のリリース ページで TrueType ファイルとして配布されています。グリッドが大きくなるほど、視覚的な QR シンボルは大きくなりますが、より長いペイロードをサポートします。


フォントのビルド

リポジトリには、Makefile と uv で管理される Python ベースのビルドパイプラインが提供されています。デフォルトの make ターゲットは、Reed‑Solomon パリティ回路を含むフルビルドを実行し、数千のコンテキスト・ルックアップを生成します。より迅速な反復作業のために、make fast-placeholder を使用して、プレースホルダーのゼロパリティによるレイアウトのみのビルドが可能です。

一般的なビルド手順:

# Install uv (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Build the fonts (full parity)
make

# Or a faster placeholder build
make fast-placeholder

ジェネレーターは、/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf にある Liberation Sans Regular を想定しています。異なるベースフォントを指定することも可能です:

uv run tools/build_font.py --base-font /path/to/YourBaseFont-Regular.ttf

生成されるアーティファクト:

  • dist/qrfont-*.ttf – 3 つのフォントファイル。
  • dist/index.html – インタラクティブなデモページ。
  • build/qrfont-*.fea – 生成された OpenType 機能ファイル。

フォントの使用方法

  1. 生成された .ttf ファイルのいずれかをシステムにインストールします。
  2. OpenType シェイピングをサポートするアプリケーション(例:最新のブラウザ、ワープロ、またはコードエディタ)を開きます。
  3. 括弧で囲まれたペイロードを含む通常のテキストを入力します。例: abc[hello]ghi
  4. 周囲の文字はベースのグリフでレンダリングされますが、括弧で囲まれたセグメントは QR コードとして表示されます。

"Mixed text such as abc[def]ghi should render as normal text, then a QR code for def, then normal text." – README.


技術的な詳細

  • Byte Mode – QR ジェネレーターは各 ASCII 文字を単一のバイトとしてエンコードし、変換を簡約化します。
  • Fixed Mask Pattern 0 – 固定マスクを使用することで、実行時のマスク選択の必要性を排除し、静的なフォントにおける実現可能性を高めています。
  • Reed‑Solomon Parity – OpenType のコンテキスト・ルックアップとして一連のシリーズとして実装されており、誤り訂正データをグリフストリームに直接埋め込むことができます。
  • GSUB Feature Logic – ビルドスクリプトは、区切り文字シーケンスとペイロードを構成要素として、適切な QR モジュール・グリフに置換換する置換機能を出力します。

制限事項

  • このフォントントは、GSUB 機能が適用される環境でしか動作しません。OpenType シェイピングを無視するプレーンテキスト・レンダリング・エンジンは、区切り文字とペイロードを文字としてそのまま表示します。

  • ペイロードの長さは、バリエーションによるモジュールグリッドによって制限されます(17、32、または 53 文字)。

  • 表示可能な ASCII 文字のみがサポートされています。Unicode 文字はエンコードされません。

  • このフォントは概念実証(Proof-of-concept)であり、本番環境での使用を意図していません。


ライセンス

生成されたフォントは、Liberation Sans Regular の Modified Version であり、SIL Open Font License v1.1 に基づいて配布されています。詳細な条件については、リポジトリ内の LICENSE-OFL.txtNOTICE.md を承るります。


結論

Jim's QR Font は、OpenType シェイピングを活用して、機能的な QR コードをテキストストリームに直接埋め込むという、OpenType シェイピングの活用方法の独創的な例を示しています。括弧で囲まれた ASCII 文字を QR グリフとして変換することで、このプロジェクトは、複雑なデータエンコーディングを、フォント内で完結させることで、ウェブやデスクトップ環境において、コードなしで軽量な QR コード生成を可能にする可能性を開示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示示[... (truncated) ...]

Sources