はじめに
最近、Google Fontsにたくさんの日本語フォントが追加になりました。1
画像加工のクラウドサービスCloudinaryで新しい日本語を使えるようにするために、全ファイルをアップロードしました。
その時に使ったスクリプトを共有します
おさらい
Cloudnaryは画像を保存して配信するサービスです。画像を配信するときに、変形や文字入れの加工ができます。
Cloudinaryは文字入れ(オーバーレイ変換)をするときにフォントを指定することができるのですが、サポートされている日本語フォントがいまいちです。はっきり言ってしょぼいです。
フォントの種類が足りない場合は、フォントファイルをアップロードすることができるようになっています。2
面倒なので、Google Fontsにある日本語フォントファイルを全部アップロードしてしまいます。
使ったもの
- PHP (5.6)
- Google Fonts API
- Coudinary api + node SDK
"c:\Program Files\php-5.6.39-Win32-VC11-x64\php.exe" -v
PHP 5.6.39 (cli) (built: Dec 5 2018 21:24:55)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
CloudinaryのPHP SDKがPHP5.6を使えと言っているため。いまさら5.6で実施3
やること
- google font apiで日本語のフォントを探す
- フォントファイル(.ttf/.otf)をダウンロードする
- Cloudinaryにアップロードする
Google Fonts APIは無料で使えます。GoogleアカウントでAPIのトークンをとっておく必要があるので、自分でとりましょう。
フォントファイルを持ってくる部分と、Cloudinaryにアップロードする部分を2つにわけました。
準備
composer.jsonを作ってSDKをインストール
{
"require": {
"cloudinary/cloudinary_php": "^2"
},
"config": {
"platform": {
"php": "5.6.39"
}
}
}
Cloudinaryのマニュアルにはrequire
しか書いてないけど、PHPのバージョンを指定してインストール
composer install
コード1 (google font api)
Google Fonts APIからデータを持ってくる部分。
このAPIはパラメータで絞り込みができないので、全フォントデータを持ってきてからデータをフィルタする実装です。
日本語対応かどうかは、subsets
の配列の中にjapanese
が入っているかで判断しています。
1つのフォントに複数のスタイルが設定されている場合、フォントファイルも複数になるのでfiles
の配列から全部持ってきます。
フォントファイルの名前は以下のルールにします。この名前がそのままCloudinaryのpublic_idになり、URLで指定するフォント名となります。
font family
-font style
.拡張子(ttf or otf)
ただし、スタイル名がregularのときは、付けると長くなるので省略します。
<?php
$google_api_token = 'Your TOKEN';
$font_api_url = 'https://www.googleapis.com/webfonts/v1/webfonts?key=' . $google_api_token ;
$font_json = file_get_contents($font_api_url);
$font_list = json_decode($font_json, true);
foreach($font_list['items'] as $n=>$font){
echo ($n+1).'/'.count($font_list['items']) . " " . $font['family'] . PHP_EOL;
//日本語フォントだけ
if( in_array('japanese', $font['subsets'] )){
echo $font['family'] . PHP_EOL;
echo count($font['files']) . PHP_EOL;
$file_name_font_family = $font['family'];
foreach($font['files'] as $style=>$url){
echo " $style : $url" . PHP_EOL;
//スタイルがregularではない時だけ、ファイル名に付ける
$file_name_font_style = '';
if($style !== 'regular'){
$file_name_font_style = '_'.$style;
}
//ファイル名の拡張子は最後の.以降の文字
$splitted_url = explode('.', $url);
$file_name_ext = end($splitted_url);
//ファイル名完成
$file_name = "${file_name_font_family}${file_name_font_style}.${file_name_ext}";
//ファイルをとってきて保存
$font_data = file_get_contents($url);
$bytes = file_put_contents('fonts/' . $file_name, $font_data);
}
}
}
これを実行すると、getGoogleFont.js
の下に/fonts
フォルダが作られて、フォントファイルがダウンロードします。
2021/9/18時点だと、78ファイルをダウンロードできました。
コード2 (Cloudinary)
ローカルディスクにあるフォントファイルを順番にアップロードする部分。
Google Fontsに無いフォントでも、fonts
フォルダ内におけばアップロードします。
<?php
require_once "vendor/autoload.php";
use Cloudinary\Cloudinary;
$cloudinary = new Cloudinary('cloudinary://apikey:secret@cloudname');
foreach( glob('fonts/*') as $file){
$file_name = pathinfo($file)['basename'];
echo "uploading $file_name..." . PHP_EOL;
$api_options = ['resource_type'=>'raw','type'=>'authenticated', 'public_id'=>$file_name];
try{
$result = $cloudinary->uploadApi()->upload($file, $api_options);
echo "uploaded. public_id is " . $result['public_id'] . PHP_EOL;
}catch(Exception $ex){
echo "error" . PHP_EOL . $ex->getMessage() . PHP_EOL;
}
}
フォントファイルのサイズが大きすぎてエラーになるものがあります。
Cloudinaryの仕様上、1ファイルの最大が10485760バイト(10メガバイト)なのであきらめましょう。
[2021-09-18 20:23:49] cloudinary.CRITICAL: Request to Cloudinary server returned an error {"statusCode":400,"message":"File size too large. Got 33153716. Maximum is 10485760."} []
[2021-09-18 20:23:49] cloudinary.CRITICAL: Async request failed {"code":0,"message":"File size too large. Got 33153716. Maximum is 10485760."} []
[2021-09-18 20:23:49] cloudinary.CRITICAL: Single Chunk Async POST request failed {"code":0,"message":"File size too large. Got 33153716. Maximum is 10485760."} []
error
File size too large. Got 33153716. Maximum is 10485760.
しっぽり明朝系は全滅でした。残念。
アップロードしたフォントを使ってみる
9回オーバーレイをするとこんな感じです。

URL
上のURL。実際は1行で書きます。
https://res.cloudinary.com/kanaxx
/g_north_west,co_rgb:FFF,l_text:M%20PLUS%20Rounded%201c.ttf_80:%E5%B7%A6%E4%B8%8A
/g_north,co_rgb:FFF,l_text:Dela%20Gothic%20One.ttf_80:%E4%B8%8A
/g_north_east,co_rgb:FFF,l_text:Hachi%20Maru%20Pop.ttf_80:%E5%8F%B3%E4%B8%8A
/g_west,co_rgb:FFF,l_text:Hina%20Mincho.ttf_50:%E3%81%B2%E3%81%A0%E3%82%8A
/g_center,co_rgb:FFF,l_text:Kaisei%20Decol.ttf_50:%E3%81%BE%E3%82%93%E3%81%AA%E3%81%8B
/g_east,co_rgb:FFF,l_text:Kaisei%20HarunoUmi.ttf_50:%E3%81%BF%E3%81%8E
/g_south_west,co_rgb:FFF,l_text:Kiwi%20Maru-500.ttf_30:%E3%83%92%E3%83%80%E3%83%AA%E3%82%B7%E3%82%BF
/g_south,co_rgb:FFF,l_text:Kosugi%20Maru.ttf_30:%E3%82%B7%E3%82%BF
/g_south_east,co_rgb:FFF,l_text:Potta%20One.ttf_30:%E3%83%9F%E3%82%AE%E3%82%B7%E3%82%BF
/600x500.png
デコードすると
https://res.cloudinary.com/kanaxx
/g_north_west,co_rgb:FFF,l_text:M PLUS Rounded 1c.ttf_80:左上
/g_north,co_rgb:FFF,l_text:Dela Gothic One.ttf_80:上
/g_north_east,co_rgb:FFF,l_text:Hachi Maru Pop.ttf_80:右上
/g_west,co_rgb:FFF,l_text:Hina Mincho.ttf_50:ひだり
/g_center,co_rgb:FFF,l_text:Kaisei Decol.ttf_50:まんなか
/g_east,co_rgb:FFF,l_text:Kaisei HarunoUmi.ttf_50:みぎ
/g_south_west,co_rgb:FFF,l_text:Kiwi Maru-500.ttf_30:ヒダリシタ
/g_south,co_rgb:FFF,l_text:Kosugi Maru.ttf_30:シタ
/g_south_east,co_rgb:FFF,l_text:Potta One.ttf_30:ミギシタ
/600x500.png
Cloudinary SDKを使うとエラーになるとき
このエラーが出るときは、たぶんPHPのバージョンが違います。
PHP Fatal error: Declaration of Cloudinary\Log\LoggerDecorator::emergency($message, array $context = []) must be compatible with Psr\Log\LoggerInterface::emergency(Stringable|string $message, array $context = []): void in C:\work\cloudinary-font\vendor\cloudinary\cloudinary_php\src\Log\LoggerDecorator.php on line 195
PHP8にCloudnarySDKをインストールして使ったらエラーになりました。
GithubのREADMEにv5.6って書いてあります。