🖌

Webからローカルフォントのデータを取得する~Local Font Access APIとは~

2023/07/16に公開

Local Font Access API とは

Local Font Access API という Web API があります。この API を使うと、Web からローカルにインストールされたフォントについて、あらゆるデータを取得することができます。

https://wicg.github.io/local-font-access/

概要を聞くだけでフィンガープリントし放題っぽそうな雰囲気がぷんぷんしますが、以下の記事のように実際そのような懸念が議論されており、現状は Chromium 系のデスクトップでしか対応しておらず、Brave はこの API を直接ブロックしているようです。

https://qiita.com/rana_kualu/items/2ca7dad356c5caf34383

ローカルフォントの一覧を取得

まずはローカルにインストールされているフォントの一覧を取得してみます。以下は React での例です。

import { useState } from "react";

import type { Blob } from "buffer";

type FontData = {
  family: string;
  fullName: string;
  postscriptName: string;
  style: string;
  blob: () => Promise<Blob>;
};

const FontList: React.FC = () => {
  const [fontList, setFontList] = useState<FontData[]>([]);

  const getLocalFont = async () => {
    setFontList([]);
    try {
      const availableFonts: FontData[] = await window.queryLocalFonts();
      setFontList(availableFonts);
    } catch (err) {
      alert(err);
    }
  };

  return (
    <div>
      <button onClick={getLocalFont}>フォントを取得</button>
      <dl>
        {fontList.map((font) => {
          return (
            <>
              <dt>family</dt>
              <dd>{font.family}</dd>
              <dt>postscriptName</dt>
              <dd>{font.postscriptName}</dd>
              <dt>style</dt>
              <dd>{font.style}</dd>
            </>
          );
        })}
      </dl>
    </div>
  );
};

export default FontList;
ESLint 対応

window.queryLocalFonts()は ESLint が知らないメソッドなので、型の拡張をしてあげる必要があります。src直下などに以下のように記述しておけばエラーが消えると思います。

interface Window {
  queryLocalFonts: any;
}

初回のボタンクリックでlocal-fontsパーミッションのリクエストが行われます。

ローカルフォントへのアクセス権限を要求するブラウザのダイアログ

この権限のリクエストはユーザーのアクションによって呼び出される必要があります。今回はボタンクリックで呼び出しているので大丈夫ですが、例えばページのロード時に呼び出そうとするとエラーになります。

無事権限が取得できたら以下のようにフォントの一覧が取得できます。

各フォントについて、、、の情報が表示されている

それぞれのフォントから取得できるデータは MDN の以下のページから確認できます。

https://developer.mozilla.org/en-US/docs/Web/API/FontData

さらに詳しいデータを取得

おそらくこの API はデザインツールなどで Web フォントだけでなくローカルフォントも扱いたいという願いを叶えるために提案されていると考えられ、その用途であれば以上のデータが取得できれば十分なんですが、この API ではさらに詳細な情報を取得することが可能です。

FontDataオブジェクトにはblob()というメソッドが用意されており、このメソッドを呼び出すことでフォントのバイナリデータを取得することができます。

const fonts: FontData[] = await window.queryLocalFonts();
if (fonts.length === 0) {
  const blob = await filledFonts[0].blob();
  console.log(blob);
}

MDN のドキュメントではフォントのフォーマットを調べるサンプルコードが載っていますが、これだけではつまらないので opentype.jsというライブラリを使ってバイナリデータを解析してみます[1]

まずはopentype.jsをインストール。

yarn add opentype.js
yarn add -D @types/opentype.js

先ほどのコードを以下のように書き換えます。

import opentype from "opentype.js";

const fonts: FontData[] = await window.queryLocalFonts();
if (fonts.length === 0) {
  const blob = await filledFonts[0].blob();
  const font = opentype.parse(await blob.arrayBuffer());
  Object.entries(font.names).map(([key, value]) => {
    console.log(`${key}: ${value}`);
  });
}

Arial を例に挙げると、以下のような結果が得られます。

フォントのバージョンや説明などについての情報を取得できる

フォントの作者やライセンス、種類などの情報を取得できました。すごい。

これだけでも十分凄いんですが、さらにグリフの情報やパスデータまで取得することもできます。マジでこれどんな需要があるんだ???

おわりに

Web でフォントのバイナリデータまで取得できる必要があるのかは疑問ですが、ローカルフォントの一覧が取得できれば Web でできる表現の幅が広がりそうです。デスクトップのフォント管理アプリは数が少ない上に有料版だったり、海外製だったりで、使い心地がどうもいまいちという感じなので、この API で簡易的な自作のエミュレーションアプリを作るのも良さげだと思いました。ほかにもいろんな活用法が考えられると思うので、Google さんにはぜひ頑張ってほしいところですね。

脚注
  1. OpenType と TrueType のフォントのみ対応しています。 ↩︎

Discussion