マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

なぜ pxrubrica はデフォルトでゴーストしないか

例の記事のpxrubrica パッケージの話についてチョット補足。

pxrubrica でゴーストする話

コレで説明されているように、pxrubrica パッケージの \ruby 命令で和文文字列にルビをつけた場合、その外側との間に本来入るべき和欧文間空白(xkanjiskip)が入らない。これはそういう仕様であって、xkanjiskip を入れたい場合は、命令のオプションの補助設定に : を 入れる必要がある。*1

ところが実は、pxrubrica パッケージには、ルビ付文字列にゴーストを自動的に挿入する機能が存在する。すなわち、\rubyusejghost という命令を実行すると、ルビ付の和文に対して「ゴースト処理」が有効になる。((\rubyuseaghost を実行すると、ルビ付の欧文(\aruby 命令)について「ゴースト処理」が有効になる。))この状態だとユーザが特に何も指定しなくても、周囲の文字種に応じて kanjiskip や xkanjiskip が適切に挿入される。

% upLaTeX 文書; 文字コードは UTF-8
\documentclass[uplatex,a4paper]{jsarticle}
\usepackage{pxrubrica}
\setlength{\parindent}{0pt}
\begin{document}
% ルビ無し
{\TeX}芸術。\par
% 和欧文間空白が入らない
{\TeX}\ruby[g]{芸術}{アート}\par
% 空白挿入の指定が必要
{\TeX}\ruby[:g]{芸術}{アート}\par
% ゴースト処理を有効にする
\rubyusejghost
% 自動的に和欧文間空白が入る
{\TeX}\ruby[g]{芸術}{アート}\par
\end{document}

だとすると、当然次の疑問が生じてくる。

なぜ「ゴースト処理」は既定で有効になっていないのか。

これについてチョット説明しておく。

そもそも無闇に xkanjiskip すればよいわけではない話

先の例だとルビ付の「芸術」の前に xkanjiskip が入ったほうがよい。これは確かである。では次のようにルビ文字列が長い場合はどうか。

% upLaTeX 文書; 文字コードは UTF-8
\documentclass[uplatex,a4paper]{jsarticle}
\usepackage{pxrubrica}
%\rubysetup{<->}
\setlength{\parindent}{0pt}
\begin{document}
{\TeX}芸人。\par
{\TeX}\ruby[g]{芸人}{コメディアン}\par
{\TeX}\ruby[:g]{芸人}{コメディアン}\par
\rubyusejghost
{\TeX}\ruby[g]{芸人}{コメディアン}\par
\end{document}

この場合、「コメディアン」のルビを付けた和文「芸人」とその前の「X」の間には、xkanjiskip を入れなくとも既にその幅以上空きが入っている。これはルビが左側にはみ出したせいで隙間が生じているためである。この状態では xkanjiskip は寧ろ入れないほうが適切であろう。しかし、\rubyusejghost でゴースト処理を有効にした場合は、原則に従って xkanjiskip が入ることになってしまう。だから結局ユーザがこの xkanjiskip を抑止する処置をとる必要が生じてしまうのである。

もしこういう場合も含めて“適切に”処理できるようにしようと画策するとどうなるか。結局「pTeX がどう処理するのか」を前もって探知する必要が生じてしまう。ソレが極めて困難であるから回避策として「ゴースト処理」を使っているわけであり、ソレが復活してしまうのは本末転倒である。

そういうわけで、結局「ユーザが判断して何かを指定する」という必要性は避けられない。

ルビを「進入」しかつ「ゴースト」するとアレ

先の「芸人」の例で欧文と和文の間に「元々隙間がある」のは「ルビ文字列がはみ出した」からであった。pxrubrica パッケージでは、こういう場合に、前の文字にルビ文字列を「進入」させることができる。

% ルビ文字列を"進入"させる
{\TeX}\ruby[<g>]{芸人}{コメディアン}

先の例で、進入を有効にしてみよう。4 行目の % を外して有効化する。その上でコンパイルを行うと次のエラーが出る。

! Package pxrubrica Error: Intrusion disallowed when ghost is enabled.

見ての通りで、ようするに

「ルビの進入」と「ゴースト処理」は両立しない

のである。

※ちなみに、エラーの出る 10 行目(出力の 4 行目に相当)を削除した場合の組版結果は以下の通り。

なぜこの両者が共存できないかを説明するのは難しい。そこで、敢えて両者を一緒に使ってみて何が起こるのかを見てみよう。そのために pxghost パッケージを利用することにする。

単純に、進入があるルビ付文字列にゴースト処理を適用するとどうなるか。

% upLaTeX 文書; 文字コードUTF-8
\documentclass[uplatex,a4paper]{jsarticle}
\usepackage{pxrubrica}
\usepackage{pxghost}
\rubysetup{<->}
\setlength{\parindent}{0pt}
\begin{document}
% ゴースト処理なし
{\LaTeX}\ruby{}{ゆきだるま}芸人\par
% ゴースト処理あり
{\LaTeX}\jghostguarded{\ruby{}{ゆきだるま}}芸人\par
\end{document}

これだけ見ると、特に問題ないようにみえる。

ところが、ルビの前後で行分割が起こる場合に問題が起こる。

% upLaTeX 文書; 文字コードUTF-8
\documentclass[uplatex,a4paper]{jsarticle}
\usepackage{pxrubrica}
\usepackage{pxghost}
\rubysetup{<->}
\setlength{\parindent}{0pt}
\begin{document}
% 色々な横幅の枠の中に文書を組む
\newcommand{\xTestCase}[1]{%
#1\par
\fbox{\parbox{#1}{%
すみませんが、お客様の中に
{\LaTeX}\ruby{}{ゆきだるま}芸人
の方はございませんでしょうか。}}\par
\fbox{\parbox{#1}{%
すみませんが、お客様の中に
{\LaTeX}\jghostguarded{\ruby{}{ゆきだるま}}芸人
の方はございませんでしょうか。}}\par\bigskip}
\xTestCase{180pt}
\xTestCase{145pt}
\xTestCase{150pt}
\end{document}
  • 横幅を 145pt にした場合(2 番目)は、ゴースト有効にするとルビ文字列が枠を(つまり定められた行の領域*2を)はみ出してしまう。ゴースト無効の場合の出力は想定通りである。
  • 横幅を 150pt にした場合(3 番目)は、ゴースト有効にすると、ルビ付文字の前の行末に xkanjiskip が残ってしまう。*3

そして、pTeX の内部処理上の制約のため、行分割が起こる場合の挙動を常に正常にすることは極めて困難であり、自分はこれは不可能だと考えている。また、pTeX による行分割の結果はユーザが予め予測できないので、「行分割が起こった場合の対策をユーザに指定させる」という方針もとれない。このため「ルビ文字列の進入」と「ゴースト処理」は両立できず、従って同時に有効にしようとするとエラーを発生させているのである。

まとめ

自分としては pxrubrica パッケージにおいて「ルビの進入」は重要な機能だと考えている。従って、その機能と共存できず、かつ、ユーザによる調整を不要にするものにもなっていないという点で、「ゴースト機能」の有用性はあまり高くないと見なしているのである。

*1:詳しくはマニュアルを参照。ちなみに、デフォルトの動作は「和文間空白(kanjiskip)を入れる」になっている。

*2:一般的な書籍の(本文領域の)組版において、行頭や行末の文字にルビを付す場合にルビが本文領域をはみ出してはいけない。

*3:これはゴーストとして挿入した“全角空白 + 戻りカーン”のすぐ内側で行分割が起こっているからである。そもそもゴースト処理の目的からすると、ここでの行分割は予め抑止しておくべきなのだろう。