unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: mituharu@math.s.chiba-u.ac.jp
To: "Alex Gramiak" <agrambot@gmail.com>
Cc: 35781@debbugs.gnu.org, K?vin Le Gouguec <kevin.legouguec@gmail.com>
Subject: bug#35781: Discrepancies between xftfont.c and ftcrfont.c
Date: Tue, 21 May 2019 19:59:55 +0900	[thread overview]
Message-ID: <03f91c3a5f9c7d823e2d6d9c8dfc7b60.squirrel@weber.math.s.chiba-u.ac.jp> (raw)
In-Reply-To: <87v9y66x9q.fsf@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 317 bytes --]

> Perhaps ftcrfont.c could use FcPatternAddFTFace, FcFontMatch,
> cairo_ft_font_face_create_for_pattern, and otherwise the same pattern
> building as xftfont.c.

I tried making ftcrfont_open look much like xftfont_open.
Could you try the attached patch?

				     YAMAMOTO Mitsuharu
				mituharu@math.s.chiba-u.ac.jp

[-- Attachment #2: xft-like-ftcr.diff --]
[-- Type: application/octet-stream, Size: 29309 bytes --]

diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 2d5a7665578..7a08961847c 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -79,7 +79,6 @@ ftcrfont_glyph_extents (struct font *font,
       cairo_glyph_t cr_glyph = {.index = glyph};
       cairo_text_extents_t extents;
 
-      FT_Activate_Size (ftcrfont_info->ft_size_draw);
       cairo_scaled_font_glyph_extents (ftcrfont_info->cr_scaled_font,
 				       &cr_glyph, 1, &extents);
       cache->lbearing = floor (extents.x_bearing);
@@ -118,103 +117,154 @@ ftcrfont_match (struct frame *f, Lisp_Object spec)
 static Lisp_Object
 ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
 {
-  Lisp_Object font_object;
-
-  FT_UInt size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
+  FcResult result;
+  Lisp_Object val, filename, font_object;
+  FcPattern *pat, *match;
+  struct font_info *ftcrfont_info;
+  struct font *font;
+  double size = 0;
+  cairo_font_face_t *font_face;
+  cairo_font_extents_t extents;
+  FT_Face ft_face;
+  FcMatrix *matrix;
+
+  val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
+  if (! CONSP (val))
+    return Qnil;
+  val = XCDR (val);
+  filename = XCAR (val);
+  size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
   if (size == 0)
     size = pixel_size;
+
+  block_input ();
+
+  pat = ftfont_entity_pattern (entity, pixel_size);
+  FcConfigSubstitute (NULL, pat, FcMatchPattern);
+  FcDefaultSubstitute (pat);
+  match = FcFontMatch (NULL, pat, &result);
+  ftfont_fix_match (pat, match);
+
+  FcPatternDestroy (pat);
+  font_face = cairo_ft_font_face_create_for_pattern (match);
+  if (!font_face)
+    {
+      unblock_input ();
+      FcPatternDestroy (match);
+      return Qnil;
+    }
+  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 ();
+  cairo_scaled_font_t *scaled_font
+    = cairo_scaled_font_create (font_face, &font_matrix, &ctm, options);
+  cairo_font_face_destroy (font_face);
+  cairo_font_options_destroy (options);
+  ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
+  unblock_input ();
+
   font_object = font_build_object (VECSIZE (struct font_info),
 				   Qftcr, entity, size);
+  ASET (font_object, FONT_FILE_INDEX, filename);
+  font = XFONT_OBJECT (font_object);
+  font->pixel_size = size;
+  font->driver = &ftcrfont_driver;
+  font->encoding_charset = font->repertory_charset = -1;
+
+  ftcrfont_info = (struct font_info *) font;
+  ftcrfont_info->cr_scaled_font = scaled_font;
+
+  /* This means that there's no need of transformation.  */
+  ftcrfont_info->matrix.xx = 0;
+  if (FcPatternGetMatrix (match, FC_MATRIX, 0, &matrix) == FcResultMatch)
+    {
+      ftcrfont_info->matrix.xx = 0x10000L * matrix->xx;
+      ftcrfont_info->matrix.yy = 0x10000L * matrix->yy;
+      ftcrfont_info->matrix.xy = 0x10000L * matrix->xy;
+      ftcrfont_info->matrix.yx = 0x10000L * matrix->yx;
+    }
+
+  ftcrfont_info->metrics = NULL;
+  ftcrfont_info->metrics_nrows = 0;
+
   block_input ();
-  font_object = ftfont_open2 (f, entity, pixel_size, font_object);
-  if (FONT_OBJECT_P (font_object))
+  cairo_glyph_t stack_glyph;
+  int n = 0;
+  font->min_width = font->average_width = font->space_width = 0;
+  for (char c = 32; c < 127; c++)
     {
-      struct font *font = XFONT_OBJECT (font_object);
-      struct font_info *ftcrfont_info = (struct font_info *) font;
-      FT_Face ft_face = ftcrfont_info->ft_size->face;
-
-      font->driver = &ftcrfont_driver;
-      FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw);
-      FT_Activate_Size (ftcrfont_info->ft_size_draw);
-      if (ftcrfont_info->bitmap_strike_index < 0)
-	FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size);
-      else
-	FT_Select_Size (ft_face, ftcrfont_info->bitmap_strike_index);
-      cairo_font_face_t *font_face =
-	cairo_ft_font_face_create_for_ft_face (ft_face, 0);
-      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 ();
-      ftcrfont_info->cr_scaled_font =
-	cairo_scaled_font_create (font_face, &font_matrix, &ctm, options);
-      cairo_font_face_destroy (font_face);
-      cairo_font_options_destroy (options);
-      ftcrfont_info->metrics = NULL;
-      ftcrfont_info->metrics_nrows = 0;
-      if (ftcrfont_info->bitmap_strike_index >= 0)
+      cairo_glyph_t *glyphs = &stack_glyph;
+      int num_glyphs = 1;
+      cairo_status_t status =
+	cairo_scaled_font_text_to_glyphs (ftcrfont_info->cr_scaled_font,
+					  0, 0, &c, 1, &glyphs, &num_glyphs,
+					  NULL, NULL, NULL);
+
+      if (status == CAIRO_STATUS_SUCCESS)
 	{
-	  /* Several members of struct font/font_info set by
-	     ftfont_open2 are bogus.  Recalculate them with cairo
-	     scaled font functions.  */
-	  cairo_font_extents_t extents;
-	  cairo_scaled_font_extents (ftcrfont_info->cr_scaled_font, &extents);
-	  font->ascent = lround (extents.ascent);
-	  Lisp_Object val = assq_no_quit (QCminspace,
-					  AREF (entity, FONT_EXTRA_INDEX));
-	  if (!(CONSP (val) && NILP (XCDR (val))))
+	  if (glyphs != &stack_glyph)
+	    cairo_glyph_free (glyphs);
+	  else if (stack_glyph.index)
 	    {
-	      font->descent = lround (extents.descent);
-	      font->height = font->ascent + font->descent;
-	    }
-	  else
-	    {
-	      font->height = lround (extents.height);
-	      font->descent = font->height - font->ascent;
+	      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 (c == 32)
+		font->space_width = this_width;
+	      font->average_width += this_width;
+	      n++;
 	    }
+	}
+    }
+  if (n > 0)
+    font->average_width /= n;
 
-	  cairo_glyph_t stack_glyph;
-	  int n = 0;
-	  font->min_width = font->average_width = font->space_width = 0;
-	  for (char c = 32; c < 127; c++)
-	    {
-	      cairo_glyph_t *glyphs = &stack_glyph;
-	      int num_glyphs = 1;
-	      cairo_status_t status =
-		cairo_scaled_font_text_to_glyphs (ftcrfont_info->cr_scaled_font,
-						  0, 0, &c, 1,
-						  &glyphs, &num_glyphs,
-						  NULL, NULL, NULL);
-
-	      if (status == CAIRO_STATUS_SUCCESS)
-		{
-		  if (glyphs != &stack_glyph)
-		    cairo_glyph_free (glyphs);
-		  else if (stack_glyph.index)
-		    {
-		      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 (c == 32)
-			font->space_width = this_width;
-		      font->average_width += this_width;
-		      n++;
-		    }
-		}
-	    }
-	  if (n > 0)
-	    font->average_width /= n;
+  cairo_scaled_font_extents (ftcrfont_info->cr_scaled_font, &extents);
+  font->ascent = lround (extents.ascent);
+  val = assq_no_quit (QCminspace, AREF (entity, FONT_EXTRA_INDEX));
+  if (!(CONSP (val) && NILP (XCDR (val))))
+    {
+      font->descent = lround (extents.descent);
+      font->height = font->ascent + font->descent;
+    }
+  else
+    {
+      font->height = lround (extents.height);
+      font->descent = font->height - font->ascent;
+    }
 
-	  font->underline_position = -1;
-	  font->underline_thickness = 0;
-	}
+  if (XFIXNUM (AREF (entity, FONT_SIZE_INDEX)) == 0)
+    {
+      int upEM = ft_face->units_per_EM;
+
+      font->underline_position = -ft_face->underline_position * size / upEM;
+      font->underline_thickness = ft_face->underline_thickness * size / upEM;
+      if (font->underline_thickness > 2)
+	font->underline_position -= font->underline_thickness / 2;
+    }
+  else
+    {
+      font->underline_position = -1;
+      font->underline_thickness = 0;
     }
+#ifdef HAVE_LIBOTF
+  ftcrfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
+  ftcrfont_info->otf = NULL;
+#endif	/* HAVE_LIBOTF */
+  cairo_ft_scaled_font_unlock_face (scaled_font);
+  ftcrfont_info->ft_size = NULL;
   unblock_input ();
 
+  font->baseline_offset = 0;
+  font->relative_compose = 0;
+  font->default_ascent = 0;
+  font->vertical_centering = false;
+
   return font_object;
 }
 
@@ -225,19 +275,58 @@ ftcrfont_close (struct font *font)
     return;
 
   struct font_info *ftcrfont_info = (struct font_info *) font;
-  int i;
 
   block_input ();
-  for (i = 0; i < ftcrfont_info->metrics_nrows; i++)
+#ifdef HAVE_LIBOTF
+  if (ftcrfont_info->otf)
+    {
+      OTF_close (ftcrfont_info->otf);
+      ftcrfont_info->otf = NULL;
+    }
+#endif
+  for (int i = 0; i < ftcrfont_info->metrics_nrows; i++)
     if (ftcrfont_info->metrics[i])
       xfree (ftcrfont_info->metrics[i]);
   if (ftcrfont_info->metrics)
     xfree (ftcrfont_info->metrics);
-  FT_Done_Size (ftcrfont_info->ft_size_draw);
   cairo_scaled_font_destroy (ftcrfont_info->cr_scaled_font);
   unblock_input ();
+}
 
-  ftfont_close (font);
+static int
+ftcrfont_has_char (Lisp_Object font, int c)
+{
+  if (FONT_ENTITY_P (font))
+    return ftfont_has_char (font, c);
+
+  return -1;
+}
+
+static unsigned
+ftcrfont_encode_char (struct font *font, int c)
+{
+  struct font_info *ftcrfont_info = (struct font_info *) font;
+  unsigned code = FONT_INVALID_CODE;
+  unsigned char utf8[MAX_MULTIBYTE_LENGTH];
+  unsigned char *p = utf8;
+  cairo_glyph_t stack_glyph;
+  cairo_glyph_t *glyphs = &stack_glyph;
+  int num_glyphs = 1;
+
+  CHAR_STRING_ADVANCE (c, p);
+  if (cairo_scaled_font_text_to_glyphs (ftcrfont_info->cr_scaled_font, 0, 0,
+					(char *) utf8, p - utf8,
+					&glyphs, &num_glyphs,
+					NULL, NULL, NULL)
+      == CAIRO_STATUS_SUCCESS)
+    {
+      if (glyphs != &stack_glyph)
+	cairo_glyph_free (glyphs);
+      else if (stack_glyph.index)
+	code = stack_glyph.index;
+    }
+
+  return code;
 }
 
 static void
@@ -279,11 +368,15 @@ ftcrfont_get_bitmap (struct font *font, unsigned int code,
 		     struct font_bitmap *bitmap, int bits_per_pixel)
 {
   struct font_info *ftcrfont_info = (struct font_info *) font;
+  cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font;
+  FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
 
-  if (ftcrfont_info->bitmap_strike_index < 0)
-    return ftfont_get_bitmap (font, code, bitmap, bits_per_pixel);
+  ftcrfont_info->ft_size = ft_face->size;
+  int result = ftfont_get_bitmap (font, code, bitmap, bits_per_pixel);
+  cairo_ft_scaled_font_unlock_face (scaled_font);
+  ftcrfont_info->ft_size = NULL;
 
-  return -1;
+  return result;
 }
 
 static int
@@ -291,26 +384,69 @@ ftcrfont_anchor_point (struct font *font, unsigned int code, int idx,
 		       int *x, int *y)
 {
   struct font_info *ftcrfont_info = (struct font_info *) font;
+  cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font;
+  FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
 
-  if (ftcrfont_info->bitmap_strike_index < 0)
-    return ftfont_anchor_point (font, code, idx, x, y);
+  ftcrfont_info->ft_size = ft_face->size;
+  int result = ftfont_anchor_point (font, code, idx, x, y);
+  cairo_ft_scaled_font_unlock_face (scaled_font);
+  ftcrfont_info->ft_size = NULL;
 
-  return -1;
+  return result;
 }
 
+#ifdef HAVE_LIBOTF
 static Lisp_Object
-ftcrfont_shape (Lisp_Object lgstring)
+ftcrfont_otf_capability (struct font *font)
 {
+  struct font_info *ftcrfont_info = (struct font_info *) font;
+  cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font;
+  FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
+
+  ftcrfont_info->ft_size = ft_face->size;
+  Lisp_Object result = ftfont_otf_capability (font);
+  cairo_ft_scaled_font_unlock_face (scaled_font);
+  ftcrfont_info->ft_size = NULL;
+
+  return result;
+}
+#endif
+
 #if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
+static Lisp_Object
+ftcrfont_shape (Lisp_Object lgstring)
+{
   struct font *font = CHECK_FONT_GET_OBJECT (LGSTRING_FONT (lgstring));
   struct font_info *ftcrfont_info = (struct font_info *) font;
 
-  if (ftcrfont_info->bitmap_strike_index < 0)
-    return ftfont_shape (lgstring);
+  cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font;
+  FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
+
+  ftcrfont_info->ft_size = ft_face->size;
+  Lisp_Object result = ftfont_shape (lgstring);
+  cairo_ft_scaled_font_unlock_face (scaled_font);
+  ftcrfont_info->ft_size = NULL;
+
+  return result;
+}
 #endif
 
-  return make_fixnum (0);
+#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
+static int
+ftcrfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
+{
+  struct font_info *ftcrfont_info = (struct font_info *) font;
+  cairo_scaled_font_t *scaled_font = ftcrfont_info->cr_scaled_font;
+  FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
+
+  ftcrfont_info->ft_size = ft_face->size;
+  int result = ftfont_variation_glyphs (font, c, variations);
+  cairo_ft_scaled_font_unlock_face (scaled_font);
+  ftcrfont_info->ft_size = NULL;
+
+  return result;
 }
+#endif	/* HAVE_OTF_GET_VARIATION_GLYPHS */
 
 static int
 ftcrfont_draw (struct glyph_string *s,
@@ -321,8 +457,6 @@ ftcrfont_draw (struct glyph_string *s,
   struct font_info *ftcrfont_info = (struct font_info *) s->font;
   cairo_t *cr;
   cairo_glyph_t *glyphs;
-  cairo_surface_t *surface;
-  cairo_surface_type_t surface_type;
   int len = to - from;
   int i;
 
@@ -351,17 +485,7 @@ ftcrfont_draw (struct glyph_string *s,
 
   x_set_cr_source_with_gc_foreground (f, s->gc);
   cairo_set_scaled_font (cr, ftcrfont_info->cr_scaled_font);
-
-  FT_Activate_Size (ftcrfont_info->ft_size_draw);
   cairo_show_glyphs (cr, glyphs, len);
-  surface = cairo_get_target (cr);
-  /* XXX: It used to be necessary to flush when exporting.  It might
-     be the case that this is no longer necessary.  */
-  surface_type = cairo_surface_get_type (surface);
-  if (surface_type != CAIRO_SURFACE_TYPE_XLIB
-      && (surface_type != CAIRO_SURFACE_TYPE_IMAGE
-	  || cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32))
-    cairo_surface_flush (surface);
 
   x_end_cr_clip (f);
 
@@ -383,18 +507,20 @@ struct font_driver const ftcrfont_driver =
   .list_family = ftfont_list_family,
   .open = ftcrfont_open,
   .close = ftcrfont_close,
-  .has_char = ftfont_has_char,
-  .encode_char = ftfont_encode_char,
+  .has_char = ftcrfont_has_char,
+  .encode_char = ftcrfont_encode_char,
   .text_extents = ftcrfont_text_extents,
   .draw = ftcrfont_draw,
   .get_bitmap = ftcrfont_get_bitmap,
   .anchor_point = ftcrfont_anchor_point,
 #ifdef HAVE_LIBOTF
-  .otf_capability = ftfont_otf_capability,
+  .otf_capability = ftcrfont_otf_capability,
 #endif
+#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
   .shape = ftcrfont_shape,
+#endif
 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
-  .get_variation_glyphs = ftfont_variation_glyphs,
+  .get_variation_glyphs = ftcrfont_variation_glyphs,
 #endif
   .filter_properties = ftfont_filter_properties,
   .combining_capability = ftfont_combining_capability,
diff --git a/src/ftfont.c b/src/ftfont.c
index f17bd9ab3f7..639cc6c132e 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -1079,6 +1079,156 @@ ftfont_list_family (struct frame *f)
   return list;
 }
 
+void
+ftfont_fix_match (FcPattern *pat, FcPattern *match)
+{
+  /*  These values are not used for matching (except antialias), but for
+      rendering, so make sure they are carried over to the match.
+      We also put antialias here because most fonts are antialiased, so
+      the match will have antialias true.  */
+
+  FcBool b = FcTrue;
+  int i;
+  double dpi;
+
+  FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
+  if (! b)
+    {
+      FcPatternDel (match, FC_ANTIALIAS);
+      FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
+    }
+  FcPatternGetBool (pat, FC_HINTING, 0, &b);
+  if (! b)
+    {
+      FcPatternDel (match, FC_HINTING);
+      FcPatternAddBool (match, FC_HINTING, FcFalse);
+    }
+#ifndef FC_HINT_STYLE
+# define FC_HINT_STYLE "hintstyle"
+#endif
+  if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
+    {
+      FcPatternDel (match, FC_HINT_STYLE);
+      FcPatternAddInteger (match, FC_HINT_STYLE, i);
+    }
+#ifndef FC_LCD_FILTER
+  /* Older fontconfig versions don't have FC_LCD_FILTER. */
+#define FC_LCD_FILTER "lcdfilter"
+#endif
+  if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
+    {
+      FcPatternDel (match, FC_LCD_FILTER);
+      FcPatternAddInteger (match, FC_LCD_FILTER, i);
+    }
+  if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
+    {
+      FcPatternDel (match, FC_RGBA);
+      FcPatternAddInteger (match, FC_RGBA, i);
+    }
+  if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
+    {
+      FcPatternDel (match, FC_DPI);
+      FcPatternAddDouble (match, FC_DPI, dpi);
+    }
+}
+
+static void
+ftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
+{
+  Lisp_Object tail;
+  int ival;
+
+  for (tail = AREF (entity, FONT_EXTRA_INDEX); CONSP (tail); tail = XCDR (tail))
+    {
+      Lisp_Object key = XCAR (XCAR (tail));
+      Lisp_Object val = XCDR (XCAR (tail));
+
+      if (EQ (key, QCantialias))
+          FcPatternAddBool (pat, FC_ANTIALIAS, NILP (val) ? FcFalse : FcTrue);
+      else if (EQ (key, QChinting))
+	FcPatternAddBool (pat, FC_HINTING, NILP (val) ? FcFalse : FcTrue);
+      else if (EQ (key, QCautohint))
+	FcPatternAddBool (pat, FC_AUTOHINT, NILP (val) ? FcFalse : FcTrue);
+      else if (EQ (key, QChintstyle))
+	{
+	  if (FIXNUMP (val))
+	    FcPatternAddInteger (pat, FC_HINT_STYLE, XFIXNUM (val));
+          else if (SYMBOLP (val)
+                   && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
+	    FcPatternAddInteger (pat, FC_HINT_STYLE, ival);
+	}
+      else if (EQ (key, QCrgba))
+	{
+	  if (FIXNUMP (val))
+	    FcPatternAddInteger (pat, FC_RGBA, XFIXNUM (val));
+          else if (SYMBOLP (val)
+                   && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
+	    FcPatternAddInteger (pat, FC_RGBA, ival);
+	}
+      else if (EQ (key, QClcdfilter))
+	{
+	  if (FIXNUMP (val))
+	    FcPatternAddInteger (pat, FC_LCD_FILTER, ival = XFIXNUM (val));
+          else if (SYMBOLP (val)
+                   && FcNameConstant (SDATA (SYMBOL_NAME (val)), &ival))
+	    FcPatternAddInteger (pat, FC_LCD_FILTER, ival);
+	}
+#ifdef FC_EMBOLDEN
+      else if (EQ (key, QCembolden))
+	FcPatternAddBool (pat, FC_EMBOLDEN, NILP (val) ? FcFalse : FcTrue);
+#endif
+    }
+}
+
+FcPattern *
+ftfont_entity_pattern (Lisp_Object entity, int pixel_size)
+{
+  Lisp_Object val, filename, idx;
+  FcPattern *pat;
+  int i;
+
+  val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
+  eassert (CONSP (val));
+  val = XCDR (val);
+  filename = XCAR (val);
+  idx = XCDR (val);
+  pat = FcPatternCreate ();
+  FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
+  i = FONT_SLANT_NUMERIC (entity) - 100;
+  if (i < 0) i = 0;
+  FcPatternAddInteger (pat, FC_SLANT, i);
+  FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
+  FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
+  val = AREF (entity, FONT_FAMILY_INDEX);
+  if (! NILP (val))
+    FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
+  val = AREF (entity, FONT_FOUNDRY_INDEX);
+  if (! NILP (val))
+    FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
+  val = AREF (entity, FONT_SPACING_INDEX);
+  if (! NILP (val))
+    FcPatternAddInteger (pat, FC_SPACING, XFIXNUM (val));
+  val = AREF (entity, FONT_DPI_INDEX);
+  if (! NILP (val))
+    {
+      double dbl = XFIXNUM (val);
+
+      FcPatternAddDouble (pat, FC_DPI, dbl);
+    }
+  val = AREF (entity, FONT_AVGWIDTH_INDEX);
+  if (FIXNUMP (val) && XFIXNUM (val) == 0)
+    FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
+  /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
+     over 10x20-ISO8859-1.pcf.gz).  */
+  FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
+
+  ftfont_add_rendering_parameters (pat, entity);
+
+  FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
+  FcPatternAddInteger (pat, FC_INDEX, XFIXNUM (idx));
+
+  return pat;
+}
 
 Lisp_Object
 ftfont_open2 (struct frame *f,
@@ -1097,7 +1247,6 @@ ftfont_open2 (struct frame *f,
   int spacing;
   int i;
   double upEM;
-  FT_Int strike_index = -1;
 
   val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
   if (! CONSP (val))
@@ -1126,32 +1275,12 @@ ftfont_open2 (struct frame *f,
     size = pixel_size;
   if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
     {
-      int min_distance = INT_MAX;
-      bool magnify = true;
-
-      for (FT_Int i = 0; i < ft_face->num_fixed_sizes; i++)
-	{
-	  int distance = ft_face->available_sizes[i].height - (int) size;
-
-	  /* Prefer down-scaling to upscaling.  */
-	  if (magnify == (distance < 0) ? abs (distance) <= min_distance
-	      : magnify)
-	    {
-	      magnify = distance < 0;
-	      min_distance = abs (distance);
-	      strike_index = i;
-	    }
-	}
-
-      if (strike_index < 0 || FT_Select_Size (ft_face, strike_index) != 0)
+      if (cache_data->face_refcount == 0)
 	{
-	  if (cache_data->face_refcount == 0)
-	    {
-	      FT_Done_Face (ft_face);
-	      cache_data->ft_face = NULL;
-	    }
-	  return Qnil;
+	  FT_Done_Face (ft_face);
+	  cache_data->ft_face = NULL;
 	}
+      return Qnil;
     }
   cache_data->face_refcount++;
 
@@ -1164,7 +1293,6 @@ ftfont_open2 (struct frame *f,
   ftfont_info->maybe_otf = (ft_face->face_flags & FT_FACE_FLAG_SFNT) != 0;
   ftfont_info->otf = NULL;
 #endif	/* HAVE_LIBOTF */
-  ftfont_info->bitmap_strike_index = strike_index;
   /* This means that there's no need of transformation.  */
   ftfont_info->matrix.xx = 0;
   font->pixel_size = size;
@@ -1268,19 +1396,7 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
     size = pixel_size;
   font_object = font_build_object (VECSIZE (struct font_info),
 				   Qfreetype, entity, size);
-  font_object = ftfont_open2 (f, entity, pixel_size, font_object);
-  if (FONT_OBJECT_P (font_object))
-    {
-      struct font *font = XFONT_OBJECT (font_object);
-      struct font_info *ftfont_info = (struct font_info *) font;
-
-      if (ftfont_info->bitmap_strike_index >= 0)
-	{
-	  ftfont_close (font);
-	  font_object = Qnil;
-	}
-    }
-  return font_object;
+  return ftfont_open2 (f, entity, pixel_size, font_object);
 }
 
 void
@@ -2789,6 +2905,14 @@ syms_of_ftfont (void)
   /* The boolean-valued font property key specifying the use of leading.  */
   DEFSYM (QCminspace, ":minspace");
 
+  /* Fontconfig's rendering parameters.  */
+  DEFSYM (QChinting, ":hinting");
+  DEFSYM (QCautohint, ":autohint");
+  DEFSYM (QChintstyle, ":hintstyle");
+  DEFSYM (QCrgba, ":rgba");
+  DEFSYM (QCembolden, ":embolden");
+  DEFSYM (QClcdfilter, ":lcdfilter");
+
   staticpro (&freetype_font_cache);
   freetype_font_cache = list1 (Qt);
 
diff --git a/src/ftfont.h b/src/ftfont.h
index adbda49ff1c..de4e60f9aea 100644
--- a/src/ftfont.h
+++ b/src/ftfont.h
@@ -41,6 +41,8 @@ extern Lisp_Object ftfont_open2 (struct frame *f,
                                  Lisp_Object entity,
                                  int pixel_size,
                                  Lisp_Object font_object);
+extern void ftfont_fix_match (FcPattern *, FcPattern *);
+extern FcPattern *ftfont_entity_pattern (Lisp_Object, int);
 
 /* This struct is shared by the XFT, Freetype, and Cairo font
    backends.  Members up to and including 'matrix' are common, the
@@ -54,17 +56,10 @@ struct font_info
 #endif	/* HAVE_LIBOTF */
   FT_Size ft_size;
   int index;
-  /* Index of the bitmap strike used as a fallback for
-     FT_Set_Pixel_Sizes failure.  If the value is non-negative, then
-     ft_size is not of the requested size.  Otherwise it is -1.  */
-  FT_Int bitmap_strike_index;
   FT_Matrix matrix;
 
 #ifdef USE_CAIRO
   cairo_scaled_font_t *cr_scaled_font;
-  /* To prevent cairo from cluttering the activated FT_Size maintained
-     in ftfont.c, we activate this special FT_Size before drawing.  */
-  FT_Size ft_size_draw;
   /* Font metrics cache.  */
   struct font_metrics **metrics;
   short metrics_nrows;
diff --git a/src/xftfont.c b/src/xftfont.c
index 2edc51fe356..e5e237d1d4d 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -127,59 +127,6 @@ xftfont_match (struct frame *f, Lisp_Object spec)
 
 static FcChar8 ascii_printable[95];
 
-static void
-xftfont_fix_match (FcPattern *pat, FcPattern *match)
-{
-  /*  These values are not used for matching (except antialias), but for
-      rendering, so make sure they are carried over to the match.
-      We also put antialias here because most fonts are antialiased, so
-      the match will have antialias true.  */
-
-  FcBool b = FcTrue;
-  int i;
-  double dpi;
-
-  FcPatternGetBool (pat, FC_ANTIALIAS, 0, &b);
-  if (! b)
-    {
-      FcPatternDel (match, FC_ANTIALIAS);
-      FcPatternAddBool (match, FC_ANTIALIAS, FcFalse);
-    }
-  FcPatternGetBool (pat, FC_HINTING, 0, &b);
-  if (! b)
-    {
-      FcPatternDel (match, FC_HINTING);
-      FcPatternAddBool (match, FC_HINTING, FcFalse);
-    }
-#ifndef FC_HINT_STYLE
-# define FC_HINT_STYLE "hintstyle"
-#endif
-  if (FcResultMatch == FcPatternGetInteger (pat, FC_HINT_STYLE, 0, &i))
-    {
-      FcPatternDel (match, FC_HINT_STYLE);
-      FcPatternAddInteger (match, FC_HINT_STYLE, i);
-    }
-#ifndef FC_LCD_FILTER
-  /* Older fontconfig versions don't have FC_LCD_FILTER. */
-#define FC_LCD_FILTER "lcdfilter"
-#endif
-  if (FcResultMatch == FcPatternGetInteger (pat, FC_LCD_FILTER, 0, &i))
-    {
-      FcPatternDel (match, FC_LCD_FILTER);
-      FcPatternAddInteger (match, FC_LCD_FILTER, i);
-    }
-  if (FcResultMatch == FcPatternGetInteger (pat, FC_RGBA, 0, &i))
-    {
-      FcPatternDel (match, FC_RGBA);
-      FcPatternAddInteger (match, FC_RGBA, i);
-    }
-  if (FcResultMatch == FcPatternGetDouble (pat, FC_DPI, 0, &dpi))
-    {
-      FcPatternDel (match, FC_DPI);
-      FcPatternAddDouble (match, FC_DPI, dpi);
-    }
-}
-
 static void
 xftfont_add_rendering_parameters (FcPattern *pat, Lisp_Object entity)
 {
@@ -233,14 +180,13 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
 {
   FcResult result;
   Display *display = FRAME_X_DISPLAY (f);
-  Lisp_Object val, filename, idx, font_object;
+  Lisp_Object val, filename, font_object;
   FcPattern *pat = NULL, *match;
   struct font_info *xftfont_info = NULL;
   struct font *font;
   double size = 0;
   XftFont *xftfont = NULL;
   int spacing;
-  int i;
   XGlyphInfo extents;
   FT_Face ft_face;
   FcMatrix *matrix;
@@ -250,52 +196,17 @@ xftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
     return Qnil;
   val = XCDR (val);
   filename = XCAR (val);
-  idx = XCDR (val);
   size = XFIXNUM (AREF (entity, FONT_SIZE_INDEX));
   if (size == 0)
     size = pixel_size;
-  pat = FcPatternCreate ();
-  FcPatternAddInteger (pat, FC_WEIGHT, FONT_WEIGHT_NUMERIC (entity));
-  i = FONT_SLANT_NUMERIC (entity) - 100;
-  if (i < 0) i = 0;
-  FcPatternAddInteger (pat, FC_SLANT, i);
-  FcPatternAddInteger (pat, FC_WIDTH, FONT_WIDTH_NUMERIC (entity));
-  FcPatternAddDouble (pat, FC_PIXEL_SIZE, pixel_size);
-  val = AREF (entity, FONT_FAMILY_INDEX);
-  if (! NILP (val))
-    FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
-  val = AREF (entity, FONT_FOUNDRY_INDEX);
-  if (! NILP (val))
-    FcPatternAddString (pat, FC_FOUNDRY, (FcChar8 *) SDATA (SYMBOL_NAME (val)));
-  val = AREF (entity, FONT_SPACING_INDEX);
-  if (! NILP (val))
-    FcPatternAddInteger (pat, FC_SPACING, XFIXNUM (val));
-  val = AREF (entity, FONT_DPI_INDEX);
-  if (! NILP (val))
-    {
-      double dbl = XFIXNUM (val);
-
-      FcPatternAddDouble (pat, FC_DPI, dbl);
-    }
-  val = AREF (entity, FONT_AVGWIDTH_INDEX);
-  if (FIXNUMP (val) && XFIXNUM (val) == 0)
-    FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
-  /* This is necessary to identify the exact font (e.g. 10x20.pcf.gz
-     over 10x20-ISO8859-1.pcf.gz).  */
-  FcPatternAddCharSet (pat, FC_CHARSET, ftfont_get_fc_charset (entity));
-
-  xftfont_add_rendering_parameters (pat, entity);
-
-  FcPatternAddString (pat, FC_FILE, (FcChar8 *) SDATA (filename));
-  FcPatternAddInteger (pat, FC_INDEX, XFIXNUM (idx));
-
 
   block_input ();
 
+  pat = ftfont_entity_pattern (entity, pixel_size);
   /* Substitute in values from X resources and XftDefaultSet.  */
   XftDefaultSubstitute (display, FRAME_X_SCREEN_NUMBER (f), pat);
   match = XftFontMatch (display, FRAME_X_SCREEN_NUMBER (f), pat, &result);
-  xftfont_fix_match (pat, match);
+  ftfont_fix_match (pat, match);
 
   FcPatternDestroy (pat);
   xftfont = XftFontOpenPattern (display, match);
@@ -768,12 +679,6 @@ void
 syms_of_xftfont (void)
 {
   DEFSYM (Qxft, "xft");
-  DEFSYM (QChinting, ":hinting");
-  DEFSYM (QCautohint, ":autohint");
-  DEFSYM (QChintstyle, ":hintstyle");
-  DEFSYM (QCrgba, ":rgba");
-  DEFSYM (QCembolden, ":embolden");
-  DEFSYM (QClcdfilter, ":lcdfilter");
 
   DEFVAR_BOOL ("xft-font-ascent-descent-override",
 	       xft_font_ascent_descent_override,

  reply	other threads:[~2019-05-21 10:59 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-17 17:39 bug#35781: 27.0.50; [PATCH] Improve font display on Cairo builds Kévin Le Gouguec
2019-05-17 17:54 ` Dmitry Gutov
2019-05-17 18:14   ` Kévin Le Gouguec
2019-05-17 18:23     ` Kévin Le Gouguec
2019-05-17 18:24     ` Dmitry Gutov
2019-05-18 20:43 ` bug#35781: Discrepancies between xftfont.c and ftcrfont.c Kévin Le Gouguec
2019-05-19 19:48   ` Alex Gramiak
2019-05-21 10:59     ` mituharu [this message]
2019-05-21 19:03       ` Kévin Le Gouguec
2019-05-22  9:24         ` YAMAMOTO Mitsuharu
2019-05-23  2:00           ` YAMAMOTO Mitsuharu
2019-05-23 17:53             ` Kévin Le Gouguec

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=03f91c3a5f9c7d823e2d6d9c8dfc7b60.squirrel@weber.math.s.chiba-u.ac.jp \
    --to=mituharu@math.s.chiba-u.ac.jp \
    --cc=35781@debbugs.gnu.org \
    --cc=agrambot@gmail.com \
    --cc=kevin.legouguec@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).