答案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 运行中应用移位。
但这种方法还只是一种草图,还需要进一步研究和花费大量时间去实施。