読者です 読者をやめる 読者になる 読者になる

TeX Alchemist Online

TeX を使って化学のお仕事をしています。

和文ゴーストとしての全角スペース

TeX TikZ

f:id:doraTeX:20160611003733p:plain

全角スペースは,プログラマやDTPerの間ではしばしば嫌われがちな存在です。TeX文書においても例外ではありません。TeXソース中に全角スペースが入り込んでいると思わぬ害をもたらすことが多く,基本的には避けた方がよい存在です。

ですが,TeXにおいて,珍しく全角スペースが大活躍する場面があります。それは(\kern-1zw と組み合わせることによる)和文ゴーストとしての用途です。例えば,ZRさんの BXglyphwiki パッケージ にその用例が見られます。

BXglyphwiki パッケージ を使うと,GlyphWiki に登録されているグリフの字形データをダウンロードして,その画像を1文字の和文文字であるかのように整形して出力してくれます。

このように,「和文1文字として使用するために画像や図形を出力したい」という状況においては,単に「ボックスの幅・高さ・ベースラインを他の和文文字と同じに揃えて出力する」というだけでは不十分です。なぜなら,TeXエンジンによって文字間に自動挿入されるべきグルーの問題があるからです。

(u)pTeX の場合,和文文字と和文文字が隣接した場合には \kanjiskip が,和文文字と欧文文字が隣接した場合には \xkanjiskip が自動挿入されます。しかし,自分で作成したボックスの場合,そのようなグルー挿入がなされないため,「和文1文字としての使用」という意図に反した組版結果が生まれてしまいます。

例えば, を四角で囲んだ ★⃞ という合成文字を作成し,これを和文1文字として出力したい状況を考えましょう。そのために,次のような命令 \squarestar を定義したとします。

【定義】

\def\squarestar{\begingroup
  \fboxsep=0pt
  \fboxrule=.5pt
  \framebox[1zw][c]{}%
  \endgroup}

次のように使うと,確かに和文1文字として,グリッド状に正しく出力されているように見えます。

【ソース】

あいう★えお\par
あいう\squarestar えお

【出力結果】

f:id:doraTeX:20160610234156p:plain:w300

しかし,禁則処理や連続約物などで,行末調整のために追い出し・追い込みがかかるような状況では,\kanjiskip が挿入されない結果,★⃞ の前後のアキが他の和文文字間とは異なってきてしまいます。次のように,意図的に均等割り付けを発生させると,その違いが顕著に見えるようになります。

【ソース】

\fboxsep=0pt
\framebox[10zw][s]{あいう★えお}\par
\framebox[10zw][s]{あいう\squarestar えお}

【出力結果】

f:id:doraTeX:20160611001426p:plain

また,欧文文字との間に \xkanjiskip が入らないため,欧文文字が隣接した場合にアキが発生しなくなります。

【ソース】

ABC★XYZ\par
ABC\squarestar XYZ

【出力結果】

f:id:doraTeX:20160611001626p:plain:w300

解決のアイデア

★⃞ を出力する際に,

  1. 全角スペースを出力する
  2. 1文字分戻る
  3. ★⃞ を出力する
  4. 1文字分戻る
  5. 全角スペースを出力する

という順序で出力すると,この出力の左右両端は全角スペースが露出した形になります。よって,この直前・直後の和文文字との間には \kanjiskip が,欧文文字との間には \xkanjiskip が挿入されるため,他の和文文字と変わらない組版が実現できます。

試してみましょう。

【ソース】

\chardef\zenkakuSpace=\jis"2121\relax %% 全角スペース

\def\squarestar{%
  \zenkakuSpace % 全角スペースを出力
  \kern-1zw\relax % 1文字分戻る
  \begingroup
  \fboxsep=0pt
  \fboxrule=.5pt
  \framebox[1zw][c]{}%
  \endgroup
  \kern-1zw\relax % 1文字分戻る
  \zenkakuSpace % 全角スペースを出力
}

あいう★えお\par
あいう\squarestar えお

\fboxsep=0pt
\framebox[10zw][s]{あいう★えお}\par
\framebox[10zw][s]{あいう\squarestar えお}

ABC★XYZ\par
ABC\squarestar XYZ

【出力結果】

f:id:doraTeX:20160611000959p:plain

このように, ★⃞ の前後のアキが,確かに他の和文文字と同じ扱いになったことが分かります。

pxghost パッケージ

ZRさんの記事「例の和欧文間空白が入らないアレ」に掲載されている pxghost パッケージ には,今回紹介した和文ゴーストで包む手法が既にコマンド化されているのに加え,欧文ゴーストで包むコマンドも用意されています。

  • \eghostguarded{<テキスト>} : テキストの前後に「欧文ゴースト」を置いて出力する。ただし数式モードでは単純にテキストを出力する。
  • \jghostguarded{<テキスト>} : テキストの前後に「和文ゴースト」を置いて出力する。ただし数式モードでは単純にテキストを出力する。

欧文ゴースト,すなわち「見えない幅ゼロの欧文文字」を使えば,「欧文文字として扱ってほしいボックス」の周囲のアキをコントロールすることができます。

pxghost パッケージの使用例:センター試験の楕円番号

pxghost パッケージを実際に使ってみましょう。

[改訂第6版]LaTeX2e 美文書作成入門 の 付録D には,TikZ を用いてセンター試験の楕円番号を出力する \egg という命令の定義の例が載っています。

[改訂第6版] LaTeX2ε美文書作成入門

[改訂第6版] LaTeX2ε美文書作成入門

【定義】

\newcommand{\egg}[1]{\raisebox{-3pt}{%
    \begin{tikzpicture}[x=1pt,y=1pt,line width=1pt]
      \draw (0,0) ellipse (4.5 and 6);
      \draw (0,0) node {\fontfamily{phv}\fontsize{9pt}{0}\selectfont #1\/};
    \end{tikzpicture}}}

ただし,このままではやはりアキの入り方がイマイチです。

【ソース】

\fboxsep=0pt
\fbox{\parbox{15zw}{%
\egg{1}および\egg{2}$f(x)>\sin x \cos x+\tan x$なので誤り。
}}

【出力結果】 f:id:doraTeX:20160611005315p:plain

↑行長が短いため,行末調整のため大きなアキを入れることによる追い出しが行われていますが,\egg の前後だけアキが入っていません。

そこで,pxghost パッケージ\jghostguarded によって「和文ゴーストで囲む」ようにしてみましょう。

【定義】

\usepackage{pxghost}

\newcommand{\egg}[1]{\jghostguarded{%
   \raisebox{-3pt}{%
    \begin{tikzpicture}[x=1pt,y=1pt,line width=1pt]
      \draw (0,0) ellipse (4.5 and 6);
      \draw (0,0) node {\fontfamily{phv}\fontsize{9pt}{0}\selectfont #1\/};
    \end{tikzpicture}}}}

これで先程のソースをコンパイルしてみると,次のような結果になります。

【出力結果】

f:id:doraTeX:20160611005625p:plain

確かに,\egg の前後のアキが他と均等になりました。(いずれにせよ,そもそも行長が短すぎてこの組版例は不格好ですが……)

↓続編

doratex.hatenablog.jp