ctex-kit
ctex-kit copied to clipboard
「元」字在繁簡轉換時變成框([Mapping=han-simp])
遇到一个怪瑕疵:用繁簡轉換,設置\setCJKmainfont[Mapping=han-simp]{字型名}
後,「元」字會變成一个框。複製出來,用 JS 查字串.length
和字串.codePointAt()
,這个框卻根本不存在。
查所用 teckit 之轉換源表,根本沒有「元」(U+5143) 。在該轉換表中加了組映射,將「元」轉換成其它字,也根本轉換不動,仍輸出一个框。換字型,問題依舊,說明不是字型問題。
從 PDF 複製出來,八个字符只剩七个了:
換字型:
目前僅發現「元」字有此問題,而該字根本不參與繁簡轉換。
備註:
xecjk 之繁簡轉換通過 teckit 實現。teckit 轉換表在 /usr/local/texlive/版本號/texmf-dist/fonts/misc/xetex/fontmapping/xecjk/ 。
teckit 轉換表之編譯工具在此處下載。
用繁簡轉換,設置
\setCJKmainfont[Mapping=han-simp]{字型名}
後,「元」字會變成一个框。
\showbox
得到什么信息?
我好像不能复现。等一下,Mapping
不知为何在我这里不管用。你能提供一个完整例子吗?
% !TeX program = xelatex
\documentclass{article}
\usepackage{xeCJK}
\setmainfont[Mapping=han-simp]{FandolSong}
\begin{document}
一元钱
\end{document}
查所用 teckit 之轉換源表,根本沒有「元」(U+5143) 。
感觉是因为「元」不需要繁简转换。U+5143 在 Unihan_Variants.txt
里没有提及,见 ./xeCJK/build.lua
第 30、37 行。
https://github.com/CTeX-org/ctex-kit/blob/d897ea427b71787962aa988f219548fba40295e6/xeCJK/build.lua#L29-L38
我能复现了,之前是 Mapping
没生效。
log 里有一条 "Missing character" 信息(设置 \tracinglostchars=3
可以把它变成 error)。
! Missing character: There is no 𬶃 (U+2CD83) in font FandolSong/OT:language=dfl
t;mapping=han-simp;.
根据信息,元 (U+5143) 被映射到了 (U+2CD83),左鱼右大。
https://zi-hi.com/sp/uni/2CD83
% !TeX TS-program = xelatex
\documentclass{article}
\usepackage[LoadFandol=false]{xeCJK}
\setCJKmainfont[Mapping=han-simp]{FandolSong}
\tracinglostchars=3
\begin{document}
一元钱
\end{document}
补充:能找到更多映射错误的字,如,兂 (U+5142) 映射到 U+311CE。使用 STSong 字体,U+5100 - U+51FF 能得到 16 条 "Missing character",我没有查验是不是每一个都是由映射错误、而非字体缺字导致。
(设置 \tracinglostchars=3 可以把它变成 error)
我這麼設了。也報了相同的錯誤。「元」的確被轉成了「𬶃」(U+2CD83
)。
能找到更多映射错误的字,如,兂 (U+5142) 映射到 U+311CE
試了下,「兂」的確會被轉成「𱇎」。
根据信息,元 (U+5143) 被映射到了 (U+2CD83),左鱼右大。
這就奇怪了。han-simp.map 裡並无此映射關係。這些錯誤映射是哪來的?如何解決之? 我在其上級文件夾 misc 內全文搜索,都沒搜到 5143 和 5142。
我查到問題所在了。han-simp.map 裡有一條U+2CD43 <> U+2CD83
,將「𬵃」轉爲「𬶃」。將此句攺爲註釋(在行首加「;
」)或刪去,「元」字便正常了。同理,刪U+2CD42 <> U+311CE
,「兂」亦正常了。
這明顯不是碼表有誤,而是程序之咎。這種錯誤出在擴展平面,不知是 CTeX 還是 teckit 處理擴展平面碼位的功能不完善?
暫時只能發現一條刪一條。
不知是 CTeX 還是 teckit 處理擴展平面碼位的功能不完善?
我造了一个「在 plaintex 下使用 \font
xetex primitive + mapping」的例子,能复现问题。
猜测问题来源:xecjk 生成的 han-simp.map
格式不对[^1]、teckit 做的 .map
-> .tec
转换不对(可能性较小[^2])、xetex 加载并使用 .tec
不对[^3]。
[^1]: 格式需遵循 The TECkit Language: Mapping byte encodings to Unicode
[^2]: 从 https://github.com/silnrsi/teckit/issues/30 推测,teckit 支持 plane 1
[^3]: 相关逻辑似乎在 https://github.com/TeX-Live/texlive-source/blob/trunk/texk/web2c/xetexdir/XeTeX_ext.c
% !TeX TS-program = xetex -interaction=nonstopmode %.tex
\tracinglostchars=3
\def\test{元\Uchar"5143。}
% check that "mapping=<name>" works
\font\1="[FandolSong-Regular.otf]/OT:mapping=fullwidth-stop"\1
\test
\font\1="[FandolSong-Regular.otf]/OT:mapping=han-simp"\1
\test
\end
! Missing character: There is no 𬶃 (U+2CD83) in font [FandolSong-Regular.otf]/OT:mapping=han-simp.
! Missing character: There is no 𬶃 (U+2CD83) in font [FandolSong-Regular.otf]/OT:mapping=han-simp.
teckit 轉換表之編譯工具在此處下載。
顺便一提,二进制文件 teckit_compile
随 xetex 分发和安装,应该无需额外下载。可能下载的版本更新。