如何确定“多线”的高度和深度\ooalign
?
\ooalign{\relax\cr%
\noalign{\vskip-2ex}X\cr%
\noalign{\vskip+2ex}\cr%
\noalign{\vskip+1ex}X\cr%
\noalign{\vskip-1ex}%
}%
答案是深度和高度混淆我似乎只得到了下部的尺寸\ooalign
。
答案1
分析
\ooalign
使用\vtop
。如果第一个元素是框,则其高度为 的高度\ooalign
,否则高度为 0 pt。\noalign
如果开头没有\ooalign
,则第一个元素是第一行,则\ooalign
具有第一行的高度。在这种情况下,行为空(\relax
),因此高度为 0 pt。
\vtop
深度更复杂。TeX 首先在 中设置 的内容\vbox
。然后 TeX 如上所述获取高度并相应地移动参考点。因此深度是 总高度\vbox
减去上方的高度。
由于段落参数设置,中的行\ooalign
不会移动其参考点,因此行会覆盖前几行。因此,只有最后一行的深度和的贡献总和\noalign
对整体深度有影响。在这种情况下,贡献总和\noalign{\vskip...}
为 0 pt,最后一行的深度也是如此。因此的深度\ooalign
为 0 pt。
微距\charsovereachother
(无\noalign
)
当用户希望 中所有行的高度和深度最大时,可以使用以下宏\charsovereachother
代替。(仅在没有通过 手动移动的情况下才有意义)。\ooalign
\ooalign
\noalign{\vskip...}
测试文件是为纯 TeX 编写的,但该宏也可以在 LaTeX 中使用:
\edef\RestoreAtCatcode{\catcode`\noexpand\@=\the\catcode`\@\relax}
\catcode`\@=11
\newdimen\COEO@height
\newdimen\COEO@depth
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname protected\endcsname\relax
\else
\expandafter\protected
\fi
\def\charsovereachother#1{%
\leavevmode
\begingroup
\setbox0\vtop{%
\baselineskip0pt\relax
\lineskip0pt\relax
\lineskiplimit=-16383.99999pt\relax
\gdef\COEO@height{0pt}%
\gdef\COEO@depth{0pt}%
\everycr{}\tabskip0pt\halign{%
% the cell contents is measured and
% the maximum values for height and depth are remembered
\setbox0\hbox{##}%
\ifdim\COEO@height<\ht0 %
\xdef\COEO@height{\the\ht0}%
\fi
\ifdim\COEO@depth<\dp0 %
\xdef\COEO@depth{\the\dp0}%
\fi
\unhcopy0 %
\crcr
#1%
\crcr
}%
}%
\vtop{%
% update the height if necessary
\ifdim\COEO@height>\ht0 %
\hrule width0pt height\COEO@height depth0pt %
\kern-\ht0 %
\fi
\unvcopy0 %
% update the depth if necessary
\ifdim\COEO@depth>\dp0 %
\kern-\dp0 %
\kern\COEO@depth
\fi
}%
\endgroup
}%
\RestoreAtCatcode
% Test
\hrule
\ooalign{a. row$_{\hbox{(1st line)}}$\hfill\cr
\kern10em last row$^{\hbox{(2nd line)}}$}
\hrule
\bigskip
\hrule
\charsovereachother{a. row$_{\hbox{(1st line)}}$\hfill\cr
\kern10em last row$^{\hbox{(2nd line)}}$}
\hrule
\bye
答案2
可以通过从包中\charsovereachother
正确配置来直接模拟Heiko 。 \Longstack
stackengine
\documentclass{article}
\usepackage{stackengine}
\setstackEOL{\cr}\setstackgap{L}{0pt}\def\stackalignment{l}
\begin{document}
\hrule
\Longstack{a. row$_{\hbox{(1st line)}}$\hfill\cr
\kern10em last row$^{\hbox{(2nd line)}}$}
\hrule
\end{document}
请注意,\hfill
可以从论点中消除,但我将其保留在那里以匹配 Heiko 使用的论点。
还要注意,\vskip
堆叠参数中不允许使用 s,但可以根据问题以其他方式模拟。例如,OP 的 MWE 很容易用堆栈执行。如你所见,边界线可以正确捕获堆栈的高度和深度\hrule
。
\documentclass{article}
\usepackage{stackengine}
\begin{document}
\hrule
\ooalign{\relax\cr%
\noalign{\vskip-2ex}Q\cr%
\noalign{\vskip+2ex}\cr%
\noalign{\vskip+1ex}X\cr%
\noalign{\vskip-1ex}%
}%
\def\stacktype{L}
\stackunder[1ex]{\stackon[2ex]{}{Q}}{X}
\hrule
\end{document}
答案3
看完之后Heiko Oberdiek 的回答之后,我理解了(至少部分)原始代码的含义。
看完之后Steven B. Segletes 的回答,我可以将原始代码简化为
\Longstack{%
\raisebox{+2ex}{X}\cr%
\raisebox{-1ex}{X}\cr%
}
(包装和配置与 Steven B. Segletes 的回答一致)。
为了得到这个的高度和深度,还测量了替换
\raisebox{+2ex}{X}
\raisebox{-1ex}{X}
作品,即
\newlength\myHeight
\newlength\myDepth
\settoheight{\myHeight}{%
\raisebox{+2ex}{\vphantom{X}}%
\raisebox{-1ex}\vphantom{{X}}% this line only needed when this "lower X"
% would reach higher than the "upper X"
}%
\settodepth{\myDepth}{%
\raisebox{+2ex}{\vphantom{X}}% this line only needed when this "higher X"
% would reach deeper than the "lower X"
\raisebox{-1ex}{\vphantom{X}}%
}%
其中我添加了\vphantom
s 来表示“XX”比……更宽的情况\textwidth
(但“更高 X”和“更低 X”都不宽)。
然后
\hbox{\vrule\@height\myHeight%
\@depth\myDepth%
\@width\z@}
具有的高度和深度\ooalign{...}
(且宽度为零)。
梅威瑟:
\documentclass{article}
\newlength\myHeight
\newlength\myDepth
\begin{document}
\makeatletter
\hrule
\ooalign{\relax\cr%
\noalign{\vskip-2ex}{X}\cr%
\noalign{\vskip+2ex}\cr%
\noalign{\vskip+1ex}{X}\cr%
\noalign{\vskip-1ex}%
}%
%
\settoheight{\myHeight}{%
\raisebox{+2ex}{\vphantom{X}}%
\raisebox{-1ex}\vphantom{{X}}%
}%
\settodepth{\myDepth}{%
\raisebox{+2ex}{\vphantom{X}}%
\raisebox{-1ex}{\vphantom{X}}%
}%
\hbox{\vrule\@height\myHeight%
\@depth\myDepth%
\@width\z@}%
\hrule
\makeatother
\end{document}
得到以下输出:
(如果没有另外两个答案我永远也不会想到这一点 - 谢谢!)。