白屋書房Blog

組版・縦書きサイト「白屋書房」(https://hakuoku.github.io/agakuTeX/)のブログです

激闘TeX:引用符をめぐって

 約物類との格闘です。このへんIPAフォントとOTFパッケージとplextとupLaTeXのデフォルトが絡み合ってパズルのようでした。
 まずは知識のないころにけっこう苦戦した〝IPAにおけるダブルミニュート〟について。
縦書きしてみよう」ではこう解説されています。

このダブルミニュートは横書きと縦書きで異なります。文字コードで言うと、横書きの左側(起こし)が CID:7608 (Unicode: U+301D)、右側(受け)がCID:7609 (Unicode: U+301F) 、縦書きの上側(起こし)が CID:7956 (Unicode: U+201C)、右側(受け)がCID:7957 (Unicode: U+201D) です。
(中略)
ただし、CID 対応でない TrueType フォント等の場合、ダブルミニュート、特に縦書き・受けのダブルミニュートが収録されていません(IPA フォントはこれに該当します)のでご注意下さい。

 そして(美文書入門にも)以下が解決策として載っていました。

\CID{7956}CID{7956}CID{7957}\CID{7957}

 ところがこれを組んでみるとこうなります。

f:id:isaribisaitoh:20171114192520j:plain

 おかしいなということでUniViewで文字の情報を確認してみると、ブロックはCJK Symbols and Punctuationでした。名前は「ダブルプライム・クォーテーションマーク」になるらしい。ダブルミニュートは和製英語のようです。

f:id:isaribisaitoh:20171114204403j:plain

 三つしかない。
 縦書きにおける正しい字形は起こし側が「右下にある上から下に払ったダブルプライム」と、受け側が「左上にある下から上に払ったダブルプライム」になるはずです。どれも違う。
 仕方ないので片っ端からタイプセットしてみます。

\UTF{301D}UTFの301D、E、F\UTF{301E}\UTF{301F}
\CID{7608}CIDの7608、7609\CID{7609}
\UTF{201C}UTFの201C、D\UTF{201D}
\UTF{201E}UTFの201E、F\UTF{201F}
\CID{7956}CIDの7956、7957\CID{7957}

f:id:isaribisaitoh:20171114192559j:plain

 やった!二番目が成功だ!あとは三番目が普通にキーボードから全角ダブルクォートを入れた時と同じですね。
 じゃあCIDの7608って何だよと思ったんですが、CID番号ってWeb上で簡単に調べられないんですねorz Adobeの公式リファレンスPDFでうまいこと探せませんでした。
 というわけで美文書入門の付録で確認すると、確かに7608と09が横書き、7956と57が縦書きのダブルプライムでした。

f:id:isaribisaitoh:20171114192731j:plain

 しかし実際にちゃんと出力されるのは横書きのはずの7608と09です。ということは、IPAex明朝ではCIDの7608=Unicodeの301Dを右に90°回転させて起こしに、左に90°回転させて受けに使っているのではないかと推測しました。7957では回転させないで使える縦書き用のグリフそのものを呼んでいる(そしてIPAには収録されていない)から豆腐になるのかと。
 そう思うとこのへんの挙動が不明です……upLaTeX+utbookで縦書き文書をタイプセットした時に、“実際には”どの字が植えられているのかがよく分かりません。UnicodeにはCJK Compatibility Formsとして縦書き用の各種カッコが収められているんですが、例えばベタ書きでカギカッコを入れた時にこの縦書き専用の形を使っているのか、それとも横書き用の起こし側を90°回して使っているのかとか。

 ちなみにCID対応フォントで組んでみるともっと分からなくなります。小塚明朝ではこうなりました。

f:id:isaribisaitoh:20171114192706j:plain

 当たり前ですがCIDのグリフに忠実に組まれました。ただし今度は一番目を回転させてるように見受けられます。301Eは持ってないのか回転できなかったのか。
 201F(Double High-Reversed-9 Quotation Mark)は収録されてないっぽいですね。そもそもどういう記号なのかがわからん。201Eはドイツ語とかで使うみたいなんですが。

 分からないことだらけですがとりあえず出力できたのでよしとしましょう。サイトのほうのマクロをプリアンブルに入れておけば\〟だけで出せるようになります。

「約物」セクション追加

全角半角・タテヨコのくだりが終わったので縦書きにおける約物の制御に入りました。
とりあえず“引用符”と、感嘆符! や英単語 etc. に自動で入るグルーと、(括弧類)の扱い方までです。
あとはダッシュだけかな?――と言ってもこれが一番根が深いんだけどorz

アクセントつきアルファベットの扱い方に比べたら大して複雑でもない問題なのに何をそんなに苦渋しているのかというと、ひとえに私の執筆方針すなわち「原稿中におけるコマンドを可能な限り減らす」のせいです。
フォントによってダッシュの間が繋がらないことは旧知の問題で、そのための解決策もとっくに出ています。\―コマンドを繋がるように定義して、文中に出てくるダッシュの頭にすべて\をつければいいんでした。

やりたくない。

原稿中にコマンド書きたくないんだよ!今回の問題すべてマクロ定義で片付けたけど本当は嫌なんだよ! それでも二重感嘆符なんかはもともと縦中横にしなければならないことは分かっていて、他の二桁の数字とかと同じと思えばまだ許せました。
ところが何故かダッシュだけは許せないんです。こう――打ちたいんです。
私自身がかなりダッシュを多用する性質だからかもしれません。大体が感情が高ぶってたりタメが入ったりするところに使うものなのでバックスラッシュがついてると水を差されたように感じるのかも。

とはいえ自動縦中横や自動ダッシュ置換を行えるほど筆者の技術力は高くありません。正直感嘆符の直後にカギカッコがくる時のグルー禁止処理だけで死ぬかと思った。それもまだベータ版だし。なんで次の字すなわちトークンをどこにもうまいこと代入できないんだ。
あーどうやったら「TeXレベルの」マクロ力強くなるんだろう……私が原著当たってないのが悪いんだけど、それでもどこかに定義済み変数(というものがあるのかどうか知らんけど要は状態を取得できるインターフェース的な)のリストとかハンディなコマンド一覧とかがあればずいぶん普通のプログラミングに近くなって助かるのにorz

しばらくは書いて書いて書き続けてTeX思考力を養うしかなさそうです。頑張ろう。

激闘TeX:ギリシャ文字とキリル文字

 アクセントと特殊記号 (2)前回の投稿までで、西ヨーロッパ諸語はなんとかなりました。次はギリシャ語とロシア語をなんとかする番なんですが、今まで避けてきたフォントの話題に触れなければならないのでまあめんどくさかったです。とりあえず私なりの理解をしたためてみます。

 pxcjkcatパッケージで「ギリシャキリル文字が欧文扱いに」なるはずのprefercjkvarモードを指定して文中にロシア語を書いてもエラーになります。

\usepackage[T1]{fontenc}
\usepackage{textcomp}
\usepackage[utf8]{inputenc}
\usepackage[prefercjkvar]{pxcjkcat}

 もう一度「UTF-8 で欧文文字を入力する ~inputenc パッケージ~」を熟読すると、これはどうやらupLaTeXそのものの挙動とinputencパッケージの働きによるものらしいです。
 でここから話が進まなくなって、先にエンコードに関する知識が必要なことが分かったので勉強しました。わけわかんないから今まで触らないようにしてたのに。・゚・(ノД`)・゚・。

 恐ろしいことにTeXには、我々が今まで一般的に使ってきたUTF-8やSHIFT-JISとは全く意味が異なるエンコーディングが存在します。
 すごくざっくり言っちゃうと、UTF-8というのは「筆者とテキストエディタが原稿を書く」ために用いているエンコード(=ファイルのエンコーディング)で、それとは別に「できたファイルを受け取ったTeX活字を並べる時に参照するエンコードというものがあって、それがかのフォントエンコーディングだというわけです。前者が入力、後者が出力と言えばいいでしょうか。
 そしてこの2つはまったく連動していません。いや和文の部分ではどっちもUnicodeだけど。TeXは欧文と和文を扱う部分が右脳と左脳のように分かれています。(語弊のある例えだけどいい言い回しが思いつかない)
 UTF-8で書かれたファイルを受け取ったupLaTeXが文を読み、最低限のアルファベットだけ欧文部分が扱い、和文部分がそれを除いたすべての文字をUnicode文字集合というひとつの巨大な袋から取り出して並べてくれます。これが“u”pLaTeXであるゆえんですね。
 なのでパッケージを使わずにキリル文字を原稿に書いた時も特にエラーになることはなく、代わりにカナと同じく縦向きに組まれます。ここまで前提です。

 そして今やりたいのはフランス語やギリシャ語を横倒しにする、すなわちupLaTeXが出力する時に使う「最低限のアルファベット」の範囲を拡大して、拡張アルファベットもその中に含めることです。
 デフォルトの「最低限のアルファベット」の範囲というのが遠い昔、はるか彼方の銀河系でコンピュータが128文字しか扱えなかったころに作られたOT1フォントエンコーディングになります。16×8しかない表にアルファベットと最小限の記号が詰め込まれています。これで組版システムができちゃうんだから表音文字ってのは気楽なもんだよ┐(´д`)┌
 まあそんな数では早晩破綻します。そのため16×16あるT1エンコーディングと、さらに追加の記号を収めたTS1エンコーディングが作られました。T1にはほとんどのアクセントつきアルファベットが、TS1には§などの記号が収められています。
 これらを使えるようにするための呪文が、最初に書いた\usepackage[T1]{fontenc}\usepackage{textcomp}でした。

 これでめでたくフランス語が書けるようになったかというとさにあらず。出力用の袋は追加されたけれど、まだupLaTeXがそれを認識していません。「アクセントつきアルファベットとかは欧文脳の部分で処理しろ」という命令を通してやる必要があって、これがinputencとpxcjkcatパッケージの機能になります。

 さてやっと準備が整いました。pxnoncjkモードでほとんどを欧文扱いにしてやってタイプセットすると、フランス語スペイン語あたりまではちゃんと欧文扱いで組まれますがギリシャキリル文字はダメです。何故ならT1・TS1の表の中にないから
 広がったとはいえT1エンコーディングもたかが256文字です。主要なアクセントつきアルファベットを収めたらもういっぱいです。欧文として認識はできたものの、出力の段になって肝心の活字がない、という状態こそがこの壁の原因だったようです。やれやれ。

 対策はもちろんあって、活字を用意してやればいいんです。キリル文字を含んでいるフォントエンコーディングT2Aギリシャ文字LGRです。これをT1エンコーディングに追加してやることでupLaTeXは新たな活字を手にしたことになります。

\usepackage[T2A,LGR,T1]{fontenc}  %標準にしたいものを最後に置く

 さあもう文句ないだろうと思ったら最後の試練がありました。upLaTeXは文字種を自動判別してくれませんキリル文字に出会ったらT2Aエンコーディングに切り替える、みたいな動作はしてくれないので、使うべきエンコーディングをその都度人間が指定してやらなければなりません。
 そこで登場するのがBabelパッケージです。本文において\foreignlanguage{russian}{中身}で囲ってやることでようやくT2Aエンコーディングが働き、めでたく日本語の文書に横倒しのヨーロッパ諸語を埋め込むことができました。

 ……ああ疲れた。

(※実は筆者の環境においてfontencでT2A“だけ”を指定すると、Babelを使わないベタ書きでもキリル文字とアクセント文字をどちらもきちんと組むことができました。ただどう動いているのかが分からないので裏技としておきます。鋭意調査中です)

激闘TeX:文字と記号のタテヨコ

 筆者はド素人ですが、ド素人なりにサイトのページには可能な限り分かりやすく、こうすればいいという結論を書くように心がけています。ですがもちろんそこに至るまでにものすごく迷走したり試行錯誤しています。
 失敗の繰り返しなのでサイトやQiitaみたいなところには上げられないし、ということで、自分用の備忘録として、そういうTeXとの死闘の記録や詳しい解説をここに書いていこうと思います。
(環境はすべてupLaTeX、ファイルの文字コードUTF-8です)

 さて アクセントと特殊記号 後編 では「アクセントつきアルファベットや全角扱いになってしまう記号を、“コマンドなしのベタ書きで”欧文扱いの横倒しで組ませる」ということをやりました。
 基本的には記事で書いた通りZRさんのpxcjkcatパッケージを使うんですが、思い通りの挙動にするまでがけっこう長かったです。

 とりあえず「upLaTeX でアクセント付きのラテン文字などがうまく出力されないときの対処法」を参考に一番シンプルな設定にしてみると、下の例ではハートが出てくるところでつまづきました。

\documentclass{utbook}
\usepackage[T1]{fontenc}
\usepackage{textcomp}
\usepackage[utf8]{inputenc}
\usepackage[prefernoncjk]{pxcjkcat}  %これだけ
\begin{document}
cassino de la jetée de Nice
†‡©£§¶«ギュメ»{\copyright}{\pounds}  %一般的な西欧語の文章で使う記号
♡☆♪※●▲■‼  %日本語の小説で使いそうなやつ
Братья Карамазовы  %ロシア語を使いたくなった時のために
Μοιρα  %サンホラーのために
\end{document}

 改めて先ほどの記事の補遺や、「[改訂新版]upLaTeXを使おう」の 欧文のUTF-8入力との併用 などをよく読んでみると、これはprefernoncjkモードが『漢字・かな・ハングル等の明らかな「CJK文字」以外は全て欧文扱いに』してしまうからのようです。
 CJK文字の具体的な範囲はREADMEによると、

  • kanji: 漢字・部首・注音字母: hani, haniA, haniB, haniC, hani1, hani2, cjk01, cjk02, cjk03, cjk05, cjk06, bopo, bopo1.
  • kana: ひらがな・カタカナ: hira, kana, kana1.
  • cjk: CJK 記号の一部・全角/半角互換形・彝文字: cjk04, cjk08, cjk07, cjk09, cjk10, cjk11, cjk12, cjk13, sym15, yiii, yiii1.
  • hangul: ハングル完成形・ハングル字母: hang, hang1, hang2, hangA, hangB.

 本文2行目までは全てASCII及びT1・TS1エンコーディングに含まれるいわゆる“半角”記号なので、inputencを通してLaTeXネイティブ命令に変換される1か、でなければtextcompが適切に取り扱ってくれます。
 ポイントなのが"cjk"ブロックで、3行目からはそこに含まれない(もちろんTS1にもない)ので扱いきれずにエラーを吐くみたいでした。

 解決策は\cjkcategory命令の第1引数に和文扱いしたいブロックを全部書いてやることなんですがうん、ちょっと待って。日本語の小説で使うには分が悪すぎる。
 たとえば用例として挙げられている○や▲や□は「Geometric Shapes」に属するのでIDはsym18になります。
 ところがここにハートはありません。♡や☆や♪は「Miscellaneous Symbols」(sym19)に入ります。
 これら及び必要な記号ブロックをcjk扱いにしてやっても他の文字は全部欧文扱いなので、ダッシュの位置がずれるとか縦向きにしたいまで横向きになるとかそれゆえの問題が残ります。(ダッシュは間が繋がったから位置さえマトモなら是非使いたかったんだけど…)

 あと愕然としたのが†‡ダガー・ダブルダガー)と(パラグラフ)と§(セクション)。¶と§がLatin-1 Supplementに入ってるのでてっきりダガーもだと思ったのに、何故かこいつらだけ「General Punctuation」に入ってる。
 prefernoncjkモードならGeneral~も欧文扱いになってるんだから別にいいかというとそうでもなくて、さらに愕然としたことにもGeneral Punctuationに入っているんですよ。米印が欧文扱いになってちょっと小さめに表示された時は驚いた。てっきり日本の記号だと思ってた。

f:id:isaribisaitoh:20171010203241j:plain
衝撃

 なのでダガーのみを横倒しにして他は和文扱いというようなことはできません。さらに恐ろしいことに×と÷はLatin-1 Supplementに入っていたりするのでこれも分離できません。(「Latin-1 Punctuation and Symbols」というスクリプトがあって本当に約物だけなので、これを使えば算術記号と分けて定義できそうなんだけど多分upLaTeX側で使えない)
 どうすりゃいいんだよ!必要な記号だけ横倒しできないのかよ!

 ……でえーと、私は何をしたかったんだっけ。そうそう、フランス語をきちんと表示したかったんだった。
 正直これだけの用途なら「アルファベット類のみ欧文扱いにして他は全部和文扱い」にした方が早かったです。prefernoncjkモードをやめてprefercjkvarモードを使い、欧文扱いしたいブロックを追加することにします。

\usepackage[T1]{fontenc}
\usepackage{textcomp}
\usepackage[utf8]{inputenc}
\usepackage[prefercjkvar]{pxcjkcat}  %アルファベット・ギリシャ・キリル文字のみ欧文扱いに
\cjkcategory{latn1}{noncjk}  %そこにLatin-1 Supplementを加える

 それであとはもう文体に合わせて運用していくしかなさげです。外国語が、出てきてもせいぜい仏・独・西ぐらいという人は上の設定で充分でしょう。
 逆にルーマニア語だのベトナム語だのをガリガリ使いたい人はprefernoncjkで、\cjkcategory{sym18,sym19,<あとsym04とかsym08あたり>}{cjk}をプラスしてやればだいたいなんとかなると思います。

 そしてここまでやってもなお立ちはだかるギリシャ語とキリル文字の壁。長くなったので次回に回します。

引っ越しました

恐ろしいことに最後の投稿から1年が経ってしまいましたが、また更新できそうなのでブログの方にも戻ってきました。
うかうかしてる間にTeX Liveの2017年版が出ちゃったりして愕然としています。

これまでサイトはTumblrで作っていたんですが、いろいろ無理があったのでGitHubの方にお引っ越ししました。
やっぱりソースコードを書いて表示するにはそれに合った適切な環境が必要だと痛感しました。単にMarkdown対応してるだけじゃやっぱりきついです。 そもそもこういう解説的なものを書いていくには、書いた順に記事が並んでいくブログというメディアは本質的に合わない。

https://hakuoku.github.io/agakuTeX/

構成を大幅に見直し、最初に基礎となるこちゃこちゃした文字と記号の制御をやってしまってからルビや文書構造などの大技に移行するようにしました。今のところまだアクセントつきアルファベットのあたりで、つまりはかなり最初の方です。
そもそもTumblrに上げてた情報が検証しなおしたら内容・文章ともにガタガタの間違いだらけで、大した需要もないサイトですが消え入りたくなりましたorz

サイトの構築には静的サイトジェネレーターの「Hugo」を使っています。とにかく速い!多少の知識(と英語力)は要るけど、シンプルでスピーディーでエレガントで大変おすすめです。
どちらかというとブログ的なテンプレートが多くて固定サイト用のテーマが見つからず、結局かなりの部分を自分で書くことになりました。今はつぎはぎクオリティだけど、いつか汎用化して誰でも使えるような固定サイトorドキュメンテーション用テンプレートに仕上げたいという遠大な夢があります。
コマンドラインからじゃなくてGUIでもっと手軽に使えるようになれば、ブログじゃなくて静的サイトが作りたい人の需要を満たせると思うんだけどどうだろう。シェルスクリプトにHTMLベースのガワをかぶせることは割りと簡単にできるみたいなので、そのへんも研究してみたいところです。

亀の歩みですが、少しでもお役に立てれば嬉しいです。

改行問題解決しました!

今まで小説における改行を「見たまま出力」するために、プリアンブルで \obeylines を宣言してたんですが、これだと空行そのもの、原稿中の1行とか2行アキは結局無視されるという問題がありました。
仕方ないから入れたい空行の数だけ \vspace{baselineskip} をソースに書くという手に頼っていましたが、WYSIWYG的には見づらいわセマンティック的には間違ってるわでもうどうしようもなかった。
早くなんとかしたかったものの私の知識が足りなすぎて五里霧中だったのが、先日∃x(x=a)さんがアドバイスを下さり、改行問題はここに見事に解決されました!

具体的には以下のマクロをプリアンブルに入れてやります。もちろん外部のパッケージにしても。

{\catcode`\^^M=\active%
\gdef\xobeylines{\catcode`\^^M\active \def^^M{\par\leavevmode}}%
\global\def^^M{\par\leavevmode}}

んでbegin{document}の直後で、 \xobeylines を宣言するだけ!
これで晴れて本文を、ガチで見たまま改行できるようになりました。


そもそも元の\obeylinesは、以下のように定義されてるそうです。

{\catcode`\^^M=\active % these lines must end with %
\gdef\obeylines{\catcode`\^^M\active \let^^M\par}%
\global\let^^M\par} % this is in case ^^M appears in a \write

^^Mが改行文字を表すので(ASCIIの13番)、それを全部\parに変えちゃうことでオール改行を実現しているようです。

ただこの方法だと、一つの行(=段落)を組み終わって次の行に移るためにvertical modeに遷移した時、「中身が何もない\parだけの行は無視する」というTeX本来の動作が勝ってしまいます。
そこで^^M\par\leavevmodeにしてやることで、空の行でも立ち止まって出力することが可能になった、という寸法らしいです。

TeXレベルの命令を書き換えてしまうのはちょっと怖かったので、新しい命令として定義してみました。命名は適当です。もっとちゃんとしたコマンド名があればそっちの方がいいです。
あと本家obeylinesに揃えてプリアンブルで宣言したかったんだけど、それだと機能しなかったのでdocumentの内側に書くことにしてます。(トンチンカンなこと言ってたらすみません)

これでいわば「空行含め全ての論理行をことごとくパラグラフとして扱う」ことになったので、TeX流の意味論的にはもう完全に間違ってることになりましたが、もともと正しい文法なんぞ目指しちゃいないのでよしとします。
「可能な限り生原稿に寄せた形のTeXソースにする」という(無駄な)原則に一歩近づけました。嬉しい。∃xさん本当にありがとうございました。

サイトの方の記事はこれから編集します。早くレイアウト編まで作らないと……。

参考

TEX in Practice: Volume III: Tokens, Macros - Stephan v. Bechtolsheim - Google ブックス

Introduction

まだコンテンツもろくにない状態ですが、年の瀬だし来年の抱負なども兼ねてまえがき的なものを書いておこうと思います。サイトの記事とかぶってるところもあるんで、読む意味はあんまりないです。

前提:当サイトは文庫本作成エンジン「威沙」を応援しています。

えー時々なんか技術っぽいことを呟いたりもしますが、基本的に筆者はプログラミングができません。一応勉強はしましたが商業的・学術的に使用したことは一切ありません。多分これからもないと思います。
その上で(ド素人という立場の上で)、現時点で最速で縦組みの小説本を作ろうと思ったら、とにかく威沙がおすすめです。「無料における最強の組版ソフトウェア」というキャッチフレーズの通り、ほんとに綺麗に柔軟に組めます。というわけでいくらステマの謗りを受けようとも、筆者は威沙と作者の風野旅人氏、サークル「Sylphid Software Systems」を全力で推していく所存です。

あとはやっぱデファクトスタンダードとしてのWordの地位は揺るがないと思います。プロプライエタリ(企業占有)とはいえMicrosoftが潰れるって事態はちょっと考えづらい。このサイトは徹底的にフリーソフトウェアを推していきますが、それでもLibreOfficeとかあるんだし。
だからWordその他ワープロソフトで頑張って理想に近く出力できたら、少なくともアマチュアレベルでは十分なんだと思います。

さてそういったスタンスに立った上で、以下組版をめぐる展望です。

続きを読む