Subject: bug#43058: 27.1; Support for other colour font formats

From: YAMAMOTO Mitsuharu <[email-masked]>
Date: Thu, 22 Sep 2022 11:45:02 +0900

On Thu, 27 Aug 2020 00:12:06 +0900,
Peter Oliver wrote:
> 
> Observation:
> 
> First I grabbed a COLR TTF (e.g., https://github.com/hfg-gmuend/openmoji/raw/47c9efe5449ba2ef77b77cdcae28b00811dea843/font/untouchedsvgz/OpenMoji-Color.ttf) and saved it to ~/.local/share/fonts/.  Then:
> 
> ELISP> (x-list-fonts "OpenMoji Color")
> ("-NONE-OpenMoji Color-normal-normal-normal-*-*-*-*-*-m-0-iso10646-1")
> ELISP> (font-info (car (x-list-fonts "OpenMoji Color")))
> nil
> 
> This makes me suspect that the problem isn’t with outputting with the font, but in finding the font in the first place.  I’m not sure how to go about debugging this.

The above font does not have the 'COLR' table, but the 'SVG ' one.  So
I think it is an SVG-in-OpenType font.

This font is rejected by the ftcr(hb) font backend because its average
width is computed as 0.  The average width is approximated by that of
all ASCII chars, and the width of glyph ID 0 is used for missing ones.
OpenMoji Color does not have several ASCII chars, and the width of
glyph ID 0 is 0.  That's why the average width becomes 0 there.

The patch below avoids this by taking the average of non-zero width of
the ASCII chars.  But glyphs are not displayed because SVG-in-OpenType
support in cairo is still in progress:
https://gitlab.freedesktop.org/cairo/cairo/-/merge_requests/319

				     YAMAMOTO Mitsuharu
				[email-masked]

diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index e089f9dea8..9e83ad00d4 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -233,6 +233,7 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
   cairo_glyph_t stack_glyph;
   font->min_width = font->max_width = 0;
   font->average_width = font->space_width = 0;
+  int n = 0;
   for (char c = 32; c < 127; c++)
     {
       cairo_glyph_t *glyphs = &stack_glyph;
@@ -252,17 +253,20 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
 	  stack_glyph.index = 0;
 	}
       int this_width = ftcrfont_glyph_extents (font, stack_glyph.index, NULL);
-      if (this_width > 0
-	  && (! font->min_width
-	      || font->min_width > this_width))
-	font->min_width = this_width;
-      if (this_width > font->max_width)
-	font->max_width = this_width;
-      if (c == 32)
-	font->space_width = this_width;
-      font->average_width += this_width;
+      if (this_width > 0)
+	{
+	  if (! font->min_width || font->min_width > this_width)
+	    font->min_width = this_width;
+	  if (this_width > font->max_width)
+	    font->max_width = this_width;
+	  if (c == 32)
+	    font->space_width = this_width;
+	  font->average_width += this_width;
+	  n++;
+	}
     }
-  font->average_width /= 95;
+  if (n)
+    font->average_width /= n;
 
   cairo_scaled_font_extents (ftcrfont_info->cr_scaled_font, &extents);
   font->ascent = lround (extents.ascent);