Skip to content

xeCJK: 关于重构的一些要点 #511

@RuixiZhang42

Description

@RuixiZhang42

目的

开这条 issue 的目的是为了统一整合 xeCJK 未来重构需要注意的要点。个人能力有限,会有总结不到位之处,欢迎大家补充。

本 issue 的结构

这条评论里提出第一个要点,未来的要点在下面依次提出。每个要点关注某些具体方面,会提供 MWE、截取相关 log、指出目前的不足、提出「理想的效果」。

单个标点符号的处理

通过如下 MWE 可以看出 xeCJK 其实对待标点符号也是「加法模式」,但是「过于激进」。

\documentclass{article}
\usepackage{xeCJK}
\newcommand\sampletext{逗,句。号}
\begin{document}

\showboxbreadth=\maxdimen
\showboxdepth=\maxdimen

\CJKfontspec{SimSun.ttc}%
\sampletext

\CJKfontspec{SourceHanSerifSC-Regular.otf}[Language=Chinese Simplified]%
\sampletext

\CJKfontspec{SourceHanSerifSC-Regular.otf}[Language=Chinese Traditional]%
\sampletext

\showlists

\end{document}

log 里相关的部分如下:

...
.\TU/SimSun.ttc(0)/m/n/10 逗
.\penalty 10000
.\TU/SimSun.ttc(0)/m/n/10 ,
.\rule(0.0+0.0)x-7.22656
.\glue 7.22656 minus 6.01563
.\glue 0.0 plus 0.96002
.\TU/SimSun.ttc(0)/m/n/10 句
.\penalty 10000
.\TU/SimSun.ttc(0)/m/n/10 。
.\rule(0.0+0.0)x-6.44531
.\glue 6.44531 minus 5.07813
.\glue 0.0 plus 0.96002
.\TU/SimSun.ttc(0)/m/n/10 号
...
.\TU/SourceHanSerifSC-Regular.otf(0)/m/n/10 逗
.\penalty 10000
.\TU/SourceHanSerifSC-Regular.otf(0)/m/n/10 ,
.\rule(0.0+0.0)x-7.71
.\glue 7.71 minus 6.95001
.\glue 0.0 plus 0.96002
.\TU/SourceHanSerifSC-Regular.otf(0)/m/n/10 句
.\penalty 10000
.\TU/SourceHanSerifSC-Regular.otf(0)/m/n/10 。
.\rule(0.0+0.0)x-6.77
.\glue 6.77 minus 6.35
.\glue 0.0 plus 0.96002
.\TU/SourceHanSerifSC-Regular.otf(0)/m/n/10 号
...
.\TU/SourceHanSerifSC-Regular.otf(1)/m/n/10 逗
.\penalty 10000
.\TU/SourceHanSerifSC-Regular.otf(1)/m/n/10 ,
.\rule(0.0+0.0)x-7.71
.\glue 7.71 minus 6.95001
.\glue 0.0 plus 0.96002
.\TU/SourceHanSerifSC-Regular.otf(1)/m/n/10 句
.\penalty 10000
.\TU/SourceHanSerifSC-Regular.otf(1)/m/n/10 。
.\rule(0.0+0.0)x-6.77
.\glue 6.77 minus 6.35
.\glue 0.0 plus 0.96002
.\TU/SourceHanSerifSC-Regular.otf(1)/m/n/10 号
...

问题分析

以全角句号 U+3002 为例,目前的效果是

<字> <penalty> <句号> <rule> <glue> <CJKglue> <字>

通过 log 可见两大不足:

  1. \rule 的宽度随字体而变,例如中易宋体的句号后面紧跟 -64.453125% 宽的 rule,而思源宋体(简体)的句号后面紧跟 -67.7% 宽的 rule;
  2. 思源宋体切换成繁体之后,句号已经居中,但其后的 rule 仍然是 -67.7% 宽。

重构要点

我们从铅字排印入手,提出如下两条要点:

  1. 我们应该摒弃目前的「测量标点字面」的做法,对那些占据字面小于 50% 的标点,不应该「抹掉全部空白」,而应该「统一抹掉 50%」;
  2. 我们应该分离「避头尾禁则」与「字面位置」这两个属性。例如「全角句号」是 closing 标点,不可以出现在行首,这是「禁则」属性;与之独立的应该还有「偏左半边」、「偏右半边」、「居中一半」、「居中占满」这些「字面位置」属性,其中「偏左半边」、「偏右半边」可以直接对应到直排/竖排的「偏上半边」、「偏下半边」,而保持代码实现不变。

组合:closing + 偏左半边

例如

  • 横竖排皆适用:简体中文跟日文用到的逗号 U+FF0C、句号 U+3002、顿号 U+3001、点号 U+FF0E
  • 仅限横排适用:简体中文用到的冒号 U+FF1A、分号 U+FF1B、叹号 U+FF01、问号 U+FF1F

理想效果应该是

<字>
<nobreak CJKglue> % 支持疏排,标点、汉字一起被拉开
% <nobreak penalty> 此处不再需要 penalty 了,因为已经不是合法的断行点了
<这种标点>
<rule: -50%> % 抹掉二分空白
<glue: 50% minus 50%> % 这里是可断行的位置
<CJKglue>
<字>

组合:closing + 偏右半边

这种组合不可能。

组合:closing + 居中一半

例如

  • 横竖排皆适用:繁体中文用到的逗号 U+FF0C、句号 U+3002、顿号 U+3001、点号 U+FF0E,日文用到的冒号 U+FF1A
  • 仅限横排适用:繁体中文用到的冒号 U+FF1A、分号 U+FF1B,日文用到的分号 U+FF1B

理想效果应该是

<字>
<nobreak CJKglue> % 支持疏排,标点、汉字一起被拉开
% <nobreak penalty> 此处不再需要 penalty 了,因为已经不是合法的断行点了
<nobreak glue: 25% minus 25%> % 这里不可断行
<rule: -25%> % 抹掉四分空白
<这种标点>
<rule: -25%> % 抹掉四分空白
<glue: 25% minus 25%> % 这里是可断行的位置
<CJKglue>
<字>

组合:closing + 居中占满

例如

  • 横竖排皆适用:繁体中文跟日文用到的叹号 U+FF01、问号 U+FF1F
  • 仅限竖排适用:简体中文、繁体中文跟日文用到的分号 U+FF1B,简体中文用到的叹号 U+FF01、问号 U+FF1F,等等。

理想效果应该是

<字>
<nobreak CJKglue> % 支持疏排,标点、汉字一起被拉开
% <nobreak penalty> 此处不再需要 penalty 了,因为已经不是合法的断行点了
<这种标点> % 没有空间可以挤压的标点
<CJKglue>
<字>

其余组合:opening + XXXX

如上分析,可以依次给出理想的效果。

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions