相同配置的 urxvt 在不同的 X 服务器上有不同的 width/font 渲染

Identically configured urxvt has different width/font rendering on different X servers

我有两个不同的桌面主机通过它们的 DisplayPort 输出连接到同一台 4K 显示器上的两个 DisplayPort 输入:

两个系统都是 运行 完全最新的 Debian 9,并且配置完全相同,我可以管理。特别是:

我可以在它们中的任何一个上启动一个 80 列的 xterm,配置为 XTerm*VT100*font: -misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1,它们看起来相同,宽度为 484 像素。如果我使用 ssh -X.

在显示在本地 X 服务器上的另一台机器上启动 xterm 客户端,这不会改变

然而,urxvt 因我使用的 X 服务器而异。我已将字体 X 资源配置为:

Rxvt.font:  xft:Source Code Pro:size=9,xft:Source Han Sans,xft:DejaVu Serif:size=8,xft:DejaVu Sans Mono:size=8

当我启动 urxvt 以在 idyllic 的 X 服务器上显示时,无论是在本地还是在具有 ssh -X 的另一台主机上启动,一个 80 列垂直最大化时,终端为 644 像素宽和 106 列高。但是,当我启动它以在 logarithmic 的 X 服务器上显示时(再次在本地或使用 ssh -X 的远程客户端),80 列 urxvt 是726 像素宽,但垂直最大化时仍为 106 列高。

所以,问题:

是什么导致 logarithmic 上的 urxvt 变宽,我如何才能使它与 一样漂亮的窄尺寸idyllic? 即使您不知道,调试提示也将不胜感激。我很乐意编写与 X11 服务器通信的程序(更喜欢 Python 或类似的 C 或类似的程序),让我尝试使用与 urxvt 所做的类似的渲染来查看问题是否可以解决如果您对我应该调用哪些 API 以及我应该寻找什么样的结果有具体的建议,就可以找到这种方式。

附带问题:xft: 字体由 X 客户端呈现,对吧?如果这是正确的,这似乎是一个很大的暗示,即 X11 服务器中的某些设置正在改变 same 主机上 same 客户端的方式根据正在与之通信的 X11 服务器呈现字体。

编辑:xfce4-terminal 信息

我试过启动 xfce4-terminal 并将字体设置为 9 磅 Source Code Pro 中号字体;它在两个 X11 服务器上的结果相同,总是采用 urxvtlogarithmic 上使用的更宽格式。这似乎表明它与 urxvt 本身或 Xft 库有关(如果 xfce4-terminal 不使用它;我很确定 urxvt 确实如此) ,而不是 FreeType?

编辑:xtrace 信息

我从 xtrace 那里得到了更多信息(感谢 @Uli Schlachter 的想法!)至少让我更详细地了解问题所在。 运行 即使只是 xtrace urxvt -e true 也会产生几百 KB 的输出,所以显然我不会在这里包括所有内容,但这里有一些关键位。下面的差异是会话 idyllicidyllicidylliclogarithmic,即 idyllic 运行 urxvt 在这两种情况下,但第一个显示在自身上,第二个远程显示在 logarithmic[=130= 上].

在每个 CreateWindow 调用的第 156 行确认 windows 被创建为具有相同的高度但不同的宽度,正如我上面提到的(我测量了一个 window 宽度,但其他两个像素不在):

-000:<:005e: 48: Request(1): CreateWindow depth=0x18 window=0x03200009 parent=0x000000e7 x=0 y=0 width=644 height=904 border-width=0 class=InputOutput(0x0001) visual=0x00000021 value-list={background-pixel=0x00ffffe0 border-pixel=0x00ffffe0 override-redirect=false(0x00) colormap=0x00000020}
+000:<:005e: 48: Request(1): CreateWindow depth=0x18 window=0x05400009 parent=0x000004bb x=0 y=0 width=724 height=904 border-width=0 class=InputOutput(0x0001) visual=0x00000021 value-list={background-pixel=0x00ffffe0 border-pixel=0x00ffffe0 override-redirect=false(0x00) colormap=0x00000020}

从每一个的第 138 行开始,我看到了这个差异(第二行被截断了),这似乎证实了,对于正在创建的字形,width=7width=9 相比,它是一个字符宽度问题。

-000:<:004c: 12: RENDER-Request(139,17): CreateGlyphSet gsid=0x03200008 format=0x00000024
-000:<:004d:108: RENDER-Request(139,20): AddGlyphs glyphset=0x03200008 glyphids=0x0000036d; glyphs={width=7 height=10 x=-1 y=10 xOff=9 yOff=0}; data=0x00,0x3e,...
+000:<:004c: 12: RENDER-Request(139,17): CreateGlyphSet gsid=0x05400008 format=0x00000026
+000:<:004d:388: RENDER-Request(139,20): AddGlyphs glyphset=0x05400008 glyphids=0x0000036d; glyphs={width=9 height=10 x=0 y=10 xOff=9 yOff=0}; data=0x00,0x00,...

(继续使用其他字符,宽度为 8 对 10、9 对 11 等)

所以大概是什么原因导致了这个问题出现在第 138 行之前的某个地方。之前看大多数差异似乎是用于对象的 ID 号的变化,所以找出真正的差异有点痛苦是。

那么我看到了哪些主要差异?好吧,客户端连接后的初始响应几乎相同,除了 logarithmic(带有独立 Radeon 显卡的那个)returns a lot 更多视觉效果。两者都以:

开头
{id=0x00000021 class=TrueColor(0x04) bits/rgb-value=8 colormap-entries=256 red-mask=0x00ff0000 green-mask=0x0000ff00 blue-mask=0x000000ff},
{id=0x00000022 class=DirectColor(0x05) bits/rgb-value=8 colormap-entries=256 red-mask=0x00ff0000 green-mask=0x0000ff00 blue-mask=0x000000ff},

之后的列表似乎主要是重复的,只是在 对数 侧有更多的重复。

下一个大的区别是 Reply to QueryPictFormatsscreens=... depths=... visuals={...} 视觉效果列表在 对数 一侧更长。

但最后还有一个更显着的区别:

-subpixels=Unknown(0x0);
+subpixels=HorizontalRGB(0x1);

之后有一个 QueryFont 用于固定 returns 一些不同的数据,看起来只是 ID,而且似乎只用于创建游标,因为它会在创建游标后立即关闭。然后它看起来几乎相同(同样,取模 ID,除非我遗漏了什么)直到第 139 行。

编辑:FontConfig 调试

我也试过用FC_DEBUG=8191 urxvt -e true 2>outputfile检查每个服务器的FC_DEBUG。我确认这样做时宽度确实仍然不同。比较这两个输出文件在 8.5 MB 的输出中仅产生以下差异的三个实例(- is _idyllic,+` is logarithmic):

-   rgba: 0(i)(s)
+   rgba: 1(i)(s)

问题是 Xft/FreeType 的子像素渲染,与其他一些设置一样,可以对渲染的字体宽度产生显着影响,同时根本不改变高度。

FontConfig调试清楚亚像素渲染设置不一样。在 X 资源中明确设置此项将使两个系统工作相同:

  • Xft.rgba: rgb 将使两个系统在两个 X11 服务器上呈现更宽的字体(在没有此设置的情况下呈现 logarithmic 时它们的方式)。
  • Xft.rgba: none 将使两个系统在两个 X11 服务器上呈现更窄的字体(在没有此设置的情况下呈现 idyllic 时它们的方式)。

因此,将 Xft.rgba: none 添加到 ~/.Xresources 可以解决问题。

虽然这个答案目前已被接受,因为它解决了问题,但我很乐意更改接受另一个答案,该答案提供了对这里发生的事情的更深入解释。