长行换行且不留空格,同时保持字距一致

长行换行且不留空格,同时保持字距一致

有很多帖子询问如何将长串文本/数字(没有空格)分成合理的行。这个帖子就是一个例子。最普遍接受的解决方案似乎是增加一个稍微拉伸的零宽度粘连在该字符串中的每对字符之间;也许可以添加一个额外的酌情在行尾插入/自定义连字符。

但是我看到的所有解决方案都没有解决字距调整问题。以下是两种我希望保留字距调整的场景:

  1. 长串数字(例如,圆周率的 100 位数字),设置为比例旧式数字。您会发现,字体设计师经常将字距调整为 7 ( seven.osf) 和 4 ( four.osf) 之间的数字,以及许多其他数字对。示例字体:源衬线 4
  2. 长串假名,设置在启用了 OpenType 功能的日文字体中paltkern您会发现,字体设计师通常会为 フ 和 ォ 指定比例交替宽度,以及它们之间的字距,以及许多其他假名和假名对。示例字体:来源宋体. (是的,我知道LuaTeX-ja已经实现了这一点。)

字距调整能以某种方式保留吗?首选 eTeX/XeTeX 解决方案,但也欢迎 LuaTeX 解决方案。

% run with XeLaTeX or LuaLaTeX
\documentclass{article}
\usepackage{fontspec}

\setmainfont{Source Serif 4}[Numbers={Proportional,OldStyle}]

\newcommand*\+{\hskip 0pt plus 1pt \relax}

\begin{document}

3.14159265358979323846264338327950288419716, figures kerned, cannot be wrapped.

3\+.\+1\+4\+1\+5\+9\+2\+6\+5\+3\+5\+8\+9\+7\+9\+3\+2\+3\+8\+4\+6\+2\+6\+4\+3\+3\+8\+3\+2\+7\+9\+5\+0\+2\+8\+8\+4\+1\+9\+7\+1\+6, can be wrapped, figures no longer kerned.

\end{document}

答案1

按序列分割数据后,您可以保存字距。

\documentclass{article}
\usepackage{fontspec}

\setmainfont{Source Serif Pro}[Numbers={Proportional,OldStyle}]

\ExplSyntaxOn

\seq_new:N \l__ruixi_split_items_seq
\seq_new:N \l__ruixi_split_kerns_seq

\NewDocumentCommand{\Split}{m}
 {
  \seq_set_split:Nnn \l__ruixi_split_items_seq {} { #1 }
  \seq_clear:N \l__ruixi_split_kerns_seq
  \int_step_inline:nnn { 2 } { \seq_count:N \l__ruixi_split_items_seq }
   {
    \hbox_set:Nn \l_tmpa_box
     {
      \seq_item:Nn \l__ruixi_split_items_seq { ##1-1 }
      \seq_item:Nn \l__ruixi_split_items_seq { ##1 }
     }% with kern
    \hbox_set:Nn \l_tmpb_box
     {
      \seq_item:Nn \l__ruixi_split_items_seq { ##1-1 }
      \kern0pt
      \seq_item:Nn \l__ruixi_split_items_seq { ##1 }
     }% without kern
    \seq_put_right:Ne \l__ruixi_split_kerns_seq
     {
      \dim_eval:n { \box_wd:N \l_tmpa_box - \box_wd:N \l_tmpb_box }
     }
   }
  \seq_put_right:Nn \l__ruixi_split_kerns_seq { 0pt }
  \seq_map_indexed_inline:Nn \l__ruixi_split_items_seq
   {
    ##2 \hspace{\seq_item:Nn \l__ruixi_split_kerns_seq { ##1 } plus 0.3pt}
   }
  \unskip
 }
\ExplSyntaxOff

\begin{document}

3.14159265358979323846264338327950288419716

\Split{3.14159265358979323846264338327950288419716}

\parbox[t]{3cm}{\Split{3.14159265358979323846264338327950288419716}}

\end{document}

当然,如果在段落内使用它,胶水可以参与线条的拉伸。

在此处输入图片描述

\Split{3.14159}}如果我设置一个包含以下内容的框

\hbox(5.39+1.4)x31.42, direction TLT
.\TU/SourceSerifPro(0)/m/n/10 

答案2

这是数字的解决方案,但没有理由它不能用于字符。秘诀在于我使用了空格,mod因此空格只插入在数字组之后,因此对保留在组内,因此字体字距也保留。对于 cjk 和其他复杂的 utf 情况,Lua 解决方案最好进行更多检查。演示中,我使用了数论书籍中的常见做法,将3.4空格向左移动一点。

% run with XeLaTeX or LuaLaTeX
\documentclass{article}
\usepackage{fontspec}

\setmainfont{Source Serif 4}[{Numbers=Proportional,OldStyle}]

\newcommand*\+{\hskip 0pt plus 1pt \relax}

\begin{document}

3.14159265358979323846264338327950288419716, figures kerned, cannot be wrapped.

3\+.\+1\+4\+1\+5\+9\+2\+6\+5\+3\+5\+8\+9\+7\+9\+3\+2\+3\+8\+4\+6\+2\+6\+4\+3\+3\+8\+3\+2\+7\+9\+5\+0\+2\+8\+8\+4\+1\+9\+7\+1\+6, can be wrapped, figures no longer kerned.

\ExplSyntaxOn
\cs_set:Npn\spaceone{\hspace{5pt}}
%\cs_set:Npn\spacetwo #1{\fbox{#1}\hskip1sp}
\tl_put_left:Nn\l_tmpa_tl{14159265358979 323846264338327950288419716}
\fboxsep=0pt\fboxrule=0sp
\int_set:Nn\l_tmpa_int{0}

\def\insertskip #1 
{#1
 \int_incr:N\l_tmpa_int
 \int_set:Nn\l_tmpb_int{ \int_mod:nn{\int_use:N\l_tmpa_int}{4} } 
 \int_compare:nNnTF{\int_use:N\l_tmpb_int}=0{\int_gset:Nn\l_tmpa_int{0}\spaceone}{}
}

Output:\par
\DeclareDocumentCommand\Out{}{
\parindent0pt
\begin{minipage}[t]{1em}
3.
\end{minipage}
\begin{minipage}[t]{4cm}\large
    \tl_map_function:NN\l_tmpa_tl\insertskip
\end{minipage}  
}
\ExplSyntaxOff
\Out
\end{document}

上图无比例,下图有比例。 在此处输入图片描述

在此处输入图片描述

相关内容