如何使现有的基于 \strut 的代码与重音字母一起工作?

如何使现有的基于 \strut 的代码与重音字母一起工作?

\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

相关内容