なんとSVG画像からフォント作成できる。
前回まで
じつはIcoMoonというWEBアプリを使えばSVG画像からフォントを作れる。以前に試したことがあった。でもこれ、WOFF2形式は生成してくれない。SVG,TTF,WOFFだけ。
今回
- 自分でSVGフォント・ファイルを書く
- 1をツールでWOFF2ファイルに変換する
- HTMLでフォントを使い表示する
フォント形式
フォントのファイル形式は以下が主流。
| フォント形式 | 概要 |
|---|---|
| SVG | 他のフォント形式に変換するためのソースコードとして使用する |
| TTF | 古いけど頻繁に使われる |
| OTF | 新しく高機能で最強だけど重いし実装大変 |
| WOFF2 | 新しく軽量(高圧縮率) |
フォント業界ではOTFが最強。合字、異体字、文字詰め、カラーフォント等の豊富な機能がある。
OTFをWOFF2に圧縮して使うのが主流。
そして今回はその一番最初であるSVGフォントについて学び、SVG→WOFF2に変換する。
SVGフォント
SVGフォントは、フォント作成用ソースコード形式である。WOFF2など他のフォント形式に変換することで使用できる。
font.svg
フォーマットは以下。
<svg> <def> <font> <font-face /> <glyph unicode="..." d="..." /> </font> </def> </svg>
| 要素 | 意味 |
|---|---|
<font> |
フォント定義 |
<font-face> |
フォントの設定情報 |
<missing-glyph> |
未対応の文字に対する形 |
<glyph> |
文字の形 |
とりあえず以前作成した二つのアイコン画像を使う。これを<svg>丸ごとコピペして上記フォーマットに含める。
<svg xmlns="http://www.w3.org/2000/svg"> <defs> <font id="my-icon-font" horiz-adv-x="256"> <font-face units-per-em="256" ascent="240" descent="-16" /> <missing-glyph horiz-adv-x="256" /> <glyph unicode=" " horiz-adv-x="256" d="" /> <glyph unicode="" glyph-name="clipboard"><svg><path d="M64 0a8 8 0 0 0-8 8v16H32a8 8 0 0 0-8 8v216a8 8 0 0 0 8 8h192a8 8 0 0 0 8-8V32a8 8 0 0 0-8-8h-24V8a8 8 0 0 0-8-8zm8 16h112v48H72V32zM40 40h16v32a8 8 0 0 0 .041.799 8 8 0 0 0 .12.79 8 8 0 0 0 .472 1.526 8 8 0 0 0 .765 1.403 8 8 0 0 0 .485.636 8 8 0 0 0 1.144 1.114 8 8 0 0 0 1.346.863 8 8 0 0 0 .729.326 8 8 0 0 0 1.54.426A8 8 0 0 0 64 80h128a8 8 0 0 0 1.59-.16 8 8 0 0 0 1.525-.473 8 8 0 0 0 .72-.347 8 8 0 0 0 .682-.418 8 8 0 0 0 2.215-2.28 8 8 0 0 0 .977-2.183 8 8 0 0 0 .29-2.14V40h16v200H40z" /></svg></glyph> <glyph unicode="" glyph-name="file"><svg><path d="M32 0a8 8 0 0 0-8 8v240a8 8 0 0 0 8 8h192a8 8 0 0 0 8-8V72a8 8 0 0 0-.006-.125 8 8 0 0 0-.021-.39 8 8 0 0 0-.032-.405 8 8 0 0 0-.056-.373 8 8 0 0 0-.076-.42 8 8 0 0 0-.09-.35 8 8 0 0 0-.121-.423 8 8 0 0 0-.131-.356 8 8 0 0 0-.153-.383 8 8 0 0 0-.171-.357 8 8 0 0 0-.182-.348 8 8 0 0 0-.219-.357 8 8 0 0 0-.213-.324 8 8 0 0 0-.242-.319 8 8 0 0 0-.25-.31 8 8 0 0 0-.38-.416l-.085-.082-63.916-63.918a8 8 0 0 0-.049-.045 8 8 0 0 0-.27-.244 8 8 0 0 0-.32-.284 8 8 0 0 0-.351-.257 8 8 0 0 0-.291-.207 8 8 0 0 0-.365-.22 8 8 0 0 0-.33-.187 8 8 0 0 0-.457-.213 8 8 0 0 0-.25-.11 8 8 0 0 0-.48-.169 8 8 0 0 0-.288-.096 8 8 0 0 0-.447-.105 8 8 0 0 0-.338-.076 8 8 0 0 0-.422-.059 8 8 0 0 0-.37-.045A8 8 0 0 0 160 0zm8 16h112v56a8 8 0 0 0 .041.799 8 8 0 0 0 .94 3.037 8 8 0 0 0 .417.682 8 8 0 0 0 2.28 2.214 8 8 0 0 0 2.965 1.15A8 8 0 0 0 160 80h56v160H40zm128 11.312L204.688 64H168z" /></svg></glyph> </font></defs></svg>
見慣れない属性と値がある。
| 属性 | 概要 |
|---|---|
id="my-icon-font" |
たぶんアイコンの識別子になる |
horiz-adv-x="256" |
横書きにおける次の文字の基準位置 |
units-per-em="256" |
文字を表示する際のエム平方を描画単位に分割する際の細かさ。大抵はこの1emが他の単位(px等)に割り当てられることで文字の大きさが決定される。他のフォント形式では250(Intellifont)、 1000(Type1)、 2048(TrueType, TrueType GX, Open-Type)となっている。 |
ascent="240" |
ベースラインからの高さ |
descent="-16" |
ベースラインから下にはみ出る量 |
unicode="" |
私用領域E000〜F8FFの一部である |
glyph-name="clipboard" |
グリフの名前 |
ぶっちゃけ値はよく理解していない。IcoMoonでSVGからフォントを作るにて生成されたSVGファイルの値を参考にした。
256と書いてある所は画像のpxサイズを設定していたようだ。今回は256x256pxなので、そのように設定した。ascentとdescentは英字における基準座標gやyなど下部にはみ出るような字の位置に関する値と思われる- 二値は絶対値にして足した数がサイズと一致するようになっていたのでそれに合わせた(
240+(-16*-1)=256)
unicodeはそのグリフに対応する文字コードポイント
<glyph>がメイン。ここにフォント図形データと、それに対応する文字コードポイントをセットする。
ここで問題なのは<glyph>の座標系。<path>と同じくd属性値で図形を描画しているのだが、座標系が異なるせいでそのまま移植すると上下逆さまになる。
| 要素 | 座標系 |
|---|---|
<glyph> |
原点は左下(Y軸は上へ向かって進む) |
<path> |
原点は左上(Y軸は下へ向かって進む) |
座標系の変換には次の対処法が思いつく。
- Inkscapeなどの作画ツールで上下反転させた図形を作る
- 画像の
<svg>を丸ごと<glyph>に入れたら自動的に正しい座標データにしてくれるツールを使う
前者は面倒すぎてやる気にならない。そこで後者のツールを探した。
fontconv
どうやら次のような問題点があるらしい。
- 合字、異体字には非対応
書いてないがカラーフォント(COLRv1)等にも非対応なのだろう。
しかしそんな些細なことはどうでもいい。先程挙げた主要な形式の相互変換ができる。それも簡単なコマンドで。神ツール。製作者様に感謝。
インストール
- Node.jsをインストールする
- 端末を起動する
sudo npm install fontconvコマンドを実行する
実行
fontconv font.svg font.woff2
第一引数が入力ファイル。第二引数が出力ファイル。
前者のfont.svgは先述のコードの通りに作ったファイル。後者は作って欲しい形式の拡張子を指定すればいい。あとは好きな名前で。
実行するとWOFF2ファイルが生成される。中身はバイナリ形式なので閲覧できない。
利用
早速WOFF2をHTMLで表示してみる。
style.css
@font-face { font-family: 'my-icon-font'; src: url('font.woff2?cet901') format('woff2'), url('font.svg?cet901#my-icon-font') format('svg'); font-weight: normal; font-style: normal; font-display: block; } [class^="icon-"], [class*=" icon-"] { /* use !important to prevent issues with browser extensions that change fonts */ font-family: 'my-icon-font' !important; speak: never; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; /* Better Font Rendering =========== */ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .icon{width:1em;height:1em;} .icon-clipboard:before{content:"\e900";} .icon-file:before{content:"\e901";}
IcoMoonで出力されたCSSファイルのうち主要部分をパクった。
ポイントはフォントと合わせること。
| フォント | CSS |
|---|---|
glyph-name属性値 |
class名icon-* |
unicode属性値 |
contentプロパティ値 |
glyph-nameとclass名のほうは別に何でもいい。アイコン画像の内容が判る名前にしてフォント側とCSS側で一致させることをお勧めする。今回はclipboardとfile。
unicode属性値のほうが大事。具体的には以下二箇所。これはどちらもUnicodeのコードポイントを示している。表現の仕方はそれぞれの文脈で違うが、e900の部分がそれ。
| フォント | CSS |
|---|---|
 |
\e900 |
 |
\e901 |
もしフォントのグリフが増えたらCSS側も増やしていくこと。
.icon-新識別子:before{content:"コードポイント";}
| 項目 | 値の例 |
|---|---|
新識別子 |
重複しない小文字の文字列 |
コードポイント |
Unicodeの私用領域で他と重複しないコードポイント(\e902等) |
url('font.woff2?cet901')の?cet901はバージョン値。IcoMoonでついていたURLクエリ。
ググったら以下StackOverflowがヒット。見るとバージョン値であり、キャッシュ更新に使うようだ。つまりフォントを更新したらURLクエリの値を変更することでキャッシュも更新される。
index.html
<meta charset="UTF-8"> <link rel="stylesheet" href="style.css"/> <i class="icon-clipboard"></i> <i class="icon-file"></i>
これでクリップボードとファイルの図形が表示された。
HTTPSサーバ上で動かす必要はない。ただHTMLファイルをブラウザで開けば表示される。

一応、以下のように表示することも可能。お好みで。
<meta charset="UTF-8"> <link rel="stylesheet" href="style.css"/> <i class="icon-"></i> <i class="icon-"></i>