Enable subpixel positioning for text only on high scaling factors
authorEmmanuele Bassi <ebassi@gnome.org>
Mon, 17 Jul 2023 11:24:27 +0000 (12:24 +0100)
committerEmmanuele Bassi <ebassi@gnome.org>
Sat, 29 Jul 2023 08:14:57 +0000 (11:14 +0300)
With our current font rendering stack, subpixel positioning simply does
not look good on non-HiDPI displays compared to font hinting.

While we have a setting as a way to restore font hinting, it's fairly
clunky to use with sandboxed applications, since it requires injecting a
settings.ini file in every application's configuration directory, or
adding the user's own configuration directory into the sandbox.

As a workaround, we can check the scaling factor used by GTK, and only
enable subpixel positioning if the factor is greater than one.

gtk/gtkwidget.c

index dd2920e59778ca1f3ed3a28d0f0c4295499384de..353097bbe348071c603b556b72d5e73d9a8ea19c 100644 (file)
@@ -6463,6 +6463,8 @@ gtk_widget_update_pango_context (GtkWidget        *widget,
   GtkSettings *settings;
   cairo_font_options_t *font_options;
   guint old_serial;
+  gboolean hint_font_metrics = FALSE;
+  int scale;
 
   old_serial = pango_context_get_serial (context);
 
@@ -6470,14 +6472,18 @@ gtk_widget_update_pango_context (GtkWidget        *widget,
   pango_context_set_font_description (context, font_desc);
   pango_font_description_free (font_desc);
 
+  scale = gtk_widget_get_scale_factor (widget);
   settings = gtk_widget_get_settings (widget);
 
-  if (settings &&
+  if (settings != NULL &&
       cairo_version () >= CAIRO_VERSION_ENCODE (1, 17, 4))
     {
-      gboolean hint_font_metrics;
-
       g_object_get (settings, "gtk-hint-font-metrics", &hint_font_metrics, NULL);
+
+      /* Override the user setting on non-HiDPI */
+      if (scale == 1)
+        hint_font_metrics = TRUE;
+
       pango_context_set_round_glyph_positions (context, hint_font_metrics);
     }
 
@@ -6495,13 +6501,25 @@ gtk_widget_update_pango_context (GtkWidget        *widget,
 
       options = cairo_font_options_copy (gtk_settings_get_font_options (settings));
       cairo_font_options_merge (options, font_options);
+
+      cairo_font_options_set_hint_metrics (options,
+                                           hint_font_metrics == 1 ? CAIRO_HINT_METRICS_ON
+                                                                  : CAIRO_HINT_METRICS_OFF);
+
       pango_cairo_context_set_font_options (context, options);
       cairo_font_options_destroy (options);
     }
   else if (settings)
     {
-      pango_cairo_context_set_font_options (context,
-                                            gtk_settings_get_font_options (settings));
+      cairo_font_options_t *options;
+
+      options = cairo_font_options_copy (gtk_settings_get_font_options (settings));
+      cairo_font_options_set_hint_metrics (options,
+                                           hint_font_metrics == 1 ? CAIRO_HINT_METRICS_ON
+                                                                  : CAIRO_HINT_METRICS_OFF);
+
+      pango_cairo_context_set_font_options (context, options);
+      cairo_font_options_destroy (options);
     }
 
   pango_context_set_font_map (context, gtk_widget_get_effective_font_map (widget));
@@ -6801,6 +6819,8 @@ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
     gtk_style_context_set_scale (priv->context, gtk_widget_get_scale_factor (widget));
 G_GNUC_END_IGNORE_DEPRECATIONS
 
+  gtk_widget_update_default_pango_context (widget);
+
   g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_SCALE_FACTOR]);
 
   gtk_widget_forall (widget, (GtkCallback)_gtk_widget_scale_changed, NULL);