はじめに #
フォントファミリーを 'Noto Sans CJK JP'
や 'Noto Sans JP','Noto Sans SC'
と指定した場合、
主に簡体字中国語で用いられる漢字の表示が不適切になる場合がある.
例:
- 我们必须尽快复习功课。
- 请记得出门时关灯。
复, 关, 门 ではなく 复, 关, 门 と表示されるべきだ.
SC を優先表示する漢字一覧 #
私の主観に基づいて、中文简体用のフォントを優先表示させるべき漢字を列挙した.
次の CSS にて font-family: 'Noto Sans SC';
で登場する順である.
Noto Sans JP | Noto Sans SC | Unicode |
---|---|---|
迂 | 迂 | U+8fc2 |
汲 | 汲 | U+6c72 |
迄 | 迄 | U+8fc4 |
丫 | 丫 | U+4e2b |
芒 | 芒 | U+8292 |
迁 | 迁 | U+8fc1 |
剪 | 剪 | U+526a |
圾 | 圾 | U+573e |
窗 | 窗 | U+7a97 |
启 | 启 | U+542f |
极 | 极 | U+6781 |
适 | 适 | U+9002 |
达 | 达 | U+8fbe |
复 | 复 | U+590d |
运 | 运 | U+8fd0 |
关 | 关 | U+5173 |
类 | 类 | U+7c7b |
门 | 门 | U+95e8 |
迂汲迄丫芒迁剪圾窗启极适达复运关类门
CSS における解決法 #
HTML の <head>
に次のコードが埋め込まれていることとする.
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100..900&family=Noto+Sans+SC:wght@100..900&display=swap" rel="stylesheet">
CSS にて、SC を優先表示する漢字を集めたフォントファミリー Noto Sans SC partial
を次のように定義する.
ただし、src
に記載されたフォントのURLは本記事執筆時のものである.更新される可能性があるため、先程の CSS を確認すること.
/*
JP より先に SC を表示させたいもの
Unicode Converter: https://tech-unlimited.com/escape-unicode.html
see: https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100..900&family=Noto+Sans+SC:wght@100..900&display=swap
*/
/* [33] */
@font-face { /* 迂 */
font-family: 'Noto Sans SC partial';
src: url('https://fonts.gstatic.com/s/notosanssc/v37/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.33.woff2') format('woff2');
unicode-range: U+8fc2;
}
/* [61] */
@font-face { /* 汲 */
font-family: 'Noto Sans SC partial';
src: url('https://fonts.gstatic.com/s/notosanssc/v37/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.61.woff2') format('woff2');
unicode-range: U+6c72;
}
/* [100] */
@font-face { /* 迄 */
font-family: 'Noto Sans SC partial';
src: url('https://fonts.gstatic.com/s/notosanssc/v37/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.100.woff2') format('woff2');
unicode-range: U+8fc4;
}
/* [104] */
@font-face { /* 丫 */
font-family: 'Noto Sans SC partial';
src: url('https://fonts.gstatic.com/s/notosanssc/v37/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.104.woff2') format('woff2');
unicode-range: U+4e2b;
}
/* [109] */
@font-face { /* 芒, 迁 */
font-family: 'Noto Sans SC partial';
src: url('https://fonts.gstatic.com/s/notosanssc/v37/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.109.woff2') format('woff2');
unicode-range: U+8292, U+8fc1;
}
/* [111] */
@font-face { /* 剪, 圾 */
font-family: 'Noto Sans SC partial';
src: url('https://fonts.gstatic.com/s/notosanssc/v37/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.111.woff2') format('woff2');
unicode-range: U+526a, U+573e,;
}
/* [113] */
@font-face { /* 窗 */
font-family: 'Noto Sans SC partial';
src: url('https://fonts.gstatic.com/s/notosanssc/v37/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.113.woff2') format('woff2');
unicode-range: U+7a97;
}
/* [114] */
@font-face { /* 启 */
font-family: 'Noto Sans SC partial';
src: url('https://fonts.gstatic.com/s/notosanssc/v37/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.114.woff2') format('woff2');
unicode-range: U+542f;
}
/* [115] */
@font-face { /* 极, 适 */
font-family: 'Noto Sans SC partial';
src: url('https://fonts.gstatic.com/s/notosanssc/v37/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.115.woff2') format('woff2');
unicode-range: U+6781, U+9002;
}
/* [116] */
@font-face { /* 达 */
font-family: 'Noto Sans SC partial';
src: url('https://fonts.gstatic.com/s/notosanssc/v37/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.116.woff2') format('woff2');
unicode-range: U+8fbe;
}
/* [117] */
@font-face { /* 复, 运 */
font-family: 'Noto Sans SC partial';
src: url('https://fonts.gstatic.com/s/notosanssc/v37/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.117.woff2');
unicode-range: U+590d, U+8fd0;
}
/* [118] */
@font-face { /* 关, 类, 门 */
font-family: 'Noto Sans SC partial';
src: url('https://fonts.gstatic.com/s/notosanssc/v37/k3kXo84MPvpLmixcA63oeALhLOCT-xWNm8Hqd37g1OkDRZe7lR4sg1IzSy-MNbE9VH8V.118.woff2') format('woff2');
unicode-range: U+5173, U+7c7b, U+95e8;
}
フォントファミリーは次のように指定する.
font-family: 'Noto Sans SC partial','Noto Sans JP','Noto Sans SC';
調査方法 #
自分でフォントを比較したい人向けに、手順を載せておく.
- Noto Sans JP と Noto Sans SC 両方に含まれる漢字を抽出
- 両者間でのフォントの違いを比較するために一覧表を作成
- 自身の主観に基づいて、SC を優先表示する漢字を列挙
- 漢字の見た目は日本語を優先する
- 次を満たすものを候補とする
- 日本語よりも中国語でよく使われている
- 見た目が日本語より中国語のほうが良い
- 候補に挙がった漢字のうち、簡体字が存在するものは除去する
インストール #
Python 3.8 以上がインストールされていること.(cf. User documentation)
pip install fonttools
フォントのダウンロード #
- https://fonts.google.com/noto
- 「Noto Sans Japanese」と「Noto Sans Simplified Chinese」を「Get Font」
- 👜 https://fonts.google.com/selection から「Download all」
cmap テーブルを出力 #
ファイルのパスは適宜変更すること.
ttx -t cmap NotoSansJP-VariableFont_wght.ttf
ttx -t cmap NotoSansSC-VariableFont_wght.ttf
指定したファイルと同じディレクトリに .ttx
ファイルが生成される.
Unicode の取り出し #
生成された各 .ttx
について、Unicode のみ抽出する.
Visual Studio Code で .ttx
を開き、正規表現を用いた置換を行う.
-
Find
.*code="0x([0-9A-Fa-f]+).*
-
Replace
U+$1
Unicode 以外の行は削除する.
-
Find
^(?!U\+).*\n
-
Replace (なし)
5桁未満の Unicode はゼロ埋めする.後でソートして重複を削除するためである.
-
Find
U\+([0-9A-Fa-f]+)
-
Replace
U+0000$1
-
Find
U\+0*([0-9A-Fa-f]{5,})
-
Replace
U+$1
共通する文字を抽出 #
Noto Sans JP と Noto Sans SC 両方に含まれる文字の Unicode を抽出する.
grep を用いる.Windows では Git Bash や WSL で利用できる.
grep -x -f NotoSansJP-VariableFont_wght.ttx NotoSansSC-VariableFont_wght.ttx | sort | uniq > Noto-Sans-JP-SC-common-codes.txt
一覧表を作成 #
Visual Studio Code で Noto-Sans-JP-SC-common-codes.txt
を開き、正規表現を用いた置換を行う.
-
Find
U\+0*([0-9A-Fa-f]+)
-
Replace
<tr><td>&#x$1</td><td>&#x$1</td><td><code>U+$1</code></td></tr>
次の内容の index.html
を作成する.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style>
@font-face {
font-family: 'Noto Sans JP';
src: url(NotoSansJP-Regular.ttf);
}
@font-face {
font-family: 'Noto Sans SC';
src: url(NotoSansSC-Regular.ttf);
}
tr > td:first-child {
font-family: 'Noto Sans JP';
font-size: xxx-large;
}
tr > td:nth-child(2) {
font-family: 'Noto Sans SC';
font-size: xxx-large;
}
</style>
</head>
<body>
<table>
<tr>
<th>Noto Sans JP</th>
<th>Noto Sans SC</th>
<th>Unicode</th>
</tr>
<!-- 先程の正規表現で得たコードをここに貼りつける -->
</table>
</body>
</html>
index.html
が入っているのと同じディレクトリに NotoSansJP-Regular.ttf
と NotoSansSC-Regular.ttf
を配置する.
あとは人力でがんばれ.