[pango/kill-ft-face: 22/33] fc: Move font setup code from the shaper



commit 12ebd744bcff8f4dd1c613c3111ad96164ebe8aa
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Nov 19 11:47:42 2018 -0500

    fc: Move font setup code from the shaper
    
    Move all the code that sets up the hb_font_t to
    pango_fc_font_create_hb_font, and use it from
    the shaper. This is the second step towards
    taking over font management.
    
    Even better, harfbuzz has a ready-made function
    for this. We can drop a lot of FT_Face-using code
    this way. We assume unhinted rendering for now,
    so we can set ppem to 0.

 pango/pangofc-font.c    | 127 +++++++++++++++++-
 pango/pangofc-fontmap.c |   4 +-
 pango/pangofc-shape.c   | 334 ++++--------------------------------------------
 3 files changed, 153 insertions(+), 312 deletions(-)
---
diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c
index 75fcdde0..6e93c161 100644
--- a/pango/pangofc-font.c
+++ b/pango/pangofc-font.c
@@ -46,6 +46,7 @@
 #include "pango-layout.h"
 #include "pango-impl-utils.h"
 
+#include <harfbuzz/hb-ot.h>
 #include <fontconfig/fcfreetype.h>
 
 #include FT_TRUETYPE_TABLES_H
@@ -1092,15 +1093,135 @@ pango_fc_font_get_raw_extents (PangoFcFont    *fcfont,
   PANGO_FC_FONT_UNLOCK_FACE (fcfont);
 }
 
+extern gpointer get_gravity_class (void);
+
+static PangoGravity
+pango_fc_font_key_get_gravity (PangoFcFontKey *key)
+{
+  FcPattern *pattern;
+  PangoGravity gravity = PANGO_GRAVITY_SOUTH;
+  FcChar8 *s;
+
+  pattern = pango_fc_font_key_get_pattern (key);
+  if (FcPatternGetString (pattern, PANGO_FC_GRAVITY, 0, (FcChar8 **)&s) == FcResultMatch)
+    {
+      GEnumValue *value = g_enum_get_value_by_nick (get_gravity_class (), (char *)s);
+      gravity = value->value;
+    }
+
+  return gravity;
+}
+
+static double
+get_font_size (PangoFcFontKey *key)
+{
+  FcPattern *pattern;
+  double size;
+  double dpi;
+
+  pattern = pango_fc_font_key_get_pattern (key);
+  if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
+    return size;
+
+  /* Just in case FC_PIXEL_SIZE got unset between pango_fc_make_pattern()
+   * and here.  That would be very weird.
+   */
+
+  if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) != FcResultMatch)
+    dpi = 72;
+
+  if (FcPatternGetDouble (pattern, FC_SIZE, 0, &size) == FcResultMatch)
+    return size * dpi / 72.;
+
+  /* Whatever */
+  return 18.;
+}
+
+static void
+parse_variations (const char      *variations,
+                  hb_variation_t **hb_variations,
+                  guint           *n_variations)
+{
+  guint n;
+  hb_variation_t *var;
+  int i;
+  const char *p;
+
+  n = 1;
+  for (i = 0; variations[i]; i++)
+    {
+      if (variations[i] == ',')
+        n++;
+    }
+
+  var = g_new (hb_variation_t, n);
+
+  p = variations;
+  n = 0;
+  while (p && *p)
+    {
+      char *end = strchr (p, ',');
+      if (hb_variation_from_string (p, end ? end - p: -1, &var[n]))
+        n++;
+      p = end ? end + 1 : NULL;
+    }
+
+  *hb_variations = var;
+  *n_variations = n;
+}
+
 static hb_font_t *
 pango_fc_font_create_hb_font (PangoFont *font)
 {
-  PangoFcFont *fcfont = PANGO_FC_FONT (font);
+  PangoFcFont *fc_font = PANGO_FC_FONT (font);
+  PangoFcFontKey *key;
   hb_face_t *hb_face;
+  hb_font_t *hb_font;
+  double x_scale_inv, y_scale_inv;
+  double x_scale, y_scale;
+  double size;
+  PangoGravity gravity;
+
+  x_scale_inv = y_scale_inv = 1.0;
+  key = _pango_fc_font_get_font_key (fc_font);
+  if (key)
+    {
+      const PangoMatrix *matrix = pango_fc_font_key_get_matrix (key);
+      pango_matrix_get_font_scale_factors (matrix, &x_scale_inv, &y_scale_inv);
+    }
+  if (PANGO_GRAVITY_IS_IMPROPER (gravity))
+  {
+    x_scale_inv = -x_scale_inv;
+    y_scale_inv = -y_scale_inv;
+  }
+
+  x_scale = 1. / x_scale_inv;
+  y_scale = 1. / y_scale_inv;
+
+  size = get_font_size (key);
+  gravity = pango_fc_font_key_get_gravity (key);
+  hb_face = pango_fc_font_map_get_hb_face (PANGO_FC_FONT_MAP (fc_font->fontmap), fc_font);
 
-  hb_face = pango_fc_font_map_get_hb_face (PANGO_FC_FONT_MAP (fcfont->fontmap), fcfont);
+  hb_font = hb_font_create (hb_face);
+  hb_font_set_scale (hb_font,
+                     size * PANGO_SCALE * x_scale,
+                     size * PANGO_SCALE * y_scale);
+  if (key)
+    {
+      const char *variations = pango_fc_font_key_get_variations (key);
+      if (variations)
+        {
+          guint n_variations;
+          hb_variation_t *hb_variations;
+
+          parse_variations (variations, &hb_variations, &n_variations);
+          hb_font_set_variations (hb_font, hb_variations, n_variations);
+
+          g_free (hb_variations);
+        }
+    }
 
-  return hb_font_create (hb_face);
+  return hb_font;
 }
 
 static void
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index 21277044..72f9c70d 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -264,7 +264,9 @@ static FcPattern       *pango_fc_patterns_get_font_pattern (PangoFcPatterns *pat
 static FcPattern *uniquify_pattern (PangoFcFontMap *fcfontmap,
                                    FcPattern      *pattern);
 
-static gpointer
+gpointer get_gravity_class (void);
+
+gpointer
 get_gravity_class (void)
 {
   static GEnumClass *class = NULL; /* MT-safe */
diff --git a/pango/pangofc-shape.c b/pango/pangofc-shape.c
index 2846449e..9ea9c25f 100644
--- a/pango/pangofc-shape.c
+++ b/pango/pangofc-shape.c
@@ -70,249 +70,6 @@ release_buffer (hb_buffer_t *buffer, gboolean free_buffer)
     hb_buffer_destroy (buffer);
 }
 
-typedef struct _PangoFcHbContext {
-  FT_Face ft_face;
-  PangoFcFont *fc_font;
-  gboolean vertical;
-  double x_scale, y_scale; /* CTM scales. */
-} PangoFcHbContext;
-
-static hb_bool_t
-pango_fc_hb_font_get_nominal_glyph (hb_font_t *font, void *font_data,
-                                   hb_codepoint_t unicode,
-                                   hb_codepoint_t *glyph,
-                                   void *user_data G_GNUC_UNUSED)
-{
-  PangoFcHbContext *context = (PangoFcHbContext *) font_data;
-  PangoFcFont *fc_font = context->fc_font;
-
-  *glyph = pango_fc_font_get_glyph (fc_font, unicode);
-  if (G_LIKELY (*glyph))
-    return TRUE;
-
-  *glyph = PANGO_GET_UNKNOWN_GLYPH (unicode);
-
-  /* We draw our own invalid-Unicode shape, so prevent HarfBuzz
-   * from using REPLACEMENT CHARACTER. */
-  if (unicode > 0x10FFFF)
-    return TRUE;
-
-  return FALSE;
-}
-
-static hb_bool_t
-pango_fc_hb_font_get_variation_glyph (hb_font_t *font,
-                                      void *font_data,
-                                      hb_codepoint_t unicode,
-                                      hb_codepoint_t variation_selector,
-                                      hb_codepoint_t *glyph,
-                                      void *user_data G_GNUC_UNUSED)
-{
-  PangoFcHbContext *context = (PangoFcHbContext *) font_data;
-  FT_Face ft_face = context->ft_face;
-  unsigned int g;
-
-  g = FT_Face_GetCharVariantIndex (ft_face, unicode, variation_selector);
-
-  if (G_UNLIKELY (!g))
-    return FALSE;
-
-  *glyph = g;
-  return TRUE;
-}
-
-static hb_bool_t
-pango_fc_hb_font_get_glyph_contour_point (hb_font_t *font, void *font_data,
-                                         hb_codepoint_t glyph, unsigned int point_index,
-                                         hb_position_t *x, hb_position_t *y,
-                                         void *user_data G_GNUC_UNUSED)
-{
-  return FALSE;
-#if 0
-  FT_Face ft_face = (FT_Face) font_data;
-  int load_flags = FT_LOAD_DEFAULT;
-
-  /* TODO: load_flags, embolden, etc */
-
-  if (HB_UNLIKELY (FT_Load_Glyph (ft_face, glyph, load_flags)))
-      return FALSE;
-
-  if (HB_UNLIKELY (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE))
-      return FALSE;
-
-  if (HB_UNLIKELY (point_index >= (unsigned int) ft_face->glyph->outline.n_points))
-      return FALSE;
-
-  *x = ft_face->glyph->outline.points[point_index].x;
-  *y = ft_face->glyph->outline.points[point_index].y;
-
-  return TRUE;
-#endif
-}
-
-static hb_position_t
-pango_fc_hb_font_get_glyph_advance (hb_font_t *font, void *font_data,
-                                   hb_codepoint_t glyph,
-                                   void *user_data G_GNUC_UNUSED)
-{
-  PangoFcHbContext *context = (PangoFcHbContext *) font_data;
-  PangoFcFont *fc_font = context->fc_font;
-  PangoRectangle logical;
-
-  pango_font_get_glyph_extents ((PangoFont *) fc_font, glyph, NULL, &logical);
-
-  return logical.width;
-}
-
-static hb_bool_t
-pango_fc_hb_font_get_glyph_extents (hb_font_t *font,  void *font_data,
-                                   hb_codepoint_t glyph,
-                                   hb_glyph_extents_t *extents,
-                                   void *user_data G_GNUC_UNUSED)
-{
-  PangoFcHbContext *context = (PangoFcHbContext *) font_data;
-  PangoFcFont *fc_font = context->fc_font;
-  PangoRectangle ink;
-
-  pango_font_get_glyph_extents ((PangoFont *) fc_font, glyph, &ink, NULL);
-
-  if (G_LIKELY (!context->vertical)) {
-    extents->x_bearing  = ink.x;
-    extents->y_bearing  = ink.y;
-    extents->width      = ink.width;
-    extents->height     = ink.height;
-  } else {
-    /* XXX */
-    extents->x_bearing  = ink.x;
-    extents->y_bearing  = ink.y;
-    extents->width      = ink.height;
-    extents->height     = ink.width;
-  }
-
-  return TRUE;
-}
-
-static hb_bool_t
-pango_fc_hb_font_get_glyph_h_origin (hb_font_t *font, void *font_data,
-                                    hb_codepoint_t glyph,
-                                    hb_position_t *x, hb_position_t *y,
-                                    void *user_data G_GNUC_UNUSED)
-{
-  PangoFcHbContext *context = (PangoFcHbContext *) font_data;
-  FT_Face ft_face = context->ft_face;
-  int load_flags = FT_LOAD_DEFAULT;
-
-  if (!context->vertical) return TRUE;
-
-  if (FT_Load_Glyph (ft_face, glyph, load_flags))
-    return FALSE;
-
-  /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
-   * have a Y growing upward.  Hence the extra negations. */
-  *x = -PANGO_UNITS_26_6 (ft_face->glyph->metrics.horiBearingX -   ft_face->glyph->metrics.vertBearingX);
-  *y = +PANGO_UNITS_26_6 (ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY));
-
-  return TRUE;
-}
-
-static hb_bool_t
-pango_fc_hb_font_get_glyph_v_origin (hb_font_t *font, void *font_data,
-                                    hb_codepoint_t glyph,
-                                    hb_position_t *x, hb_position_t *y,
-                                    void *user_data G_GNUC_UNUSED)
-{
-  PangoFcHbContext *context = (PangoFcHbContext *) font_data;
-  FT_Face ft_face = context->ft_face;
-  int load_flags = FT_LOAD_DEFAULT;
-
-  /* pangocairo-fc configures font in vertical origin for vertical writing. */
-  if (context->vertical) return TRUE;
-
-  if (FT_Load_Glyph (ft_face, glyph, load_flags))
-    return FALSE;
-
-  /* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
-   * have a Y growing upward.  Hence the extra negation. */
-  *x = PANGO_UNITS_26_6 (ft_face->glyph->metrics.horiBearingX -   ft_face->glyph->metrics.vertBearingX);
-  *y = PANGO_UNITS_26_6 (ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY));
-
-  /* XXX */
-
-  return TRUE;
-}
-
-
-static hb_position_t
-pango_fc_hb_font_get_h_kerning (hb_font_t *font, void *font_data,
-                               hb_codepoint_t left_glyph, hb_codepoint_t right_glyph,
-                               void *user_data G_GNUC_UNUSED)
-{
-  PangoFcHbContext *context = (PangoFcHbContext *) font_data;
-  FT_Face ft_face = context->ft_face;
-  FT_Vector kerning;
-
-  if (FT_Get_Kerning (ft_face, left_glyph, right_glyph, FT_KERNING_DEFAULT, &kerning))
-    return 0;
-
-  return PANGO_UNITS_26_6 (kerning.x * context->x_scale);
-}
-
-static hb_font_funcs_t *
-pango_fc_get_hb_font_funcs (void)
-{
-  static hb_font_funcs_t *funcs;
-
-  if (G_UNLIKELY (!funcs)) {
-    funcs = hb_font_funcs_create ();
-    hb_font_funcs_set_nominal_glyph_func (funcs, pango_fc_hb_font_get_nominal_glyph, NULL, NULL);
-    hb_font_funcs_set_variation_glyph_func (funcs, pango_fc_hb_font_get_variation_glyph, NULL, NULL);
-    hb_font_funcs_set_glyph_h_advance_func (funcs, pango_fc_hb_font_get_glyph_advance, NULL, NULL);
-    hb_font_funcs_set_glyph_v_advance_func (funcs, pango_fc_hb_font_get_glyph_advance, NULL, NULL);
-    hb_font_funcs_set_glyph_h_origin_func (funcs, pango_fc_hb_font_get_glyph_h_origin, NULL, NULL);
-    hb_font_funcs_set_glyph_v_origin_func (funcs, pango_fc_hb_font_get_glyph_v_origin, NULL, NULL);
-    hb_font_funcs_set_glyph_h_kerning_func (funcs, pango_fc_hb_font_get_h_kerning, NULL, NULL);
-    /* Don't need v_kerning. */
-    hb_font_funcs_set_glyph_extents_func (funcs, pango_fc_hb_font_get_glyph_extents, NULL, NULL);
-    hb_font_funcs_set_glyph_contour_point_func (funcs, pango_fc_hb_font_get_glyph_contour_point, NULL, NULL);
-    /* Don't need glyph_name / glyph_from_name */
-  }
-
-  return funcs;
-}
-
-static void
-parse_variations (const char      *variations,
-                  hb_variation_t **hb_variations,
-                  guint           *n_variations)
-{
-  guint n;
-  hb_variation_t *var;
-  int i;
-  const char *p;
-
-  n = 1;
-  for (i = 0; variations[i]; i++)
-    {
-      if (variations[i] == ',')
-        n++;
-    }
-
-  var = g_new (hb_variation_t, n);
-
-  p = variations;
-  n = 0;
-  while (p && *p)
-    {
-      char *end = strchr (p, ',');
-      if (hb_variation_from_string (p, end ? end - p: -1, &var[n]))
-        n++;
-      p = end ? end + 1 : NULL;
-    }
-
-  *hb_variations = var;
-  *n_variations = n;
-}
-
 void
 _pango_fc_shape (PangoFont           *font,
                 const char          *item_text,
@@ -322,11 +79,7 @@ _pango_fc_shape (PangoFont           *font,
                 const char          *paragraph_text,
                 unsigned int         paragraph_length)
 {
-  PangoFcHbContext context;
   PangoFcFont *fc_font;
-  PangoFcFontKey *key;
-  FT_Face ft_face;
-  hb_face_t *hb_face;
   hb_font_t *hb_font;
   hb_buffer_t *hb_buffer;
   hb_direction_t hb_direction;
@@ -338,64 +91,12 @@ _pango_fc_shape (PangoFont           *font,
   unsigned int item_offset = item_text - paragraph_text;
   hb_feature_t features[32];
   unsigned int num_features = 0;
-  double x_scale_inv, y_scale_inv;
   PangoGlyphInfo *infos;
-  const char *variations;
 
   g_return_if_fail (font != NULL);
   g_return_if_fail (analysis != NULL);
 
-  fc_font = PANGO_FC_FONT (font);
-  ft_face = pango_fc_font_lock_face (fc_font);
-  if (!ft_face)
-    return;
-
-  /* TODO: Cache hb_font? */
-
-  x_scale_inv = y_scale_inv = 1.0;
-  key = _pango_fc_font_get_font_key (fc_font);
-  if (key)
-  {
-    const PangoMatrix *matrix = pango_fc_font_key_get_matrix (key);
-    pango_matrix_get_font_scale_factors (matrix, &x_scale_inv, &y_scale_inv);
-  }
-  if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity))
-  {
-    x_scale_inv = -x_scale_inv;
-    y_scale_inv = -y_scale_inv;
-  }
-  context.x_scale = 1. / x_scale_inv;
-  context.y_scale = 1. / y_scale_inv;
-  context.ft_face = ft_face;
-  context.fc_font = fc_font;
-  context.vertical = PANGO_GRAVITY_IS_VERTICAL (analysis->gravity);
-  hb_face = hb_ft_face_create_cached (ft_face);
-  hb_font = hb_font_create (hb_face);
-  hb_font_set_funcs (hb_font,
-                    pango_fc_get_hb_font_funcs (),
-                    &context,
-                    NULL);
-  hb_font_set_scale (hb_font,
-                    +(((gint64) ft_face->size->metrics.x_scale * ft_face->units_per_EM) >> 12) * 
context.x_scale,
-                    -(((gint64) ft_face->size->metrics.y_scale * ft_face->units_per_EM) >> 12) * 
context.y_scale);
-  hb_font_set_ppem (hb_font,
-                   fc_font->is_hinted ? ft_face->size->metrics.x_ppem : 0,
-                   fc_font->is_hinted ? ft_face->size->metrics.y_ppem : 0);
-
-  if (key)
-  {
-    variations = pango_fc_font_key_get_variations (key);
-    if (variations)
-    {
-      guint n_variations;
-      hb_variation_t *hb_variations;
-
-      parse_variations (variations, &hb_variations, &n_variations);
-      hb_font_set_variations (hb_font, hb_variations, n_variations);
-
-      g_free (hb_variations);
-    }
-  }
+  hb_font = pango_font_get_hb_font (font);
 
   hb_buffer = acquire_buffer (&free_buffer);
 
@@ -418,6 +119,7 @@ _pango_fc_shape (PangoFont           *font,
   hb_buffer_add_utf8 (hb_buffer, paragraph_text, paragraph_length, item_offset, item_length);
 
   /* Setup features from fontconfig pattern. */
+  fc_font = PANGO_FC_FONT (font);
   if (fc_font->font_pattern)
     {
       char *s;
@@ -495,7 +197,7 @@ _pango_fc_shape (PangoFont           *font,
     }
 
   hb_position = hb_buffer_get_glyph_positions (hb_buffer, NULL);
-  if (context.vertical)
+  if (PANGO_GRAVITY_IS_VERTICAL (analysis->gravity))
     for (i = 0; i < num_glyphs; i++)
       {
         /* 90 degrees rotation counter-clockwise. */
@@ -515,7 +217,26 @@ _pango_fc_shape (PangoFont           *font,
 
   if (fc_font->is_hinted)
   {
-    if (context.x_scale == 1.0 && context.y_scale == 1.0)
+    double x_scale_inv, y_scale_inv;
+    double x_scale, y_scale;
+    PangoFcFontKey *key;
+
+    x_scale_inv = y_scale_inv = 1.0;
+    key = _pango_fc_font_get_font_key (fc_font);
+    if (key)
+      {
+        const PangoMatrix *matrix = pango_fc_font_key_get_matrix (key);
+        pango_matrix_get_font_scale_factors (matrix, &x_scale_inv, &y_scale_inv);
+      }
+    if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity))
+      {
+        x_scale_inv = -x_scale_inv;
+        y_scale_inv = -y_scale_inv;
+      }
+    x_scale = 1. / x_scale_inv;
+    y_scale = 1. / y_scale_inv;
+
+    if (x_scale == 1.0 && y_scale == 1.0)
       {
        for (i = 0; i < num_glyphs; i++)
          infos[i].geometry.width = PANGO_UNITS_ROUND (infos[i].geometry.width);
@@ -523,7 +244,7 @@ _pango_fc_shape (PangoFont           *font,
     else
       {
 #if 0
-       if (context.vertical)
+       if (PANGO_GRAVITY_IS_VERTICAL (analysis->gravity))
          {
            /* XXX */
            double tmp = x_scale;
@@ -532,8 +253,8 @@ _pango_fc_shape (PangoFont           *font,
          }
 #endif
 #define HINT(value, scale_inv, scale) (PANGO_UNITS_ROUND ((int) ((value) * scale)) * scale_inv)
-#define HINT_X(value) HINT ((value), context.x_scale, x_scale_inv)
-#define HINT_Y(value) HINT ((value), context.y_scale, y_scale_inv)
+#define HINT_X(value) HINT ((value), x_scale, x_scale_inv)
+#define HINT_Y(value) HINT ((value), y_scale, y_scale_inv)
        for (i = 0; i < num_glyphs; i++)
          {
            infos[i].geometry.width    = HINT_X (infos[i].geometry.width);
@@ -547,7 +268,4 @@ _pango_fc_shape (PangoFont           *font,
   }
 
   release_buffer (hb_buffer, free_buffer);
-  hb_font_destroy (hb_font);
-  hb_face_destroy (hb_face);
-  pango_fc_font_unlock_face (fc_font);
 }


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