[pango/wip/matthiasc/font-variations] wip: nonworking



commit 50aebebe07019a3b33b8e7a6f7b1ce5b60290acd
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Sep 5 23:21:38 2017 -0400

    wip: nonworking

 pango/fonts.c              |   60 ++++++++++++++++++++++++++++-----
 pango/pangocairo-fcfont.c  |   80 ++++++++++++++++++++++++++++++++++++++++++-
 pango/pangocairo-font.c    |   17 ++++++++-
 pango/pangocairo-private.h |    5 ++-
 pango/pangofc-fontmap.c    |   16 ++++++++-
 pango/pangofc-fontmap.h    |    2 +
 pango/pangofc-shape.c      |   42 +++++++++++++++++++++++
 7 files changed, 207 insertions(+), 15 deletions(-)
---
diff --git a/pango/fonts.c b/pango/fonts.c
index 71a0e00..a6d48c6 100644
--- a/pango/fonts.c
+++ b/pango/fonts.c
@@ -56,6 +56,7 @@ struct _PangoFontDescription
 
   guint16 mask;
   guint static_family : 1;
+  guint static_variations : 1;
   guint size_is_absolute : 1;
 
   int size;
@@ -77,6 +78,7 @@ static const PangoFontDescription pfd_defaults = {
 
   0,                   /* mask */
   0,                   /* static_family */
+  0,                   /* static_variations*/
   FALSE,               /* size_is_absolute */
 
   0,                   /* size */
@@ -483,18 +485,39 @@ pango_font_description_get_gravity (const PangoFontDescription *desc)
 }
 
 void
-pango_font_description_set_variations (PangoFontDescription *desc,
-                                       const char           *variations)
+pango_font_description_set_variations_static (PangoFontDescription *desc,
+                                              const char           *variations)
 {
   g_return_if_fail (desc != NULL);
 
-  g_free (desc->variations);
-  desc->variations = g_strdup (variations);
+  if (desc->variations == variations)
+    return;
+
+  if (desc->variations && !desc->static_variations)
+    g_free (desc->variations);
 
-  if (variations != NULL)
-    desc->mask |= PANGO_FONT_MASK_VARIATIONS;
+  if (variations)
+    {
+      desc->variations = (char *)variations;
+      desc->static_variations = TRUE;
+      desc->mask |= PANGO_FONT_MASK_VARIATIONS;
+    }
   else
-    desc->mask &= ~PANGO_FONT_MASK_VARIATIONS;
+    {
+      desc->variations = pfd_defaults.variations;
+      desc->static_variations = pfd_defaults.static_variations;
+      desc->mask &= ~PANGO_FONT_MASK_VARIATIONS;
+    }
+}
+void
+pango_font_description_set_variations (PangoFontDescription *desc,
+                                       const char           *variations)
+{
+  g_return_if_fail (desc != NULL);
+
+  pango_font_description_set_variations_static (desc, g_strdup (variations));
+  if (variations)
+    desc->static_variations = FALSE;
 }
 
 const char *
@@ -567,6 +590,7 @@ pango_font_description_merge (PangoFontDescription       *desc,
                              gboolean                    replace_existing)
 {
   gboolean family_merged;
+  gboolean variations_merged;
 
   g_return_if_fail (desc != NULL);
 
@@ -574,6 +598,7 @@ pango_font_description_merge (PangoFontDescription       *desc,
     return;
 
   family_merged = desc_to_merge->family_name && (replace_existing || !desc->family_name);
+  variations_merged = desc_to_merge->variations && (replace_existing || !desc->variations);
 
   pango_font_description_merge_static (desc, desc_to_merge, replace_existing);
 
@@ -582,6 +607,12 @@ pango_font_description_merge (PangoFontDescription       *desc,
       desc->family_name = g_strdup (desc->family_name);
       desc->static_family = FALSE;
     }
+
+  if (variations_merged)
+    {
+      desc->variations = g_strdup (desc->variations);
+      desc->static_variations = FALSE;
+    }
 }
 
 /**
@@ -629,6 +660,8 @@ pango_font_description_merge_static (PangoFontDescription       *desc,
     }
   if (new_mask & PANGO_FONT_MASK_GRAVITY)
     desc->gravity = desc_to_merge->gravity;
+  if (new_mask & PANGO_FONT_MASK_VARIATIONS)
+    pango_font_description_set_variations_static (desc, desc_to_merge->variations);
 
   desc->mask |= new_mask;
 }
@@ -724,6 +757,7 @@ pango_font_description_copy  (const PangoFontDescription  *desc)
     }
 
   result->variations = g_strdup (result->variations);
+  result->static_variations = FALSE;
 
   return result;
 }
@@ -756,6 +790,10 @@ pango_font_description_copy_static (const PangoFontDescription *desc)
   if (result->family_name)
     result->static_family = TRUE;
 
+
+  if (result->variations)
+    result->static_variations = TRUE;
+
   return result;
 }
 
@@ -857,7 +895,8 @@ pango_font_description_free  (PangoFontDescription  *desc)
   if (desc->family_name && !desc->static_family)
     g_free (desc->family_name);
 
-  g_free (desc->variations);
+  if (desc->variations && !desc->static_variations)
+    g_free (desc->variations);
 
   g_slice_free (PangoFontDescription, desc);
 }
@@ -1112,7 +1151,10 @@ parse_variations (const char  *word,
                   char       **variations)
 {
   if (word[0] != '@')
-    return FALSE;
+    {
+      *variations = NULL;
+      return FALSE;
+    }
 
   /* XXX: actually validate here */
   *variations = g_strndup (word + 1, wordlen - 1);
diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c
index 30ecde4..f39a4d7 100644
--- a/pango/pangocairo-fcfont.c
+++ b/pango/pangocairo-fcfont.c
@@ -33,6 +33,9 @@
 #include "pangofc-private.h"
 #include "pango-impl-utils.h"
 
+#include <hb-ot.h>
+#include <freetype/ftmm.h>
+
 #define PANGO_TYPE_CAIRO_FC_FONT           (pango_cairo_fc_font_get_type ())
 #define PANGO_CAIRO_FC_FONT(object)        (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_CAIRO_FC_FONT, 
PangoCairoFcFont))
 #define PANGO_CAIRO_FC_FONT_CLASS(klass)   (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_CAIRO_FC_FONT, 
PangoCairoFcFontClass))
@@ -115,16 +118,88 @@ pango_cairo_fc_font_get_glyph_extents (PangoFont      *font,
                                               logical_rect);
 }
 
+#define FloatToFixed(f) ((FT_Fixed)((f)*65536))
+
+gboolean
+parse_variation_settings (FT_MM_Var   *amaster,
+                          const char  *settings,
+                          FT_UInt     *num_coords,
+                          FT_Fixed   **coords)
+{
+  int i;
+
+  *num_coords = amaster->num_axis;
+  *coords = g_new (FT_Fixed, amaster->num_axis);
+
+  for (i = 0; i < amaster->num_axis; i++)
+    {
+      FT_Var_Axis *axis = &amaster->axis[i];
+      char tag[5];
+      char *p;
+      FT_Fixed value = axis->def;
+
+      hb_tag_to_string (axis->tag, tag);
+      tag[4] = '\0';
+
+      p = strstr (settings, tag);
+      if (p && p[4] == '=')
+        {
+          char *end = NULL;
+          double dval;
+          dval = g_ascii_strtod (p + 5, &end);
+          if (end != NULL && *end != ',' && *end != '\0')
+            g_warning ("Failed to parse axis value for %s", tag);
+          else
+            value = FloatToFixed(dval);
+        }
+
+      *coords[i] = value;
+    }
+
+  return TRUE;
+}
+
+static void
+apply_font_variation (FT_Face ft_face,
+                      const char *settings)
+{
+  FT_MM_Var *amaster = NULL;
+  FT_UInt num_coords;
+  FT_Fixed *coords;
+  FT_Error err;
+
+  if ((err = FT_Get_MM_Var (ft_face, &amaster)) != 0)
+    {
+      g_warning ("Failed to load font variation descriptor (%d)", err);
+      return;
+    }
+
+  if (parse_variation_settings (amaster, settings, &num_coords, &coords))
+    {
+      if ((err = FT_Set_MM_Design_Coordinates (ft_face, num_coords, coords)) != 0)
+        g_warning ("Failed to set font variation (%d)", err);
+    }
+
+  free (amaster);
+}
+
 static FT_Face
 pango_cairo_fc_font_lock_face (PangoFcFont *font)
 {
   PangoCairoFcFont *cffont = (PangoCairoFcFont *) (font);
   cairo_scaled_font_t *scaled_font = _pango_cairo_font_private_get_scaled_font (&cffont->cf_priv);
+  const char *settings = _pango_cairo_font_private_get_variation_settings (&cffont->cf_priv);
+  FT_Face ft_face;
 
   if (G_UNLIKELY (!scaled_font))
     return NULL;
 
-  return cairo_ft_scaled_font_lock_face (scaled_font);
+  ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
+
+  if (settings)
+    apply_font_variation (ft_face, settings);
+
+  return ft_face;
 }
 
 static void
@@ -252,7 +327,8 @@ _pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap,
                                        get_gravity (pattern),
                                        pango_fc_font_key_get_context_key (key),
                                        pango_fc_font_key_get_matrix (key),
-                                       &font_matrix);
+                                       &font_matrix,
+                                        pango_fc_font_key_get_variation (key));
 
   ((PangoFcFont *)(cffont))->is_hinted = _pango_cairo_font_private_is_metrics_hinted (&cffont->cf_priv);
 
diff --git a/pango/pangocairo-font.c b/pango/pangocairo-font.c
index b86f85b..8fb8746 100644
--- a/pango/pangocairo-font.c
+++ b/pango/pangocairo-font.c
@@ -55,6 +55,7 @@ _pango_cairo_font_private_scaled_font_data_destroy (PangoCairoFontPrivateScaledF
   if (data)
     {
       cairo_font_options_destroy (data->options);
+      g_free (data->variation_settings);
       g_slice_free (PangoCairoFontPrivateScaledFontData, data);
     }
 }
@@ -134,6 +135,15 @@ done:
   return cf_priv->scaled_font;
 }
 
+const char *
+_pango_cairo_font_private_get_variation_settings (PangoCairoFontPrivate *cf_priv)
+{
+  if (G_UNLIKELY (cf_priv->data == NULL))
+    return NULL;
+
+  return cf_priv->data->variation_settings;
+}
+
 /**
  * pango_cairo_font_get_scaled_font:
  * @font: a #PangoFont from a #PangoCairoFontMap
@@ -589,14 +599,15 @@ _pango_cairo_font_private_initialize (PangoCairoFontPrivate      *cf_priv,
                                      PangoGravity                gravity,
                                      const cairo_font_options_t *font_options,
                                      const PangoMatrix          *pango_ctm,
-                                     const cairo_matrix_t       *font_matrix)
+                                     const cairo_matrix_t       *font_matrix,
+                                      const char                 *variation_settings)
 {
   cairo_matrix_t gravity_matrix;
 
   cf_priv->cfont = cfont;
   cf_priv->gravity = gravity;
 
-  cf_priv->data = _pango_cairo_font_private_scaled_font_data_create (); 
+  cf_priv->data = _pango_cairo_font_private_scaled_font_data_create ();
 
   /* first apply gravity rotation, then font_matrix, such that
    * vertical italic text comes out "correct".  we don't do anything
@@ -619,6 +630,8 @@ _pango_cairo_font_private_initialize (PangoCairoFontPrivate      *cf_priv,
     cairo_matrix_init_identity (&cf_priv->data->ctm);
 
   cf_priv->data->options = cairo_font_options_copy (font_options);
+  cf_priv->data->variation_settings = g_strdup (variation_settings);
+
   cf_priv->is_hinted = cairo_font_options_get_hint_metrics (font_options) != CAIRO_HINT_METRICS_OFF;
 
   cf_priv->scaled_font = NULL;
diff --git a/pango/pangocairo-private.h b/pango/pangocairo-private.h
index 704ae49..85cbf9e 100644
--- a/pango/pangocairo-private.h
+++ b/pango/pangocairo-private.h
@@ -70,6 +70,7 @@ struct _PangoCairoFontPrivateScaledFontData
   cairo_matrix_t font_matrix;
   cairo_matrix_t ctm;
   cairo_font_options_t *options;
+  char *variation_settings;
 };
 
 struct _PangoCairoFontPrivate
@@ -112,9 +113,11 @@ void _pango_cairo_font_private_initialize (PangoCairoFontPrivate      *cf_priv,
                                           PangoGravity                gravity,
                                           const cairo_font_options_t *font_options,
                                           const PangoMatrix          *pango_ctm,
-                                          const cairo_matrix_t       *font_matrix);
+                                          const cairo_matrix_t       *font_matrix,
+                                           const char                 *variation_settings);
 void _pango_cairo_font_private_finalize (PangoCairoFontPrivate *cf_priv);
 cairo_scaled_font_t *_pango_cairo_font_private_get_scaled_font (PangoCairoFontPrivate *cf_priv);
+const char *_pango_cairo_font_private_get_variation_settings (PangoCairoFontPrivate *cf_priv);
 gboolean _pango_cairo_font_private_is_metrics_hinted (PangoCairoFontPrivate *cf_priv);
 void _pango_cairo_font_private_get_glyph_extents (PangoCairoFontPrivate *cf_priv,
                                                  PangoGlyph             glyph,
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
index 70e9ee7..da22463 100644
--- a/pango/pangofc-fontmap.c
+++ b/pango/pangofc-fontmap.c
@@ -364,6 +364,7 @@ struct _PangoFcFontKey {
   FcPattern *pattern;
   PangoMatrix matrix;
   gpointer context_key;
+  char *variation;
 };
 
 static void
@@ -569,7 +570,8 @@ pango_fc_font_key_equal (const PangoFcFontKey *key_a,
                         const PangoFcFontKey *key_b)
 {
   if (key_a->pattern == key_b->pattern &&
-      0 == memcmp (&key_a->matrix, &key_b->matrix, 4 * sizeof (double)))
+      0 == memcmp (&key_a->matrix, &key_b->matrix, 4 * sizeof (double)) &&
+      0 == g_strcmp0 (key_a->variation, key_b->variation))
     {
       if (key_a->context_key && key_b->context_key)
        return PANGO_FC_FONT_MAP_GET_CLASS (key_a->fontmap)->context_key_equal (key_a->fontmap,
@@ -594,6 +596,9 @@ pango_fc_font_key_hash (const PangoFcFontKey *key)
       hash ^= PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap,
                                                                            key->context_key);
 
+    if (key->variation)
+      hash ^= g_str_hash (key->variation);
+
     return (hash ^ GPOINTER_TO_UINT (key->pattern));
 }
 
@@ -607,6 +612,8 @@ pango_fc_font_key_free (PangoFcFontKey *key)
     PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap,
                                                                  key->context_key);
 
+  g_free (key->variation);
+
   g_slice_free (PangoFcFontKey, key);
 }
 
@@ -624,6 +631,7 @@ pango_fc_font_key_copy (const PangoFcFontKey *old)
                                                                                     old->context_key);
   else
     key->context_key = NULL;
+  key->variation = g_strdup (old->variation);
 
   return key;
 }
@@ -638,6 +646,7 @@ pango_fc_font_key_init (PangoFcFontKey    *key,
   key->pattern = pattern;
   key->matrix = *pango_fc_fontset_key_get_matrix (fontset_key);
   key->context_key = pango_fc_fontset_key_get_context_key (fontset_key);
+  key->variation = g_strdup (pango_font_description_get_variations (pango_fc_fontset_key_get_description 
(fontset_key)));
 }
 
 /* Public API */
@@ -690,6 +699,11 @@ pango_fc_font_key_get_context_key (const PangoFcFontKey *key)
   return key->context_key;
 }
 
+const char *
+pango_fc_font_key_get_variation (const PangoFcFontKey *key)
+{
+  return key->variation;
+}
 
 /*
  * PangoFcPatterns
diff --git a/pango/pangofc-fontmap.h b/pango/pangofc-fontmap.h
index 4dab083..24e303a 100644
--- a/pango/pangofc-fontmap.h
+++ b/pango/pangofc-fontmap.h
@@ -71,6 +71,8 @@ PANGO_AVAILABLE_IN_1_24
 const PangoMatrix *pango_fc_font_key_get_matrix      (const PangoFcFontKey *key);
 PANGO_AVAILABLE_IN_1_24
 gpointer           pango_fc_font_key_get_context_key (const PangoFcFontKey *key);
+PANGO_AVAILABLE_IN_1_40
+const char        *pango_fc_font_key_get_variation   (const PangoFcFontKey *key);
 
 #endif
 
diff --git a/pango/pangofc-shape.c b/pango/pangofc-shape.c
index 60f829f..1a82ffc 100644
--- a/pango/pangofc-shape.c
+++ b/pango/pangofc-shape.c
@@ -282,6 +282,38 @@ pango_fc_get_hb_font_funcs (void)
   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,
@@ -310,6 +342,7 @@ _pango_fc_shape (PangoFont           *font,
   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);
@@ -350,6 +383,15 @@ _pango_fc_shape (PangoFont           *font,
   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);
+  variations = pango_fc_font_key_get_variation (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_buffer = acquire_buffer (&free_buffer);
 


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