由于中文标点左右单引号 ‘’、左右双引号 “”、省略号……和破折号——在 Unicode 中已经不属于中文范畴,西方文字也采用。因此那几个标点符号在西文字体中都是单宽度。除非使用传统的 GB locale, 否则在 UTF-8 环境下,字符终端 xterm 中的那几个标点都被认为是西文字体,显示单宽度。如果想让那几个标点符号变成双宽度,那么可以使用 xterm 提供的一个选项 -cjk_width:
Set the cjkWidth resource to “true”. When turned on, characters with East Asian Ambiguous (A) category in UTR 11 have a column width of 2. Otherwise, they have a column width of 1. This may be useful for some legacy CJK text terminal-based programs assuming box drawings and others to have a column width of 2. It also should be turned on when you specify a TrueType CJK double-width (bi-width/monospace) font either with -fa at the command line or faceName resource. The default is “false”
但是如此一来,许多其他符号也变成了双宽度,导致显示严重错乱。于是我用 FontForge 修改字体,将那几个标点符号的字体宽度加倍。不过修改后发现 xterm 似乎不能正确对待那几个字符,显示出错。似乎 xterm 认定了那几个字符就必须是单宽度,除非使用 -cjk_width 选项。
有无什么办法解决?哪怕修改 xterm 的代码也行。
去修改 glibc 的 wcswidth 函数的代码。
1赞
谢谢回复。
glibc 是底层核心库,改动的影响面太大。应该不至于一定要到 glibc 里去修改,因为 xterm 提供了一个选项 -cjk_width 可以让那些标点显示双宽度。只是一旦用了那个选项,其他的 Unicode 符号也会变成双宽度,导致显示错乱。如果只修改 xterm, 让那少数几个标点符号双宽度,而其他字符不变,就最好不过了。
另外在修改字体之后,我发现 GTK 程序能够感应到。也就是说:如果换上被我修改后的字体(将那几个标点符号的字体宽度加倍),那么 GTK 程序无需作任何修改,就获得了想要的双宽度效果。
你修改 xterm 调用 wcswidth 的地方吧。
一般的 GUI 程序是字体绘制多大,它就留多大的空白。终端程序需要严格的等宽,因此它只看字符有多宽(使用 glibc 的函数),然后留多少个格子。
根据您提供的线索,我修改了 xterm 的源代码。确实起到了效果,却引出了新问题。因为基于 ncurses 的应用程序几乎最终都要用上 libc 的 wcwidth/wcswidth 函数来判断字符该占据多少 “格”。如果只修改 xterm 的实现,那么 ncurses 程序却依然通过 libc 获得字符宽度,就会出现显示错乱。
这也就是为何 xterm 的文档不建议使用它提供的 -cjk_width 选项的原因。最终还是您上面说的,要去修改 libc 里的相关代码才是彻底的解决办法。
非常感谢您提供的帮助,这个问题已经解决。能否再帮我看一下刚刚提出的新问题:
fontconfig 提供 “别名”(alias) 字体匹配机制,比如:
<alias>
<family>serif</family>
<prefer>
<family>Font 1</family>
<family>Font 2</family>
<family>Font 3</family>
<family>Font 4</family>
<family>Font 5</family>
</prefer>
</alias>
如果应用程序请求字体 serif, 那么 fontconfig 会根据 “prefer” 的顺序(如果是弱绑定,那么先匹配语言 lang )匹配字体。这样可以让显示效果更佳的字体排在前面,而当字体里字符不存在时,再到后面显示效果更次的字体里去寻找。
fontconfig 的这种字体匹配机制似乎并非对上级应用程序透明,或者说:需要上级程序参与到字体匹配之中。因为我发现基于 libXft 的程序好像只匹配一次字体。匹配成功后,如果存在 “缺字” 的情况,并不会自动到后面的字体列表里去寻找。而 Xft 又是基于 fontconfig 的,因此可以断定 fontconfig 的别名字体机制并非对上次应用透明。
我看了一下应用程序,是调用了 libXft 的这个函数:
XftFont* XftFontOpenName( Display *dpy, int screen, unsigned char *fontname )
如果对该函数的第三个参数 fontname 传入诸如 “serif:bold:size=16” 这类的字体 Pattern, 那么可以匹配到一个字体,却无法在 “缺字” 的情况下继续匹配后面的字体。
如果 Xft 本身支持 “缺字替换” 的功能,那么该调用哪个函数?如果不支持,那么该如何直接调用 fontconfig 的函数,让 “缺字替换” 功能得以实现?
我发现 GTK 程序完美支持 fontconfig 的 “缺字替换” 功能,当然 GTK 并不依赖 Xft. 我对字体领域知之甚少,看 libXft 的文档以及源代码已经一头雾水,对于更加庞杂的 fontconfig 和 GTK, 就更难掌握了。如果哪位高人知道该如何做,恳请提供一些思路。
或许您可以继续给我提供思路。
system
(system)
关闭
2022年12月16日 10:50
6
本主题在最后一个回复创建后60分钟后自动锁定。不再允许添加新回复。