Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2024年08月27日] [更新 2024年09月18日] Delphi 一般・その他 [未分類 - OS の操作等]
ブラウザで使用可能なフォントかを判定する JavaScript
動作確認等 Windows 10 ビルド 19045 Pro 64 bit
Google Chrome 127, Microsoft Edge 128, Firefox 129
[整理番号 - 1918]







ウェブブラウザで使用可能なフォントであるかを判定


特定のフォント名のフォントが,現在の環境のウェブ寺ウザで有効であるかをチェックするツールと,その方法に関する 記事です.本ページで提供しているフォントファイルを使用します.







01_専用のフォントを使用して文字の描画幅で判定
f3013glyph.zip [10 KB] 2024年09月18日版 説明ファイルなし
改変,(改変した内容も含めて) 再配布も再掲載も自由


上のダウンロードのリンクから f3013glyph.zip をダウンロードすると,f3013glyph..woff2 というフォントファイルがあります.これを使用します.
このフォントには Unicoe のコードポイント U+002E, U+0041, U+3013, U+3042, U+4E9C だけに文字を収録しています.これらは本来「.」 (ピリオド) 「A」 (半角の A) 「〓」 (通称ゲタ文字) 「あ」「亜」ですが,このフォントには全て「.」が収録されています.下表は,文字のサイスを 30px にしてこれらの文字を 游ゴシック で描画した時の文字の描画幅を調べた結果です.
. ピリオドの描画幅が一番小さい値となっています.



UCS 文字 フォント 描画幅
U+3013 游ゴシック 30
U+0041 A 游ゴシック 19
U+3013
U+0041
. 游ゴシック 8


以下は,数文字だけを表示する単純なウェブページの HTML コードです.
文字 (テキスト) を描画する場合,このコードのように <style>,つまり CSS で描画に使用するフォントを複数指定する場合があります.文字を描画する時,ウェブブラウザは,最初に指定したフォントを使用します.最初のフォントが現在の環境で使用できないか,描画する文字が収録されていないフォントの場合,2 番目のフォントを使用しようとします.
2 番目のフォントが現在の環境で使用できないか,描画する文字が収録されていないフォントの場合,3 番目のフォント内を探しにいきます.このようなフォントの指定がない場合は,現在のブラウザのデフォルトのフォントが使用されます.


<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <style>
  .test-style {
      font-family : "ヒラギノ角ゴシック", "Yu Gothic UI", "MS Pゴシック", sans-serif;
      font-size : 50px;
  }
  </style>   
</head>
<body>
  <div class="test-style">テスト文字列</div>
 </body>  
</html>


2 番目ロのフォントに,今回提供している f3013glyph フォントを指定してゲタ文字 〓 を描画します.実際にゲタ文字が描画できれば,1 番目のフォントは現在の環境で使用可能なフォントということになります.
もし,1 番目のフォントが現在の環境では使用できないフォントであれば,2 番目のフォントである f3013glyph フォントを使用してタ文字を描画しますから,実際には . (ピリオド) になります.上の表で示したように,〓 と . とでは描画の幅が違います.この描画の幅の違いで,現在の環境じて使用可能なフォントであるかを判定します.

一般的なフォントであれば,A と 〓 は収録されています.



[備考 1]
フォントの設定がない場合,あるいは存在しないフォント名だけを指定した場合,あるいは現在の環境では使用できないフォントだけを指定した場合は,ブラウザのデフォルトのフォントを使用して描画されます.


[備考 2]
Windows 10 では,Emoji の文字は特別な扱いとなっています.Emoji の文字は,フォントの設定には関係なく,自動的に Segoe UI Emoji を使用して描画します.
従来の絵文字は,:現在 Unicode Emoji に登録されている文字であれは,Segoe UI Emoji を指定することによって Emoji としてのカラー絵文字になります.





02_フォント名が有効かを判定する JavaScript のコード


拡張子が woff2 のファイルはウェブフォント用のファイルです.ローカルな環境でも使用できます.以下のように設定して使用します.
font-family は,フォント名です.任意の名前を設定できます.src の url はファイルのフルパスです.赤線の部分がディレクトリです.



<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <style>
  @font-face {
      font-family: 'f3013glyphfont';
      src: url('../../fonts/f3013glyph.woff2') format('woff2');
  } 
  </style>   
</head>
<body>

 </body>  
</html>


HTML ファイルと同じディレクトリ内に置いた場合,url は次のようになります.



      src: url('./f3013glyph.woff2') format('woff2');


以下は,実際にフォント名の有効性をチェックする関数のコードです.canvas のコンテキストに文字を描画して文字の描画幅を取得します.このコードでは canvas を表示しないで取得します.

この関数は,ページを読み込んだ直後に 1 回だけ実行するようにします.そうしないと,初回実行時に正しい描画幅が取得できません.おそらくフォントの読み込みやそのキャッシュなど,初期化状態が関係していると思われますが,詳細は不明です.この関数を続けて実行しても改善されないことを考えるとタイムラグが必要なようです.実際,初回実行時の後,alert でダイアログを表示すると,その後は正常に描画幅が取得できるようになりました.



  <script>
  //-------------------------------------------------------------------------- 
  //  引数のフォント名の有効性をチェックする関数                             
  //  使用可能であれば true を返す
  //
  //  この関数は,ページ読み込み後に 1 回引数なしで実行しておく必要がある
  //-------------------------------------------------------------------------- 
  function checkFontEnabled(fontface) {  

    const size = '30px';   
    var elemDummy = document.createElement("div");
    const ctx = document.createElement('canvas').getContext('2d');

    ctx.font = size + " f3013glyphfont";
    var wdBase = ctx.measureText('.').width;

    ctx.font = size + " " + fontface + ",f3013glyphfont";
    var wdAlpha = ctx.measureText('A').width;
    var wdGeta = ctx.measureText('〓').width;

    delete ctx;

    return wdAlpha > wdBase || wdGeta > wdBase;
  }   

  //-------------------------------------------------------------------------- 
  // ページ読込後に引数なしで関数を実行する
  // これでウェブフォントが実際にロードされてこの関数が使用可能になる
  checkFontEnabled();
  </script>


<div< や <span> タグ要素に文字を描画しても文字の描画幅を取得できます.以下はその例です.ただし,この場合,style の position プロパティの値を absolute か fixed にします.そうしないと実際の描画幅ではなく,描画可能な幅の取得になります.

このコードによる処理の場合も,この関数を使用するページ読み込んだ直後に 1 回この関数を実行しておく必要があります.



  <script>
  //-------------------------------------------------------------------------- 
  //  引数のフォント名の有効性をチェックする関数                             
  //  使用可能であれば true を返す
  //
  //  この関数は,ページ読み込み後に 1 回引数なしで実行しておく必要がある
  //-------------------------------------------------------------------------- 
  function checkFontEnabled(fontface) {  

    var elemDummy = document.createElement("div");
    elemDummy.style.cssText = 'position:absolute;visibility:hidden;';
    document.body.appendChild(elemDummy);

    elemDummy.style.fontSize = '30px';

    elemDummy.style.fontFamily = "f3013glyphfont";
    elemDummy.innerText = '.';
    var wdBase = elemDummy.offsetWidth;  

    elemDummy.style.fontFamily = fontface + ",f3013glyphfont";
    elemDummy.innerText = 'A';
    var wdAlpha = elemDummy.offsetWidth;          
    elemDummy.innerText = '〓';
    var wdGeta = elemDummy.offsetWidth;

    elemDummy.remove();

    return wdAlpha > wdBase || wdGeta > wdBase;
  }   

  //-------------------------------------------------------------------------- 
  // ページ読込後に引数なしで関数を実行する
  // これでウェブフォントが実際にロードされてこの関数が使用可能になる
  checkFontEnabled();
  </script>


f3013glyph..woff2 には,「あ」と「亜」に相当するコードポイントにも文字「.」を収録しています.これは,日本語用のフォント (和文フォント) と欧文フォントの判定用として利用することができます.必要に応じて使用してください.





03_使用可能なフォント名かを判定するツール


作成した関数を使用した例です.左側の入力欄にフォント名を入力すると,結果をその下に表示します.右側のリストのフォント名をクリックすると,そのフォント名を入力できます.
単純な使用例のサンプルも作成しました.



serif は,明朝体のようなセリフ付き書体の総称です.sans-serif は,セリフなしのゴシック系の書体の総称です.sans はフランス語の ~ がないという意味で,具体的なフォント名はウェブブラウザによって異なります.



フォント名

フォント名の例
sans-serif Noto Sans JP
serif Noto Sans Mono CJK JP
BIZ UDMincho Noto Serif CJK JP
BIZ UDP明朝 Osaka
BIZ UDゴシック Osaka-等幅
BIZ UD明朝 VL Pゴシック
Droid Sans Fallback クレー
IPA P明朝 ヒラギノ角ゴシック
IPAゴシック メイリオ
IPA明朝 筑紫A丸ゴシック
Meiryo UI 筑紫B丸ゴシック
MS Pゴシック 凸版文久ゴシック
MS P明朝 凸版文久見出しゴシック
MS UI Gothic 游ゴシック
MS ゴシック 游ゴシック体
MS 明朝 游明朝
Noto Sans CJK JP 游明朝体


Meiryo が標準フォント (既定のフォント) のブラウザがありました.そこで,sans-serif を指定して文字を描画したグリフのデータと,Meiryo を指定して描画したグリフのデータを比較してみました.以下の記事にその結果を掲載しています.
Meiryo が sans-serif のフォントであれば,同じグリフになります.



イリオと Meiryo は同じフォントです.メイリオは日本語名 (日本語表記) で Meiryo は英語名 (英語表示) です.以下は,そのことを確認するテストサンプルです.



[備考]
これは,正確には半角の A またはゲタ文字 〓 がフォントに収録されているかのチェックです.たとえ使用可能なフォントでも,A も 〓 も収録していないフォントの場合は,使用できない結果となります.例えは Emoji 専用のフォント Noto Color Emoji は使用できない結果となります.これは,一般的な文字の描画には使用できないということになります.

また,使用可能の判定になったとしても,フォントに収録されていない文字は,そのフォントでは描画できません.そのような文字は,別のフォントで描画されます.





04_ウェブページで使用しているフォント名を調べる


提供している zip 書庫に,今回作成したフォントを利用した detect_fontname_Bookmarklet.js という JavaScript のファイルを追加しています.この JavaScript のコードをブラウザのブックマークに登録して,ブックマークレットとして使用すると,ウェブページで使用しているフォント名を調べることができます.
以下は,同じ処理コードの detect_fontname.js を使用した動作確認用のサンプルです.



JavaScript のコードをブックマークレットとして登録する方法です.
下のボタンをクリックすると  detect_fontname_Bookmarklet.js のコードが表示されます.これを全て選択してコピーします.[Ctrl} + [A], [Ctrl] + [C] で全てコピーできます.




次に,ブックマークバーを表示して新規にブックマークを追加します.Microsoft Edge には新規追加の機能はありません.適当なページをブックマークに追加して,それを編集します.
Microsoft Edge では「お気に入り」という用語を使用しています.



ウェブブラウザ ブックマークバー表示トグル ブックマークの新規追加手順
Google Chrome 127 [Ctrl] + [Shift] + [B] ブックマークバーの上で
マウスの右ボタンをクリック
[ページを追加] を選択
Microsoft Edge 128 [Ctrl] + [Shift] + [B] [Ctrl} + [D] で編集ダイアログ表示
[詳細] をクリック
あとは下図の説明を参照
Firefox 129 [Ctrl] + [Shift] + [B] ブックマークバーの上で
マウスの右ボタンをクリック
[ブックマークを追加] を選択


下図は Google Chrome の場合です.[名前] はブックマークの表示名です.[URL] の欄には,コピーしたコードを貼り付けます.[保存] をクリックすれば登録は完了です.



図1
ブックマークの編集画面
  • 適当な名前を入力
  • [URL] に JavaScript のコードを貼り付ける
  • [保存] をクリック

登録したブックマークレットの使用方法です.
ウェブページを表示したら,登録したブックマークをクリックします.そのウェブページで,上の動作確認用のサンプルページと同じ機能が実現できます.漢字を収録していない欧文フォントなどを検出した場合は,( ) 内に日本語に使用する和文用フォント名を表示します.
ウェブブラウザの拡張機能とは違い,別のページを表示したり,[F5] キーなどで再読み込みをすると,このブックマークレットは無効になります.


Firefox では,コンテンツセキュリティポリシー (CSP) が有効になっていてブックマークレットが動作しない場合があります.その場合は [高度な設定] で設定を変更します.
アドレスバーに about:config を入力して [Enter] キーを押下して設定の検索ページを表示します.検索欄に security.csp.enable を入力します.右端の双方向矢印のようなアイコンをクリックすると false と true が切り換わります.false にして設定ページ (タブ) を閉じます.



[備考 1]
このブックマークレットでは,前項までの説明で使用したフォントファイルは使用しません.フォントは,文字列データに変換して JavaScript のコードに埋め込んでいます.


[備考 2]
ブックマークの管理のショートカットキーは [Ctrl} + [Shift] + [O] です.Firefox では [Ctrl] + [B] でブックマークをリスト表示します.



書体の総称名である sans-sefit, serif などの具体的なフォント名はウェブブラウザによって異なります.下表を参考にして確認してください.表中のコマンドをアドレスバーで実行すると,該当ペインまたは該当項目を表示します.



ウェブブラウザ [設定] の左ペイン 右ペイン内の位置
Google Chrome 127 デザイン] をクリック
chrome://settings/appearance
[フォントをカスタマイズ]
chrome://settings/fonts
Microsoft Edge 128 [外観] をクリック
edge://settings/appearance
[フォントのカスタマイズ] までスクロール
edge://settings/fonts
Firefox 129 [一般] をクリック
about:preferences#general
[言語と外観] [フォント]
[詳細設定] をクリック


フォントの総称名 書体
sans-serif ゴシック体・黑体 (Heiti)
serif 明朝体・宋体 (Songti)
system-ui 現システムの UI フォント
monospace 等幅フォント
cursive 筆記体
fantasy 装飾系フォント






05_ブックマークレットにおける JavaScript のコード


ブックマークレットとして使用する javaScript は次のように先頭に javascript: を追加するだけです.基本的にはこれで動作しますが,若干留意することがあります.



ブックマークレットの構造.先頭に javascript: を追加する

javascript:

    ここに通常の JavaScript のコードを記述                            


まず,コード内にコメントは使用できません.コメントの部分で処理が止まります.ブラウザによっては,現在のオブジェクト名だけを現在のタブに表示することがあります.そり場合は,[F5] キーで現在のページを再読み込みします.
イベントの登録は,通常は以下のようにページがロードされてから実行するようににしますが,これはブックマークレットでは無効です.ブックマークレットは,一般的には,既に読み込まれて表示されているウェブへページに対する操作です.



  window.onload = function() {

    各種イベントの捕捉用コード                             
    ブックマークレットではこの部分は実行されない                             

  }


処理コード全体が関数としての戻り値がない場合,正常に処理しない場合があります.この場合は,以下のように処理コード全体を (function(){ と })(); の間に挿入して,関数として実行するようにします.
イベントの登録には addEventListener を使用します.



  先頭に javascript: を追加                             
  JavaScript のコード全体を (function(){ と })(); の間に書く

  イベントの捕捉には addEventListener を使用する
  addEventListener の第 1 引数はイベントのタイプ ( 種類 ) の文字列 ( ここでは click )
  対象が document の時はページ全体のイベントの捕捉
  対象が document.body の時は body 内で発生したイベントの捕捉
  その他の対象は getElementById で取得した要素 ( element オブジェクト ) など

javascript:(function(){
  document.addEventListener('click', function(event) {
    if (event.target.tagName !== 'HTML') {
      event.preventDefault();
      event.target.remove();
    }
  });
})();


上のコードはブックマークレットとして動作します.以下のリンクのページは,その動作確認用のサンプルです.JavaScript のコードは HTML コードの最後の部分に記述しています.したがって,ページの再読み込みを行っても自動的に JavaScriipt が実行されます.



ブックマークバーを表示して,そのブックマークバーに以下のリンクをドラッグ & ドロップするとブックマークレットとして登録できます.登録しないで,以下のリンクをクリックすると,本ページでこの JavaScript の機能が有効になります.機能を解除するには,[F5] キーなどでページの再読み込みをします.


ページのタグ削除 (ブックマーク登録用リンク)

このリンクのコードは次のようになっています.href は,ブックマークの URL 欄の値のことです.改行は削除して 1 行にしています.この場合,JavaScipr のコード内に " (ダブルクォーテーション) があると,そこでコードが途切れてしまいます." はあらかじめ &quot; に置換しておく必要があります.
ブックマークの編集ダイアログて゜,URL 欄に入力すると改行なしの 1 行のコードにできます.


  
<a href="javascript: から始まるコード">ページのタグ削除</a>
  


[備考 1]
ブックマークレットが正常に動作しない時の挙動は,JavaScript のコードとウェブブラウザによって違うことがあります.何の変化もない場合,現在のタブにオブジェクトの名前だけを表示する場合,エラーを表示する場合などがあります.
そのような場合は,ページの再読み込みでブックマークレットを無効にします.


[備考 2
古いバージョンのウェブブラウザでは,JavaScript によってブックマークへの登録やブックマークの登録画面を表示できました.現在は,それらの機能は廃止となっています.





06_自 JavaScript で他の JavaScript を使用


ブックマークレットの JavaScript では,現在表示中のウェブページに読み込まれている JavaScript のライブラリの機能は使用できます.それ以外の JavaScript を使用する場合は,自身の JavaScript 内でロードする必要があります.
以下のサンプルで使用している方法はその 1 つの例です.



以下は,このサンプルの JavaScript のコードです.JavaScript のファイルは,HTTPS サーバにないと,読み込むことはできても JavaScript としては機能しません.



  <script>
  //--------------------------------------------------------------------------                             
  J//  JavaScriipt の実行時に動的に他の JavaScript をロードする
  //  XMLHttpRequest を利用して jQuery をロードする例
  //  Open の最後の引数を false にすると同期処理
  //--------------------------------------------------------------------------

  var xhr = new XMLHttpRequest();
  
    //  処理のイベントハンドラ
    xhr.onreadystatechange = function() { 
      if (xhr.readyState == 4) {
        // 終了時 ( 失敗か成功かは xhr.status の値で判定 )
      }
    }
    
  xhr.open('GET', 'http://code.jquery.com/jquery-3.2.1.min.js', false);
  xhr.send("");

  // eval によって,取得した文字列が jQuery のコードとして実際に使用可能になる
  // テキストファイルの場合は eval を実行しないで xhr.responseText で取得する
  eval(xhr.responseText);
    
  // ここは上の処理が終わらないと実行されない

  //--------------------------------------------------------------------------
  //  jQuery が使用可能になったので,jQuery を使用してサーバからファイルを取得
  //  ローカルな環境で実行する場合はローカルサーバを起動しておく
  //--------------------------------------------------------------------------
  
  var url = 'http://mrxray.on.coocan.jp/Delphi/Others/'
  
  $.get(url + 'checkFontEnabled_LoadJS_Text.txt',function(data) {
    var text = data.split(/\n/);
    $('#res-1').html(text);
  }); 
  
  // ここはファイルの読み込みが終了しなくても実行される
  
</script>


ウェブぺーージの操作などを行う JavaScript を作成してサーバに置きます.端末側では,上の JQuery のロードと同じように,そのサーバの JavaScriipt を読み込むだけのブックマークレットを作成してブックマークに登録します.そうしておけば,サーバの JavaScriipt に修正・変更があっても,端末側でブックマークを編集をする必要がありません.