Subject: Respects Fontconfig settings for ftcr and ftcrhb font backends

From: Mike <[email-masked]>
Date: Thu, 24 Jul 2025 21:12:36 -0400

Tags: patch

The ftcr and ftcrhb backends use cairo to render fonts, but cairo does
not respect font specific fontconfig settings. This patch queries
fontconfig with the specific font, and then it translates the fontconfig
settings into cairo font settings.

Both backends would also ignore :hinting and :autohint properties from
the font-spec. This patch fixes that too.

In GNU Emacs 30.1 (build 1, x86_64-redhat-linux-gnu) of 2025-05-25 built
 on 02c108121fcd
System Description: Oracle Linux Server 9.4

Configured using:
 'configure --without-all --without-x --without-ns
 --with-compress-install --with-modules --with-sqlite3=yes
 --with-zlib=yes --with-threads=yes --with-modules=yes
 --with-file-notification=inotify
 --srcdir=/ports/editors/emacs30-nox11/work/emacs-30.1
 --localstatedir=/pkg/var --disable-autodepend --prefix=/pkg
 --build=x86_64-redhat-linux --host=x86_64-redhat-linux
 --infodir=/pkg/info --mandir=/pkg/man --enable-option-checking=yes
 'CFLAGS=-O2 -O3 -march=ivybridge -I/usr/include -I/pkg/include'
 'CPPFLAGS=-I/usr/include -I/pkg/include'
 'LDFLAGS=-L/pkg/gcc14/lib/gcc/x86_64-redhat-linux/14.2.0
 -Wl,-R/pkg/gcc14/lib/gcc/x86_64-redhat-linux/14.2.0 -L/pkg/gcc14/lib64
 -Wl,-R/pkg/gcc14/lib64 -L/usr/lib64 -Wl,-R/usr/lib64 -L/pkg/lib
 -Wl,-R/pkg/lib''

-- 
Thanks
Mike
diff -ur emacs-30.1.orig/src/ftcrfont.c emacs-30.1/src/ftcrfont.c
--- emacs-30.1.orig/src/ftcrfont.c	2025-02-18 13:31:36.000000000 -0500
+++ emacs-30.1/src/ftcrfont.c	2025-07-24 20:51:23.985418024 -0400
@@ -128,12 +128,48 @@
   return ftfont_match2 (f, spec, Qftcr);
 }
 
+/* Older Fontconfig versions don't have these macros. */
+
+#ifndef FC_HINT_STYLE
+# define FC_HINT_STYLE "hintstyle"
+#endif
+
+#ifndef FC_LCD_FILTER
+#define FC_LCD_FILTER "lcdfilter"
+#endif
+
+static void
+ftcrfont_init_options(FcPattern *match, cairo_font_options_t *options)
+{
+  FcBool b = FcTrue;
+  if (FcResultMatch == FcPatternGetBool (match, FC_HINTING, 0, &b))
+    {
+      // hintfull by default.
+      int hintstyle = 3;
+      FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hintstyle);
+      // CAIRO_HINT_STYLE_NONE starts at 1.
+      cairo_font_options_set_hint_style (options, hintstyle + 1);
+    }
+  int rgba = 0;
+  if (FcResultMatch == FcPatternGetBool (match, FC_RGBA, 0, &rgba))
+    cairo_font_options_set_subpixel_order (options, rgba);
+
+  if (FcResultMatch == FcPatternGetBool (match, FC_ANTIALIAS, 0, &b))
+    {
+      int lcdfilter = 0;
+      if (FcResultMatch == FcPatternGetInteger (match, FC_LCD_FILTER, 0, &lcdfilter) && lcdfilter)
+        cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_SUBPIXEL);
+      else
+        cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_DEFAULT);
+    }
+}
+
 static Lisp_Object
 ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
 {
   FcResult result;
   Lisp_Object val, filename, font_object;
-  FcPattern *pat, *match;
+  FcPattern *pat, *spat, *match;
   struct font_info *ftcrfont_info;
   struct font *font;
   double size = 0;
@@ -154,11 +190,15 @@
   block_input ();
 
   pat = ftfont_entity_pattern (entity, pixel_size);
-  FcConfigSubstitute (NULL, pat, FcMatchPattern);
-  FcDefaultSubstitute (pat);
-  match = FcFontMatch (NULL, pat, &result);
+  spat = FcPatternDuplicate (pat);
+  FcConfigSubstitute (NULL, spat, FcMatchPattern);
+  FcDefaultSubstitute (spat);
+  match = FcFontMatch (NULL, spat, &result);
   ftfont_fix_match (pat, match);
 
+  FcPatternPrint (match);
+
+  FcPatternDestroy (spat);
   FcPatternDestroy (pat);
   font_face = cairo_ft_font_face_create_for_pattern (match);
   if (!font_face
@@ -181,6 +221,9 @@
   if (be_use_subpixel_antialiasing ())
     cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_SUBPIXEL);
 #endif
+
+  ftcrfont_init_options (match, options);
+
   cairo_scaled_font_t *scaled_font
     = cairo_scaled_font_create (font_face, &font_matrix, &ctm, options);
   cairo_font_face_destroy (font_face);
diff -ur emacs-30.1.orig/src/ftfont.c emacs-30.1/src/ftfont.c
--- emacs-30.1.orig/src/ftfont.c	2025-02-17 17:38:58.000000000 -0500
+++ emacs-30.1/src/ftfont.c	2025-07-24 20:46:20.942317098 -0400
@@ -1213,17 +1213,16 @@
   int i;
   double dpi;
 
-  FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
-  if (! b)
+  if (FcResultMatch == FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b))
     {
       FcPatternDel (match, FC_ANTIALIAS);
-      FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
+      FcPatternAddBool (match, FC_ANTIALIAS, b);
     }
-  FcPatternGetBool (pat, FC_HINTING, 0, &b);
-  if (! b)
+
+  if (FcResultMatch == FcPatternGetBool (pat, FC_HINTING, 0, &b))
     {
       FcPatternDel (match, FC_HINTING);
-      FcPatternAddBool (match, FC_HINTING, FcFalse);
+      FcPatternAddBool (match, FC_HINTING, b);
     }
 #ifndef FC_HINT_STYLE
 # define FC_HINT_STYLE "hintstyle"