\parbox[c] で縦方向の位置を揃える方法

\parbox[c] で縦方向の位置を揃える方法

- たかはし いっき の投稿
返信数: 7
行の途中で改行を含むかもしれない文章を挿入したいです。
\parbox[c] を使うと parbox の中と外で文字の縦方向の位置がすこしずれてしまいます。
たとえば、下記例のひとつめの parbox 内の M と外側の M の縦方向の位置がずれてしまいます。

\documentclass{article}
\begin{document}
M\parbox[c]{1em}{M}M\parbox[c]{1em}{M\\M}M
\end{document}

上記例で、ひとつ目の parbox 内の M と外側の M と縦方向の位置を揃えた出力をえる良い方法はありますか?
例では英語ですが、日本語文章・luatex-ja で対応できると嬉しいです。
たかはし いっき への返信

Re: \parbox[c] で縦方向の位置を揃える方法

- 北見 けん の投稿
\parbox の [c]オプションの機能は、次のようにすると確認できますが、
ボックスの天地中心を周囲の数式アクシス(≒数式のマイナス記号の高さ)にそろえる仕様なので、
ボックス内外のベースラインは揃わないのですよね。

\documentclass{article}
\begin{document}
M$-$\parbox[c]{1em}{\vrule M}\parbox[t]{1em}{\vrule M}M$-$\parbox[c]{1em}{\vrule M\\\vrule M}M
\end{document}

これが [c]オプションではなく [t]オプションであれば、上記の例の通り
ボックス内の一行目のベースラインを周囲のベースラインに合わせてくれますが、
ボックスの中身が1行だけの場合と2行以上の場合で扱いを変えなければいけなくなりますね。
1行だけのときは [c] ではなく [t] にすればよく、実際この方法がおすすめです。

1行だけの場合も例外扱いせずに済ませるには、
[c]オプションのようにボックスの天地中心を周囲の数式アクシスに合わせるのではなく、
ボックスの天地中心を周囲の「行の天地中心」に合わせるのが良いわけですが、
行を構成する文字ごとに高さは異なるので「行の天地中心」というものはあやふやなものです。
この方針で行くなら、「行の天地中心」というものをある程度恣意的に決めてやる必要がありますね。
例えば「M」の高さを行の高さと見なすとか、和文1文字の高さを行の高さと見なすとかですね。
文書全体を通して、どのような例外が起こり得るのか検討して、妥当な「行の天地中心」を定義することになると思います。
北見 けん への返信

Re: \parbox[c] で縦方向の位置を揃える方法

- 本田 知亮 の投稿
>ボックスの中身が1行だけの場合と2行以上の場合で扱いを変えなければいけなくなりますね

varwidthを使うのはどうでしょうか

\documentclass{article}
\usepackage{varwidth}
\begin{document}
M$-$%
\begin{varwidth}[t]{1em}\vrule M\end{varwidth}%
\begin{varwidth}[t]{1em}\vrule M\end{varwidth}M$-$%
\begin{varwidth}{1em}\vrule M\\\vrule M\end{varwidth}M

M$-$\parbox[c]{1em}{\vrule M}\parbox[t]{1em}{\vrule M}M$-$\parbox[c]{1em}{\vrule M\\\vrule M}M

\end{document}

ちなみにこのvarwidth,
作者がDonald Arseneauさんということもあって,
すごいことを中でやってます.
本田 知亮 への返信

Re: \parbox[c] で縦方向の位置を揃える方法

- 北見 けん の投稿
varwidthパッケージ、ソースは読まずにドキュメントを眺めただけですが。

minipage類似の環境で、異なる点は、
中身の幅が短い場合にボックスそのものの幅を切り詰めてくれるという説明でした。

なのでやはり、
中身が1行だけのときは[t]オプションで周囲とベースラインを揃えて、
中身が複数行のときは[c]オプション(デフォルトなので[c]を省いても適用される)で
ボックスの天地中央を周囲の数式中心軸に揃えるということになるのじゃないかと思います。

(誤解してるかなぁ・・・)
北見 けん への返信

Re: \parbox[c] で縦方向の位置を揃える方法

- 北見 けん の投稿
> 例えば「M」の高さを行の高さと見なすとか

ということで、ボックスの中心を周囲の「M」の中心に揃えてみた例です。
ちょっと試してみるだけなので、\parbox を変更して全く同じ例文で比較してあります。
実際に運用するならマクロ名や引数の取り方などを検討する必要があるでしょう。

\documentclass{article}

\begin{document}

M$-$\parbox[c]{1em}{\vrule M}\parbox[t]{1em}{\vrule M}M$-$\parbox[c]{1em}{\vrule M\\\vrule M}M
%
\begingroup
%
\renewcommand{\parbox}[3][]{%
  \begingroup
    \setbox0\vbox{\hsize#2\relax\parindent0pt#3}%
    \dimen0=\ht0
    \advance\dimen0\dp0
    \setbox2\hbox{M}%
    \advance\dimen0-\ht2
    \divide\dimen0by2
    \lower\dimen0\box0
  \endgroup
}
%
M$-$\parbox[c]{1em}{\vrule M}\parbox[t]{1em}{\vrule M}M$-$\parbox[c]{1em}{\vrule M\\\vrule M}M

\endgroup

\end{document}

(追記です)
書いている間に本田さんから別案が・・・
varwidthというパッケージは知りませんでした。
北見 けん への返信

Re: \parbox[c] で縦方向の位置を揃える方法

- 帯田 木偶太 の投稿
行送りを乱すようなものがボックス中にないという前提を置いていいなら、
こんな方法もあるような気がしますが…

何かまずいことがあるでしょうか?

================

\documentclass{jarticle}\relax
\makeatletter
        \newcommand{\centeredparbox}[2]{%
                \settodepth{\@tempdima}{\parbox[t]{#1}{#2}}%
                \settodepth{\@tempdimb}{\parbox[b]{#1}{#2}}%
                \addtolength{\@tempdima}{-\@tempdimb}%
                \raisebox{.5\@tempdima}{\parbox[t]{#1}{#2}}%
        }
\makeatother
\begin{document}

1行の場合

M\centeredparbox{5em}{M}M

\bigskip\hrule\bigskip

2行の場合\bigskip

M\centeredparbox{5em}{M M M M M M}M

\bigskip\hrule\bigskip

3行の場合\bigskip

M\centeredparbox{5em}{M M M M M M M M M M M}M

\bigskip\hrule\bigskip

周囲に背の高い文字がない場合\bigskip

m\centeredparbox{5em}{M}m

\bigskip\hrule\bigskip

1行で深さの大きいものがある場合\bigskip

M\centeredparbox{5em}{M\raisebox{-10pt}{y}}M

\bigskip\hrule\bigskip

複数行で、その最終行に深さの大きいものがある場合\bigskip

M\centeredparbox{5em}{M M M M M M M M M M \raisebox{-10pt}{y}M}M

\bigskip\hrule\bigskip

複数行で、その途中の行に深さの大きいものがある場合はうまくいかない\bigskip

M\centeredparbox{5em}{M M M M M M \raisebox{-10pt}{y}M M M M M}M

\end{document}

帯田 木偶太 への返信

Re: \parbox[c] で縦方向の位置を揃える方法

- 北見 けん の投稿
ボックス内部の一行目のベースラインと最終行のベースラインのちょうど真ん中を
周囲の行のベースラインに合わせるということですね。
これだと、行中の文字の高さ不揃いを気にしなくて良いですね。
ボックスの中身の行数が奇数のときは真ん中の行で揃いますし。
良いポリシーだと思います。
たかはし いっき への返信

Re: \parbox[c] で縦方向の位置を揃える方法

- たかはし いっき の投稿
みなさまさまざまな解決方法をありがとうございます。
一般的な文字のみ扱う予定ですので帯田様の方法で対応いたします。
みなさま、あたらめてありがとうございました。大変助かりました。