emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master d1dde7d: Use bitmap strikes as fallbacks for ftcr f


From: YAMAMOTO Mitsuharu
Subject: [Emacs-diffs] master d1dde7d: Use bitmap strikes as fallbacks for ftcr font backend
Date: Fri, 19 Apr 2019 23:44:39 -0400 (EDT)

branch: master
commit d1dde7d04e5244179735592adc11d2a6f0af64ac
Author: YAMAMOTO Mitsuharu <address@hidden>
Commit: YAMAMOTO Mitsuharu <address@hidden>

    Use bitmap strikes as fallbacks for ftcr font backend
    
    * src/ftfont.h (struct font_info): New member bitmap_strike_index.
    * src/ftfont.c (ftfont_open2): Try bitmap strikes as fallbacks.
    (ftfont_open): Discard bitmap strikes.
    * src/ftcrfont.c (ftcrfont_open): Recalculate metrics for bitmap strikes.
    (ftcrfont_get_bitmap, ftcrfont_anchor_point, ftcrfont_shape): New functions.
    (struct font_driver): Use them.
---
 src/ftcrfont.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++----
 src/ftfont.c   |  44 ++++++++++++++++++++++---
 src/ftfont.h   |   4 +++
 3 files changed, 137 insertions(+), 11 deletions(-)

diff --git a/src/ftcrfont.c b/src/ftcrfont.c
index 4845ee4..e341c40 100644
--- a/src/ftcrfont.c
+++ b/src/ftcrfont.c
@@ -135,7 +135,10 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int 
pixel_size)
       font->driver = &ftcrfont_driver;
       FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw);
       FT_Activate_Size (ftcrfont_info->ft_size_draw);
-      FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size);
+      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;
@@ -148,6 +151,56 @@ ftcrfont_open (struct frame *f, Lisp_Object entity, int 
pixel_size)
       cairo_font_options_destroy (options);
       ftcrfont_info->metrics = NULL;
       ftcrfont_info->metrics_nrows = 0;
+      if (ftcrfont_info->bitmap_strike_index >= 0)
+       {
+         /* 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);
+         font->descent = lround (extents.descent);
+         font->height = lround (extents.height);
+
+         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
+                   {
+                     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;
+
+         font->underline_position = -1;
+         font->underline_thickness = 0;
+       }
     }
   unblock_input ();
 
@@ -211,6 +264,43 @@ ftcrfont_text_extents (struct font *font,
 }
 
 static int
+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;
+
+  if (ftcrfont_info->bitmap_strike_index < 0)
+    return ftfont_get_bitmap (font, code, bitmap, bits_per_pixel);
+
+  return -1;
+}
+
+static int
+ftcrfont_anchor_point (struct font *font, unsigned int code, int idx,
+                      int *x, int *y)
+{
+  struct font_info *ftcrfont_info = (struct font_info *) font;
+
+  if (ftcrfont_info->bitmap_strike_index < 0)
+    return ftfont_anchor_point (font, code, idx, x, y);
+
+  return -1;
+}
+
+static Lisp_Object
+ftcrfont_shape (Lisp_Object lgstring)
+{
+#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
+  struct font_info *ftcrfont_info = (struct font_info *) font;
+
+  if (ftcrfont_info->bitmap_strike_index < 0)
+    return ftfont_shape (lgstring);
+#endif
+
+  return make_fixnum (0);
+}
+
+static int
 ftcrfont_draw (struct glyph_string *s,
                int from, int to, int x, int y, bool with_background)
 {
@@ -286,14 +376,12 @@ struct font_driver const ftcrfont_driver =
   .encode_char = ftfont_encode_char,
   .text_extents = ftcrfont_text_extents,
   .draw = ftcrfont_draw,
-  .get_bitmap = ftfont_get_bitmap,
-  .anchor_point = ftfont_anchor_point,
+  .get_bitmap = ftcrfont_get_bitmap,
+  .anchor_point = ftcrfont_anchor_point,
 #ifdef HAVE_LIBOTF
   .otf_capability = ftfont_otf_capability,
 #endif
-#if defined HAVE_M17N_FLT && defined HAVE_LIBOTF
-  .shape = ftfont_shape,
-#endif
+  .shape = ftcrfont_shape,
 #ifdef HAVE_OTF_GET_VARIATION_GLYPHS
   .get_variation_glyphs = ftfont_variation_glyphs,
 #endif
diff --git a/src/ftfont.c b/src/ftfont.c
index 3e820f5..d0078a3 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -1097,6 +1097,7 @@ 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,12 +1127,32 @@ ftfont_open2 (struct frame *f,
     size = pixel_size;
   if (FT_Set_Pixel_Sizes (ft_face, size, size) != 0)
     {
-      if (cache_data->face_refcount == 0)
+      int min_distance = INT_MAX;
+      bool magnify = true;
+
+      for (FT_Int i = 0; i < ft_face->num_fixed_sizes; i++)
        {
-         FT_Done_Face (ft_face);
-         cache_data->ft_face = NULL;
+         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)
+           {
+             FT_Done_Face (ft_face);
+             cache_data->ft_face = NULL;
+           }
+         return Qnil;
        }
-      return Qnil;
     }
   cache_data->face_refcount++;
 
@@ -1144,6 +1165,7 @@ 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;
@@ -1229,7 +1251,19 @@ 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);
-  return ftfont_open2 (f, entity, pixel_size, font_object);
+  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;
 }
 
 void
diff --git a/src/ftfont.h b/src/ftfont.h
index 327cd08..adbda49 100644
--- a/src/ftfont.h
+++ b/src/ftfont.h
@@ -54,6 +54,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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]