\strut
基于的解决方案假设高度不能超过 8.5 pt,深度不能超过 3.5 pt。但对于重音字母,这个假设并不成立。在第二个示例中,最后一行比第一个示例中的要低。如何在不更改主宏的情况下使两个示例中的基线相同?
示例 1:
\input template
\font\tenrm=rm-lmr10 \tenrm
\marginalstar
X
\char'101
\bye
示例 2:
\input template
\font\tenrm=rm-lmr10 \tenrm
\marginalstar
X
\char'200
\bye
模板.tex:
\def\marginalstar{\strut\vadjust{\kern-\dp\strutbox\smash{\llap{* }}\kern\dp\strutbox}}
\nopagenumbers
\hsize1em
\emergencystretch=1em
\noindent
如果不存在使现有代码能够处理重音字母的解决方法,那么在编写新代码时应遵循哪些准则?基于 \strut 的解决方案是否不好?如何避免它们?如何确保在所有需要\strut
使用的情况下,都可以不使用 \strut?(例如 - 在表格中绘制规则;TeXbook 第 82 页给出了另一个示例)
编辑 再举两个例子来说明这一点。第二个例子中,右边框被撕裂了。
示例 3:
\font\tenrm=rm-lmr10 \tenrm
\hsize=5em
\hrule
\settabs 2 \columns
\+ \strut\vrule\hfill W\hfill\vrule& \hfill X \hfill\strut\vrule&\cr
\hrule
\+ \strut\vrule\hfill \char'101\hfill\vrule& \hfill Z \hfill\strut\vrule&\cr
\hrule
\bye
示例 4:
\font\tenrm=rm-lmr10 \tenrm
\hsize=5em
\hrule
\settabs 2 \columns
\+ \strut\vrule\hfill W\hfill\vrule& \hfill X \hfill\strut\vrule&\cr
\hrule
\+ \strut\vrule\hfill \char'200\hfill\vrule& \hfill Z \hfill\strut\vrule&\cr
\hrule
\bye
所以根据@David Carlisle的说法应该是:
\setbox\strutbox=\hbox{\vrule height9.5pt depth2.5pt width0pt}
因为:
$ tftopl rm-lmr10|grep CHARHT|sort|tail -n1
(CHARHT R 0.9205)
$ tftopl rm-lmr10|grep CHARDP|sort|tail -n1
(CHARDP R 0.25)
正确的?
答案1
\strut
不是一个内置命令,它只是
\setbox\strutbox=\hbox{\vrule height8.5pt depth3.5pt width\z@}
\def\strut{\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi}
其设计适合于设置在 12pt 基线上的 10pt 计算机现代英语文本。
如果您有任何其他类型的文本,您需要调整\strutbox
以获得合适的高度和深度,
在这种情况下,您会 \lineskip
在行间得到 1pt,因为重音符号 A 的高度为 9.20499pt,\strut
深度为 3.5pt,因此它们无法适合 12pt 的基线跳跃。
您可能需要将基线跳跃更改为 12.5pt,并将支柱调整为 9.3 高和 3.2 深或类似的,或者您可以尝试将其挤入 12pt,支柱高 9.2,深 2.8
为了解决 latex 评论中的问题,你可以这样做
\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\begin{document}
\showoutput
\expandafter\show\the\font
\sbox0{Ă \v{A}\c{c}g(Q)$\sum_0^n(x)_7^n$}
\typeout{\the\ht0+\the\dp0=\the\dimexpr\ht0+\dp0\relax}
\usebox{0}
\end{document}
这表明 latex/plain tex 并不是真正的问题,而是字体选择。使用上面的 ec 字体,看起来你只需要 9pt 高和 3pt 深的支撑就可以了,这与 latex 的设置不太一样,因为 latex 会在每次尺寸更改后将其重置为
\setbox\strutbox\hbox{%
\vrule\@height.7\baselineskip
\@depth.3\baselineskip
\@width\z@}%
因此对于 12pt 基线来说,其为 8.4pt+3.6pt,但\set@fontsize
如果字体中有大量重音大写字母且没有大的降部,则可以重新定义为使用 .75 和 .25 作为乘数。
答案2
更新添加了 LaTeX 的补丁,以根据 OP 在评论中的要求\selectfont
修改其定义方式。以进一步适应个人需求。当调用时,新字体尚未加载,因此,我最终在最后添加了一些额外的代码,而不是修补。\strutbox
\set@fontsize
\selectfont
\set@fontsize
TeX
具有一种将行\baselineskip
分开的机制,大多数情况下都可以正常工作。正如@DavidCarlisle 的回答中所解释的那样,\strutbox
是用 的临时.7:.3:1
规则定义的height:depth:baselineskip
。不幸的是,这意味着\strut
在原本对齐良好的情况下添加 有时会造成错位。下面是一个例子,其中来自支柱的深度加上来自下一行重音字符的高度将总和超过 baselineskip,因为 低于.7\baselineskip
重音字符的高度。
\documentclass[12pt]{article}
\usepackage [utf8]{inputenc}
\usepackage [T1]{fontenc}
\usepackage {multicol}
\begin{document}\pagestyle{empty}\thispagestyle{empty}
Without struts:
\begin{multicols}{2}
Etat de droit Etat de droit Etat de droit Etat de droit Etat de droit
Etat de droit Etat de droit Etat de droit\par
\columnbreak
\'Etat de droit \'Etat de droit \'Etat de droit \'Etat de droit \'Etat
de droit \'Etat de droit \'Etat de droit\par
\end{multicols}
With two added struts (the one on the left does no harm), the
alignment is off!:
\begin{multicols}{2}
\strut Etat de droit Etat de droit Etat de droit Etat de droit Etat de droit
Etat de droit Etat de droit Etat de droit\par
\columnbreak
\strut État de droit État de droit État de droit État de droit État
de droit État de droit État de droit\par
\end{multicols}
\end{document}
生产
法国新闻组的一个帖子中讨论了这个问题,以下情况更糟糕lmodern
:
\documentclass[12pt]{article}
\usepackage [utf8]{inputenc}
\usepackage [T1]{fontenc}
\usepackage {multicol}
\usepackage{lmodern}
\begin{document}\pagestyle{empty}\thispagestyle{empty}
Without struts:
\begin{multicols}{2}
Etat de droit Etat de droit Etat de droit Etat de droit Etat de droit
Etat de droit Etat de droit Etat de droit\par
\columnbreak
\'Etat de droit \'Etat de droit \'Etat de droit \'Etat de droit \'Etat
de droit \'Etat de droit \'Etat de droit\par
\end{multicols}
With two added struts (the one on the left does no harm), the
alignment is off!:
\begin{multicols}{2}
\strut Etat de droit Etat de droit Etat de droit Etat de droit Etat de droit
Etat de droit Etat de droit Etat de droit\par
\columnbreak
\strut État de droit État de droit État de droit État de droit État
de droit État de droit État de droit\par
\end{multicols}
With more struts at the right, alignment even more off:
\begin{multicols}{2}
\strut Etat de droit Etat de droit Etat de droit Etat de droit Etat de droit
Etat de droit Etat de droit Etat de droit\par
\columnbreak
\strut État de droit État de droit État de droit \strut État de droit État
de droit État de droit État de droit\par
\end{multicols}
\end{document}
修补代码\selectfont
。
\documentclass[12pt]{article}
\usepackage [utf8]{inputenc}
\usepackage [T1]{fontenc}
\usepackage {multicol}
\usepackage{lmodern}
% patch \selectfont
\makeatletter
\newbox\igor@tempbox
% or \@tempboxa but perhaps some code calls \selectfont
% not expecting \@tempboxa to be modified
\def\igor@fixstrutbox{\setbox\igor@tempbox\hbox{ÉÈÙÀĂÅ}%
% first we reset the \strutbox to not inherit a situation which
% could go through unmodified but would depend upon the sequence
% of earlier font changes, if you didn't make the change now.
%
\setbox\strutbox\hbox{\vrule
\@height.7\baselineskip
\@depth.3\baselineskip
\@width\z@}%
\ifdim\ht\igor@tempbox>\ht\strutbox
% comment out these two lines in real use cases
\typeout{IGOR: MODIFYING DEFAULT STRUTBOX\on@line.}%
\typeout{IGOR: old=\the\ht\strutbox, new=\the\ht\igor@tempbox}%
\setbox\strutbox\hbox{\vrule
\@height\ht\igor@tempbox % add some extra?
\@depth\dimexpr\baselineskip-\ht\igor@tempbox\relax
\@width\z@}\fi }%
\expandafter\def
\csname selectfont \expandafter\expandafter\expandafter
\endcsname
\expandafter\expandafter\expandafter
{\csname selectfont \endcsname\igor@fixstrutbox}%
\makeatother
\begin{document}\pagestyle{empty}\thispagestyle{empty}
Without struts (no problems):
\begin{multicols}{2}
Etat de droit Etat de droit Etat de droit Etat de droit Etat de droit
Etat de droit Etat de droit Etat de droit\par
\columnbreak
État de droit État de droit État de droit État de droit État
de droit État de droit État de droit\par
\end{multicols}
With struts: (careful to put a strut also on left first line.)
\begin{multicols}{2}
\strut Etat de droit Etat de droit Etat de droit Etat de droit Etat de droit
Etat de droit Etat de droit Etat de droit\par
\columnbreak
\strut État de droit État de droit État de droit État de droit État
de droit État de droit État de droit\par
\end{multicols}
\Large
Changed size.
\begin{multicols}{2}
\strut Etat de droit Etat de droit Etat de droit Etat de droit Etat de droit
Etat de droit Etat de droit Etat\par\hrule
\columnbreak
\strut État de droit État de droit État de droit \strut État de droit État
de droit État de droit État de droit\par\hrule
\end{multicols}
\sffamily
Other font.
\begin{multicols}{2}
\strut Etat de droit Etat de droit Etat de droit Etat de droit Etat de droit
Etat de droit Etat de droit Etat de droit\par\hrule
\columnbreak
\strut État de droit État de droit État de droit \strut État de droit État
de droit État de droit État de droit\par\hrule
\end{multicols}
\end{document}
日志(\igor@fixstrutbox
仅包含É
,并且是使用早期版本的代码):
(/usr/local/texlive/2015/texmf-dist/tex/latex/lm/t1lmr.fd
File: t1lmr.fd 2009/10/30 v1.6 Font defs for Latin Modern
)
IGOR: MODIFYING DEFAULT STRUTBOX on input line 30.
IGOR: old=10.14995pt, new=11.004pt
IGOR: MODIFYING DEFAULT STRUTBOX on input line 51.
IGOR: old=15.39993pt, new=15.68199pt
LaTeX Font Info: Try loading font information for T1+lmss on input line 62.
(/usr/local/texlive/2015/texmf-dist/tex/latex/lm/t1lmss.fd
File: t1lmss.fd 2009/10/30 v1.6 Font defs for Latin Modern
)
IGOR: MODIFYING DEFAULT STRUTBOX on input line 73.
IGOR: old=10.14995pt, new=11.004pt
切换到sans serif
不会造成任何调整,但如果\igor@fixstrutbox
设置了\hbox{ĂÉÈÅ}
,则会得到(再次使用早期的代码,而不是重新编译)。
IGOR: MODIFYING DEFAULT STRUTBOX on input line 30.
IGOR: old=10.14995pt, new=11.004pt
IGOR: MODIFYING DEFAULT STRUTBOX on input line 51.
IGOR: old=15.39993pt, new=15.68199pt
LaTeX Font Info: Try loading font information for T1+lmss on input line 62.
(/usr/local/texlive/2015/texmf-dist/tex/latex/lm/t1lmss.fd
File: t1lmss.fd 2009/10/30 v1.6 Font defs for Latin Modern
)
IGOR: MODIFYING DEFAULT STRUTBOX on input line 62.
IGOR: old=15.68199pt, new=15.97498pt
IGOR: MODIFYING DEFAULT STRUTBOX on input line 73.
IGOR: old=10.14995pt, new=11.004pt
仅\hbox{Ă}
显示此字符在无衬线字体中比É
至少在\Large
字体大小中更高是相同的。
我已将 编辑\igor@fixstrutbox
为始终先将 重置\strutbox
为默认的 LaTeX 定义,因为如果不这样做,保留\strutbox
或修改 的决定将取决于早期字体更改的历史记录,因为 LaTeX 仅在某些情况下调用 ,\set@fontsize
这赋予(由 执行)\relax
无意义。 更改后,我尚未更新上面的图像和日志。\size@update
\selectfont
答案3
我提供了另一个答案,它利用了 的一个特性XeTeX
,即它的参数\XeTeXuseglyphmetrics
。这个想法如下:
\XeTeXuseglyphmetrics 0
并且所有角色框将具有相同的高度和深度。将支柱箱的高度设置为这个共同高度,并将其深度设置为所需的值,以使两者之和等于\baselineskip
。
然后你可以重置
\XeTeXuseglypmetrices 1
对于默认框。
以下代码说明了这一点xetex
。它包含一个\fbox
宏,该宏不添加额外的高度、深度或宽度来框住其材料。该\TEST
宏应该显示一些这样的框,包含字符和支柱,或仅包含支柱,或包含普通字符和\vrule
。我们大多数时候都会看到lineskip
胶水添加,因为如果我们发现重音字母和支柱(支柱的深度太大),高度 + 深度总是超过基线跳过。
然后在底部我们设置一个更好的支柱,并看到没有多余的垂直行间空格。最后一步是用“Times New Roman”完成的,这是我的 Mac 上的系统字体。
忘记密码:
\newdimen\fboxrule
\fboxrule 0.4pt
\def\mycolor {rgb 0 0 1}
\def\fbox #1{\leavevmode
{\special{color push \mycolor}%
\hbox{\vtop{\vbox{%
\hrule height \fboxrule
\kern -\fboxrule
\hbox{\vrule width \fboxrule\kern-\fboxrule
\special{color pop}%
#1%
\special{color push \mycolor}%
\kern-\fboxrule\vrule width \fboxrule}%
}\kern-\fboxrule
\hrule height\fboxrule}}%
\special{color pop}%
}%
}
\def\TEST {\noindent
\fbox{\strut\kern1cm
{\def\mycolor{rgb 1 0 0 }\fbox {A}\fbox{E}\fbox{C}\fbox{gg}%
\kern1cm\strut}}
ABCD
\fbox{\strut\kern.5cm\strut}
\vrule height\ht\strutbox
depth \dp\strutbox
\noindent
\fbox{\strut\kern1cm
{\def\mycolor{rgb 1 0 0 }\fbox {A}\fbox{É}\fbox{Ç}\fbox{gg}%
\kern1cm\strut}}
ABCD
\fbox{\strut\kern.5cm\strut}
\vrule height\ht\strutbox
depth \dp\strutbox
\par
}
\font\lmfont=rm-lmr10
\lmfont
Latin Modern
\the\ht\strutbox, \the\dp\strutbox, \the\baselineskip
\XeTeXuseglyphmetrics=1
\TEST
\XeTeXuseglyphmetrics=0
\TEST
\font\times="Times New Roman"
\times
Times New Roman
\XeTeXuseglyphmetrics=1
\TEST
\XeTeXuseglyphmetrics=0
\TEST
\setbox0\hbox{A}\the\ht0, \the\dp0, common height plus depth of strut=
\the\dimexpr\ht0+\dp\strutbox\relax, bigger than
\the\baselineskip
With better strut:
\setbox\strutbox\hbox{\vrule height\ht0
depth\dimexpr\baselineskip-\ht0\relax}
\XeTeXuseglyphmetrics=0
\TEST
\XeTeXuseglyphmetrics=1
\TEST
\nopagenumbers
\bye