swaywm / sway

i3-compatible Wayland compositor
https://swaywm.org
MIT License
14.33k stars 1.09k forks source link

Font is rendered slightly larger than it should be #6281

Open sbogomolov opened 3 years ago

sbogomolov commented 3 years ago

Screenshot showing the issue.

As a workaround I set the font size to 9.7 in sway config.

schauveau commented 3 years ago

I switched to foot a few weeks ago and I also noticed that the font size are slightly off. However, I am tented to blame foot more than sway. This is because terminals are true monospace applications that work by rendering each individual character in a fixed size cell. Regular applications like sway probably work quite differently even for monospace fonts.

There is also the issue of screen dpi vs screen scaling. The root terminal has an option dpi-aware to scale the font according to the screen dpi or to the screen scale factor (as set by 'output scale' in sway?). I am not sure how to get the screen dpi on wayland but on my laptop xdpyinfo | grep 'resolution:' returns 96x96 and the foot font scaling varies a lot with and without dpi-aware.

sbogomolov commented 3 years ago

@schauveau thanks for the input! I have disabled the dpi-aware for foot and also use scaling of 1.0. I've noticed this not only with foot though. I've tried alacritty and termite as well. Even bemenu renders fonts the same way terminals do. For now it seems that only sway renders them slightly larger.

I have also compared it to i3 (which is where I am coming from) and it did not have this issue. The same monospace font in i3 is rendered the same both by i3 and by termite. Not sure this comparison is fair, but the difference was quite noticeable when I switched from i3 to sway.

schauveau commented 3 years ago

Looking at your screenshot and accounting for the missing column and slightly different alignments, I would says that the font in Sway is slightly stretched vertically. The horizontal scaling looks fine. Assuming that this is effectively a bug in Sway, my guess would be that Sway incorrectly computed the vertical dimension of the text texture (forgot to remove the space between the lines?).

sbogomolov commented 3 years ago

That is a very good observation! I did not notice the missing column. Now when I look at it, it does indeed looks like the font rendered by sway is stretched vertically.

schauveau commented 3 years ago

Looking at the source:

At line 594, the texture_box variable is combined with output->wlr_output->transform_matrix to get a projection matrix. I do not know enough but I would not be surprised if the vertical scaling was introduced here.

Maybe because the pixels on your screen are not perfectly square? What DPI do you have in xdpyinfo?

sbogomolov commented 3 years ago

This is what I get:

$ xdpyinfo | grep 'resolution:'
  resolution:    96x96 dots per inch
schauveau commented 3 years ago

Another suspicious part is the scaling at lines 557 and 558. At first, I ignored those operations because they affects both the width and height identically but then I noticed that the results are integers. That means that if rounding occurs then the smallest (so the height) is likely to be affected more than the biggest (the width). That could cause the height to change by up to 1 pixel which is significant.

I am not a sway dev by the way so I think that I will stop here. That's quite interesting but unfortunately I have other things to do.

sbogomolov commented 3 years ago

Thanks for looking into it. I'm sure that your insights will help in fixing this.

dnkl commented 3 years ago

I switched to foot a few weeks ago and I also noticed that the font size are slightly off. However, I am tented to blame foot more than sway

Foot's default behavior is to scale fonts using your monitor's true DPI, as long as the scaling factor is 1. If you have set a scaling factor, then foot will do what almost all other applications do: assume a DPI of 96, and instead scale the fonts using the scaling factor.

This can be changed to either always using the monitor DPI (dpi-aware=yes), or to always use the scaling factor (dpi-aware=no).

I'm not aware of any Wayland generic way of getting the DPI. But foot will tell you if you start it from another terminal:

...
info: wayland.c:1234: eDP-1: 1920x1080+0x0@60Hz 0x42ED 15.33" scale=1 PPI=147x154 (physical) PPI=147x154 (logical), DPI=143.66
...

In the example above, the relevant numbers are: 1920x1080, 15.33" and the DPI: 143.66. Use e.g. https://www.calculators.tech/dpi-calculator to check the numbers.

This is what I get:

$ xdpyinfo | grep 'resolution:'
  resolution:    96x96 dots per inch

96 is almost certainly not your monitor's actual DPI.

DPI is hard. It's definition has been butchered by X11. As a result, almost all applications ignore the true DPI. This is why foot looks different compared to many other applications.

You might find this interresting: https://codeberg.org/dnkl/foot/src/commit/4a945ce4661bbe3358216138c24e9faacabd1cd1/README.md#user-content-dpi-and-font-size

emersion commented 3 years ago

There's been discussion about a protocol to provide UI scaling information to Wayland clients: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/34

schauveau commented 3 years ago

@emersion Does Sway make use of UI scaling information that are not given to the client? If so that could explain why sbogomolov titles are slightly stretched vertically?

emersion commented 3 years ago

No, Sway doesn't do any magic with DPI. Sway should always scale surfaces with the same ratio for the x and y axes.

sbogomolov commented 3 years ago

@dnkl I am using foot with dpi-aware=no and my scaling factor is 1.

The point @schauveau was making about int truncation does sound like a lead. When I change the font size in sway config to 9.7 I'm getting the font size which is very close to what I see elsewhere. So by going from 10 to 9.7 I'm reducing the font height, but not the font width.

This is how it looks like with font size of 9.7 in sway config: screenshot.

dnkl commented 3 years ago

@sbogomolov which version of fcft do you have? In versions prior to 2.4, fcft truncated the FontConfig provided pixel size when setting the font size in FreeType. In 2.4 and up, fcft instead rounds it.

In other words, if FontConfig tells us to use a pixel size of 13.7, fcft < 2.4 would tell FreeType to load the font at 13px, while fcft 2.4 will use 14px.

sbogomolov commented 3 years ago

@dnkl I'm using FontConfig version 2.13.93. Shouldn't this also affect foot? Or is it using a different mechanism to determine the pixel size of the font?

dnkl commented 3 years ago

@sbogomolov

which version of fcft do you have?

fcft is the font rasterization library foot uses. It uses fontconfig and freetype to load and rasterize glyphs.

If you have foot, you have fcft. Safest way to check the version is by looking at foot's output:

info: fcft.c:266: fcft: 2.4.0-5-g5cea209 (May 30 2021, branch 'master') +graphemes +runs

Shouldn't this also affect foot? Or is it using a different mechanism to determine the pixel size of the font?

My point was, if your foot uses an older version of fcft, it may incorrectly use a 1px smaller font than e.g. Sway.

sbogomolov commented 3 years ago

@dnkl I see your point now. The version of fcft I have is 2.3.3, which is below 2.4. And I can confirm that foot prints to its output that it is using font size of 13px. Would that also explain why i3, alacritty and termite render the same font size as foot? Are they all using fcft? Wouldn't it then make sense for sway to also use it? :)

Thanks for the explanation though, it is starting to make more sense.

dnkl commented 3 years ago

@sbogomolov

Are they all using fcft?

Nah, fcft is my own creation and is so far only used by my own projects. Not sure which font libraries those other applications are using. Chances are, if they're using Pango then they behave like Sway. I wouldn't be surprised if other non-Pango based applications have the same bug fcft had.

Wouldn't it then make sense for sway to also use it? :)

Well, I do have a patch set for Sway that does just that: https://codeberg.org/dnkl/sway. But no, fcft isn't as capable as Pango and probably never will be. So no, I don't see any reason for upstream Sway to switch.

You could perhaps try building foot from git, with fcft as a subproject? That way, foot will link statically against the most recent fcft, and you don't have to touch your system installation.

sbogomolov commented 3 years ago

@dnkl This is definitely something I could try. Just to confirm if that makes foot look identical to sway. Another approach could be to use font sizes in px everywhere, but I'm not sure it is supported by everything. I'll update this issue once I get foot built from git.

P.S. I'm a bit disappointed that Fedora 34 does not have a more recent version of fctl :)

dnkl commented 3 years ago

P.S. I'm a bit disappointed that Fedora 34 does not have a more recent version of fctl :)

Surely there must be a way to report out-of-date packages?

sbogomolov commented 3 years ago

P.S. I'm a bit disappointed that Fedora 34 does not have a more recent version of fctl :)

Surely there must be a way to report out-of-date packages?

I'll look into it.

sbogomolov commented 3 years ago

@dnkl

You could perhaps try building foot from git, with fcft as a subproject? That way, foot will link statically against the most recent fcft, and you don't have to touch your system installation.

I have built foot from git with fcft version 2.4.0-7-g62a3ba7. Font size did not change, so the rounding bug was probably not affecting me in this scenario. This again starts to look like there might be a problem with the sway font rendering.

Surely there must be a way to report out-of-date packages?

I'll look into it.

I was not able to find the maintainer, so I'm not sure where to report it.