summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2018-04-24 16:54:14 -0400
committerMatthias Clasen <mclasen@redhat.com>2018-04-24 17:35:44 -0400
commitd026e96e7da91ade2aecfb02ad2144cd406c0d6e (patch)
tree32e193ae0dca068a8dcb4cafa31f1d275c619a67
parent74e7a3356da7e12d7d51297ea1e75976fd1c3ec3 (diff)
downloadpango-d026e96e7da91ade2aecfb02ad2144cd406c0d6e.tar.gz
Allow setting OpenType features on font descriptions
-rw-r--r--pango/fonts.c162
-rw-r--r--pango/pango-font.h25
2 files changed, 170 insertions, 17 deletions
diff --git a/pango/fonts.c b/pango/fonts.c
index d9a07c0b..1617c0b7 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 */
@@ -526,7 +530,7 @@ pango_font_description_set_variations_static (PangoFontDescription *desc,
/**
* pango_font_description_set_variations:
- * @desc: a #PangoFontDescription.
+ * @desc: a #PangoFontDescription
* @variations: a string representing the variations
*
* Sets the variations field of a font description. OpenType
@@ -558,15 +562,15 @@ pango_font_description_set_variations (PangoFontDescription *desc,
* pango_font_description_get_variations:
* @desc: a #PangoFontDescription
*
- * Gets the variations field of a font description. See
- * pango_font_description_set_variations().
+ * Gets the variations field of a font description.
+ * See pango_font_description_set_variations().
*
- * Return value: (nullable): the varitions field for the font
+ * Return value: (nullable): the variations 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)
@@ -577,6 +581,96 @@ pango_font_description_get_variations (const PangoFontDescription *desc)
}
/**
+ * pango_font_description_set_features_static:
+ * @desc: a #PangoFontDescription
+ * @features: a string representing the features
+ *
+ * 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.
+ *
+ * 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
+ *
+ * Sets the features field of a font description. OpenType
+ * font features allow to change characteristics of a font,
+ * such as small caps.
+ *
+ * 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_features (PangoFontDescription *desc,
+ const char *features)
+{
+ g_return_if_fail (desc != NULL);
+
+ pango_font_description_set_features_static (desc, g_strdup (features));
+ if (features)
+ desc->static_features = FALSE;
+}
+
+/**
+ * pango_font_description_get_features:
+ * @desc: a #PangoFontDescription
+ *
+ * Gets the features field of a font description.
+ * See pango_font_description_set_features().
+ *
+ * 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.44
+ **/
+const char *
+pango_font_description_get_features (const PangoFontDescription *desc)
+{
+ g_return_val_if_fail (desc != NULL, NULL);
+
+ return desc->features;
+}
+
+/**
* pango_font_description_get_set_fields:
* @desc: a #PangoFontDescription
*
@@ -639,6 +733,7 @@ pango_font_description_merge (PangoFontDescription *desc,
{
gboolean family_merged;
gboolean variations_merged;
+ gboolean features_merged;
g_return_if_fail (desc != NULL);
@@ -647,6 +742,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 +757,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 +812,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 +891,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 +911,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 +945,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 +984,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 +1027,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 +1058,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 +1325,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 +1380,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 +1388,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 +1564,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 4af31a95..cc7e1ae5 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