はじめに
OpenTypeフォントには「palt(Proportional Alternate Widths)」という機能があります。これは、字形の左右の余白を調整し、いわゆるプロポーショナルな文字組を実現するための仕組みです。CSSではfont-feature-settings: "palt"
として有効化します。
しかし、このpaltはすべてのフォントで使えるわけではありません。InDesignでは「オプティカルカーニング」という名称でプロポーショナルメトリクスを持たないフォントについても字形に基づいた詰め処理を提供しており、日常的に使用されていると認識しています。本記事ではWebページやCSS組版における代替案を2つ紹介します。
以下の例で使用しているのは「Zen Kaku Gothic Antique」です。
あるフォントが提供しているOpenType機能を調べるにはotfinfo
コマンドが便利です。以下の通り、Zen Kaku Gothic Antiqueはpaltを提供していません。
$ docker run --rm --interactive --tty --mount type=bind,source=.,target=/workdir --workdir /workdir registry.gitlab.com/islandoftex/images/texlive:TL2024-historic otfinfo -f ZenKakuGothicAntique-Regular.ttf
aalt Access All Alternates
case Case-Sensitive Forms
ccmp Glyph Composition/Decomposition
frac Fractions
fwid Full Widths
hwid Half Widths
kern Kerning
mark Mark Positioning
mkmk Mark to Mark Positioning
ordn Ordinals
sups Superscript
vert Vertical Writing
vkna Vertical Kana Alternates
vrt2 Vertical Alternates and Rotation
Canvasで字形を解析して詰める
まず紹介するのは、Canvasを使用するアプローチです。1文字ずつ文字を描画して、ビットマップ画像を解析して字形(この実装では凸包)を取得し、詰め幅を得ます。テキストノードを個別のspan
要素に分け、それぞれにletter-spacing
を適用することで文字間隔を調整します。
この方法は、字形そのものに基づいた詰め処理を行うため、比較的複雑な形状も扱えるのが特徴です。「チ」と句点「。」のようにアキが噛み合った文字同士なら、潜り込むような間隔で並べることもできます。
一方で、この処理をクライアント側でのスクリプト実行でおこなう場合、初回ロード時の処理負荷が高くなる課題もあります。画像サイズを小さくすれば負荷は軽減されますが、そのぶん形状の精度は下がります。対策として、上記の実装では、JSOM文字列で詰め量を文字ごとにキャッシュできるようにしてあります。またNode.js(JSDOM)でも使えるため、事前にサーバー上で詰め処理を適用したHTMLを生成できるようになっています。
フォントファイルを加工してpaltを有効にする
もうひとつの方法は、フォントファイルそのものを加工して、疑似paltを追加・有効化するというものです。具体的には、フォントのGPOSテーブルに細工しています。
$ docker run --rm --interactive --tty --mount type=bind,source=.,target=/workdir --workdir /workdir registry.gitlab.com/islandoftex/images/texlive:TL2024-historic otfinfo -f palt-0_5.ttf | grep palt
palt Proportional Alternate Widths
この方法では、加工後のフォントファイルを一度生成すれば、OpenType機能に対応したすべてのアプリケーションでpalt機能を利用できるようになります。HTMLやCSSに特別な工夫を施す必要がなく、クライアント側での処理負荷も発生しません。
ただし、フォントファイルの改変および再配布には注意が必要です。また、この手法では、元の余白以上の詰めは起こらず、あくまで機械的な均等処理に留まります。