CTeX-org / ctex-kit

Macro Packages and Scripts for Chinese TeX users
966 stars 124 forks source link

如何基于 luatex-ja 实现 xeCJK 的 \CJKfamily+{} 的功能? #618

Closed zepinglee closed 2 years ago

zepinglee commented 2 years ago

问题源自 https://github.com/tuna/thuthesis/issues/771

xeCJK\CJKfamily+{} 可以使包括西文字符在内的所有字符都使用当前的 CJK 字体,这一功能在实现宋体的数字时比较方便。不过 ctex 在使用 LuaTeX 编译时虽然也提供了 \CJKfamily{} 命令,但是并没有 \CJKfamily+ 对所有字符有效的功能。如果基于 luatex-ja 让西文字符使用 CJK 字体,尤其是对数字(0~9)和括号等符号?

luatex-ja 可以使用 \ltjdefcharrange\ltjsetparameter{jacharrange = {-1, +2}} 设置部分字符选择 CJK/西文字体,但这一方法不能用于 U+0000–U+007F,包括数字和括号。

Note that characters U+0000–U+007F are always treated as an ALchar (this cannot be customized).

另外需要考虑的一点是,需要使用 CJK 字体的内容是由用户录入的,保存在 \thu@date 的宏中,所以不能直接使用 \ltjjachar`2 的方式。

\documentclass{ctexart}
\setCJKmainfont{SimSun}
\begin{document}
2022年5月2日(星期一)\par

% xeCJK
{\CJKfamily+{}2022年5月2日(星期一)\par}
\end{document}

xeCJK 的效果:

Screen Shot 2022-05-02 at 15 14 59

使用 LuaTeX 编译时会给出警告 Package ctex Warning: Unknown CJK family `+' is being ignored.

muzimuzhi commented 2 years ago

塞一个 \fontspec 进去?

zepinglee commented 2 years ago

塞一个 \fontspec 进去?

考虑过这个解决方案,但是模板中配置了中易、思源等多种字体,而且 \CJKfamily+{} 需要用在宋体、楷体两种情况,使用 \fontspec 调用字体就过于复杂了。

Sophanatprime commented 2 years ago

可以从对应于 \CJK@family 的 font selection 中得到字体名和 RawFeature,然后再使用 \fontspec。不过这样的话其它信息就没了,还需保存先前的 afont,只能算个丐版的。

\documentclass{ctexart}
\setCJKmainfont{SimSun}
\begin{document}
2022年5月2日(星期一)\par

{\makeatletter
\ExplSyntaxOn
\use:e { \cs_new:Npn \exp_not:N \__@@_fontspec:w #1 \token_to_str:N : } #2 at #3pt #4 \s_stop
  {
    \fontspec{#1}[RawFeature={#2}]
  }
\RenewDocumentCommand \CJKfamily { t+ m }
  { 
    \ctex_ltj_switch_family:x {#2} 
    \bool_if:nT {#1}
      {
        \DeclareFixedFont \l_tmp_font {\CJK@encoding} {\CJK@family} {\f@series} {\f@shape}
          { \fp_eval:n { \f@size * 1.00001 } pt }
        \exp_after:wN \__@@_fontspec:w \tex_fontname:D \l_tmp_font at 10.0pt \s_stop
      }
    \tex_ignorespaces:D 
  }
\ExplSyntaxOff

2022年5月2日(星期一)

\CJKfamily+{zhsong}
2022年5月2日(星期一)

\CJKfamily+{zhkai}
2022年5月2日(星期一)
}
\end{document}
image
RuixiZhang42 commented 2 years ago

@Sophanatprime \f@size * 1.00001 其实是很危险的,一旦发生 Scale×\f@size * 1.00001pt 跟 Scale×\f@sizept 相等,任何对 \l_tmp_font 的设定就会覆盖掉同字号原本的设定。参见三年前的这条:

https://github.com/wspr/unicode-math/issues/515

Sophanatprime commented 2 years ago

覆盖原本的设定在本例中应该问题不大吧。否则就使用 https://github.com/wspr/unicode-math/issues/515#issuecomment-465989167 动态确定了。

zepinglee commented 2 years ago

可以从对应于 \CJK@family 的 font selection 中得到字体名和 RawFeature,然后再使用 \fontspec。不过这样的话其它信息就没了,还需保存先前的 afont,只能算个丐版的。

\documentclass{ctexart}
\setCJKmainfont{SimSun}
\begin{document}
2022年5月2日(星期一)\par

{\makeatletter
\ExplSyntaxOn
\use:e { \cs_new:Npn \exp_not:N \__@@_fontspec:w #1 \token_to_str:N : } #2 at #3pt #4 \s_stop
  {
    \fontspec{#1}[RawFeature={#2}]
  }
\RenewDocumentCommand \CJKfamily { t+ m }
  { 
    \ctex_ltj_switch_family:x {#2} 
    \bool_if:nT {#1}
      {
        \DeclareFixedFont \l_tmp_font {\CJK@encoding} {\CJK@family} {\f@series} {\f@shape}
          { \fp_eval:n { \f@size * 1.00001 } pt }
        \exp_after:wN \__@@_fontspec:w \tex_fontname:D \l_tmp_font at 10.0pt \s_stop
      }
    \tex_ignorespaces:D 
  }
\ExplSyntaxOff

2022年5月2日(星期一)

\CJKfamily+{zhsong}
2022年5月2日(星期一)

\CJKfamily+{zhkai}
2022年5月2日(星期一)
}
\end{document}
image

原来是保存在 \CJK@family 中,感谢!