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

Font height specification in pixels #2010

Closed
ewhac opened this issue Sep 3, 2023 · 11 comments
Closed

Font height specification in pixels #2010

ewhac opened this issue Sep 3, 2023 · 11 comments
Labels
enhancement New feature or request

Comments

@ewhac
Copy link

ewhac commented Sep 3, 2023

Describe the bug
The docs and code suggest that specifying a font's size using the h parameter (e.g. :se gfn=ProFont:h9) describes the font's height in pixels. This does not appear to be the case. Depending on the display's DPI, a given font size will yield significantly different results. This happens regardless of the system display resolution as reported by xdpyinfo.

My guess is the problem lies in the Skia library, since Neovide doesn't appear to determine display DPI, nor make adjustments to the user's requested font sizes.

To Reproduce
Steps to reproduce the behavior:

  1. Find two Linux machines with significantly different DPI displays.
  2. Launch Neovide on each.
  3. Set gfn on each machine/display to the same font face and size.
  4. The rendered glyphs will be of different pixel dimensions, depending on actual display DPI.

Expected behavior
The rendered fonts should be of the same pixel dimensions, regardless of display DPI; or at least respect the user-specificed DPI in the system preferences. (If you want font size described in a resolution-independent manner, then you should have a different specifier (p?) to describe the font's size in points.)

Screenshots

All windows used the font Iosevka Extended.

h9 on a 109 DPI display:

neovide-iosevka-9-109dpi

h6 on a 145 DPI display:

neovide-iosevka-6-145dpi

h5 on a 210 DPI display:

neovide-iosevka-5-210dpi

For reference, here's the Kitty terminal emulator, with font_size 5 on a 210 DPI display. It looks exactly as tiny on the other DPI displays as well:

kitty-iosevka-05

Desktop (please complete the following information):

  • OS: Debian Sid (unstable)
  • Neovide 11.0 and 11.1
  • Neovim 0.9.1

Please run neovide --log and paste the contents of the .log file created in the current directory here:
neovide_rCURRENT.log

Additional context

@ewhac ewhac added the bug Something isn't working label Sep 3, 2023
@MultisampledNight
Copy link
Contributor

Hi, thanks for reporting!

https://neovide.dev/configuration.html#font and :help guifont both list the hX font option to accept values in points, not in pixels. It'd be interesting to know where you've read about pixels in specific though, most likely some docs are out of date.

@fredizzimo
Copy link
Member

This issue is also missing some other details. Like

  1. Which desktop environment you are using
  2. Wayland or X11
  3. Which scaling level you are using for those DPI

That said, the scaling appears to be slightly buggy in X11, but not in Wayland. In Wayland it's totally consistent with Kate for example. But on X11, the text size can be either bigger or smaller depending on which scaling your are using, and Neovide is displaying it at the wrong size. I don't know what's the cause for this, but it's a well known fact that X11 has quite broken HiDPI support.

@fredizzimo
Copy link
Member

fredizzimo commented Sep 3, 2023

Ah, I see, winit reports a scale factor of 1.1667, although I have it set to 100% in X11 KDE Plasma. So that explains the difference.

@fredizzimo
Copy link
Member

fredizzimo commented Sep 3, 2023

For the scale factor on X11 it appears like winit is doing it’s own calculation, see rust-windowing/winit#2231. Apparently it can be overridden by WINIT_X11_SCALE_FACTOR=1, but I have not tested it.

Yes, that makes the size consistent with Wayland and Windows. But not with Kate on X11, which renders the text slightly bigger than Kate on Wayland.

@ewhac
Copy link
Author

ewhac commented Sep 3, 2023

This issue is also missing some other details. Like

  1. Which desktop environment you are using

Xfce 4.18, with AwesomeWM replacing the default window manager.

  1. Wayland or X11

X11, because AwesomeWM doesn't do Wayland, and because NVIDIA.

  1. Which scaling level you are using for those DPI

None, as far as I'm aware. On all systems, the Xfce Appearance preferences have DPI set to 96, and no scaling is applied via xrandr.

It'd be interesting to know where you've read about pixels in specific though, most likely some docs are out of date.

A discussion in the SkiaSharp repo led to this message on the Skia mailing list suggesting that, yes, the font size is effectively specified in pixels. Granted, this was three years ago.

There's also an attempt in Neovide to convert from points to pixels here using a fixed ratio (96 / 72):

fn points_to_pixels(value: f32) -> f32 {
// Fonts in neovim are using points, not pixels.
//
// Skia docs is incorrectly stating it uses points, but uses pixels:
// https://api.skia.org/classSkFont.html#a7e28a156a517d01bc608c14c761346bf
// https://github.com/mono/SkiaSharp/issues/1147#issuecomment-587421201
//
// So, we need to convert points to pixels.
//
// In reality, this depends on DPI/PPI of monitor, but here we only care about converting
// from points to pixels, so this is standard constant values.
if cfg!(target_os = "macos") {
// On macos points == pixels
value
} else {
let pixels_per_inch = 96.0;
let points_per_inch = 72.0;
value * (pixels_per_inch / points_per_inch)
}
}

But, again, this doesn't appear to actually be the case -- h9 will come out as different pixel sizes depending on the display's actual DPI, as back-calculated from the values reported from xrandr. If you're going for resolution-independent rendering, this is what you want. However, what I'd like is for a size specification to result in glyphs the same pixel size across all displays.

@MultisampledNight MultisampledNight changed the title Linux - Inconsistent/Confusing Font Sizing Font height specification in pixels Sep 3, 2023
@MultisampledNight MultisampledNight added enhancement New feature or request and removed bug Something isn't working labels Sep 3, 2023
@fredizzimo
Copy link
Member

There's also an attempt in Neovide to convert from points to pixels here using a fixed ratio (96 / 72):

That's not just an attempt, that's the standard.
The conversion rate a point is 1/72 inch https://en.wikipedia.org/wiki/Point_(typography) and a logical pixel is defined as 1/96 inch, https://en.wikipedia.org/wiki/Pixel. These are also standardised by W3 here https://www.w3.org/TR/css3-values/#absolute-lengths

This value is then scaled to physical pixels using the desktop scaling factor here https://github.com/neovide/neovide/blob/598f7779a404b729de33d748780e5be0de0197d5/src/renderer/fonts/caching_shaper.rs#L73C43-L73C43, scale_factor is the desktop scaling factor, and the fudge_factor is a small factor to make the width of the font exact pixels, so that it can be rendered on a grid with good looking spacing.

On a modern desktop you set the scale factor on each monitor so that you have a consistent font size on all of them, no matter the actual physical DPI they might have.

I believe the problem you are describing is caused by a wrongly configured scaling factor, or that it's not passed on to winit. And as I explained earlier, I believe their calculations are flawed. But that does not matter since you can set it to whatever you want with WINIT_X11_SCALE_FACTOR.

@ewhac
Copy link
Author

ewhac commented Sep 3, 2023

(...many Google searches later...)

Ah, here we are:

X11: Many man-hours have been spent trying to figure out how to handle DPI in X11. Winit currently uses a three-pronged approach:

  • Use the value in the WINIT_X11_SCALE_FACTOR environment variable, if present.
  • If not present, use the value set in Xft.dpi in Xresources.
  • Otherwise, calculate the scale factor based on the millimeter monitor dimensions provided by XRandR.

I don't have Xft.dpi set in Xresources, instead relying on the DPI setting in Xfce's Appearance settings. So it looks like winit fell back to calculating it from XRandR.

Adding Xft.dpi: 96 to Xresources, or setting WINIT_X11_SCALE_FACTOR=1.0, results in the font sizing I'm looking for on all my machines.

(This is not the first time I've bumped into puzzling DPI issues...)

@fredizzimo
Copy link
Member

Great that you got it working, I think we need a FAQ entry about the WINIT_X11_SCALE_FACTOR.

And it looks like the Wayland documentation is wrong, Winit 0.28 added support for fractional scaling, and I'm pretty sure it worked when I tested it.
https://github.com/rust-windowing/winit/releases/tag/v0.28.0

@Kethku
Copy link
Member

Kethku commented Nov 6, 2023

Added a faq. Closing

@Kethku Kethku closed this as completed Nov 6, 2023
@ewhac
Copy link
Author

ewhac commented Dec 1, 2023

This issue appears to have resurfaced. After explicitly setting Xft.dpi: 96 in Xresources, everything worked for many weeks. Then I pulled and built a new copy of neovide from top-of-tree, and now I have unwelcome scaling again.

neovide --log contains the fo0llowwing entries:

TRACE [neovide::settings] Initial value load failed for scale_factor: Error processing request: 1 - 'Key not found: neovide_scale_factor')
[ ... ]
INFO [neovide::window::window_wrapper] window created (scale_factor: 1.1667, font_dimensions: Dimensions { width: 13, height: 27 })

The factor 1.1667 doesn't seem to make any sense -- it can't be derived from the physical DPI of either of my monitors. If I launch neovide with the environment variable WINIT_X11_SCALE_FACTOR=1.0, then I get the desired behavior.

This feels like a regression in winit rather than neovide...

@fredizzimo
Copy link
Member

It's quite possible, they switched x11rb instead XLib

The calculation is done here https://github.com/rust-windowing/winit/blob/master/src/platform_impl/linux/x11/util/randr.rs

And although, it does not make sense to me, you would get a 1.1667 scale factor if your physical monitor is 112 DPI, which sounds very plausible (112/96 = 1.667).

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

No branches or pull requests

4 participants