🔠

PHPとfontforgeで実装するWebフォント変換サーバー

に公開

はじめに

Webサイトで好きなフォントを使いたい時、「Webフォント」は非常に強力な選択肢です。しかし、フォント形式にはOTF, TTF, WOFF, WOFF2, EOT, SVGなど様々な種類があり、クロスブラウザ対応を考えると複数の形式を用意する必要があって面倒ですよね。

また、フォントファイルをサーバーにアップロードして変換ツールにかける、という作業も手間がかかります。

この記事では、そんな手間を解消するために、PHPのプログラムからサーバーサイドでフォント形式を自動変換する仕組みを実装した際の知見を共有します。

やりたいこと

  • ユーザーがフォームからOTFまたはTTF形式のフォントファイルをアップロードする。
  • サーバー側で、アップロードされたフォントを主要なWebフォント形式(WOFF2, WOFF, EOT, SVG)に一括変換する。
  • 変換したフォントファイルをZIPファイルにまとめて、ユーザーにダウンロードさせる。

中核を担う技術:FontForgeと各種コンバーター

今回の仕組みの心臓部となるのが、CUI(コマンドライン)で動作するフォント編集・変換ツールです。これらをPHPのexec()関数から呼び出して利用します。

  • FontForge:
    オープンソースの高機能フォントエディタ。コマンドラインからスクリプトを実行でき、OTFからTTFTTFからSVGなど、主要な変換を担います。
  • ttf2eot, ttf2woff, woff2_compress:
    それぞれTTFを各Webフォント形式に変換するための専用コンバーターツールです。事前にサーバーにインストールしておく必要があります。
# 事前に必要なツールをインストールしておく
sudo apt-get install fontforge woff-tools woff2 ...

実装のポイント (CakePHPでの例)

今回はCakePHPのコントローラー内に実装した例を元に、処理の流れを解説します。

1. ファイルのアップロードと前処理

まず、フォームから送信されたフォントファイルを受け取ります。ファイル名に日本語などが含まれているとサーバーで扱いにくいため、Inflector::slug()などを使って英数字の安全なファイル名に変換しておきます。

$data = $this->request->getData();
$tmp_path = TMP . 'web_font_files/';

$original_pathinfo = pathinfo($data['WebFontFile']['ttf']['name']);
// ファイル名をASCII文字のみに変換
$file_name = \Cake\Utility\Inflector::slug($original_pathinfo['filename']);

$ttf_file_name = $file_name . '.ttf';
$ttf_file_path = $tmp_path . $ttf_file_name;

// アップロードされたファイルを一時ディレクトリにコピー
exec("cp {$data['WebFontFile']['ttf']['tmp_name']} " . $ttf_file_path);

2. OTFからTTFへの変換

アップロードされたのがOTFファイルだった場合、まずFontForgeを使ってTTFに変換します。TTFの方が他のWebフォント形式への変換元として扱いやすいためです。

if (!empty($data['WebFontFile']['otf']['name'])) {
    // ...前処理...

    // FontForgeのスクリプト機能を使ってOTFをTTFに変換
    exec('fontforge -lang=ff -c \'Open($1); Generate($1:r + ".ttf")\' ' . $otf_file_path);

    // ...後処理...
}

fontforge -lang=ff -c '...'というコマンドで、FontForgeのスクリプトを直接実行しています。

3. TTFから各種Webフォントへの変換

ベースとなるTTFファイルが用意できたら、そこから各種コンバーターを使ってWOFF2, WOFF, EOT, SVGを生成していきます。

// ttf => svg に変換
exec('fontforge -lang=ff -c \'Open($1); Generate($1:r + ".svg")\' ' . $ttf_file_path);

// ttf => eot に変換
$eot_file_path = $tmp_path . $file_name . '.eot';
exec('ttf2eot ' . $ttf_file_path . ' ' . $eot_file_path);

// ttf => woff に変換
exec('ttf2woff ' . $ttf_file_path);

// ttf => woff2 に変換
exec('woff2_compress ' . $ttf_file_path);

exec()で外部コマンドを順番に実行しているだけですが、これで一時ディレクトリに各形式のフォントファイルが生成されます。

4. ZIP圧縮とダウンロード

最後に、生成された全てのフォントファイルをzipコマンドで一つのファイルにまとめ、一時ファイルを削除してから、ユーザーをダウンロード用のURLにリダイレクトさせます。

$zip_files = '';
// ... 生成されたファイルのパスを$zip_filesにまとめる ...

$dl_file_path = WWW_ROOT . 'files/';
$zip_file = $file_name . '.zip';

// -j オプションでディレクトリ構造を無視して圧縮
exec('zip -j ' . $dl_file_path . $zip_file . $zip_files);

// ... 一時ファイルを削除 ...

// ダウンロードアクションにリダイレクト
return $this->redirect(['action's => 'downloadWebFont', '?' => ['file' => $zip_file]]);

注意点

  • セキュリティ: exec()関数は、ユーザーからの入力をそのまま渡すと非常に危険です(OSコマンドインジェクション)。ファイル名などをescapeshellarg()でエスケープ処理するか、今回の例のようにInflector::slug()で安全な文字列に変換する処理が必須です。
  • サーバー負荷: フォントの変換処理はCPUに負荷がかかります。利用頻度が高いサービスにする場合は、処理をキューイングするなどの非同期化を検討する必要があります。
  • エラーハンドリング: exec()の実行結果をしっかりハンドリングし、変換に失敗した場合の処理を実装することが重要です(コード例では省略しています)。

まとめ

PHPからFontForgeなどのコマンドラインツールを呼び出すことで、Webフォントの変換処理を自動化する仕組みを実装しました。

Webサービスとして公開すれば、デザイナーやフロントエンドエンジニアの面倒なフォント変換作業を効率化できる、価値あるツールになるかもしれません。PHPの可能性とLinuxコマンドの強力さを再認識できた、楽しい開発でした。


この記事で紹介した内容以外にも、技術情報をブログで発信しています。
MyNote
https://mynote.meantix.com/

Discussion