Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

「元」字在繁簡轉換時變成框([Mapping=han-simp]) #696

Open
heangfat opened this issue Feb 15, 2024 · 6 comments
Open

「元」字在繁簡轉換時變成框([Mapping=han-simp]) #696

heangfat opened this issue Feb 15, 2024 · 6 comments

Comments

@heangfat
Copy link

遇到一个怪瑕疵:用繁簡轉換,設置\setCJKmainfont[Mapping=han-simp]{字型名}後,「元」字會變成一个框。複製出來,用 JS 查字串.length字串.codePointAt(),這个框卻根本不存在。
查所用 teckit 之轉換源表,根本沒有「元」(U+5143) 。在該轉換表中加了組映射,將「元」轉換成其它字,也根本轉換不動,仍輸出一个框。換字型,問題依舊,說明不是字型問題。

ZFJ9ZPIW}@F~BEU8@CD)5NE
從 PDF 複製出來,八个字符只剩七个了:
9_F}90BTY0{V2C83%K 0

換字型:
4VQ0I4W0(STO2B }QBTDMJF ZN0ZRUJ `@CG~)Y6BO$BMF

目前僅發現「元」字有此問題,而該字根本不參與繁簡轉換。


備註:

xecjk 之繁簡轉換通過 teckit 實現。teckit 轉換表在 /usr/local/texlive/版本號/texmf-dist/fonts/misc/xetex/fontmapping/xecjk/ 。

teckit 轉換表之編譯工具在此處下載。

@muzimuzhi
Copy link
Contributor

muzimuzhi commented Feb 15, 2024

用繁簡轉換,設置\setCJKmainfont[Mapping=han-simp]{字型名}後,「元」字會變成一个框。

\showbox 得到什么信息?

我好像不能复现。等一下,Mapping 不知为何在我这里不管用。你能提供一个完整例子吗?

% !TeX program = xelatex
\documentclass{article}
\usepackage{xeCJK}
\setmainfont[Mapping=han-simp]{FandolSong}

\begin{document}
一元钱
\end{document}

image

查所用 teckit 之轉換源表,根本沒有「元」(U+5143) 。

感觉是因为「元」不需要繁简转换。U+5143 在 Unihan_Variants.txt 里没有提及,见 ./xeCJK/build.lua 第 30、37 行。

ctex-kit/xeCJK/build.lua

Lines 29 to 38 in d897ea4

local function make_teckit_mapping()
local unihan_variants = "Unihan_Variants.txt"
local f = io.open(supportdir .. "/" .. unihan_variants, "r")
if not f then
local unihan_zip = supportdir .. "/Unihan.zip"
local zfile = zip_open(unihan_zip)
if not zfile then
local status, err = http_request{
url = "http://www.unicode.org/Public/UNIDATA/Unihan.zip",
sink = ltn12_sink_file(io.open(unihan_zip, "wb")) }

@muzimuzhi
Copy link
Contributor

muzimuzhi commented Feb 15, 2024

我能复现了,之前是 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
image

% !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",我没有查验是不是每一个都是由映射错误、而非字体缺字导致。

@heangfat
Copy link
Author

heangfat commented Feb 15, 2024

(设置 \tracinglostchars=3 可以把它变成 error)

我這麼設了。也報了相同的錯誤。「元」的確被轉成了「𬶃」(U+2CD83)。

能找到更多映射错误的字,如,兂 (U+5142) 映射到 U+311CE

試了下,「兂」的確會被轉成「𱇎」。

根据信息,元 (U+5143) 被映射到了 (U+2CD83),左鱼右大。

這就奇怪了。han-simp.map 裡並无此映射關係。這些錯誤映射是哪來的?如何解決之?
我在其上級文件夾 misc 內全文搜索,都沒搜到 5143 和 5142。

@heangfat
Copy link
Author

heangfat commented Feb 15, 2024

我查到問題所在了。han-simp.map 裡有一條U+2CD43 <> U+2CD83,將「𬵃」轉爲「𬶃」。將此句攺爲註釋(在行首加「;」)或刪去,「元」字便正常了。同理,刪U+2CD42 <> U+311CE,「兂」亦正常了。

這明顯不是碼表有誤,而是程序之咎。這種錯誤出在擴展平面,不知是 CTeX 還是 teckit 處理擴展平面碼位的功能不完善?

暫時只能發現一條刪一條。

@muzimuzhi
Copy link
Contributor

muzimuzhi commented Feb 15, 2024

不知是 CTeX 還是 teckit 處理擴展平面碼位的功能不完善?

我造了一个「在 plaintex 下使用 \font xetex primitive + mapping」的例子,能复现问题。

猜测问题来源:xecjk 生成的 han-simp.map 格式不对1、teckit 做的 .map -> .tec 转换不对(可能性较小2)、xetex 加载并使用 .tec 不对3

% !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.

image

teckit 轉換表之編譯工具在此處下載。

顺便一提,二进制文件 teckit_compile 随 xetex 分发和安装,应该无需额外下载。可能下载的版本更(gèng)新。

Footnotes

  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

@wangweixuan
Copy link

wangweixuan commented Jul 2, 2024

我用 TECkit 提供的 txtconv 工具能复现,所以是 TECkit 自身的问题。

文档和代码(编译器转换器)上看,TECkit 会根据字符所在平面确定一个 pageMap,再用剩下的高八位从 pageMap 里选择一个 characterMap,最后用低八位从 characterMap 里选择映射的目标。pageMap 的元素是 uint8 型的,说明 characterMap 最多存在 256 个;同时每个 characterMap 里字符的低八位一旦相同就会发生冲突。这样来看,考虑到 han-simp 有 6285 条映射,发生冲突的概率是很大的 ($6285/256^2=9.5\,\%$)。

我根据 han-simp.map 找了一下错误映射的字符,在基本平面里有 130 个:

ふブ㒍㒥㖰㗂㛷㜥㝢㟈㣐㣑㣞㣥㣷㤇㧠㨹㩍㫐㫧㬙㭘㲞㲡㲢㲷㴘㴡㶞㷑㷕㷻㸦㹜㿴䁝䂔䂙䂸䃝䄑䆛䈆䈱䋓䎴䒦䗑䚡䜝䞉䡤䤦䥁䧲䩡䪒䫡䯏䯺䱔䳕䴐䷍䷘乲仙侇侍俘偂偈傚傛兂元兮冼剂厖呾啙囡垒壒壖夡婘宙尗峽嵈帏帒店弭弻悠悴惴愝慀懆押挠挫挺掻搯撂撣敢旫晓柆柏柛柳栏栦栽楈槞櫢毡毢毪沥泋

实测这 130 个确实发生错误。包含其他平面的完整的冲突列表请见:Gist

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants