HiDPI support: Difference between revisions

From FreeCAD Documentation
No edit summary
No edit summary
(41 intermediate revisions by 5 users not shown)
Line 1: Line 1:
{{TOCright}}
HiDPI support refers to the issue of displaying raster graphics (fonts, cursors, images) on high-resolution displays.


[[File:HiDpiDevicePixelRatio.png|thumb|left|Device pixel ratio. 100% = 1, 200% = 2, 150% = 1.5]]
The issue is that the physical size of a display remains the same while its resolution increases.


This is a [[Development_roadmap|project]] dedicated to support high-resolution displays in FreeCAD.
== Issues ==

HiDPI support refers to the issue of displaying raster graphics (fonts, cursors, images) and UI elements (buttons, menus, handles) on high-resolution displays. It's also a term introduced by Apple.

The issue is that the physical size of a display remains the same (from 21 to 32 inches) while its resolution increases (FullHD, 4K, 8K).

To solve the issue, Apple introduced "HiDPI", that is scaling all the UI elements according to the font size. Font sizes are specified in points, while their pixel value is calculated using DPI and device pixel ratio which is a scale factor specified by a user in OS settings. At the same time, raster images are rendered at their true pixel size, so individual pixels are less noticeable. It means that raster images are provided at higher resolution to make up for their size on a screen. Vector graphics (UI elements) are rendered accordingly, at higher resolution.

== Master plan ==

=== Part one ===

Goal: Make sure that we make the most out of Qt support.

* In progress. Migrate the user base to Qt > 5.6 and set the AA_EnableHighDpiScaling to true.
* Scale all cursors and icons (multiplying them by devicePixelRatio) https://github.com/FreeCAD/FreeCAD/pull/3712
* Make all pixel graphics vector or available at various pixel density

=== Part two ===

Goal: Make sure that the system font is correctly determined.

* Bundle appropriate QPA theme plugins on all major platforms (AppImage, etc)
* Find ways to detect that system's font is changed
* Remove the toolbar/icon size setting and make the toolbar size relative to the system font
* Add an experimental setting "scale factor" which will depend on device pixel ratio and/or system font size
* Rescale the toolbar/icon size according to the new experimental setting
* Gather user feedback whether we need the customizable toolbar icon size

=== Part three ===

Goal: Make all UI widgets size relative to the font size

* In all appropriate places, get system font metrics to determine the size of a widget.
* In places where real size is referenced, assume font size as a relative measure (72 points = 96 virtual pixels = 1 inch).
* Choose a reference device relative to which UI could scale up and down.
* 2D coordinates and sizes should assume device-independent pixels.
* Make sure qreal versions of APIs are used.
* Turn off AA_EnableHighDpiScaling

=== Part four ===

Goal: Support rescaling when the window is moved from one screen to another

* Detect that device pixel ratio has changed
* Notify all widgets depending on device pixel ratio or the font size

== Background ==

=== Display resolutions ===
[[File:Vector Video Standards8.svg|800px]]
=== Device pixel ratio ===

It's a well-known concept for Web and Android developers. But not so much for desktop developers.

Basically, it's the ratio between physical pixels and device-independent pixels.

First things first. UI positioning and size (x, y, width, height) are historically defined in pixels.

But as more variety of displays resolutions become available at many different physical sizes, it's become a problem software developers need to be aware of.

FreeCAD development was started in 2002, long before such a problem was even foreseen.

Ok, why not just increase DPI, you ask. Well, the issue is that you still want to benefit from the high-resolution display.

All the raster graphics need to contain more pixels, while vector graphics (fonts and icons) should be of the same physical size as visible on the display.

If you just change DPI, you would scale everything up and down. But in fact, you need all the pixel sizes to remain the same, while resources (images) to be displayed in a higher resolution.

So the concept of "Device-independent pixels" was introduced. The idea was that developers could keep not worrying about the physical size of a display and design UIs in virtual pixels.

But the reality is that if you use raster graphics, it becomes pixelized, blurry, or aliased as it is displayed in non-native resolution. So developers now need to provide multiple versions of raster images, for each device pixel ratio. Usually, it's whole numbers: 1, 2, 3, 4. But it can also be fractional (125%, 150%, 175% = 1.25, 1.5, 1.75) meaning that there's still some scaling involved, but not as apparent.

* https://stackoverflow.com/questions/8785643/what-exactly-is-device-pixel-ratio
* https://stackoverflow.com/questions/13911786/what-is-device-pixel-ratio-for

== Issue testing/demonstration ==

=== OS X ===

# Open "Display"
# Choose "Scaled"
# Choose "Larger text" - this increases device pixel ratio

Video: https://www.youtube.com/watch?v=4U3eh_fMo4o

=== X Window ===

Useful commands:
<pre>
~$ xrdb -query
*customization: -color
Xft.dpi: 192
Xft.antialias: 1
Xft.hinting: 1
Xft.hintstyle: hintslight
Xft.rgba: rgb
Xcursor.size: 128
Xcursor.theme: DMZ-White
</pre>

<pre>
~$ xdpyinfo | grep -B 2 resolution
screen #0:
dimensions: 3840x2160 pixels (1016x572 millimeters)
resolution: 96x96 dots per inch
</pre>
=== Ubuntu (GNOME Shell) ===

# Open "Displays" (Settings > Devices > Displays)
# Select the highest resolution available
# Select scaling higher than 100%

== Issues and solutions ==


* Raster images (cursors, icons)
* Raster images (cursors, icons)
Line 11: Line 124:
* Snap distance
* Snap distance
* Selection distance (the hot area around selectable objects)
* Selection distance (the hot area around selectable objects)

=== Font size ===

Fonts are usually vector. So they don't require a higher resolution version to be able to scale up (in pixels). However, we can't just increase every font size and call it a day. People are used to font sizes in relation to how they look on paper. And on paper, it is known that 72pt font takes one inch, and on displays of old days, an inch was equal to 96 pixels at 1:1 zoom level.

So, as display resolutions become higher, displays could fit more text lines of the same size. So naturally, as display physical size remains the same and our eyes don't become better at discerning smaller detail, we perceive the same font point size as smaller on higher resolutions.

To overcome this issue, OS implemented what it's called DPI scaling (or DPI font settings in the older days) or High-DPI scaling of the recent 4K displays. Users could change the DPI and benefit from much more real estate in terms of pixels while keeping a comfortable to read font size.

=== Custom cursor size ===

The cursor size is kind of difficult. Qt recommends using a hardcoded image size of 32x32. As of 5.x it doesn't provide any functionality to integrate with OS and query the size of the mouse pointer. It's a shame since it means you can't benefit from accessibility settings, where cursor size can be set to an arbitrarily large value.

So, until Qt provides better guidance on the cursor size, let's use an image of 32 * device pixel ratio.

In OS, for example in GNOME, cursor size appears to be fixed in terms of virtual pixels. That is, it respects the device pixel ratio (keep the same apparent size). But it does increase when you change the display resolution (that is, stays the same in pixels, but increase in apparent size).

For example, here's a default setting for virtual pixels in GNOME:

<pre>
~$ gsettings get org.gnome.desktop.interface cursor-size
64
</pre>

Taking into account the scale factor, it means the physical pixel size of 128.

Qt doesn't provide the functionality to retrieve that value. So we have to either hard code it or provide a user setting to change that.


== Forum threads ==
== Forum threads ==


* [https://forum.freecadweb.org/viewtopic.php?t=34916 Improve support of high DPI displays]
* [https://forum.freecadweb.org/viewtopic.php?t=34916 Improve support of high DPI displays] - general Qt support
* [https://forum.freecadweb.org/viewtopic.php?&t=48719 Custom cursors and high dpi (Windows and MacOS testers needed)]
* [https://forum.freecadweb.org/viewtopic.php?t=39325 News: Qt 5.14 Is Bringing Significantly Better HiDPI Support] - general Qt support
* [https://forum.freecadweb.org/viewtopic.php?&t=48719 Custom cursors and high dpi (Windows and MacOS testers needed)] - raster cursor image issue
* [https://forum.freecadweb.org/viewtopic.php?t=34853 HiDPI Support in Sketcher View] - selection distance issue
* [https://forum.freecadweb.org/viewtopic.php?t=10512 High DPI Improvements] - PR "High DPI Fixes" https://github.com/FreeCAD/FreeCAD/pull/54, bad quality, 2015
* [https://forum.freecadweb.org/viewtopic.php?t=12123 High dpi] - experimental build with "High DPI Improvements" PR
* [https://forum.freecadweb.org/viewtopic.php?t=41656 GUI font size] - font size issue and the QT_SCALE_FACTOR workaround
* [https://forum.freecadweb.org/viewtopic.php?t=28838 BUG? Cropped icons] - issues with HiDPI on multiple displays
* [https://forum.freecadweb.org/viewtopic.php?t=20977 FreeCAD 0.17 on macOS Update (Qt 5 builds now available)] - issues with HiDPI on OS X after upgrade to Qt5
* [https://forum.freecadweb.org/viewtopic.php?f=3&t=29743 Ticket #3537 - Draft Edit mode not working on MacOS X (HiDPi issue)] - OS X + HiDPI, Qt5
* [https://forum.freecadweb.org/viewtopic.php?t=39975 Menu distorted on MAC external display] - OS X + HiDPI, external display
* [https://forum.freecadweb.org/viewtopic.php?t=19724&start=60 macOS Qt5 plan and status] - OS X dropped support for Qt4, HiDPI issues
* https://www.google.com/search?q=freecad+hidpi+site:forum.freecadweb.org
* https://www.google.com/search?q=freecad+hidpi+site:forum.freecadweb.org
* [https://forum.freecadweb.org/viewtopic.php?f=10&t=52307 A suggestion to disable "dump" scaling before tackling the font size issues]
* [https://forum.freecadweb.org/viewtopic.php?f=3&t=42835 Navigation cube scaling]
* [https://forum.freecadweb.org/viewtopic.php?p=450061#p450061 Navigation cube scaling 2]


== Relevant changes ==
== Relevant changes ==
Line 35: Line 188:


* Tickets tagged with [https://tracker.freecadweb.org/search.php?tag_string=HiDPI HiDPI]
* Tickets tagged with [https://tracker.freecadweb.org/search.php?tag_string=HiDPI HiDPI]

== External references ==

* https://doc.qt.io/qt-5/highdpi.html
* https://doc.qt.io/qt-5/scalability.html
* https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows
* https://docs.microsoft.com/en-us/windows/win32/w8cookbook/high-dpi-for-desktop-apps-in-windows-8-1?redirectedfrom=MSDN

[[Category:Roadmap{{#translation:}}]]
{{clear}}

Revision as of 22:28, 4 March 2022

Device pixel ratio. 100% = 1, 200% = 2, 150% = 1.5

This is a project dedicated to support high-resolution displays in FreeCAD.

HiDPI support refers to the issue of displaying raster graphics (fonts, cursors, images) and UI elements (buttons, menus, handles) on high-resolution displays. It's also a term introduced by Apple.

The issue is that the physical size of a display remains the same (from 21 to 32 inches) while its resolution increases (FullHD, 4K, 8K).

To solve the issue, Apple introduced "HiDPI", that is scaling all the UI elements according to the font size. Font sizes are specified in points, while their pixel value is calculated using DPI and device pixel ratio which is a scale factor specified by a user in OS settings. At the same time, raster images are rendered at their true pixel size, so individual pixels are less noticeable. It means that raster images are provided at higher resolution to make up for their size on a screen. Vector graphics (UI elements) are rendered accordingly, at higher resolution.

Master plan

Part one

Goal: Make sure that we make the most out of Qt support.

  • In progress. Migrate the user base to Qt > 5.6 and set the AA_EnableHighDpiScaling to true.
  • Scale all cursors and icons (multiplying them by devicePixelRatio) https://github.com/FreeCAD/FreeCAD/pull/3712
  • Make all pixel graphics vector or available at various pixel density

Part two

Goal: Make sure that the system font is correctly determined.

  • Bundle appropriate QPA theme plugins on all major platforms (AppImage, etc)
  • Find ways to detect that system's font is changed
  • Remove the toolbar/icon size setting and make the toolbar size relative to the system font
  • Add an experimental setting "scale factor" which will depend on device pixel ratio and/or system font size
  • Rescale the toolbar/icon size according to the new experimental setting
  • Gather user feedback whether we need the customizable toolbar icon size

Part three

Goal: Make all UI widgets size relative to the font size

  • In all appropriate places, get system font metrics to determine the size of a widget.
  • In places where real size is referenced, assume font size as a relative measure (72 points = 96 virtual pixels = 1 inch).
  • Choose a reference device relative to which UI could scale up and down.
  • 2D coordinates and sizes should assume device-independent pixels.
  • Make sure qreal versions of APIs are used.
  • Turn off AA_EnableHighDpiScaling

Part four

Goal: Support rescaling when the window is moved from one screen to another

  • Detect that device pixel ratio has changed
  • Notify all widgets depending on device pixel ratio or the font size

Background

Display resolutions

Device pixel ratio

It's a well-known concept for Web and Android developers. But not so much for desktop developers.

Basically, it's the ratio between physical pixels and device-independent pixels.

First things first. UI positioning and size (x, y, width, height) are historically defined in pixels.

But as more variety of displays resolutions become available at many different physical sizes, it's become a problem software developers need to be aware of.

FreeCAD development was started in 2002, long before such a problem was even foreseen.

Ok, why not just increase DPI, you ask. Well, the issue is that you still want to benefit from the high-resolution display.

All the raster graphics need to contain more pixels, while vector graphics (fonts and icons) should be of the same physical size as visible on the display.

If you just change DPI, you would scale everything up and down. But in fact, you need all the pixel sizes to remain the same, while resources (images) to be displayed in a higher resolution.

So the concept of "Device-independent pixels" was introduced. The idea was that developers could keep not worrying about the physical size of a display and design UIs in virtual pixels.

But the reality is that if you use raster graphics, it becomes pixelized, blurry, or aliased as it is displayed in non-native resolution. So developers now need to provide multiple versions of raster images, for each device pixel ratio. Usually, it's whole numbers: 1, 2, 3, 4. But it can also be fractional (125%, 150%, 175% = 1.25, 1.5, 1.75) meaning that there's still some scaling involved, but not as apparent.

Issue testing/demonstration

OS X

  1. Open "Display"
  2. Choose "Scaled"
  3. Choose "Larger text" - this increases device pixel ratio

Video: https://www.youtube.com/watch?v=4U3eh_fMo4o

X Window

Useful commands:

~$ xrdb -query
*customization:	-color
Xft.dpi:	192
Xft.antialias:	1
Xft.hinting:	1
Xft.hintstyle:	hintslight
Xft.rgba:	rgb
Xcursor.size:	128
Xcursor.theme:	DMZ-White
~$ xdpyinfo | grep -B 2 resolution
screen #0:
  dimensions:    3840x2160 pixels (1016x572 millimeters)
  resolution:    96x96 dots per inch

Ubuntu (GNOME Shell)

  1. Open "Displays" (Settings > Devices > Displays)
  2. Select the highest resolution available
  3. Select scaling higher than 100%

Issues and solutions

  • Raster images (cursors, icons)
  • Fonts (defined in pixels rather than points)
  • Cursor hot point
  • Zoom/Rotate origin
  • Snap distance
  • Selection distance (the hot area around selectable objects)

Font size

Fonts are usually vector. So they don't require a higher resolution version to be able to scale up (in pixels). However, we can't just increase every font size and call it a day. People are used to font sizes in relation to how they look on paper. And on paper, it is known that 72pt font takes one inch, and on displays of old days, an inch was equal to 96 pixels at 1:1 zoom level.

So, as display resolutions become higher, displays could fit more text lines of the same size. So naturally, as display physical size remains the same and our eyes don't become better at discerning smaller detail, we perceive the same font point size as smaller on higher resolutions.

To overcome this issue, OS implemented what it's called DPI scaling (or DPI font settings in the older days) or High-DPI scaling of the recent 4K displays. Users could change the DPI and benefit from much more real estate in terms of pixels while keeping a comfortable to read font size.

Custom cursor size

The cursor size is kind of difficult. Qt recommends using a hardcoded image size of 32x32. As of 5.x it doesn't provide any functionality to integrate with OS and query the size of the mouse pointer. It's a shame since it means you can't benefit from accessibility settings, where cursor size can be set to an arbitrarily large value.

So, until Qt provides better guidance on the cursor size, let's use an image of 32 * device pixel ratio.

In OS, for example in GNOME, cursor size appears to be fixed in terms of virtual pixels. That is, it respects the device pixel ratio (keep the same apparent size). But it does increase when you change the display resolution (that is, stays the same in pixels, but increase in apparent size).

For example, here's a default setting for virtual pixels in GNOME:

~$ gsettings get org.gnome.desktop.interface cursor-size
64

Taking into account the scale factor, it means the physical pixel size of 128.

Qt doesn't provide the functionality to retrieve that value. So we have to either hard code it or provide a user setting to change that.

Forum threads

Relevant changes

Bugtracker Issues

  • Tickets tagged with HiDPI

External references