From bc0aa23777f2aae42b29597a04c0d14007063149 Mon Sep 17 00:00:00 2001 From: Pieter van Prooijen Date: Tue, 29 Mar 2022 21:21:52 +0200 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. Do this at initialization and when the entries change, re-rendering the frames. * src/ftcrfont.c (ftcrfont_open): Use the font_options derived from gsettings when opening a font. * src/ftcrfont.c: (ftcrfont_cached_font_ok): Report a cached font as invalid if its font options differ from the current gsettings ones. * src/xsettings.c, src/xsettings.h (xsettings_get_font_options): Retrieve the current gsettings derived cairo font_options. * src/xsettings.c (apply_gsettings_font_hinting): Convert the gsettings hint setting to the font_options struct. * src/xsettings.c (apply_gsettings_font_antialias): Convert the gsettings antialias setting to the font_options struct. * src/xsettings.c (apply_gsettings_font_rgba_order): Convert the gsettings rgba order setting to the font_options struct. * src/xsettings.c (init_gsettings): Invoke the apply functions when initializing from gsettings. * src/xsettings.c (something_changed_gsettingsCB): Invoke the apply functions if the relevant gsettings changed. * src/xsettings.c (store_font_options_changed): Store an event to re-render the fonts. --- src/ftcrfont.c | 32 ++++++++++ src/xsettings.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++ src/xsettings.h | 4 ++ 3 files changed, 187 insertions(+) diff --git a/src/ftcrfont.c b/src/ftcrfont.c index 98a28af5f2..103da93d51 100644 --- a/src/ftcrfont.c +++ b/src/ftcrfont.c @@ -37,6 +37,9 @@ #include "font.h" #include "ftfont.h" #include "pdumper.h" +#ifdef HAVE_PGTK +#include "xsettings.h" +#endif #ifdef USE_BE_CAIRO #define RED_FROM_ULONG(color) (((color) >> 16) & 0xff) @@ -168,7 +171,12 @@ 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); + +#ifdef HAVE_PGTK + cairo_font_options_t *options = xsettings_get_font_options (); +#else cairo_font_options_t *options = cairo_font_options_create (); +#endif #ifdef USE_BE_CAIRO if (be_use_subpixel_antialiasing ()) cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_SUBPIXEL); @@ -624,6 +632,27 @@ ftcrfont_draw (struct glyph_string *s, return len; } +#ifdef HAVE_PGTK +/* Determine if the cached font should be re-opened, by comparing + its font_options with the ones derived from gsettings. */ +static bool +ftcrfont_cached_font_ok (struct frame *f, Lisp_Object font_object, + Lisp_Object entity) +{ + struct font_info *info = (struct font_info *) XFONT_OBJECT (font_object); + + cairo_font_options_t *options = cairo_font_options_create (); + cairo_scaled_font_get_font_options (info->cr_scaled_font, options); + cairo_font_options_t *gsettings_options = xsettings_get_font_options (); + + bool equal = cairo_font_options_equal (options, gsettings_options); + cairo_font_options_destroy (options); + cairo_font_options_destroy (gsettings_options); + + return equal; +} +#endif + #ifdef HAVE_HARFBUZZ static Lisp_Object @@ -694,6 +723,9 @@ ftcrhbfont_end_hb_font (struct font *font, hb_font_t *hb_font) #endif .filter_properties = ftfont_filter_properties, .combining_capability = ftfont_combining_capability, +#ifdef HAVE_PGTK + .cached_font_ok = ftcrfont_cached_font_ok +#endif }; #ifdef HAVE_HARFBUZZ struct font_driver ftcrhbfont_driver; diff --git a/src/xsettings.c b/src/xsettings.c index 71d02e6152..2538ab51b3 100644 --- a/src/xsettings.c +++ b/src/xsettings.c @@ -215,11 +215,118 @@ #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; +#ifdef HAVE_PGTK + +/* The cairo font_options as obtained using gsettings. */ +static cairo_font_options_t *font_options; + +/* Store an event for re-rendering of the fonts. */ +static void +store_font_options_changed (void) +{ + if (dpyinfo_valid (first_dpyinfo)) + { + store_config_changed_event (Qfont_render, + XCAR (first_dpyinfo->name_list_element)); + } +} + +/* 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")) + cairo_font_options_set_hint_style (font_options, + CAIRO_HINT_STYLE_FULL); + else if (!strcmp (hinting, "medium")) + cairo_font_options_set_hint_style (font_options, + CAIRO_HINT_STYLE_MEDIUM); + else if (!strcmp (hinting, "slight")) + cairo_font_options_set_hint_style (font_options, + CAIRO_HINT_STYLE_SLIGHT); + else if (!strcmp (hinting, "none")) + 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")) + cairo_font_options_set_antialias (font_options, + CAIRO_ANTIALIAS_NONE); + else if (!strcmp (antialias, "grayscale")) + cairo_font_options_set_antialias (font_options, + CAIRO_ANTIALIAS_GRAY); + else if (!strcmp (antialias, "rgba")) + 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")) + cairo_font_options_set_subpixel_order (font_options, + CAIRO_SUBPIXEL_ORDER_RGB); + else if (!strcmp (rgba_order, "bgr")) + cairo_font_options_set_subpixel_order (font_options, + CAIRO_SUBPIXEL_ORDER_BGR); + else if (!strcmp (rgba_order, "vrgb")) + cairo_font_options_set_subpixel_order (font_options, + CAIRO_SUBPIXEL_ORDER_VRGB); + else if (!strcmp (rgba_order, "vbgr")) + 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 @@ -273,6 +380,23 @@ something_changed_gsettingsCB (GSettings *settings, } } #endif /* USE_CAIRO || HAVE_XFT */ +#ifdef HAVE_PGTK + else if (strcmp (key, GSETTINGS_FONT_ANTIALIASING) == 0) + { + apply_gsettings_font_antialias (settings); + store_font_options_changed (); + } + else if (strcmp (key, GSETTINGS_FONT_HINTING) == 0) + { + apply_gsettings_font_hinting (settings); + store_font_options_changed (); + } + else if (strcmp (key, GSETTINGS_FONT_RGBA_ORDER) == 0) + { + apply_gsettings_font_rgba_order (settings); + store_font_options_changed (); + } +#endif /* HAVE_PGTK */ } #endif /* HAVE_GSETTINGS */ @@ -900,6 +1024,18 @@ init_gsettings (void) dupstring (¤t_font, g_variant_get_string (val, NULL)); g_variant_unref (val); } + + /* Only use the gsettings font entries for non-X11 cairo backends + (which is the recommended way of running pgtk builds). + For the X11 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 +1157,17 @@ xsettings_get_system_normal_font (void) } #endif +#ifdef HAVE_PGTK +/* Return the cairo font options, updated from the gsettings font + config entries. The caller should call cairo_font_options_destroy + on the result. */ +cairo_font_options_t * +xsettings_get_font_options (void) +{ + 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 +1220,10 @@ syms_of_xsettings (void) gconf_client = NULL; PDUMPER_IGNORE (gconf_client); #endif +#ifdef HAVE_PGTK + 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..c7fe861c40 100644 --- a/src/xsettings.h +++ b/src/xsettings.h @@ -41,5 +41,9 @@ #define XSETTINGS_H extern const char *xsettings_get_system_normal_font (void); #endif +#ifdef HAVE_PGTK +#include +extern cairo_font_options_t *xsettings_get_font_options (void); +#endif #endif /* XSETTINGS_H */ -- 2.32.0