CTeX-org / forum

A temporarily alternate forum of `bbs.ctex.org`
https://t.me/chinesetex
Apache License 2.0
210 stars 16 forks source link

[NFSS] 关于使表示字体的控制序列等于\relax的作用(的问题) #293

Closed RadioNoiseE closed 1 year ago

RadioNoiseE commented 1 year ago

问题

刚刚在看LuaTeX-ja的基本文档类ltjsclasses的实现的时候, 发现了如下的宏组合:

\expandafter\let\csname OT1/cmr/m/n/10\endcsname\relax
\expandafter\let\csname TU/lmr/m/n/10\endcsname\relax
\expandafter\let\csname OMX/cmex/m/n/10\endcsname\relax

以及随后的:

\expandafter\let\csname JY3/mc/m/n/10\endcsname\relax

第一段宏出现在修改NFSS的\get@external@font, 即实际载入某一字型某一尺寸的宏之前; 而第二段宏则出现在补正完\get@external@font, 将要重新申明两组汉字字形之前。 (见下图1、2红色标注处) image image 我不明白为什么要有这样的操作。

猜测

我一开始猜是防止那个表示字体的控制序列被展开 (TeX by Topic「展开」那章里提到\relax不可被展开)。 后来想想觉得有点扯,就去看了source2e里的ltfss部分。
然后就看到了,这样一个序列(在一系列复杂的操作后) 存储的会成为\font@name的值, 而在随后的\pickup@font中它的值等于\relax与否会决定 需不需要使用\define@newfont来(可能再次)载入字体。 我就又猜测(似乎这个靠谱一点),让它等于\relax可能是为了 在对\get@external@font的重定义后重新使用它的新定义 (正确地)载入对应的字体?

对猜测2的疑问

如果(我是说如果)猜测2是正确的,那么它为什么只针对 OT1编码的cmr字体、TU编码的lmr字体、以及OMX编码的数学主字体的10pt呢? 同时这个文档类只支持LuaTeX引擎,默认用的主字体是TU/lmr, 为什么也要覆盖OT1/cmr呢?(不是cmunxx的OTF字体)。 (提到10pt又是因为这个补正只在文档类设置的主字号不等于10pt时生效。)
所以感觉这个猜想也不太对。

其它(废话)

似乎在BXjscls的mag=xreal时也见的到类似的宏片段。 (因为我的语文肯定不很好,为了更清楚地表述说了一堆废话, 开issue想问的问题是什么) 所以问题就是为什么要让这一串(如TU/lmr/m/n/10的宏)等价于\relax。 又要麻烦各位老师了。

muzimuzhi commented 1 year ago

完全是猜的:看起来是做了「取消它们的定义、patch NFSS 内部命令、让默认字族用 patch 后的 NFSS 重新声明(也许是在用到它们的时候,也许是在 begindocument)」。\let\relax 是为了骗过 NFSS,让它认为某个字体尚未定义。例如 latex2e 里有多处这样的逻辑,

\xdef\font@name{\csname\curr@fontshape/\f@size\endcsname}%
\pickup@font
\font@name

其中 \pickup@font 里就使用是否为 \relax 来判断一个类似 \OT1/cmr/m/n/10 的 font selection command 是否有定义。

%% run `latexdef -s \pickup@font`
% latex.ltx, line 8564:
\def\pickup@font{%
    \expandafter \ifx \font@name \relax
       \define@newfont
    \fi}

(在 etex 的 \ifdefined/\ifcsname 广泛可使用之前,因为 \csname ... \endcsname 会把创建出来的未定义控制序列变成 \relax,在 tex 里无法可展开地区分一个需要拼出来的控制序列是真的未定义还是 \let 到了 \relax。这个历史包袱导致 latex 里经常不区分这两者,见 \@ifundefined。这也影响到了 expl3,见 https://github.com/latex3/latex3/issues/1150。)

似乎在BXjscls的mag=xreal时也见的到类似的宏片段。

找了一下,是这段,由 https://github.com/zr-tex8r/BXjscls/commit/d12483bc2c257937572f3f2affcfe142a296e340 添加

  \ifbxjs@TUenc
    \expandafter\let\csname TU/lmr/m/n/10\endcsname\relax
  \else
    \expandafter\let\csname OT1/cmr/m/n/10\endcsname\relax
  \fi

(依然是看起来)你的「为什么」是有意义的

同时这个文档类只支持LuaTeX引擎,默认用的主字体是TU/lmr, 为什么也要覆盖OT1/cmr呢?(不是cmunxx的OTF字体)。

我(可以说)完全没有用过 ltjsclasses,你对它的了解比我多,大概也比大部分非日语 latex 用户多,完全可以直接向 luatexja 提问(日文英文均可,用软件翻译也没问题的,勇敢一些)

If you have questions or recognize bugs/have feature requests, we would like you to create a thread in the forum or a ticket in the way which !OSDN.net supplies:

https://osdn.net/projects/luatex-ja/wiki/FrontPage(en)

如果担心 https://osdn.net/projects/luatex-ja 的活跃度不够,你可以同时在 tex.stackexchange.com 提问,在两个帖子里备注「同时在xx发帖,链接是xxx」就行。我猜 tex.stackexchange.com 上的主要也是非 ltjsclasses 用户,但了解 NFSS 的人更多。

RadioNoiseE commented 1 year ago

看起来是做了「取消它们的定义、patch NFSS 内部命令、让默认字族用 patch 后的 NFSS 重新声明(也许是在用到它们的时候,也许是在 begindocument)」。\let 为 \relax 是为了骗过 NFSS,让它认为某个字体尚未定义。例如 latex2e 里有多处这样的逻辑 那么我似乎还有一个问题就是为什么只针对10pt的字体补正(因为只有文档类指定的全局字号不是10pt、magscale≠1时才会激活补正宏片段)。我去看了看ltx2e的preload font部分的strip出来的文档,发现似乎只针对OT1这些传统编码和数学字体作了预载入。可能是LuaLaTeX预载入的是10pt的字体?

还有,我在内核里发现了类似的宏片段(!)image 看了注释和你的解释后,这段宏的作用我应该明白了。谢谢你!

那么现在的问题只剩为什么是10pt和OT1编码的问题了。

完全可以直接向 luatexja 提问(日文英文均可,用软件翻译也没问题的,勇敢一些) 嗯嗯。虽然我二外选的是日语、但上课我也没怎么听就是了,英语我在班里算是倒数()。而且似乎osdn和tex.stackexchange被污染的有点厉害,虽然没被墙,但也是不怎么打得开的状态。不过我会去试试看问OT1编码的问题的。

超感谢你的回答! (因为为什么\let\relax我已经明白了,所以这个issue就关掉了?

muzimuzhi commented 1 year ago

而且似乎osdn和tex.stackexchange被污染的有点厉害,虽然没被墙,但也是不怎么打得开的状态。

Across the Great Wall we can reach every corner in the world https://www.thepaper.cn/newsDetail_forward_1798864

大胆试。交流具体软件的具体问题,所需的英文和英语考试考察的英文不完全相同,而且你还有各种翻译和辅助软件可以帮忙。

RadioNoiseE commented 1 year ago

Across the Great Wall we can reach every corner in the world https://www.thepaper.cn/newsDetail_forward_1798864

(笑)

RadioNoiseE commented 1 year ago

我刚打算去问的,在看该怎么问的时候,看到了fontdef.dtx里的image 然后就明白为什么了(一个作为保险的对latex2e内核字体回落的覆盖好像是。

(再次感谢)