Subject: bug#54564: closed (Re: bug#54564: 29.0.50; [PATCH] Use gsettings font rendering entries for pgtk builds)

From: [email-masked] (GNU bug Tracking System)
Date: Fri, 13 May 2022 12:52:02 +0000

Your bug report

#54564: 29.0.50; [PATCH] Use gsettings font rendering entries for pgtk builds

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
54564: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=54564
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#54564: 29.0.50; [PATCH] Use gsettings font rendering entries for pgtk builds
From: Po Lu <[email-masked]>
To: Pieter van Prooijen <[email-masked]>
Cc: [email-masked]
Date: Fri, 13 May 2022 20:51:36 +0800
List-Id: <debbugs-submit.debbugs.gnu.org>

Pieter van Prooijen <[email-masked]> writes:

> Hello All,
>
> The copyright assignment paperwork came through, is it possible to
> incorporate the gsetting font rendering changes? I've attached a patch
> against the current master, let me know if I need to change anything.

Thank you.  I will install this shortly and am closing this bug.

Subject: 29.0.50; [PATCH] Use gsettings font rendering entries for pgtk builds
From: Pieter van Prooijen <[email-masked]>
To: [email-masked]
Date: Fri, 25 Mar 2022 12:23:10 +0100
List-Id: <debbugs-submit.debbugs.gnu.org>

Hello, 

When using the pgtk build of emacs under Wayland/Ubuntu, I noticed that
the font hinting was different from the regular X (Ubuntu supplied)
version of emacs.

I have the gsettings config for font hinting set to "full" on my
system, using the fonts tab in the gnome-tweaks tool.

It looks like Cairo defaults to the "slight" hinting setting when using
the Wayland backend for display and will only use the gsettings config
when rendering to an X backend, when it reads the current font settings
from xrdb.

I've attached a patch (against
380f0443b288c68df3762ee20d78719f08dd92ff) which applies the font
entries from gsettings (if present) when creating a font in Cairo.

Note that this patch won't dynamically re-render when emacs is already
running (like it does when changing the system font).
I made an attempt to hook into the gsettings change callback, but could
not force a re-creation of the font with the changed parameters,for
instance using a 'font-render' config changed event. Any pointers on
how to achieve this?
 
Do you think if this patch is a good approach to get the pgtk build to
use the system preferences for font hinting and anti-aliasing?

Kind Regards,

Pieter van Prooijen
    
From 6fe888e7c14ef5aad124c0d68fcd071cd5b65e81 Mon Sep 17 00:00:00 2001
From: Pieter van Prooijen <[email-masked]>
Date: Fri, 25 Mar 2022 11:47:39 +0100
Subject: [PATCH] Use gsettings font rendering entries for pgtk builds

If present, apply the gsettings font hinting and antialiasing entries
when creating a font in cairo.
* src/xsettings.c, src/xsettings.h: read and apply gsetting entries.
* src/ftcrfont.c: use the font_options from xsettings.c when creating a font.
---
 src/ftcrfont.c  |   6 ++-
 src/xsettings.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/xsettings.h |   5 +-
 3 files changed, 127 insertions(+), 2 deletions(-)

diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 98a28af5f2..b659024524 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -37,6 +37,7 @@
 #include "font.h"
 #include "ftfont.h"
 #include "pdumper.h"
+#include "xsettings.h"
 
 #ifdef USE_BE_CAIRO
 #define RED_FROM_ULONG(color)	(((color) >> 16) & 0xff)
@@ -168,10 +169,13 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
   cairo_matrix_t font_matrix, ctm;
   cairo_matrix_init_scale (&font_matrix, pixel_size, pixel_size);
   cairo_matrix_init_identity (&ctm);
-  cairo_font_options_t *options = cairo_font_options_create ();
+
 #ifdef USE_BE_CAIRO
+  cairo_font_options_t *options = cairo_font_options_create();
   if (be_use_subpixel_antialiasing ())
     cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_SUBPIXEL);
+#else
+  cairo_font_options_t *options = xsettings_get_font_options();
 #endif
   cairo_scaled_font_t *scaled_font
     = cairo_scaled_font_create (font_face, &font_matrix, &ctm, options);
diff --git a/src/xsettings.c b/src/xsettings.c
index 71d02e6152..c72d59e99b 100644
--- a/src/xsettings.c
+++ b/src/xsettings.c
@@ -57,6 +57,7 @@ Copyright (C) 2009-2022 Free Software Foundation, Inc.
 #if defined USE_CAIRO || defined HAVE_XFT
 #ifdef USE_CAIRO
 #include <fontconfig/fontconfig.h>
+#include <cairo.h>
 #else  /* HAVE_XFT */
 #include <X11/Xft/Xft.h>
 #endif
@@ -67,6 +68,10 @@ Copyright (C) 2009-2022 Free Software Foundation, Inc.
 static Display_Info *first_dpyinfo;
 static Lisp_Object current_tool_bar_style;
 
+#ifdef USE_CAIRO
+static cairo_font_options_t *font_options;
+#endif
+
 /* Store a config changed event in to the event queue.  */
 
 static void
@@ -215,11 +220,96 @@ #define GSETTINGS_MONO_FONT  "monospace-font-name"
 #define GSETTINGS_FONT_NAME  "font-name"
 #endif
 
+#ifdef HAVE_PGTK
+#define GSETTINGS_FONT_ANTIALIASING "font-antialiasing"
+#define GSETTINGS_FONT_RGBA_ORDER   "font-rgba-order"
+#define GSETTINGS_FONT_HINTING      "font-hinting"
+#endif
 
 /* The single GSettings instance, or NULL if not connected to GSettings.  */
 
 static GSettings *gsettings_client;
 
+/* For hinting and antialias no dynamic re-display is (yet) possible,
+   because cairo applies these options when creating the font, not when
+   rendering it.
+*/
+
+#ifdef HAVE_PGTK
+/* Apply changes in the hinting system setting */
+static void
+apply_gsettings_font_hinting(GSettings *settings)
+{
+  GVariant *val = g_settings_get_value (settings, GSETTINGS_FONT_HINTING);
+  if (val)
+    {
+      g_variant_ref_sink (val);
+      if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
+	{
+	  const char *hinting = g_variant_get_string (val, NULL);
+
+	  if (strcmp (hinting, "full") == 0)
+	    cairo_font_options_set_hint_style(font_options, CAIRO_HINT_STYLE_FULL);
+	  else if (strcmp (hinting, "medium") == 0)
+	    cairo_font_options_set_hint_style(font_options, CAIRO_HINT_STYLE_MEDIUM);
+	  else if (strcmp (hinting, "slight") == 0)
+	    cairo_font_options_set_hint_style(font_options, CAIRO_HINT_STYLE_SLIGHT);
+	  else if (strcmp (hinting, "none") == 0)
+	    cairo_font_options_set_hint_style(font_options, CAIRO_HINT_STYLE_NONE);
+	}
+      g_variant_unref (val);
+    }
+}
+
+/* Apply changes in the antialiasing system setting */
+static void
+apply_gsettings_font_antialias(GSettings *settings)
+{
+  GVariant *val = g_settings_get_value (settings, GSETTINGS_FONT_ANTIALIASING);
+  if (val)
+    {
+      g_variant_ref_sink (val);
+      if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
+	{
+	  const char *antialias = g_variant_get_string (val, NULL);
+
+	  if (strcmp (antialias, "none") == 0)
+	    cairo_font_options_set_antialias(font_options, CAIRO_ANTIALIAS_NONE);
+	  else if (strcmp(antialias, "grayscale") == 0)
+	    cairo_font_options_set_antialias(font_options, CAIRO_ANTIALIAS_GRAY);
+	  else if (strcmp(antialias, "rgba") == 0)
+	    cairo_font_options_set_antialias(font_options, CAIRO_ANTIALIAS_SUBPIXEL);
+	}
+      g_variant_unref (val);
+    }
+}
+
+/* Apply the settings for the rgb element ordering */
+static void
+apply_gsettings_font_rgba_order(GSettings *settings)
+{
+  GVariant *val = g_settings_get_value (settings, GSETTINGS_FONT_RGBA_ORDER);
+  if (val)
+    {
+      g_variant_ref_sink (val);
+      if (g_variant_is_of_type (val, G_VARIANT_TYPE_STRING))
+	{
+	  const char *rgba_order = g_variant_get_string (val, NULL);
+
+	  if (strcmp (rgba_order, "rgb") == 0)
+	    cairo_font_options_set_subpixel_order(font_options, CAIRO_SUBPIXEL_ORDER_RGB);
+	  else if (strcmp (rgba_order, "bgr") == 0)
+	    cairo_font_options_set_subpixel_order(font_options, CAIRO_SUBPIXEL_ORDER_BGR);
+	  else if (strcmp (rgba_order, "vrgb") == 0)
+	    cairo_font_options_set_subpixel_order(font_options, CAIRO_SUBPIXEL_ORDER_VRGB);
+	  else if (strcmp (rgba_order, "vbgr") == 0)
+	    cairo_font_options_set_subpixel_order(font_options, CAIRO_SUBPIXEL_ORDER_VBGR);
+	}
+      g_variant_unref (val);
+    }
+}
+#endif /* HAVE_PGTK */
+
 /* Callback called when something changed in GSettings.  */
 
 static void
@@ -900,6 +990,18 @@ init_gsettings (void)
         dupstring (&current_font, g_variant_get_string (val, NULL));
       g_variant_unref (val);
     }
+
+  /* Only use the gsettings font entries for non-X cairo backends
+     (which is the recommended way of running pgtk builds).
+     For the X backend cairo will apply these entries itself,
+     reading them from xrdb. */
+#ifdef HAVE_PGTK
+  font_options = cairo_font_options_create ();
+  apply_gsettings_font_antialias(gsettings_client);
+  apply_gsettings_font_hinting(gsettings_client);
+  apply_gsettings_font_rgba_order(gsettings_client);
+#endif /* HAVE_PGTK */
+
 #endif /* USE_CAIRO || HAVE_XFT */
 
 #endif /* HAVE_GSETTINGS */
@@ -1021,6 +1123,18 @@ xsettings_get_system_normal_font (void)
 }
 #endif
 
+#ifdef USE_CAIRO
+/* Return the cairo font options, possibly initialized in
+   init_gsettings() */
+cairo_font_options_t *
+xsettings_get_font_options (void) {
+  if (font_options == NULL)
+    return cairo_font_options_create();
+  else
+    return cairo_font_options_copy(font_options);
+}
+#endif
+
 DEFUN ("font-get-system-normal-font", Ffont_get_system_normal_font,
        Sfont_get_system_normal_font,
        0, 0, 0,
@@ -1073,6 +1187,10 @@ syms_of_xsettings (void)
   gconf_client = NULL;
   PDUMPER_IGNORE (gconf_client);
 #endif
+#ifdef USE_CAIRO
+  font_options = NULL;
+  PDUMPER_IGNORE (font_options);
+#endif
 
   DEFSYM (Qmonospace_font_name, "monospace-font-name");
   DEFSYM (Qfont_name, "font-name");
diff --git a/src/xsettings.h b/src/xsettings.h
index ccaa36489d..15984e8865 100644
--- a/src/xsettings.h
+++ b/src/xsettings.h
@@ -40,6 +40,9 @@ #define XSETTINGS_H
 #ifdef USE_LUCID
 extern const char *xsettings_get_system_normal_font (void);
 #endif
-
+#ifdef USE_CAIRO
+struct cairo_font_options_t;
+extern cairo_font_options_t *xsettings_get_font_options (void);
+#endif
 
 #endif /* XSETTINGS_H */
-- 
2.32.0