初歩のシェルスクリプトで遊ぶ[ぬかみそフォントの制作サポート(1)]
OTEditとNフォントとUnicode-CID対応
OTEditが文字数の多いOpenTypeフォント、「Pr6N」に対応してる、と分かって、さてどうすんべかと。
単に文字数が多いだけでなくて、いわゆるNフォントのようなので。Unicodeで作ったTrueTypeフォントをコピーしてOpenTypeにするとき、手順が変わるんじゃないかってのを、現在検討してます。
以下、そのメモ。
資料がねぇよ
使いやすい資料が見つからん。
168文字をどうするか
字形変更分の168文字をどうするかってのが、中心になる問題。
たとえば「辻」の文字を作ったTTFファイルを、コピーしてOTFに変換したとき、stdフォントだとCID3056番にコピーされた。これが、Pr6Nだと8267番にコピーされる。
3056番は1点しんにょうで、8267番は2点しんにょう。だからテキストエディタで「辻」って打って、フォントを指定すると、同じunicodeの文字からでも違う文字のCIDが指定されて、1点しんにょうになったり、2点になったりする。
フォントの制作手順として、まず1点しんにょうで作っている現状のnukamisoだと、今までの手順で「N」フォントにコピーすると、1点しんにょうの「辻」を、2点のところにコピーしちゃう。これはまずい。
今までどおりNでないProフォントで出すなら問題なさそうだけど、文字数を増やしたいのなら、Nフォントにすることを検討しなきゃなんないな、手順を変えてツールを作り替えなきゃなんないな、ってのが今ここです。
とりあえず資料作り_ダウンロードとcsvファイルへの変換
フォントエディタ OTEdit for Windows のダウンロード | フォント・外字ソフトのことなら武蔵システム
武蔵システムから資料として、UnicodeとCIDの対応表がダウンロードできる。これを元にして、資料つくります。
zip書庫がふたつ、1-4と1-7のがあります。それぞれのzipの「UnicodeとCIDの対応.xls」、これらを、テキストファイルに変換して、1枚の資料にまとめます。
- 「UnicodeとCIDの対応.xls」のファイルをLibreOfficeで開く
- csvファイルに変換保存する。区切り文字は「タブ」。それぞれファイル名は、
- テキストエディタでcsvを開き、1行目、「Unicode CID」の行を削除する
- 改行コードをLFに書き換える
こんな感じのテキストファイルになります。unicode0x0020は、CID1。なんてのの繰り返し。
0020 1 0021 2 0022 3 0023 4 0024 5 0025 6 0026 7 0027 8 0028 9 0029 10 002A 11 002B 12 002C 13 002D 14
シェルでの作業_Unicodeに重複が無いことを確認する
- テキストファイルの行数を数える
- テキストファイルからUnicodeのみ抜き出して、ソートして重複行を除き、行数を数える
- 同様にCIDのみ抜き出し、ソートして重複行を除き、行数を数える
$ cat ./1-4.csv | wc -l 10164 $ cat ./1-4.csv | cut -f 1 | sort | uniq | wc -l 10164 $ cat ./1-4.csv | cut -f 2 | sort | uniq | wc -l 9866 $ cat ./1-7.csv | wc -l 15846 $ cat ./1-7.csv | cut -f 1 | sort | uniq | wc -l 15846 $ cat ./1-7.csv | cut -f 2 | sort | uniq | wc -l 15539
UnicodeとCIDの列を調べると、
- unicodeに重複はない。
- CIDには、重複がある。
1-7に取りこぼしが無いか確認する
1-4の文字は、すべて1-7に含まれてるはず。このへんを確認する。
「unicode CID」の列になっているcsvファイルの、左側1列、unicodeだけ抜き出したテキストファイルを作る
$ cut -f 1 0< ./1-4.csv 1>1-4_f1.txt $ cut -f 1 0< ./1-7.csv 1>1-7_f1.txt
これらはそれぞれ、unicodeの数字に重複が無いことは確認できているから、
$ wc 1-4_f1.txt 10164 10164 51013 1-4_f1.txt
行数は10164行、単語数も当然、10164。10164種類の16進数が、すべて「1-7_f1.txt」にも入ってることを確認すればいい。
例えば文字コード「9BFA」が、「1-7_f1.txt」に入っていることを確認するなら、恰好悪いやり方だけど、grepしてみると分かる。
$ grep -x -e '9BFA' ./1-7_f1.txt 9BFA
このように、Unicodeが入ってるなら一行分の出力が得られる。もし「1-7_f1.txt」に含まれていない文字を探したなら、
$ grep -x -e '_9BFA' ./1-7_f1.txt (出力なし)
出力が得られない。
このgrepを、1-4に含まれるunicodeひとつにつき一回ずつ、繰り返す
$ cat ./1-4_f1.txt | xargs -I '{}' grep -x -e '{}' ./1-7_f1.txt 0020 0021 0022 0023 0024 0025 0026 0027 0028 0029
xargsで繰り返して、 grep -x で一行単位で検索する。
行数がgrepに引っかかった数になると分かったので、以上のコマンドの行数を数える。
$ cat ./1-4_f1.txt | xargs -I '{}' grep -x -e '{}' ./1-7_f1.txt | wc 10164 10164 51013
10164回、grepで探したら見つかった。1-4に入ってるunicodeは、すべて取りこぼしなく、1-7にも入ってる、と確認した。
ふたつの表を結合する
1-4のテキストファイルと1-7のテキストファイルを、Unicodeを軸にして、ひとつの表にまとめる。
joinのためにsortしておいて、一時ファイルを作ってから、joinで結合する。
2列めと3列目を逆にしたものも作っておく。
$ sort ./1-4.csv 1>1-4_sort.csv $ sort ./1-7.csv 1>1-7_sort.csv $ join -a 1 ./1-7_sort.csv ./1-4_sort.csv 1> join1-7_1-4.csv $ join -a 2 ./1-4_sort.csv ./1-7_sort.csv 1> join1-4_1-7.csv
結果はこんな感じです。Unicode,CIDの2004,CIDの90、というように。
0020 1 1 0021 2 2 0022 3 3 0023 4 4 0024 5 5 0025 6 6 0026 7 7 0027 8 8 0028 9 9 0029 10 10 002A 11 11 002B 12 12 002C 13 13 002D 14 14 002E 15 15
横道にいったん入り、差分をつくる
先ほど作っておいた、2列目と3列目が逆になったcsvファイル。これをdiffで比較すると、「辻」がそれぞれ異なるCIDにコピーされたように、違うCIDにコピーされる行を抜き出せます。
$ diff ./join1-7_1-4.csv ./join1-4_1-7.csv 987c987 < 2225 15489 666 --- > 2225 666 15489 1888c1888 < 2F5B 7965 1383 --- > 2F5B 1383 7965 3200c3200 < 5026 7674 1863 --- > 5026 1863 7674 $ diff ./join1-7_1-4.csv ./join1-4_1-7.csv | grep -e '^<' < 2225 15489 666 < 2F5B 7965 1383 < 5026 7674 1863 < 50C5 7662 1735 < 5132 7798 3813 < 514E 13949 3136 < 51A4 7817 4228 < 51DE 20300 14352 < 5307 20301 8404 < 537F 7661 1698 < 53A9 20271 1243 $ diff ./join1-7_1-4.csv ./join1-4_1-7.csv | grep -e '^<' | cut -f 2- -d ' ' 2225 15489 666 2F5B 7965 1383 5026 7674 1863 50C5 7662 1735 5132 7798 3813 514E 13949 3136 51A4 7817 4228 51DE 20300 14352 5307 20301 8404 537F 7661 1698 53A9 20271 1243 53C9 20281 2085 53DB 7978 3412
10進数と検索用文字を付加する
結合したcsvテキストファイルは
「Unicode CID2004 CID90」
の並びになってます。CIDが無いものは空白。このテキストファイルを、以下のシェルスクリプトに通します。これはdashじゃだめで、「#!/bin/bash」が必須。
#!/bin/bash # =============================================================================== # ■ unicodeの16進数を10進数に変換して、新しく列に追加する_ ttedit_20210306.sh # # ・input # unicode(HEX) CID2004 CID90 # # ・output # unicode(DEC) unicode(HEX) CID2004 CID90 文字 # # 空のCID90には、0を入れる # # =============================================================================== while read uniCode cID2004 cID90 ; do # ユニコード16進数を10進数に変換する uniCodeDec=`bc --standard << __STDIN obase=10 ibase=16 ${uniCode} __STDIN` # もし空なら0にセット cID90="${cID90:-0}" printf "%s %s %s %s \U${uniCode}\n" "${uniCodeDec}" "${uniCode}" "${cID2004}" "${cID90}" done
$ cat ./join1-7_1-4.csv | ./ttedit_20210306.sh 32 0020 1 1 33 0021 2 2 ! 34 0022 3 3 " 35 0023 4 4 # 36 0024 5 5 $ 37 0025 6 6 % 38 0026 7 7 & 39 0027 8 8 ' 40 0028 9 9 ( 41 0029 10 10 )
- 16進数のunicodeを10進数に変換して、1列目に追加
- 16進数のunicodeを、bashのprintfの機能を利用して、可読文字に変換、最終列に追加
- 空のCID、CID90の列に、「0」を入れる
- 空白区切りをタブ区切りに整形する
この出力を「sort -V」すると、1列目の10進数でソートされて、Unicode順に並びます。