[pango] Bug 738505 - Add fontfeatures support in PangoAttributes and markup



commit ba53f29f7c2c105becb898d6417a4c160b7fc1e5
Author: Behdad Esfahbod <behdad behdad org>
Date:   Thu Jun 18 11:49:40 2015 -0700

    Bug 738505 - Add fontfeatures support in PangoAttributes and markup
    
    https://bugzilla.gnome.org/show_bug.cgi?id=738505
    
    Patch from Matthias Clasen, based on early patch from Akira TAGOH.
    
    There's room for improvement in how this is done, but it works now
    for simple cases, which is what most people will be using it for.
    
    Finally!

 docs/pango-sections.txt  |    2 +
 pango-view/Makefile.am   |    1 +
 pango/pango-attributes.c |   51 ++++++++++++++++++++++++++++++++++++----------
 pango/pango-attributes.h |   21 ++++++++++++++++++-
 pango/pango-layout.c     |    5 ++++
 pango/pango-markup.c     |   12 +++++++++-
 pango/pangofc-shape.c    |   39 +++++++++++++++++++++++++++++++++++
 7 files changed, 117 insertions(+), 14 deletions(-)
---
diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt
index 43bdf83..0401a15 100644
--- a/docs/pango-sections.txt
+++ b/docs/pango-sections.txt
@@ -336,6 +336,7 @@ PangoAttrFloat
 PangoAttrFontDesc
 PangoAttrShape
 PangoAttrSize
+PangoAttrFontFeatures
 pango_parse_markup
 pango_markup_parser_new
 pango_markup_parser_finish
@@ -379,6 +380,7 @@ pango_attr_letter_spacing_new
 pango_attr_fallback_new
 pango_attr_gravity_new
 pango_attr_gravity_hint_new
+pango_attr_font_features_new
 PangoColor
 PANGO_TYPE_COLOR
 pango_color_parse
diff --git a/pango-view/Makefile.am b/pango-view/Makefile.am
index ffb937d..b432e50 100644
--- a/pango-view/Makefile.am
+++ b/pango-view/Makefile.am
@@ -4,6 +4,7 @@ TEST_TEXTS =                    \
        test-arabic.txt         \
        test-chinese.txt        \
        test-devanagari.txt     \
+       test-feature-tag.markup \
        test-gurmukhi.txt       \
        test-hebrew.txt         \
        test-ipa.txt            \
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 72455ac..da9fefe 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -1101,6 +1101,31 @@ pango_attr_gravity_hint_new (PangoGravityHint hint)
   return pango_attr_int_new (&klass, (int)hint);
 }
 
+/**
+ * pango_attr_font_features_new:
+ * @features: a string with OpenType font features, in CSS syntax
+ *
+ * Create a new font features tag attribute.
+ *
+ * Return value: (transfer full): the newly allocated #PangoAttribute,
+ *               which should be freed with pango_attribute_destroy().
+ *
+ * Since: 1.38
+ **/
+PangoAttribute *
+pango_attr_font_features_new (const gchar *features)
+{
+  static const PangoAttrClass klass = {
+    PANGO_ATTR_FONT_FEATURES,
+    pango_attr_string_copy,
+    pango_attr_string_destroy,
+    pango_attr_string_equal
+  };
+
+  g_return_val_if_fail (features != NULL, NULL);
+
+  return pango_attr_string_new (&klass, features);
+}
 
 /*
  * Attribute List
@@ -1928,17 +1953,21 @@ pango_attr_iterator_get_font (PangoAttrIterator     *iterator,
              gboolean found = FALSE;
 
              tmp_list2 = *extra_attrs;
-             while (tmp_list2)
-               {
-                 PangoAttribute *old_attr = tmp_list2->data;
-                 if (attr->klass->type == old_attr->klass->type)
-                   {
-                     found = TRUE;
-                     break;
-                   }
-
-                 tmp_list2 = tmp_list2->next;
-               }
+             /* Hack: special-case FONT_FEATURES.  We don't want them to
+              * override each other, so we never merge them.  This should
+              * be fixed when we implement attr-merging. */
+             if (attr->klass->type != PANGO_ATTR_FONT_FEATURES)
+               while (tmp_list2)
+                 {
+                   PangoAttribute *old_attr = tmp_list2->data;
+                   if (attr->klass->type == old_attr->klass->type)
+                     {
+                       found = TRUE;
+                       break;
+                     }
+
+                   tmp_list2 = tmp_list2->next;
+                 }
 
              if (!found)
                *extra_attrs = g_slist_prepend (*extra_attrs, pango_attribute_copy (attr));
diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h
index 1e0feb7..684b4a9 100644
--- a/pango/pango-attributes.h
+++ b/pango/pango-attributes.h
@@ -75,6 +75,7 @@ typedef struct _PangoAttrFloat    PangoAttrFloat;
 typedef struct _PangoAttrColor    PangoAttrColor;
 typedef struct _PangoAttrFontDesc PangoAttrFontDesc;
 typedef struct _PangoAttrShape    PangoAttrShape;
+typedef struct _PangoAttrFontFeatures PangoAttrFontFeatures;
 
 /**
  * PANGO_TYPE_ATTR_LIST:
@@ -167,7 +168,8 @@ typedef enum
   PANGO_ATTR_STRIKETHROUGH_COLOR,/* PangoAttrColor */
   PANGO_ATTR_ABSOLUTE_SIZE,    /* PangoAttrSize */
   PANGO_ATTR_GRAVITY,          /* PangoAttrInt */
-  PANGO_ATTR_GRAVITY_HINT      /* PangoAttrInt */
+  PANGO_ATTR_GRAVITY_HINT,     /* PangoAttrInt */
+  PANGO_ATTR_FONT_FEATURES     /* PangoAttrString */
 } PangoAttrType;
 
 /**
@@ -406,6 +408,22 @@ struct _PangoAttrFontDesc
   PangoFontDescription *desc;
 };
 
+/**
+ * PangoAttrFontFeatures:
+ * @attr: the common portion of the attribute
+ * @features: the featues, as a string in CSS syntax
+ *
+ * The #PangoAttrFontFeatures structure is used to represent OpenType
+ * font features as an attribute.
+ *
+ * Since: 1.38
+ */
+struct _PangoAttrFontFeatures
+{
+  PangoAttribute attr;
+  gchar *features;
+};
+
 PangoAttrType         pango_attr_type_register (const gchar        *name);
 const char *          pango_attr_type_get_name (PangoAttrType       type) G_GNUC_CONST;
 
@@ -456,6 +474,7 @@ PangoAttribute *pango_attr_shape_new_with_data (const PangoRectangle       *ink_
 
 PangoAttribute *pango_attr_gravity_new      (PangoGravity     gravity);
 PangoAttribute *pango_attr_gravity_hint_new (PangoGravityHint hint);
+PangoAttribute *pango_attr_font_features_new (const gchar *features);
 
 GType              pango_attr_list_get_type      (void) G_GNUC_CONST;
 PangoAttrList *    pango_attr_list_new           (void);
diff --git a/pango/pango-layout.c b/pango/pango-layout.c
index 934e22a..862ae8b 100644
--- a/pango/pango-layout.c
+++ b/pango/pango-layout.c
@@ -3852,6 +3852,11 @@ no_shape_filter_func (PangoAttribute *attribute,
     PANGO_ATTR_UNDERLINE,
     PANGO_ATTR_STRIKETHROUGH,
     PANGO_ATTR_RISE
+    /* Ideally we want font-features here, because we don't
+     * want it to break shaping runs.  But if we put it here,
+     * it won't show up in the shaper anymore :(.  To be
+     * fixed later. */
+    /* PANGO_ATTR_FONT_FEATURES */
   };
 
   int i;
diff --git a/pango/pango-markup.c b/pango/pango-markup.c
index c96c29e..aedf96f 100644
--- a/pango/pango-markup.c
+++ b/pango/pango-markup.c
@@ -1077,6 +1077,7 @@ span_parse_func     (MarkupData            *md G_GNUC_UNUSED,
   const char *fallback = NULL;
   const char *gravity = NULL;
   const char *gravity_hint = NULL;
+  const char *font_features = NULL;
 
   g_markup_parse_context_get_position (context,
                                       &line_number, &char_number);
@@ -1119,7 +1120,9 @@ span_parse_func     (MarkupData            *md G_GNUC_UNUSED,
        CHECK_ATTRIBUTE2(weight, "font_weight");
 
        CHECK_ATTRIBUTE (foreground);
-       CHECK_ATTRIBUTE2 (foreground, "fgcolor");
+       CHECK_ATTRIBUTE2(foreground, "fgcolor");
+
+       CHECK_ATTRIBUTE (font_features);
        break;
       case 's':
        CHECK_ATTRIBUTE (size);
@@ -1142,7 +1145,7 @@ span_parse_func     (MarkupData            *md G_GNUC_UNUSED,
        break;
       default:
        CHECK_ATTRIBUTE (background);
-       CHECK_ATTRIBUTE2 (background, "bgcolor");
+       CHECK_ATTRIBUTE2(background, "bgcolor");
        CHECK_ATTRIBUTE2(foreground, "color");
        CHECK_ATTRIBUTE (rise);
        CHECK_ATTRIBUTE (variant);
@@ -1431,6 +1434,11 @@ span_parse_func     (MarkupData            *md G_GNUC_UNUSED,
                     pango_attr_language_new (pango_language_from_string (lang)));
     }
 
+  if (G_UNLIKELY (font_features))
+    {
+      add_attribute (tag, pango_attr_font_features_new (font_features));
+    }
+
   return TRUE;
 
  error:
diff --git a/pango/pangofc-shape.c b/pango/pangofc-shape.c
index 2f6c7cc..f94f5eb 100644
--- a/pango/pangofc-shape.c
+++ b/pango/pangofc-shape.c
@@ -377,6 +377,45 @@ _pango_fc_shape (PangoFont           *font,
        }
     }
 
+  if (analysis->extra_attrs)
+    {
+      GSList *tmp_attrs;
+
+      for (tmp_attrs = analysis->extra_attrs; tmp_attrs && num_features < G_N_ELEMENTS (features); tmp_attrs 
= tmp_attrs->next)
+       {
+        if (((PangoAttribute *) tmp_attrs->data)->klass->type == PANGO_ATTR_FONT_FEATURES)
+          {
+            const PangoAttrFontFeatures *fattr = (const PangoAttrFontFeatures *) tmp_attrs->data;
+             const gchar *feat;
+             const gchar *end;
+             int len;
+
+             feat = fattr->features;
+
+             while (feat != NULL && num_features < G_N_ELEMENTS (features))
+               {
+                 end = strchr (feat, ',');
+                 if (end)
+                   len = end - feat;
+                 else
+                   len = -1;
+
+                 if (hb_feature_from_string (feat, len, &features[num_features]))
+                 {
+                   num_features++;
+                   features[num_features].start = 0;
+                   features[num_features].end = -1;
+                 }
+
+                 if (end == NULL)
+                   break;
+
+                 feat = end + 1;
+               }
+          }
+       }
+    }
+
   hb_shape (hb_font, hb_buffer, features, num_features);
 
   if (PANGO_GRAVITY_IS_IMPROPER (analysis->gravity))


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