我需要严格按照单行格式(即每行一个“短语”)排版大量短“短语”(由几个单词组成)。我还使用 XeLaTeX 下的 fontspec 来扩展默认排版样式中的字母间距。当“短语”对于可用的文本宽度来说有点太长(字母间距已扩展)时,就会出现问题。有没有办法检测 XeLaTeX 中的换行并自动减少字母间距以使“短语”适合?
例如:第一个 parbox - 不需要的换行;第二个 parbox - 所需的结果。
\documentclass{article}
\usepackage{fontspec}
\usepackage{polyglossia}
\setmainfont{Times New Roman}
\setlength\parindent{0pt}
\begin{document}%
\parbox{4.5cm}{\addfontfeature{LetterSpace=10.0}AAA BBB CCC DDD EEE FFF}\\
\parbox{4.5cm}{\addfontfeature{LetterSpace=0.0}AAA BBB CCC DDD EEE FFF}
\end{document}
==================
编辑/更新:基于 egreg 的代码,我尝试构建一些半工作的东西,并且成功了 50%。简而言之,我尝试删除“拟合循环”(用零间距替换它)并将“拉伸” \makebox-es 转换为“左对齐”:
\documentclass{article}
\usepackage{fontspec}
\usepackage{polyglossia}
\setmainfont{Times New Roman}
\setlength\parindent{0pt}
\ExplSyntaxOn
\box_new:N \l__avilov_spaceout_try_box
\fp_new:N \l__avilov_spaceout_factor_fp
\NewDocumentCommand{\spaceouttowidth}{mm}
{% #1 = width, #2 = text
% initialize
\fp_set:Nn \l__avilov_spaceout_factor_fp { 10 }
\avilov_spaceout_main:nn { #1 } { #2 }
}
\cs_new_protected:Nn \avilov_spaceout_main:nn
{
\hbox_set:Nn \l__avilov_spaceout_try_box
{
\addfontfeature{LetterSpace=\fp_use:N \l__avilov_spaceout_factor_fp}
#2
}
\dim_compare:nTF { \box_wd:N \l__avilov_spaceout_try_box <= #1 }
{% the box fits
\makebox[#1][l]{\hbox_unpack_drop:N \l__avilov_spaceout_try_box}
}
{% reset the letter spacing to zero
\fp_set:Nn \l__avilov_spaceout_factor_fp { 0 }
\makebox[#1][l]{\hbox_unpack_drop:N \l__avilov_spaceout_try_box}
}
% uncomment the next line to print the factor (debugging tool)
\makebox[0pt][l]{\tiny\fp_use:N \l__avilov_spaceout_factor_fp}
}
\ExplSyntaxOff
\begin{document}
\rule{5cm}{0.4pt}
\spaceouttowidth{5cm}{AAA BBB CCC DDD EEE FFF}
\spaceouttowidth{5cm}{AAA BBB CCC DDD EEE FF}
\spaceouttowidth{5cm}{AAA BBB CC DD EE FF}
\spaceouttowidth{5cm}{AAA BBB CCC DDD EEE FFF GGG}
\end{document}
可以看出,(在 \makebox-es 中将 [s] 更改为 [l] 后)不再对 LetterSpacing 做出反应 - 我不明白为什么。请帮忙!
另外,我希望有一个故障安全行为,即使“缩小”的文本不适合,它也会换行(即具有 parbox 行为),而不仅仅是向右突出。我也不明白如何编写代码。
答案1
您可以边试排版边减少字母间距。最后,通过稍微扩大单词间距,文本就可以排版到规定的宽度。
\documentclass{article}
\usepackage{fontspec}
\usepackage{polyglossia}
\setmainfont{Times New Roman}
\setlength\parindent{0pt}
\ExplSyntaxOn
\box_new:N \l__avilov_spaceout_try_box
\fp_new:N \l__avilov_spaceout_factor_fp
\NewDocumentCommand{\spaceouttowidth}{mm}
{% #1 = width, #2 = text
% initialize
\fp_set:Nn \l__avilov_spaceout_factor_fp { 10 }
\avilov_spaceout_main:nn { #1 } { #2 }
}
\cs_new_protected:Nn \avilov_spaceout_main:nn
{
\hbox_set:Nn \l__avilov_spaceout_try_box
{
\addfontfeature{LetterSpace=\fp_use:N \l__avilov_spaceout_factor_fp}
#2
}
\dim_compare:nTF { \box_wd:N \l__avilov_spaceout_try_box <= #1 }
{% the box fits
\makebox[#1][s]{\hbox_unpack_drop:N \l__avilov_spaceout_try_box}
% uncomment the next line to print the factor (debugging tool)
%\makebox[0pt][l]{\tiny\fp_use:N \l__avilov_spaceout_factor_fp}
}
{% reduce the letter spacing and retry
\fp_add:Nn \l__avilov_spaceout_factor_fp { -0.1 }
\fp_compare:nTF { \l__avilov_spaceout_factor_fp > 0 }
{% still something to do
\avilov_spaceout_main:nn { #1 } { #2 }
}
{% give up
\mode_leave_vertical: \box_use:N \l__avilov_spaceout_try_box
% uncomment the next line to print the message (debugging tool)
%\makebox[0pt][l]{\tiny !!!!!~Doesn't~fit}
}
}
}
\ExplSyntaxOff
\begin{document}
\rule{5cm}{0.4pt}
\spaceouttowidth{5cm}{AAA BBB CCC DDD EEE FFF}
\spaceouttowidth{5cm}{AAA BBB CCC DDD EEE FF}
\spaceouttowidth{5cm}{AAA BBB CCC DDD EEE FFF GGG}
\end{document}
对于图片,我删除了%
字符以获取调试信息。
小心!这很慢。
当试验不成功时,不填充宽度并换行:
\documentclass{article}
\usepackage{fontspec}
\usepackage{polyglossia}
\setmainfont{Times New Roman}
\setlength\parindent{0pt}
\ExplSyntaxOn
\box_new:N \l__avilov_spaceout_try_box
\fp_new:N \l__avilov_spaceout_factor_fp
\NewDocumentCommand{\spaceouttowidth}{mm}
{% #1 = width, #2 = text
% initialize
\fp_set:Nn \l__avilov_spaceout_factor_fp { 10 }
\avilov_spaceout_main:nn { #1 } { #2 }
}
\cs_new_protected:Nn \avilov_spaceout_main:nn
{
\hbox_set:Nn \l__avilov_spaceout_try_box
{
\addfontfeature{LetterSpace=\fp_use:N \l__avilov_spaceout_factor_fp}
#2
}
\dim_compare:nTF { \box_wd:N \l__avilov_spaceout_try_box <= #1 }
{% the box fits
\mode_leave_vertical: \box_use:N \l__avilov_spaceout_try_box
% uncomment the next line to print the factor (debugging tool)
\makebox[0pt][l]{\tiny\fp_use:N \l__avilov_spaceout_factor_fp}
}
{% reduce the letter spacing and retry
\fp_add:Nn \l__avilov_spaceout_factor_fp { -0.1 }
\fp_compare:nTF { \l__avilov_spaceout_factor_fp > 0 }
{% still something to do
\avilov_spaceout_main:nn { #1 } { #2 }
}
{% give up
\parbox[t]{#1}
{
\raggedright
\addfontfeature{LetterSpace=10}
#2
% uncomment the next line to print the factor (debugging tool)
\makebox[0pt][l]{\tiny !!!!!~Doesn't~fit}
}
}
}
}
\ExplSyntaxOff
\begin{document}
\rule{5cm}{0.4pt}
\spaceouttowidth{5cm}{AAA BBB CCC DDD EEE FFF}
\spaceouttowidth{5cm}{AAA BBB CCC DDD EEE FF}
\spaceouttowidth{5cm}{AAA BBB CCC DDD EEE FFF GGG}
\end{document}
你可能希望设置字母间距的最小值,比如 5,
\fp_compare:nTF { \l__avilov_spaceout_factor_fp > 4.9 }