[pango/wip/matthiasc/font-features: 2/2] Allow setting OpenType features on font descriptions



commit 3c372aa2115f362378f5ed4e492439cc0a9bc39d
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Apr 24 16:54:14 2018 -0400

    Allow setting OpenType features on font descriptions

 pango/fonts.c      |  150 +++++++++++++++++++++++++++++++++++++++++----------
 pango/pango-font.h |   25 ++++++---
 2 files changed, 138 insertions(+), 37 deletions(-)
---
diff --git a/pango/fonts.c b/pango/fonts.c
index d9a07c0..2fa27a6 100644
--- a/pango/fonts.c
+++ b/pango/fonts.c
@@ -53,10 +53,12 @@ struct _PangoFontDescription
   PangoGravity gravity;
 
   char *variations;
+  char *features;
 
   guint16 mask;
   guint static_family : 1;
   guint static_variations : 1;
+  guint static_features : 1;
   guint size_is_absolute : 1;
 
   int size;
@@ -75,10 +77,12 @@ static const PangoFontDescription pfd_defaults = {
   PANGO_STRETCH_NORMAL,        /* stretch */
   PANGO_GRAVITY_SOUTH,  /* gravity */
   NULL,                 /* variations */
+  NULL,                 /* features */
 
   0,                   /* mask */
   0,                   /* static_family */
-  0,                   /* static_variations*/
+  0,                   /* static_variations */
+  0,                   /* static_features */
   0,                   /* size_is_absolute */
 
   0,                   /* size */
@@ -525,55 +529,93 @@ pango_font_description_set_variations_static (PangoFontDescription *desc,
 }
 
 /**
- * pango_font_description_set_variations:
- * @desc: a #PangoFontDescription.
- * @variations: a string representing the variations
+ * pango_font_description_set_features_static:
+ * @desc: a #PangoFontDescription
+ * @features: a string representing the features 
  *
- * Sets the variations field of a font description. OpenType
- * font variations allow to select a font instance by specifying
- * values for a number of axes, such as width or weight.
+ * Like pango_font_description_set_features(), except that no
+ * copy of @features is made. The caller must make sure that the
+ * string passed in stays around until @desc has been freed
+ * or the name is set again. This function can be used if
+ * @features is a static string such as a C string literal,
+ * or if @desc is only needed temporarily.
  *
- * The format of the variations string is AXIS1=VALUE,AXIS2=VALUE...,
- * with each AXIS a 4 character tag that identifies a font axis,
- * and each VALUE a floating point number. Unknown axes are ignored,
- * and values are clamped to their allowed range.
+ * Since: 1.44
+ **/
+void
+pango_font_description_set_features_static (PangoFontDescription *desc,
+                                            const char           *features)
+{
+  g_return_if_fail (desc != NULL);
+
+  if (desc->features == features)
+    return;
+
+  if (desc->features && !desc->static_features)
+    g_free (desc->features);
+
+  if (features)
+    {
+      desc->features = (char *)features;
+      desc->static_features = TRUE;
+      desc->mask |= PANGO_FONT_MASK_FEATURES;
+    }
+  else
+    {
+      desc->features = pfd_defaults.features;
+      desc->static_features = pfd_defaults.static_features;
+      desc->mask &= ~PANGO_FONT_MASK_FEATURES;
+    }
+}
+
+/**
+ * pango_font_description_set_features:
+ * @desc: a #PangoFontDescription
+ * @features: a string representing the features 
  *
- * Pango does not currently have a way to find supported axes of
- * a font. Both harfbuzz or freetype have API for this.
+ * Sets the features field of a font description. OpenType
+ * font features allow to change characteristics of a font,
+ * such as small caps.
  *
- * Since: 1.42
+ * The format of the variations string is the same that is allowed
+ * by CSS.
+ *
+ * Pango does not currently have a way to find features of a font.
+ * Both harfbuzz or freetype have API for this.
+ *
+ * Since: 1.44
  **/
 void
-pango_font_description_set_variations (PangoFontDescription *desc,
-                                       const char           *variations)
+pango_font_description_set_features (PangoFontDescription *desc,
+                                     const char           *features)
 {
   g_return_if_fail (desc != NULL);
 
-  pango_font_description_set_variations_static (desc, g_strdup (variations));
-  if (variations)
-    desc->static_variations = FALSE;
+  pango_font_description_set_features_static (desc, g_strdup (features));
+  if (features)
+    desc->static_features = FALSE;
 }
 
 /**
- * pango_font_description_get_variations:
+ * pango_font_description_get_features:
  * @desc: a #PangoFontDescription
  *
- * Gets the variations field of a font description. See
- * pango_font_description_set_variations().
+ * Gets the features field of a font description.
+ * See pango_font_description_set_features().
  *
- * Return value: (nullable): the varitions field for the font
+ * Return value: (nullable): the features field for the font
  *               description, or %NULL if not previously set.  This
  *               has the same life-time as the font description itself
  *               and should not be freed.
  *
- * Since: 1.42
+ * Since: 1.44
  **/
 const char *
-pango_font_description_get_variations (const PangoFontDescription *desc)
+pango_font_description_get_features (const PangoFontDescription *desc)
 {
   g_return_val_if_fail (desc != NULL, NULL);
 
-  return desc->variations;
+  return desc->features;
 }
 
 /**
@@ -639,6 +681,7 @@ pango_font_description_merge (PangoFontDescription       *desc,
 {
   gboolean family_merged;
   gboolean variations_merged;
+  gboolean features_merged;
 
   g_return_if_fail (desc != NULL);
 
@@ -647,6 +690,7 @@ pango_font_description_merge (PangoFontDescription       *desc,
 
   family_merged = desc_to_merge->family_name && (replace_existing || !desc->family_name);
   variations_merged = desc_to_merge->variations && (replace_existing || !desc->variations);
+  features_merged = desc_to_merge->features && (replace_existing || !desc->features);
 
   pango_font_description_merge_static (desc, desc_to_merge, replace_existing);
 
@@ -661,6 +705,12 @@ pango_font_description_merge (PangoFontDescription       *desc,
       desc->variations = g_strdup (desc->variations);
       desc->static_variations = FALSE;
     }
+
+  if (features_merged)
+    {
+      desc->features = g_strdup (desc->features);
+      desc->static_features = FALSE;
+    }
 }
 
 /**
@@ -710,6 +760,8 @@ pango_font_description_merge_static (PangoFontDescription       *desc,
     desc->gravity = desc_to_merge->gravity;
   if (new_mask & PANGO_FONT_MASK_VARIATIONS)
     pango_font_description_set_variations_static (desc, desc_to_merge->variations);
+  if (new_mask & PANGO_FONT_MASK_FEATURES)
+    pango_font_description_set_features_static (desc, desc_to_merge->features);
 
   desc->mask |= new_mask;
 }
@@ -787,7 +839,7 @@ pango_font_description_better_match (const PangoFontDescription *desc,
  *               %NULL.
  **/
 PangoFontDescription *
-pango_font_description_copy  (const PangoFontDescription  *desc)
+pango_font_description_copy (const PangoFontDescription  *desc)
 {
   PangoFontDescription *result;
 
@@ -807,6 +859,9 @@ pango_font_description_copy  (const PangoFontDescription  *desc)
   result->variations = g_strdup (result->variations);
   result->static_variations = FALSE;
 
+  result->features = g_strdup (result->features);
+  result->static_features = FALSE;
+
   return result;
 }
 
@@ -838,10 +893,12 @@ pango_font_description_copy_static (const PangoFontDescription *desc)
   if (result->family_name)
     result->static_family = TRUE;
 
-
   if (result->variations)
     result->static_variations = TRUE;
 
+  if (result->features)
+    result->static_features = TRUE;
+
   return result;
 }
 
@@ -875,7 +932,8 @@ pango_font_description_equal (const PangoFontDescription  *desc1,
         desc1->gravity == desc2->gravity &&
         (desc1->family_name == desc2->family_name ||
          (desc1->family_name && desc2->family_name && g_ascii_strcasecmp (desc1->family_name, 
desc2->family_name) == 0)) &&
-         (g_strcmp0 (desc1->variations, desc2->variations) == 0);
+         (g_strcmp0 (desc1->variations, desc2->variations) == 0) &&
+         (g_strcmp0 (desc1->features, desc2->features) == 0));
 }
 
 #define TOLOWER(c) \
@@ -917,6 +975,8 @@ pango_font_description_hash (const PangoFontDescription *desc)
     hash = case_insensitive_hash (desc->family_name);
   if (desc->variations)
     hash ^= g_str_hash (desc->variations);
+  if (desc->features)
+    hash ^= g_str_hash (desc->features);
   hash ^= desc->size;
   hash ^= desc->size_is_absolute ? 0xc33ca55a : 0;
   hash ^= desc->style << 16;
@@ -946,6 +1006,9 @@ pango_font_description_free  (PangoFontDescription  *desc)
   if (desc->variations && !desc->static_variations)
     g_free (desc->variations);
 
+  if (desc->features && !desc->static_features)
+    g_free (desc->features);
+
   g_slice_free (PangoFontDescription, desc);
 }
 
@@ -1210,6 +1273,23 @@ parse_variations (const char  *word,
   return TRUE;
 }
 
+static gboolean
+parse_features (const char  *word,
+                size_t       wordlen,
+                char       **features)
+{
+  if (word[0] != '#')
+    {
+      *features = NULL;
+      return FALSE;
+    }
+
+  /* XXX: actually validate here */
+  *features = g_strndup (word + 1, wordlen - 1);
+
+  return TRUE;
+}
+
 /**
  * pango_font_description_from_string:
  * @str: string representation of a font description.
@@ -1248,7 +1328,7 @@ pango_font_description_from_string (const char *str)
   len = strlen (str);
   last = str + len;
   p = getword (str, last, &wordlen, "");
-  /* Look for variations at the end of the string */
+  /* Look for variations or features at the end of the string */
   if (wordlen != 0)
     {
       if (parse_variations (p, wordlen, &desc->variations))
@@ -1256,6 +1336,11 @@ pango_font_description_from_string (const char *str)
          desc->mask |= PANGO_FONT_MASK_VARIATIONS;
          last = p;
         }
+      if (parse_features (p, wordlen, &desc->features))
+        {
+         desc->mask |= PANGO_FONT_MASK_FEATURES;
+         last = p;
+        }
     }
 
   p = getword (str, last, &wordlen, ",");
@@ -1427,6 +1512,11 @@ pango_font_description_to_string (const PangoFontDescription  *desc)
       g_string_append (result, desc->variations);
     }
 
+  if (desc->features && desc->mask & PANGO_FONT_MASK_FEATURES)
+    {
+      g_string_append (result, " #");
+      g_string_append (result, desc->features);
+    }
   return g_string_free (result, FALSE);
 }
 
diff --git a/pango/pango-font.h b/pango/pango-font.h
index 4af31a9..cc7e1ae 100644
--- a/pango/pango-font.h
+++ b/pango/pango-font.h
@@ -146,19 +146,21 @@ typedef enum {
  * @PANGO_FONT_MASK_SIZE: the font size is specified.
  * @PANGO_FONT_MASK_GRAVITY: the font gravity is specified (Since: 1.16.)
  * @PANGO_FONT_MASK_VARIATIONS: OpenType font variations are specified (Since: 1.42)
+ * @PANGO_FONT_MASK_FEATURES: OpenType font features are specified (Since: 1.44)
  *
  * The bits in a #PangoFontMask correspond to fields in a
  * #PangoFontDescription that have been set.
  */
 typedef enum {
-  PANGO_FONT_MASK_FAMILY  = 1 << 0,
-  PANGO_FONT_MASK_STYLE   = 1 << 1,
-  PANGO_FONT_MASK_VARIANT = 1 << 2,
-  PANGO_FONT_MASK_WEIGHT  = 1 << 3,
-  PANGO_FONT_MASK_STRETCH = 1 << 4,
-  PANGO_FONT_MASK_SIZE    = 1 << 5,
-  PANGO_FONT_MASK_GRAVITY = 1 << 6,
+  PANGO_FONT_MASK_FAMILY     = 1 << 0,
+  PANGO_FONT_MASK_STYLE      = 1 << 1,
+  PANGO_FONT_MASK_VARIANT    = 1 << 2,
+  PANGO_FONT_MASK_WEIGHT     = 1 << 3,
+  PANGO_FONT_MASK_STRETCH    = 1 << 4,
+  PANGO_FONT_MASK_SIZE       = 1 << 5,
+  PANGO_FONT_MASK_GRAVITY    = 1 << 6,
   PANGO_FONT_MASK_VARIATIONS = 1 << 7,
+  PANGO_FONT_MASK_FEATURES   = 1 << 8
 } PangoFontMask;
 
 /* CSS scale factors (1.2 factor between each size) */
@@ -288,6 +290,15 @@ void                 pango_font_description_set_variations    (PangoFontDescript
 PANGO_AVAILABLE_IN_1_42
 const char          *pango_font_description_get_variations    (const PangoFontDescription *desc) G_GNUC_PURE;
 
+PANGO_AVAILABLE_IN_1_44
+void                 pango_font_description_set_features_static (PangoFontDescription     *desc,
+                                                                 const char               *features);
+PANGO_AVAILABLE_IN_1_44
+void                 pango_font_description_set_features      (PangoFontDescription       *desc,
+                                                               const char                 *features);
+PANGO_AVAILABLE_IN_1_44
+const char          *pango_font_description_get_features      (const PangoFontDescription *desc) G_GNUC_PURE;
+
 PANGO_AVAILABLE_IN_ALL
 PangoFontMask pango_font_description_get_set_fields (const PangoFontDescription *desc) G_GNUC_PURE;
 PANGO_AVAILABLE_IN_ALL


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