From fbc75ec8e012d2eff3ab755a77dd3ba6c2964a26 Mon Sep 17 00:00:00 2001 From: iwbnwif Date: Mon, 4 Nov 2019 20:04:12 +0000 Subject: [PATCH 1/3] Add support for fractional font scaling to wxGTK3 Respect the system font scaling parameter (e.g. "Fonts->Scaling Factor" in Gnome Tweaks, "Force font DPI" in KDE System Settings or GDK_DPI_SCALE environment variable) when drawing text using wxFont. This ensures that generic widgets have their text scaled appropriately to be consistent with native widgets. Closes https://github.com/wxWidgets/wxWidgets/pull/1635 --- src/generic/graphicc.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/generic/graphicc.cpp b/src/generic/graphicc.cpp index 4bbca0ae54..6f3480fbc7 100644 --- a/src/generic/graphicc.cpp +++ b/src/generic/graphicc.cpp @@ -526,6 +526,9 @@ protected: WindowHDC m_mswWindowHDC; int m_mswStateSavedDC; #endif +#ifdef __WXGTK__ + float m_fontScalingFactor; +#endif private: cairo_t* m_context; @@ -2360,6 +2363,14 @@ wxCairoContext::~wxCairoContext() void wxCairoContext::Init(cairo_t *context) { +#ifdef __WXGTK__ + // Attempt to find the system font scaling parameter (e.g. "Fonts->Scaling + // Factor" in Gnome Tweaks, "Force font DPI" in KDE System Settings or + // GDK_DPI_SCALE environment variable). + GdkScreen* screen = gdk_screen_get_default(); + m_fontScalingFactor = screen ? gdk_screen_get_resolution(screen) / 96.0 : 1.0; +#endif + m_context = context; if ( m_context ) { @@ -2660,9 +2671,12 @@ void wxCairoContext::DoDrawText(const wxString& str, wxDouble x, wxDouble y) fontData->Apply(this); #ifdef __WXGTK__ - const wxFont& font = fontData->GetFont(); + wxFont font = fontData->GetFont(); if ( font.IsOk() ) { + // Apply GDK font scaling factor. + font.Scale(m_fontScalingFactor); + wxGtkObject layout(pango_cairo_create_layout (m_context)); pango_layout_set_font_description(layout, font.GetNativeFontInfo()->description); pango_layout_set_text(layout, data, data.length()); @@ -2710,7 +2724,7 @@ void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDoub #ifdef __WXGTK__ // Use Pango instead of Cairo toy font API if we have the font. - const wxFont& font = fontData->GetFont(); + wxFont font = fontData->GetFont(); if ( font.IsOk() ) { // Note that there is no need to call Apply() at all in this case, it @@ -2718,6 +2732,9 @@ void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDoub // measuring its extent. int w, h; + // Apply GDK font scaling factor. + font.Scale(m_fontScalingFactor); + wxGtkObject layout(pango_cairo_create_layout (m_context)); pango_layout_set_font_description(layout, font.GetNativeFontInfo()->description); const wxCharBuffer data = str.utf8_str(); @@ -2787,7 +2804,11 @@ void wxCairoContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& if (data.length()) { wxGtkObject layout(pango_cairo_create_layout(m_context)); - const wxFont& font = static_cast(m_font.GetRefData())->GetFont(); + wxFont font = static_cast(m_font.GetRefData())->GetFont(); + + // Apply GDK font scaling factor. + font.Scale(m_fontScalingFactor); + pango_layout_set_font_description(layout, font.GetNativeFontInfo()->description); pango_layout_set_text(layout, data, data.length()); PangoLayoutIter* iter = pango_layout_get_iter(layout); From 4d4e3e71a51c967970410f97d52a9b3b278fb219 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 13 Nov 2019 19:12:34 +0100 Subject: [PATCH 2/3] Use helper function for applying scaled font to PangoLayout Don't scale, or even copy, the font object unnecessarily in the common case when the font scaling factor is 1.0 anyhow. No real changes, just make the code slightly more efficient and also a bit more concise after the changes of the previous commit. --- src/generic/graphicc.cpp | 49 ++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/generic/graphicc.cpp b/src/generic/graphicc.cpp index 6f3480fbc7..363ef12356 100644 --- a/src/generic/graphicc.cpp +++ b/src/generic/graphicc.cpp @@ -527,7 +527,32 @@ protected: int m_mswStateSavedDC; #endif #ifdef __WXGTK__ + // This factor must be applied to the font before actually using it, for + // consistency with the text drawn by GTK itself. float m_fontScalingFactor; + + // Tiny helper actually applying the font. It's convenient because it can + // be called with a temporary wxFont, as we're going to make a copy of its + // Pango font description inside this function before the font object is + // destroyed. + static void DoApplyFont(PangoLayout* layout, const wxFont& font) + { + pango_layout_set_font_description + ( + layout, + font.GetNativeFontInfo()->description + ); + } + + // Function applying the Pango font description for the given font scaled by + // the font scaling factor if necessary to the specified layout. + void ApplyFont(PangoLayout* layout, const wxFont& font) const + { + // Only scale the font if we really need to do it. + DoApplyFont(layout, m_fontScalingFactor == 1.0f + ? font + : font.Scaled(m_fontScalingFactor)); + } #endif private: @@ -2671,15 +2696,15 @@ void wxCairoContext::DoDrawText(const wxString& str, wxDouble x, wxDouble y) fontData->Apply(this); #ifdef __WXGTK__ - wxFont font = fontData->GetFont(); + const wxFont& font = fontData->GetFont(); if ( font.IsOk() ) { - // Apply GDK font scaling factor. - font.Scale(m_fontScalingFactor); - wxGtkObject layout(pango_cairo_create_layout (m_context)); - pango_layout_set_font_description(layout, font.GetNativeFontInfo()->description); + ApplyFont(layout, font); pango_layout_set_text(layout, data, data.length()); + + // Note that Pango attributes don't depend on font size, so we don't + // need to use the scaled font here. font.GTKSetPangoAttrs(layout); cairo_move_to(m_context, x, y); @@ -2724,7 +2749,7 @@ void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDoub #ifdef __WXGTK__ // Use Pango instead of Cairo toy font API if we have the font. - wxFont font = fontData->GetFont(); + const wxFont& font = fontData->GetFont(); if ( font.IsOk() ) { // Note that there is no need to call Apply() at all in this case, it @@ -2732,11 +2757,8 @@ void wxCairoContext::GetTextExtent( const wxString &str, wxDouble *width, wxDoub // measuring its extent. int w, h; - // Apply GDK font scaling factor. - font.Scale(m_fontScalingFactor); - wxGtkObject layout(pango_cairo_create_layout (m_context)); - pango_layout_set_font_description(layout, font.GetNativeFontInfo()->description); + ApplyFont(layout, font); const wxCharBuffer data = str.utf8_str(); if ( !data ) { @@ -2804,12 +2826,9 @@ void wxCairoContext::GetPartialTextExtents(const wxString& text, wxArrayDouble& if (data.length()) { wxGtkObject layout(pango_cairo_create_layout(m_context)); - wxFont font = static_cast(m_font.GetRefData())->GetFont(); + const wxFont& font = static_cast(m_font.GetRefData())->GetFont(); - // Apply GDK font scaling factor. - font.Scale(m_fontScalingFactor); - - pango_layout_set_font_description(layout, font.GetNativeFontInfo()->description); + ApplyFont(layout, font); pango_layout_set_text(layout, data, data.length()); PangoLayoutIter* iter = pango_layout_get_iter(layout); PangoRectangle rect; From ac14c3ffbc8d72b28068790f8a38278a16a0819c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 16 Nov 2019 00:50:13 +0100 Subject: [PATCH 3/3] Only use font scaling code with GTK 3 or later It's useless to do it for GTK 2 which doesn't support font scaling anyhow. --- src/generic/graphicc.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/generic/graphicc.cpp b/src/generic/graphicc.cpp index 363ef12356..2b4dfbca89 100644 --- a/src/generic/graphicc.cpp +++ b/src/generic/graphicc.cpp @@ -527,14 +527,12 @@ protected: int m_mswStateSavedDC; #endif #ifdef __WXGTK__ - // This factor must be applied to the font before actually using it, for - // consistency with the text drawn by GTK itself. - float m_fontScalingFactor; - // Tiny helper actually applying the font. It's convenient because it can // be called with a temporary wxFont, as we're going to make a copy of its // Pango font description inside this function before the font object is // destroyed. + // + // It's also all we need for GTK < 3. static void DoApplyFont(PangoLayout* layout, const wxFont& font) { pango_layout_set_font_description @@ -544,6 +542,11 @@ protected: ); } +#ifdef __WXGTK3__ + // This factor must be applied to the font before actually using it, for + // consistency with the text drawn by GTK itself. + float m_fontScalingFactor; + // Function applying the Pango font description for the given font scaled by // the font scaling factor if necessary to the specified layout. void ApplyFont(PangoLayout* layout, const wxFont& font) const @@ -553,7 +556,15 @@ protected: ? font : font.Scaled(m_fontScalingFactor)); } -#endif +#else // GTK < 3 + // Provide the same function even if it does nothing in this case to keep + // the same code for all GTK versions. + void ApplyFont(PangoLayout* layout, const wxFont& font) const + { + DoApplyFont(layout, font); + } +#endif // __WXGTK3__ +#endif // __WXGTK__ private: cairo_t* m_context; @@ -2388,7 +2399,7 @@ wxCairoContext::~wxCairoContext() void wxCairoContext::Init(cairo_t *context) { -#ifdef __WXGTK__ +#ifdef __WXGTK3__ // Attempt to find the system font scaling parameter (e.g. "Fonts->Scaling // Factor" in Gnome Tweaks, "Force font DPI" in KDE System Settings or // GDK_DPI_SCALE environment variable).