相同配置的urxvt在不同的X服务器上具有不同的宽度/字体渲染



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

  • 田园诗般的,一款小型PC,采用赛扬N3350处理器的板载Intel HD Graphics 500。(据我所知,我在另一个地方也有一个类似的系统,它使用奔腾N4200处理器和英特尔505图形,在4K下功能完全相同。)
  • 对数,一个相当普通的旧ATX系统,带有Intel i5-3450 CPU和ATI Radeon 7870图形卡

这两个系统都运行着最新的Debian 9,并且配置完全相同。特别是:

  • X服务器DPI在两个系统上均为96,使用grep DPI /var/log/Xorg.0.logxdpyinfo | grep dots进行检查
  • 两个系统上的Xft DPI均为120,使用xrdb -query | grep dpi进行检查
  • 两者都使用来自相同文件的xrdb -cpp cpp -merge $HOME/.Xresources进行配置,并且我已经确认xrdb -query在两者上产生相同的输出。我在两个系统上的~/.fonts中也加载了完全相同的Source Code Pro字体集

在它们中的任何一个上,我都可以启动一个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田园诗的X服务器上显示时,无论是在本地还是在另一台带有ssh -X的主机上启动,80列的终端在垂直最大化时宽644像素,高106列。然而,当我启动它在对数的X服务器上显示时(同样是本地或使用ssh -X的远程客户端),80列的urxvt宽726像素,但垂直最大化时仍然高106列。

所以,问题是:

是什么导致对数上的urxvt更宽,我如何使其具有与田园诗相同的窄尺寸即使您不知道,调试提示也将不胜感激。我很乐意编写与X11服务器对话的程序(更喜欢Python或类似程序,而不是C或类似程序),并让我使用与urxvt类似的渲染,看看是否可以通过这种方式找到问题,如果你对我应该调用什么API以及我应该寻找什么样的结果有具体的建议。

附带问题:xft:字体是由X客户端呈现的,对吗?如果这是正确的,这似乎是一个很大的提示,X11服务器中的一些设置正在改变同一主机上的相同客户端渲染字体的方式,这取决于它与哪个X11服务器对话。

编辑:xfce4-terminal信息

我试过启动xfce4-terminal,并将字体设置为9点源代码专业版介质;它在两个X11服务器上都是一样的,总是采用urxvt对数上使用的更宽的格式。这似乎表明它与urxvt本身有关,或者可能与Xft库有关(如果xfce4-terminal不使用它;我很确定urxvt使用它),而不是FreeType?

编辑:xtrace信息

我从xtrace得到了更多的信息(谢谢你的想法,@Uli Schlachter!),至少让我更详细地看到了问题所在。即使只运行xtrace urxvt -e true也会产生几百KB的输出,所以很明显,我不会在这里全部包括这些,但这里有一些关键比特。下面的差异是会话田园诗田园诗田园对数,即田园诗在两种情况下都运行urxvt,但首先在自身上显示,其次在对数上远程显示。

在每个CreateWindow调用的第156行,确认创建了具有相同高度但不同宽度的窗口,如上所述(我测量到一个窗口宽度完全打开,但其他两个像素不打开):

-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行开始,我看到了这个diff(为了保持理智,第二行被截断),这似乎证实了,对于正在创建的字形,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号的变化,所以要找出真正的差异有点困难。

那么,我看到了哪些主要区别?好吧,客户端连接后的初始响应几乎相同,只是对数(带有离散Radeon显卡的)返回了更多的视觉效果。两者都以开头

{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 QueryPictFormats:其中screens=... depths=... visuals={...}的视觉效果列表在对数侧要长得多。

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

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

在那之后,有一个用于fixed的QueryFont,它返回一些不同的数据,看起来只是ID,而且似乎只用于创建一个游标,因为它在那之后立即关闭。然后,它看起来几乎是一样的(再次,模ID,除非我错过了什么),直到第139行。

EDIT:FontConfig调试

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

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

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

FontConfig调试清楚地表明,子像素渲染设置是不同的。在X资源中明确设置这一点将使两个系统工作相同:

  • Xft.rgba: rgb将使两个系统在两个X11服务器上都能更宽地渲染字体(当其中一个系统在没有此设置的情况下渲染为对数时,它们会这样做)
  • Xft.rgba: none将使两个系统在两个X11服务器上都能使字体更窄(当其中一个系统在没有该集的情况下渲染为田园诗般的时,它们会这样做)

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

虽然这个答案是目前公认的答案,因为它解决了问题,但我很高兴能接受另一个答案,它能更深入地解释这里到底发生了什么。

最新更新