summaryrefslogtreecommitdiff
path: root/pango
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2015-06-18 11:49:40 -0700
committerBehdad Esfahbod <behdad@behdad.org>2015-06-18 11:49:40 -0700
commitba53f29f7c2c105becb898d6417a4c160b7fc1e5 (patch)
tree3bf0d589b0d549192fbbe0dc321fcd4235c416d6 /pango
parentdfe7ec760e08485520668ed1e2585c85545fc013 (diff)
downloadpango-ba53f29f7c2c105becb898d6417a4c160b7fc1e5.tar.gz
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!
Diffstat (limited to 'pango')
-rw-r--r--pango/pango-attributes.c51
-rw-r--r--pango/pango-attributes.h21
-rw-r--r--pango/pango-layout.c5
-rw-r--r--pango/pango-markup.c12
-rw-r--r--pango/pangofc-shape.c39
5 files changed, 114 insertions, 14 deletions
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 72455acd..da9fefeb 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 1e0feb7c..684b4a9f 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 934e22ae..862ae8b3 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 c96c29e9..aedf96f9 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 2f6c7cca..f94f5ebb 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))