跨越左括号前的水平空格

跨越左括号前的水平空格

所有内容都在标题中:我想删除\left[跨多行的方括号之前的水平空格。请参阅 MWE 和图片。

平均能量损失

\documentclass[12pt,a4paper,twoside,openright]{report}

\begin{document}

    \noindent
    Text left aligned.\\[0.5ex]

    \noindent
    $\left[%
    \begin{tabular}{l}%
        /X-ion/\\
        N\\
        ACT of Z-ing
    \end{tabular}%
    \right]$
    
\end{document}

在此处输入图片描述

答案1

这是“侧轴承”的问题,例如“3. 方位和前进”

最简单的方法是反复试验。在左括号前添加一个负空格,直到您满意为止。

精确的解决方案非常复杂,因为

  • 字形边界框在 vanilla TeX 或 pdfTeX 中不可用,并且
  • 找出输出中实际使用的正确字体、大小和字形并不容易。

针对此案例的具体分析

大写字母“T”使用字体“cmr12.pfb”(pdfTeX)或“lmroman12-regular.otf”(luaLaTeX)。幸运的是,这两种字体对“T”使用相同的侧边距。我.log从 LaTeX 运行写入的文件末尾获取了字体名称。

Python/FontForge 脚本从字体和字形“T”中提取左侧边界:0.035 em

用于补偿左侧轴承的负空间命令是:

\kern-0.035em

如果字体在 LaTeX 中缩放或涉及内部数学字形构造,情况会变得更加棘手。左括号由三部分组成:上部、中部和下部。

TeX 命令\showlists有助于识别字体和使用的字形。对于左括号的下半部分:

...\hbox(0.39998+17.60019)x6.66669
....\OMX/cmex/m/n/6 4

在“字符 4”(0x34)的位置,我发现了字形bracketleftbt

Python/FontForge 脚本报告左侧边距为 0.326em。现在,需要设置正确的字体以获取正确的单位“em”值:

\begingroup
    \csname OMX/cmex/m/n/6\endcsname
    \kern-0.326em\relax
\endgroup

使用周围的 TeX 宽度 6.66669pt\hbox可用于计算以 pt 为单位的侧边距,请参阅 Python/FontForge 脚本:

\kern-3.263274684684685pt\relax

我改变了最小的 TeX 示例,添加了一个\fbox线宽为 0.1pt 的细线和相同空间的分隔/边距,以直观地看到“T”和左括号从相同的水平位置开始。

在此处输入图片描述

LaTeX 文件:

\documentclass[12pt,a4paper,twoside,openright]{report}

% \showboxdepth=\maxdimen
% \showboxbreadth=\maxdimen
% \tracingonline=1

\begin{document}

    \setlength{\fboxsep}{0.1pt}
    \setlength{\fboxrule}{0.1pt}
    \fbox{%
        \begin{tabular}{@{}l@{}}
            \kern-0.035em Text left aligned.\\[0.5ex]
            % \begingroup
            %   \csname OMX/cmex/m/n/6\endcsname
            %   \kern-0.326em\relax
            % \endgroup
            \kern-3.263274684684685pt\relax
            $\left[%
                \begin{tabular}{l}%
                    /X-ion/\\
                    N\\
                    ACT of Z-ing
                \end{tabular}%
            \right]$
        \end{tabular}%
    }

% \showlists

\end{document}

提取左侧方位值的 Python/FontForge 脚本:

#!/usr/bin/env fontforge

import subprocess
from typing import Union

import fontforge  # (Python 3.8)

FONT_FOR_UPPERCASE_T_1 = 'cmr12.pfb'
FONT_FOR_UPPERCASE_T_2 = 'lmroman12-regular.otf'
FONT_FOR_LEFT_BRACKET = 'cmex10.pfb'


def find_font(name: str) -> str:
    process = subprocess.run(
        ['kpsewhich', name],
        check=True,
        stdout=subprocess.PIPE,
    )
    # Error checking omitted
    return process.stdout.decode().strip()


def get_left_side_bearing(font_name: str, glyph: Union[str, int])-> float:
    """
    Return the left side bearing of the specified glyph in the
    font, given by font_name. The unit is em.
    """
    font_path = find_font(font_name)
    font = fontforge.open(font_path)
    try:
        left_side_bearing, _, _, _ = font[glyph].boundingBox()
        return left_side_bearing / font.em
    finally:
        font.close()


def get_advance_width(font_name: str, glyph: Union[str, int])-> float:
    """
    Return the advance width of the specified glyph in the
    font, given by font_name. The unit is em.
    """
    font_path = find_font(font_name)
    font = fontforge.open(font_path)
    try:
        return font[glyph].width / font.em
    finally:
        font.close()


def main() -> None:
    # Side bearing for uppercase T
    # ----------------------------
    left_side_bearing_for_uppercase_t = get_left_side_bearing(
        FONT_FOR_UPPERCASE_T_1,
        'T',
    )
    print(
        f'=> Left side bearing of "T": {left_side_bearing_for_uppercase_t}em'
        f' ({FONT_FOR_UPPERCASE_T_1})'
    )
    left_side_bearing_for_uppercase_t = get_left_side_bearing(
        FONT_FOR_UPPERCASE_T_2,
        'T',
    )
    print(
        f'=> Left side bearing of "T": {left_side_bearing_for_uppercase_t}em'
        f' ({FONT_FOR_UPPERCASE_T_2})'
    )

    # Side bearing for left bracket
    # -----------------------------
    glyph = 'bracketleftbt'
    
    left_side_bearing_for_left_bracket = get_left_side_bearing(
        FONT_FOR_LEFT_BRACKET,
        glyph,
    )
    print(
        f'=> Left side bearing of "[": {left_side_bearing_for_left_bracket}em'
    )
    
    # ...\hbox(0.39998+17.60019)x6.66669
    #  ....\OMX/cmex/m/n/6 4
    
    tex_advance_width = 6.66669  # pt
    print(f'=> TeX advance width: {tex_advance_width}pt')

    advance_width = get_advance_width(FONT_FOR_LEFT_BRACKET, glyph)
    print(f'=> Advance width: {advance_width}em')
    
    left_side_bearing_pt = (
        tex_advance_width / advance_width * left_side_bearing_for_left_bracket
    )
    print(f'=> Left side bearing: {left_side_bearing_pt}pt')


if __name__ == '__main__':
    main()

使用 FontForge 运行脚本:

=> Left side bearing of "T": 0.035em (cmr12.pfb)
=> Left side bearing of "T": 0.035em (lmroman12-regular.otf)
=> Left side bearing of "[": 0.326em
=> TeX advance width: 6.66669pt
=> Advance width: 0.666em
=> Left side bearing: 3.263274684684685pt

LuaTeX

LuaTeX 可以访问字体字形边界框,请参阅 LuaTeX 手册“12.6.2 字形”中的关键字“边界框”。因此,可能有一种更简单的方法,即通过一些 Lua 代码,例如这里的大写字母“T”。

数学模式要复杂得多(\left-\right构造、根、\mathchoice...)。也许,所讨论的数学符号可以用 LuaTeX 属性标记。在\hbox、 页面中排版数学后,可以随后检查节点列表以识别标记的字形来计算侧边距。然后可以直接在节点列表中或在下一次 LaTeX 运行中应用移位。

但这种方法还只是一种草图,还需要进一步研究和花费大量时间去实施。

相关内容