米O'Reillyで買ったPDF本をkobo gloでも読めるように加工する
米 O'Reilly のアカウントを作って手持ちの紙本(同社から出ている英語版に限る)を登録すると、その電子書籍版が$4.99/冊で買えるらしい。自宅には CJKV Information Processing(第2版)と Fonts & Encodings があり、どちらもいろいろと役に立っているが、さすがにこれを持ち運ぼうと思うとつらい。
というわけで電子書籍版をさっそく買ってしまった。タイトルによっては eBub や mobi フォーマットも選択できるようだが、この2冊はPDF版のみ。残念ながら errata は反映されていない様子。
余白の除去
このPDFは版面の上下左右に余白が大きく取られているため、これをそのまま電子書籍端末で読もうとしても読みづらい。ググってみたところ、PDF内部の CropBox の値を書き換えて余白を除去する方法があった。
このページのスクリプトにすこし手を加え、次のようにしてみた。
svivs の現状について
Twitter を見ていて、あーそういやそんなもんあったなーと思いだしたのですが、以前 svivs というツールを作りました。
現状
当時は更新・拡張したい点などいくつかあったわけですが、結局のところ今まで放置状態になっています。理由としては、
- Ubuntu をメインで使うようになったが、Adobe AIR の開発・実行環境は Linux に対応していない
- 当時はIVSをサポートするOS・ブラウザ・その他アプリケーションが少なかったため、多くの環境で比較的確実に利用できる Adobe AIR を使っていたが、現在ではサポートが進んで問題にならなくなってきた
- そもそも、Adobe AIR 自体が結局世間ではあまり使われていない気がする
- めんど(ry
といったあたりで、残念ながら今後も放置状態が続くかと思われます。また、svivs 内部で利用しているIVDのバージョンが古いこともあり、今後の svivs の利用は推奨しません。次項の作業によってIVDを更新することは可能ですが、このような現状を把握した上で、自己責任でお願いします。
svivs で使われているIVDを更新するには
Unicode Consortium の公開するIVDは、これまで何回かアップデートが行われてきました。
svivs は当時最新版であった2010-11-14版のIVDを利用していますが、その後 Adobe-Japan1 と Hanyo-Denshi の両方のコレクションにIVSが追加された、2012-03-02版が出ています。これに対応させたい場合には、以下の作業を行なう必要があります*1。
- Versions of the IVD のリンクから、最新版の IVD_Sequences.txt をダウンロードする
- \Program Files (x86)\svivs\IVD_Sequences.txt を、ダウンロードした IVD_Sequences.txt で上書きする
- \Users\{ユーザ名}\AppData\Roaming\net.shiromoji.Svivs\ivd.sqlite を削除する
- svivs を起動する
Adobe-Japan1, Hanyo-Denshi 以外のコレクションが新設されるなどした場合には対応できませんので、ご注意ください。
アウトラインのSVGからフォントを生成 #かな書いてみる
IVSやら何やら他の話題に飛びついていたので間が空いてしまったが、明朝かな書体制作のつづき。前回はアウトラインを作ったので、今回はここからフォントを生成したい。
SVGの分割
まず、これがアウトラインのファイル。Inkscape で作成し、SVGとして保存した。アウトラインは outline という名前のレイヤーの中に作っている。仮想ボディのサイズは100pxとした。
これをグリフごとに分割し、1文字1ファイルにする。今回は(も?)Perl で簡単なスクリプトを書き、これを利用した。単純なものなので、path 要素以外の要素(グループも含む)に対応していないなどいろいろと制限はある。また XML::Simple を利用しているので、実行するには XML::Simple のインストールが必要。
#!/usr/bin/perl # # SVGをグリフごとに分割 # usage: perl split_svg.pl svg_sheet.svg list.txt use strict; use warnings; use autodie; use utf8; use 5.010; binmode STDOUT, ":utf8"; use constant OUT_DIR => "glyphs"; use constant PIXELS_PER_EM => 100; use constant UNITS_PER_EM => 1000; use XML::Simple; my ($svg_file, $list_file) = @ARGV; # SVG 読み込み my $svg = XMLin($svg_file, forcearray => 1, keyattr => []); # 行数・列数を求める my $row_max = int ($svg->{height} / PIXELS_PER_EM) - 1; my $col_max = int ($svg->{width} / PIXELS_PER_EM) - 1; # outline レイヤーを探す my $groups = $svg->{g}; my $group_outline; foreach my $group (@$groups) { if ($group->{'inkscape:label'} eq "outline") { $group_outline = $group; last; } } die "outlineレイヤーが存在しません" unless defined $group_outline; # 変換行列を求める my $transform = $group_outline->{transform}; my ($a, $b, $c, $d, $e, $f) = (1, 0, 0, 1, 0, 0); if (!defined $transform) { # noop } elsif ($transform =~ m/translate\((?<tx>-?\d+(.\d+)?(e-?\d+)?),(?<ty>-?\d+(.\d+)?(e-?\d+)?)\)/) { $e = $+{tx}; $f = $+{ty}; } elsif ($transform =~ m/matrix\((?<a>-?\d+(.\d+)?(e-?\d+)?),(?<b>-?\d+(.\d+)?(e-?\d+)?)\),(?<c>-?\d+(.\d+)?(e-?\d+)?),(?<d>-?\d+(.\d+)?(e-?\d+)?),(?<e>-?\d+(.\d+)?(e-?\d+)?),(?<f>-?\d+(.\d+)?(e-?\d+)?)/) { $a = $+{a}; $c = $+{c}; $e = $+{e}; $b = $+{b}; $d = $+{d}; $f = $+{f}; } else { die "未対応のtransformです: $transform" } # グリフごとに path を格納する変数 my @glyphs = (); foreach my $row (0 .. $row_max) { foreach my $col (0 .. $col_max) { $glyphs[$row][$col] = []; } } # @glyphs にパスを格納 my $paths = $group_outline->{path}; foreach my $path (@$paths) { my @data_args = split /\s+/, $path->{d}; my $new_data = ""; my ($col, $row); my $is_moveto_point = 1; foreach my $data_arg (@data_args) { if ($data_arg =~ m/(?<x>-?\d+(.\d+)?),(?<y>-?\d+(.\d+)?)/) { my $x = $+{x}; my $y = $+{y}; if ($is_moveto_point) { $x = $a * $x + $c * $y + $e; $y = $b * $x + $d * $y + $f; $col = int ($x / PIXELS_PER_EM); $row = int ($y / PIXELS_PER_EM); $x %= PIXELS_PER_EM; $y %= PIXELS_PER_EM; $is_moveto_point = 0; } $x *= UNITS_PER_EM / PIXELS_PER_EM; $y *= UNITS_PER_EM / PIXELS_PER_EM; $data_arg = "$x,$y" } $new_data .= "$data_arg "; } next if ($col < 0 || $col_max < $col || $row < 0 || $row_max < $row); $path->{d} = $new_data; push @{$glyphs[$row][$col]}, $path; } # リスト読み込み my @glyphname_list = (); open my $fh_list, '<:utf8', $list_file; while (my $line = <$fh_list>) { chomp $line; my @list = map { sprintf "u%x", (unpack "U*", $_) } split / +/, $line; push @glyphname_list, \@list; } close $fh_list; # 各グリフの SVG を生成 mkdir OUT_DIR if !-d OUT_DIR; foreach my $row (0 .. $row_max) { foreach my $col (0 .. $col_max) { my $svg; $svg->{'xmlns:sodipodi'} = "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"; $svg->{'xmlns:inkscape'} = "http://www.inkscape.org/namespaces/inkscape"; $svg->{width} = UNITS_PER_EM; $svg->{height} = UNITS_PER_EM; $svg->{path} = $glyphs[$row][$col]; my $svg_string = '<?xml version="1.0" encoding="UTF-8"?>'; $svg_string .= "\n" . XMLout($svg, RootName => "svg"); my $glyphname = $glyphname_list[$row][$col]; next if (!defined $glyphname || $glyphname eq "u3000"); # u3000:全角スペース open my $fh_out, '>', OUT_DIR . "/$glyphname.svg"; print $fh_out $svg_string; close $fh_out; } } exit 0;
SVGのどのマスがどのグリフか、割り当て表も用意しておく。
あ い う え お か き く け こ さ し す せ そ た ち つ て と な に ぬ ね の は ひ ふ へ ほ ま み む め も や ゆ よ ら り る れ ろ わ ゐ ん ゑ を
これを例えば
> perl split_svg.pl hiragana_1.svg hiragana_list.txt
として実行すれば、glyphs ディレクトリに一字一字のSVGが生成される。
FontForge でフォント化
そして、このバラしたSVGファイルを FontForge に取り込み、フォントを生成する。
FontForge ではSVGの1pxがフォントの1ユニットに相当する。また、OpenType の標準は1000ユニット/emなので、インポート元のSVGを1000×1000pxにしておくとちょうど良い。今回は、split_svg.pl でバラすときにSVGのサイズを1000×1000pxへ変換しているので、あとはそのままインポートするだけでよい。
#!/usr/bin/fontforge -script if ($argc != 2) Print("usage: fontforge -script " + $0 + " [version]") Quit() endif _version = $1 _fontfilename = "zeromin_" + _version + ".otf" _importfiles = "glyphs/u*.svg" New() # .notdef作成 Select(0x0000) SetWidth(1000) SetGlyphName(".notdef") # エンコードにUnicodeを指定 Reencode("unicode") # SVGをすべてインポート Import(_importfiles, 0) # 自動ヒントづけOFF SelectAll() DontAutoHint() # パスの統合 RemoveOverlap() # 整数値に丸める RoundToInt() # 半角スペース作成 Select(0u0020) SetWidth(500) # 全角スペース作成 Select(0u3000) SetWidth(1000) # フォント情報設定 SetFontNames("ZeroMin",\ "ZeroMin",\ "ZeroMin",\ "Regular",\ "© 2012 mashabow",\ _version) SetOS2Value("WinAscent", 880) SetOS2Value("WinDescent", 120) SetOS2Value("HHeadAscent", 880) SetOS2Value("HHeadDescent", -120) # OTF生成 Generate(_fontfilename) Print("generated: "+ _fontfilename) Close() Quit()
このスクリプトを FontForge で動かせば*1、とりあえずはフォントが生成される。最初の明朝体ということで「ZeroMin」と仮に名付けてみた。
試し打ち
出来上がったフォントをインストールして、さっそく試し打ち。
んー。初めてにしてはまずまずなような気もしないでもないけど、やっぱり字面の大きさや寄り引き、太さなんかのバラつきが目立つ。実用にはちょっと堪えない。
というわけで、まだまだ先は長そう。
JIS X 0208 と JIS X 0213 が改正されていた件
昨年12月に小林さんの講演を聞いたとき、JIS X 0213 が近々改正されるというようなことをおっしゃっていた。そんなことはほとんど忘れていたのだが、
584 デフォルトの名無しさん 2012/03/11(日) 13:26:15.37
文字コード総合スレ part7
そういや結局0213って改正するの? 常用漢字の関係で
588 デフォルトの名無しさん 2012/03/11(日) 16:02:37.18
JISCのサイト言ったらいつのまにか改正されててワロタ
誰も気づかなかったのか…
な、なんだってー!(AAry
JISCのサイトで調べてみると、たしかに2012年2月20日付で JIS X 0208 と JIS X 0213 が改正され、JIS X 0208:2012 と JIS X 0213:2012 になっている。それぞれ第5次規格、第3次規格にあたる。どちらも追補の形で出されており、PDFでは後ろ2ファイルが改正分になっている。
改正点はざっとこんな感じ。
- 6.6.2「字体の表現としての字形」において、旧常用漢字表「(付)字体についての解説 第1 明朝体活字のデザインについて」から引用していた「例」を削除し、代わりに新常用漢字表から引用。
- 附属書6(参考)「漢字の分類及び配列」の(旧)常用音訓を示す「[常]」を削除。(0208のみ)
- 附属書12(参考)「この規格と常用漢字表との対応」を追加。区点位置・例示字体・音訓を示す。
というわけで、2010年11月30日の常用漢字表改定に合わせた小さな改正になっている。規格の内容自体に関しては、実質的な変更はない。
花園明朝OT+Web フォントによるIVSと OpenType feature tag の表示テスト
ブラウザ上で異体字を表示するには、2つの方法がある。異体字セレクタを使ってIVSで異体字を表現する方法と、CSS3の font-feature-settings プロパティを使って OpenType feature tag によるグリフ置換をする方法だ。今回、花園明朝OTを Web フォントとして利用し、この2つの方法で異体字の表示テストを行った。
方法の具体的な解説
IVSによる方法
IVS(Ideographic Variation Sequence)は親字(基底文字)にVS(Variation Selector; U+E0100–U+E01EF)をつけて異体字を表現する。詳しくは下の Wikipedia の記事などを参照。
この方法で表現される異体字は、基底文字の包摂範囲内に含まれることになっている。プレーンテキストとして扱えるので、HTMLで表示したければそのままIVS(=基底文字+VS)を書けばよい。通常の文字と同様、数値文字参照を使って書くこともできる。フォントやOS、アプリケーションが対応していない場合には、通常の基底文字のグリフが単に表示される(ことが望まれるが、VSが豆腐などで表示されてしまうことが多い)。
例えばHTMLで
葛 葛󠄀 葛󠄁
と書けば、
葛 葛󠄀 葛󠄁
のように表示される。
OpenType feature tag による方法
OpenType にはいろいろなタグが定義されているが、漢字に関係するタグは expt, hojo, jp78, jp83, jp90, nlck, trad, aalt などである。あるグリフから別のグリフへ、一対一や一対多で置換できる。Mac OS X や InDesign、Illustrator などでは以前から使われているが、それ以外の環境ではでは対応が進んでいないため、あまり使われていない。圧→壓 のように、包摂範囲外のグリフへの置換も定義されている。
プレーンテキストでは扱えないため、HTMLではCSS3の font-feature-settings プロパティを利用してタグを指定する。これはまだドラフト段階なので、実際にはベンダー接頭辞をつけて利用することになる。
- font-feature-settings - MDN
- CSS コーナー: フォントの全要素を使用する - IEBlog 日本語
- Maniac Chef: OpenType features support on Chrome
例えば、jp90 タグを有効にするためには次のように指定する。
hoge { font-feature-settings: "jp90" 1; -moz-font-feature-settings: "jp90=1"; -ms-font-feature-settings: "jp90" 1; -webkit-font-feature-settings: "jp90" 1; }
aalt のような一対多の置換を含むタグにおいて、n 番目のグリフに置換したい場合には、上の 1 の部分に n を指定する。
2013-05-03追記:この記事を書いた時点では -moz-font-feature-settings だけ指定方法が異なっていた("jp90=1")が、現在では他と同じ形式("jp90" 1)に変更されている。
表示のテスト
花園明朝OT ver. 0.510 を Web フォントとして利用し、表示テストを行った。フォントフォーマットはOTFとWOFF(Web Open Font Format)。OTFからWOFFへの変換については、武蔵システムのWOFFコンバータを利用した。
表示テストは Firefox, Safari, Chrome, Opera, IE8 の各ブラウザで行い、すべて最新版を用いた。OSは Windows XP SP3(そろそろ潮時ですかね…)。参考までに先日インストールした Windows 8 Comsumer Preview 上でもテストをしたが、Opera とIE以外では差が見られなかった。
下の画像は、最も対応状況が優れていた Firefox での表示例。
結果一覧
ブラウザ | OS | OTF | WOFF | IVS | tag |
---|---|---|---|---|---|
Firefox 9.0 | Win XP | ○ | ○ | ○ | ○ |
Safari 5.1 | Win XP | ○ | ○ | × | × |
Chrome 17.0 | Win XP | ○ | ○ | × | ×* |
Opera 11.61 | Win XP | △† | △† | ׇ | × |
IE 8.0 | Win XP | × | × | × | × |
IE 10.0 | Win 8 CP | ○ | ○ | ○ | △§ |
OTF
- ○:OpenType フォーマットのフォントファイルを Web フォントとして利用できる。
- ×:対応しておらず、他のフォントで表示される。
WOFF
- ○:WOFFフォーマットのフォントファイルを Web フォントとして利用できる。
- ×:対応しておらず、他のフォントで表示される。
IVS
- ○:適切な異体字グリフが選択されて表示される。
- ×:VSが豆腐や中黒、空白として表示されてしまう。
tag
- ○:OpenType feature tag が利用できる。
- ×:対応しておらず、無視される。
結果一覧の註
* Chrome における OpenType feature tag 対応
expt, hojo, jp78, jp83, jp90, nlck の各タグについては、指定するとデフォルトのフォントで描画されてしまうという不具合がある。trad, aalt については、無視される(これは対応していない場合に期待される動作)。expt, hojo, jp78, jp83, jp90, nlck はすべて一対一の置換である一方、trad, aalt には一対多の置換も含まれるという共通点がある。が、これが原因かどうかははっきりしない。
† Opera における OpenType/WOFF 対応
Opera は TrueType, OpenType, SVGフォント, WOFFの各形式に対応していると謳っているが、花園明朝OTでは表示できなかった。武蔵システムのサイトの情報でも、和文 OpenType や、そこから変換したWOFFは×になっている。CFFアウトラインの和文フォントがダメなんだろうか。
‡ Opera におけるIVS対応
引用元が消えているが、Wikipedia によれば Windows 7 上の Opera でIVSが表示できるらしい。表には載せなかったが、今回 Windows 8 Comsumer Preview 上の Opera で表示できることを確認した。
§ IE10 における OpenType feature tag 対応
expt, hojo, jp78, jp83, jp90, nlck の各タグは正常に機能しグリフ置換が行われるが、trad, aalt については無視される。
また、IE10で花園明朝OTを表示させるとディセンダが大きく空いてしまうが、原因不明。
というわけで
Firefox がかなりいい感じ。他のブラウザの実装がいまいちなこともあり、実際に「使える」かどうかは疑問だが、覚えておくと何かの役に立つ……かも……?
花園明朝OTを0.510に更新、IVD 2012-03-02版に対応
Adobe-Japan1-6 準拠の漢字フォント・花園明朝OTを ver. 0.510 に更新。
以下、主な変更点について解説。
IVD 2012-03-02 版に対応
今月2日にIVD(Ideographic Variation Database)の最新版が公開され、Adobe-Japan1 に32個、Hanyo-Denshi*1 に8,850個のIVSが追加された。この追加により、Adobe-Japan1-6 に含まれる14,664個の漢字グリフすべてがIVSでアクセスできるようになった。花園明朝OTは今回これに対応。
Adobe-Japan1 コレクションに追加されたIVSについては、以下のページに詳しい。
CMap を UniJIS2004-UTF32-H ver. 1.011 に更新
文字コードとグリフ(CID)との対応表である CMap を、最新バージョンの1.011に更新した。1.010からの変更点は以下の通り。
- U+9FCC(鿌)→ CID+20156 の対応が追加された
- U+2329, 232A(〈, 〉)→ CID+682, 683 の対応が追加された
花園明朝OTは漢字フォントなので、関係するのは前者のみ。U+9FCC(鿌)は1月31日リリースの Unicode 6.1.0 で追加された統合漢字。
スペースのグリフを少し追加
CID+1(欧文スペース), CID+3000(和文スペース), CID+8720(CID+1 の vrt2 置換先グリフ)を追加した。CID+1, CID+8720 の文字幅はとりあえず半角として実装した。CID+8720 を追加した理由は次の項で。
Firefox において Web フォントに使用できない問題を解消
Firefox で花園明朝OTを Web フォントとして使おうとしても、ファイルのダウンロード自体は行われるものの花園明朝OTで描画されない問題があった。
これについて、上の記事のコメントでえむけいさんから次のような情報をいただいた(ありがとうございます)。
Windowsでは、CFFアウトラインのOpenTypeフォントのGSUBテーブルにvrt2 featureが定義されていないのにvhea/vmtxテーブルがあると、OSに不正なフォントして弾かれます。インストールすれば使えるようですが、WebフォントをロードするためのAPIはWebから任意のデータを受け取る可能性があって、フォントレンダリングエンジンの脆弱性も実際に何度か発見されているので、チェックが厳しくなっているようです。
花園明朝OTが web font で使えないっぽい - しろもじメモランダム
縦書きグリフを追加するか、vhea/vmtxテーブルを削除してください。
このアドバイスに従い、縦書きグリフ CID+8720 を追加して以下のように vrt2 feature を定義した。
feature vrt2 { sub \1 by \8720; } vrt2;
これにより、Firefox での問題は解消されたようだ。縦書きグリフを追加するのではなく vhea/vmtx テーブルを削除する方法もあるが、これを試したところ Microsoft Word で縦書きができなくなった(花園明朝OTを指定してもMS明朝で描画される)ので採らなかった。
なお、上の記事では「Chrome で試したら『エラー このページの表示中に問題が発生しました』云々と出てページすら表示されなかった」と書いたが、こちらについては Chrome のアップデートの過程で解消されていた様子。
*1:こちらは花園明朝OTには収録していない。
Windows 8 Consumer Preview のIMEにおけるIVS対応
昨年9月13日に公開された Windows 8 Developer Preview では、IMEの変換候補にIVSを含む語が現れるようになっているとのことだった。
Windows 8 では IVS(Ideographic Variation Sequence)を変換候補から選択できるようになっています。IVSとは?については、こちらなど詳しく書いてあるので参考にしてください。
IVSを利用した文字を変換候補に表示させない方法|窓のくすり箱
実例を示すと、Windows 7まではJIS90とJIS2004の文字の混在がIMEでできませんでした。したがって、辻という文字はJIS90では「一点しんにょう」ですし、JIS2004では「二点しんにょう」となり、双方を同時に使うということはできませんでした。Windows 7で旧字体を使いたい場合は、JIS90互換フォントパッケージをインストールする必要がありました。
これがWindows 8から変わります。
今回 Windows 8 Consumer Preview が公開され、自分の環境にもインストールをしたので、IMEのIVS対応について改めて確認してみた。IMEのバージョンは Microsoft IME 2012 (15.0.8250.0)。
プロパティ > 詳細設定 > [変換]タブ > 詳細設定 をクリックすると、以下のようなウィンドウが現れる。
この [変換文字制限] の項で [変換文字制限をしない] を選択すると、IVSを含む語が候補に出現するようになる。デフォルトでは [IVS (Ideographic Variation Sequence) を含む文字を制限する] になっているので、IVSを含む語は出現しない。Developer Preview の段階では [変換文字制限をしない] がデフォルトだったようだが、さすがに混乱が懸念されるので変更したのだろう。
下の図はメモ帳上で「くず」を変換してみた様子。
JIS2004字形 と、JIS90字形 が変換候補に表示されている。JIS2004字形を選択すると単に [U+845B] が入力されるだけだが、JIS90字形を選択するとVS付きのIVS [U+845B U+E0100] が入力される。
「味噌」「祇園」「辻」など、JIS2004で例示字形が変更された文字が対象のようだ。ただ、「いばらき」で変換した場合に候補に出るのはVSなしの [U+8328](茨)のみで、JIS90字形の [U+8328 U+E0100] は出てこないなど、辞書への収録基準はよくわからない。
カーソルの移動や削除などはIVS(=基底文字+VS)で1単位となっているため、「変な箇所で切り貼りしてしまって別の基底文字にVSがついてしまった」というようなミスはあまり心配しなくてよい。また、そもそも上述のようにIVSを含む候補の表示はデフォルトでオフになっているので、IVSを含んだ文書が Windows 8 によって爆発的に増えるというわけでもないだろう。ただ、IVSを扱える環境が徐々に広まりつつあるのは事実だ。
なお、マイクロソフトはこれまで後方互換性のためにJIS90互換フォントパッケージを提供してきたが、Windows 8 以降には提供しないと発表されている。
マイクロソフトでは、JIS90互換フォントパックを提供するのは、Windows 7用が最後になることも明らかにした。Windows 7の次のバージョンからは、JIS2004に完全移行するとしている。
マイクロソフト、JIS90互換フォントの提供はWindows 7で最後 -INTERNET Watch