From efa66e7b634050ef395418b544b012a4a5183973 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 5 Sep 2017 07:37:31 -0400 Subject: Add initial support for OpenType font variations This commit lets PangoFontDescription carry font variation information as a string. Only pangocairo has been updated to make use of this information. We pass it to harfbuzz for shaping, and we pass it to cairo when creating scaled fonts. --- docs/pango-sections.txt | 3 + pango/fonts.c | 172 +++++++++++++++++++++++++++++++++++++++++++--- pango/pango-font.h | 13 +++- pango/pangocairo-fcfont.c | 17 ++++- pango/pangofc-fontmap.c | 43 +++++++++++- pango/pangofc-fontmap.h | 13 ++++ pango/pangofc-shape.c | 45 ++++++++++++ 7 files changed, 291 insertions(+), 15 deletions(-) diff --git a/docs/pango-sections.txt b/docs/pango-sections.txt index 3573fb61..42e2581b 100644 --- a/docs/pango-sections.txt +++ b/docs/pango-sections.txt @@ -199,6 +199,9 @@ pango_font_description_set_absolute_size pango_font_description_get_size_is_absolute pango_font_description_set_gravity pango_font_description_get_gravity +pango_font_description_set_variations +pango_font_description_set_variations_static +pango_font_description_get_variations pango_font_description_get_set_fields pango_font_description_unset_fields pango_font_description_merge diff --git a/pango/fonts.c b/pango/fonts.c index 49e035b8..d9a07c0b 100644 --- a/pango/fonts.c +++ b/pango/fonts.c @@ -52,8 +52,11 @@ struct _PangoFontDescription PangoStretch stretch; PangoGravity gravity; + char *variations; + guint16 mask; guint static_family : 1; + guint static_variations : 1; guint size_is_absolute : 1; int size; @@ -71,10 +74,12 @@ static const PangoFontDescription pfd_defaults = { PANGO_WEIGHT_NORMAL, /* weight */ PANGO_STRETCH_NORMAL, /* stretch */ PANGO_GRAVITY_SOUTH, /* gravity */ + NULL, /* variations */ 0, /* mask */ 0, /* static_family */ - FALSE, /* size_is_absolute */ + 0, /* static_variations*/ + 0, /* size_is_absolute */ 0, /* size */ }; @@ -479,6 +484,98 @@ pango_font_description_get_gravity (const PangoFontDescription *desc) return desc->gravity; } +/** + * pango_font_description_set_variations_static: + * @desc: a #PangoFontDescription + * @variations: a string representing the variations + * + * Like pango_font_description_set_variations(), except that no + * copy of @variations 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 + * @variations is a static string such as a C string literal, or + * if @desc is only needed temporarily. + * + * Since: 1.42 + **/ +void +pango_font_description_set_variations_static (PangoFontDescription *desc, + const char *variations) +{ + g_return_if_fail (desc != NULL); + + if (desc->variations == variations) + return; + + if (desc->variations && !desc->static_variations) + g_free (desc->variations); + + if (variations) + { + desc->variations = (char *)variations; + desc->static_variations = TRUE; + desc->mask |= PANGO_FONT_MASK_VARIATIONS; + } + else + { + desc->variations = pfd_defaults.variations; + desc->static_variations = pfd_defaults.static_variations; + desc->mask &= ~PANGO_FONT_MASK_VARIATIONS; + } +} + +/** + * pango_font_description_set_variations: + * @desc: a #PangoFontDescription. + * @variations: a string representing the variations + * + * 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. + * + * 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. + * + * Pango does not currently have a way to find supported axes of + * a font. Both harfbuzz or freetype have API for this. + * + * Since: 1.42 + **/ +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; +} + +/** + * pango_font_description_get_variations: + * @desc: a #PangoFontDescription + * + * Gets the variations field of a font description. See + * pango_font_description_set_variations(). + * + * Return value: (nullable): the varitions 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 + **/ +const char * +pango_font_description_get_variations (const PangoFontDescription *desc) +{ + g_return_val_if_fail (desc != NULL, NULL); + + return desc->variations; +} + /** * pango_font_description_get_set_fields: * @desc: a #PangoFontDescription @@ -541,6 +638,7 @@ pango_font_description_merge (PangoFontDescription *desc, gboolean replace_existing) { gboolean family_merged; + gboolean variations_merged; g_return_if_fail (desc != NULL); @@ -548,6 +646,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); @@ -556,6 +655,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; + } } /** @@ -603,6 +708,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; } @@ -697,6 +804,9 @@ pango_font_description_copy (const PangoFontDescription *desc) result->static_family = FALSE; } + result->variations = g_strdup (result->variations); + result->static_variations = FALSE; + return result; } @@ -728,6 +838,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; } @@ -760,7 +874,8 @@ pango_font_description_equal (const PangoFontDescription *desc1, desc1->size_is_absolute == desc2->size_is_absolute && 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)); + (desc1->family_name && desc2->family_name && g_ascii_strcasecmp (desc1->family_name, desc2->family_name) == 0)) && + (g_strcmp0 (desc1->variations, desc2->variations) == 0); } #define TOLOWER(c) \ @@ -800,6 +915,8 @@ pango_font_description_hash (const PangoFontDescription *desc) if (desc->family_name) hash = case_insensitive_hash (desc->family_name); + if (desc->variations) + hash ^= g_str_hash (desc->variations); hash ^= desc->size; hash ^= desc->size_is_absolute ? 0xc33ca55a : 0; hash ^= desc->style << 16; @@ -826,6 +943,9 @@ pango_font_description_free (PangoFontDescription *desc) if (desc->family_name && !desc->static_family) g_free (desc->family_name); + if (desc->variations && !desc->static_variations) + g_free (desc->variations); + g_slice_free (PangoFontDescription, desc); } @@ -1031,7 +1151,7 @@ find_field_any (const char *str, int len, PangoFontDescription *desc) } static const char * -getword (const char *str, const char *last, size_t *wordlen) +getword (const char *str, const char *last, size_t *wordlen, const char *stop) { const char *result; @@ -1039,7 +1159,7 @@ getword (const char *str, const char *last, size_t *wordlen) last--; result = last; - while (result > str && !g_ascii_isspace (*(result - 1)) && *(result - 1) != ',') + while (result > str && !g_ascii_isspace (*(result - 1)) && !strchr (stop, *(result - 1))) result--; *wordlen = last - result; @@ -1073,6 +1193,23 @@ parse_size (const char *word, return FALSE; } +static gboolean +parse_variations (const char *word, + size_t wordlen, + char **variations) +{ + if (word[0] != '@') + { + *variations = NULL; + return FALSE; + } + + /* XXX: actually validate here */ + *variations = g_strndup (word + 1, wordlen - 1); + + return TRUE; +} + /** * pango_font_description_from_string: * @str: string representation of a font description. @@ -1110,10 +1247,19 @@ pango_font_description_from_string (const char *str) len = strlen (str); last = str + len; - p = getword (str, last, &wordlen); + p = getword (str, last, &wordlen, ""); + /* Look for variations at the end of the string */ + if (wordlen != 0) + { + if (parse_variations (p, wordlen, &desc->variations)) + { + desc->mask |= PANGO_FONT_MASK_VARIATIONS; + last = p; + } + } - /* Look for a size at the end of the string - */ + p = getword (str, last, &wordlen, ","); + /* Look for a size */ if (wordlen != 0) { gboolean size_is_absolute; @@ -1127,7 +1273,7 @@ pango_font_description_from_string (const char *str) /* Now parse style words */ - p = getword (str, last, &wordlen); + p = getword (str, last, &wordlen, ","); while (wordlen != 0) { if (!find_field_any (p, wordlen, desc)) @@ -1135,7 +1281,7 @@ pango_font_description_from_string (const char *str) else { last = p; - p = getword (str, last, &wordlen); + p = getword (str, last, &wordlen, ","); } } @@ -1234,7 +1380,7 @@ pango_font_description_to_string (const PangoFontDescription *desc) * in a keyword like "Bold", or if the family name ends in * a number and no keywords will be added. */ - p = getword (desc->family_name, desc->family_name + strlen(desc->family_name), &wordlen); + p = getword (desc->family_name, desc->family_name + strlen(desc->family_name), &wordlen, ","); if (wordlen != 0 && (find_field_any (p, wordlen, NULL) || (parse_size (p, wordlen, NULL, NULL) && @@ -1275,6 +1421,12 @@ pango_font_description_to_string (const PangoFontDescription *desc) g_string_append (result, "px"); } + if (desc->variations && desc->mask & PANGO_FONT_MASK_VARIATIONS) + { + g_string_append (result, " @"); + g_string_append (result, desc->variations); + } + return g_string_free (result, FALSE); } diff --git a/pango/pango-font.h b/pango/pango-font.h index a9702954..4af31a95 100644 --- a/pango/pango-font.h +++ b/pango/pango-font.h @@ -145,6 +145,7 @@ typedef enum { * @PANGO_FONT_MASK_STRETCH: the font stretch is specified. * @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) * * The bits in a #PangoFontMask correspond to fields in a * #PangoFontDescription that have been set. @@ -156,7 +157,8 @@ typedef enum { 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_GRAVITY = 1 << 6, + PANGO_FONT_MASK_VARIATIONS = 1 << 7, } PangoFontMask; /* CSS scale factors (1.2 factor between each size) */ @@ -277,6 +279,15 @@ void pango_font_description_set_gravity (PangoFontDescript PANGO_AVAILABLE_IN_1_16 PangoGravity pango_font_description_get_gravity (const PangoFontDescription *desc) G_GNUC_PURE; +PANGO_AVAILABLE_IN_1_42 +void pango_font_description_set_variations_static (PangoFontDescription *desc, + const char *settings); +PANGO_AVAILABLE_IN_1_42 +void pango_font_description_set_variations (PangoFontDescription *desc, + const char *settings); +PANGO_AVAILABLE_IN_1_42 +const char *pango_font_description_get_variations (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 diff --git a/pango/pangocairo-fcfont.c b/pango/pangocairo-fcfont.c index 30ecde4d..ef4273e7 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 +#include + #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)) @@ -222,6 +225,8 @@ _pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap, FcMatrix fc_matrix, *fc_matrix_val; double size; int i; + cairo_font_options_t *options; + const char *variations; g_return_val_if_fail (PANGO_IS_CAIRO_FC_FONT_MAP (cffontmap), NULL); g_return_val_if_fail (pattern != NULL, NULL); @@ -247,13 +252,23 @@ _pango_cairo_fc_font_new (PangoCairoFcFontMap *cffontmap, cairo_matrix_scale (&font_matrix, size, size); + options = pango_fc_font_key_get_context_key (key); + variations = pango_fc_font_key_get_variations (key); + if (variations) { + options = cairo_font_options_copy (options); + cairo_font_options_set_variations (options, variations); + } + _pango_cairo_font_private_initialize (&cffont->cf_priv, (PangoCairoFont *) cffont, get_gravity (pattern), - pango_fc_font_key_get_context_key (key), + options, pango_fc_font_key_get_matrix (key), &font_matrix); + if (variations) + cairo_font_options_destroy (options); + ((PangoFcFont *)(cffont))->is_hinted = _pango_cairo_font_private_is_metrics_hinted (&cffont->cf_priv); return (PangoFcFont *) cffont; diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c index 70e9ee7e..c5e95c44 100644 --- a/pango/pangofc-fontmap.c +++ b/pango/pangofc-fontmap.c @@ -357,6 +357,7 @@ struct _PangoFcFontsetKey { int pixelsize; double resolution; gpointer context_key; + char *variations; }; struct _PangoFcFontKey { @@ -364,6 +365,7 @@ struct _PangoFcFontKey { FcPattern *pattern; PangoMatrix matrix; gpointer context_key; + char *variations; }; static void @@ -381,8 +383,9 @@ pango_fc_fontset_key_init (PangoFcFontsetKey *key, key->pixelsize = get_scaled_size (fcfontmap, context, desc); key->resolution = pango_fc_font_map_get_resolution (fcfontmap, context); key->language = language; + key->variations = g_strdup (pango_font_description_get_variations (desc)); key->desc = pango_font_description_copy_static (desc); - pango_font_description_unset_fields (key->desc, PANGO_FONT_MASK_SIZE); + pango_font_description_unset_fields (key->desc, PANGO_FONT_MASK_SIZE | PANGO_FONT_MASK_VARIATIONS); if (context && PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get) key->context_key = (gpointer)PANGO_FC_FONT_MAP_GET_CLASS (fcfontmap)->context_key_get (fcfontmap, context); @@ -397,6 +400,8 @@ pango_fc_fontset_key_equal (const PangoFcFontsetKey *key_a, if (key_a->language == key_b->language && key_a->pixelsize == key_b->pixelsize && key_a->resolution == key_b->resolution && + ((key_a->variations == NULL && key_b->variations == NULL) || + (key_a->variations && key_b->variations && (strcmp (key_a->variations, key_b->variations) == 0))) && pango_font_description_equal (key_a->desc, key_b->desc) && 0 == memcmp (&key_a->matrix, &key_b->matrix, 4 * sizeof (double))) { @@ -422,6 +427,9 @@ pango_fc_fontset_key_hash (const PangoFcFontsetKey *key) hash ^= key->pixelsize; + if (key->variations) + hash ^= g_str_hash (key->variations); + if (key->context_key) hash ^= PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap, key->context_key); @@ -435,6 +443,7 @@ static void pango_fc_fontset_key_free (PangoFcFontsetKey *key) { pango_font_description_free (key->desc); + g_free (key->variations); if (key->context_key) PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_free (key->fontmap, @@ -454,6 +463,8 @@ pango_fc_fontset_key_copy (const PangoFcFontsetKey *old) key->matrix = old->matrix; key->pixelsize = old->pixelsize; key->resolution = old->resolution; + key->variations = g_strdup (old->variations); + if (old->context_key) key->context_key = PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_copy (key->fontmap, old->context_key); @@ -569,6 +580,8 @@ pango_fc_font_key_equal (const PangoFcFontKey *key_a, const PangoFcFontKey *key_b) { if (key_a->pattern == key_b->pattern && + ((key_a->variations == NULL && key_b->variations == NULL) || + (key_a->variations && key_b->variations && (strcmp (key_a->variations, key_b->variations) == 0))) && 0 == memcmp (&key_a->matrix, &key_b->matrix, 4 * sizeof (double))) { if (key_a->context_key && key_b->context_key) @@ -590,6 +603,9 @@ pango_fc_font_key_hash (const PangoFcFontKey *key) /* We do a bytewise hash on the doubles */ hash = hash_bytes_fnv ((unsigned char *)(&key->matrix), sizeof (double) * 4, hash); + if (key->variations) + hash ^= g_str_hash (key->variations); + if (key->context_key) hash ^= PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_hash (key->fontmap, key->context_key); @@ -607,6 +623,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->variations); + g_slice_free (PangoFcFontKey, key); } @@ -619,6 +637,7 @@ pango_fc_font_key_copy (const PangoFcFontKey *old) FcPatternReference (old->pattern); key->pattern = old->pattern; key->matrix = old->matrix; + key->variations = g_strdup (old->variations); if (old->context_key) key->context_key = PANGO_FC_FONT_MAP_GET_CLASS (key->fontmap)->context_key_copy (key->fontmap, old->context_key); @@ -637,6 +656,7 @@ pango_fc_font_key_init (PangoFcFontKey *key, key->fontmap = fcfontmap; key->pattern = pattern; key->matrix = *pango_fc_fontset_key_get_matrix (fontset_key); + key->variations = g_strdup (fontset_key->variations); key->context_key = pango_fc_fontset_key_get_context_key (fontset_key); } @@ -690,6 +710,11 @@ pango_fc_font_key_get_context_key (const PangoFcFontKey *key) return key->context_key; } +const char * +pango_fc_font_key_get_variations (const PangoFcFontKey *key) +{ + return key->variations; +} /* * PangoFcPatterns @@ -1445,7 +1470,8 @@ static FcPattern * pango_fc_make_pattern (const PangoFontDescription *description, PangoLanguage *language, int pixel_size, - double dpi) + double dpi, + const char *variations) { FcPattern *pattern; const char *prgname; @@ -1490,6 +1516,7 @@ pango_fc_make_pattern (const PangoFontDescription *description, FC_DPI, FcTypeDouble, dpi, FC_SIZE, FcTypeDouble, pixel_size * (72. / 1024. / dpi), FC_PIXEL_SIZE, FcTypeDouble, pixel_size / 1024., + PANGO_FC_FONT_VARIATIONS, FcTypeString, variations ? variations : "", NULL); if (pango_font_description_get_family (description)) @@ -1655,7 +1682,8 @@ pango_fc_fontset_key_make_pattern (PangoFcFontsetKey *key) return pango_fc_make_pattern (key->desc, key->language, key->pixelsize, - key->resolution); + key->resolution, + key->variations); } static PangoFcPatterns * @@ -1739,12 +1767,14 @@ pango_fc_fontset_cache (PangoFcFontset *fontset, { /* Add to cache initially */ +#if 1 if (cache->length == FONTSET_CACHE_SIZE) { PangoFcFontset *tmp_fontset = g_queue_pop_tail (cache); tmp_fontset->cache_link = NULL; g_hash_table_remove (priv->fontset_hash, tmp_fontset->key); } +#endif fontset->cache_link = g_list_prepend (NULL, fontset); } @@ -1783,6 +1813,7 @@ pango_fc_font_map_load_fontset (PangoFontMap *fontmap, pango_fc_fontset_cache (fontset, fcfontmap); pango_font_description_free (key.desc); + g_free (key.variations); return g_object_ref (fontset); } @@ -2287,6 +2318,12 @@ pango_fc_font_description_from_pattern (FcPattern *pattern, gboolean include_siz pango_font_description_set_gravity (desc, gravity); } + if (include_size && FcPatternGetString (pattern, PANGO_FC_FONT_VARIATIONS, 0, (FcChar8 **)&s) == FcResultMatch) + { + if (s && *s) + pango_font_description_set_variations (desc, (char *)s); + } + return desc; } diff --git a/pango/pangofc-fontmap.h b/pango/pangofc-fontmap.h index 4dab0839..63452a83 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_variations (const PangoFcFontKey *key); #endif @@ -311,6 +313,17 @@ PangoFontDescription *pango_fc_font_description_from_pattern (FcPattern *pattern */ #define PANGO_FC_FONT_FEATURES "fontfeatures" +/** + * PANGO_FC_FONT_VARIATIONS: + * + * String representing a fontconfig property name that Pango reads from font + * patterns to populate list of OpenType font variations to be used for a font. + * + * The property will have a number of string elements, each of which is the + * OpenType axis setting of the form AXIS=VALUE. + */ +#define PANGO_FC_FONT_VARIATIONS "fontvariations" + G_END_DECLS #endif /* __PANGO_FC_FONT_MAP_H__ */ diff --git a/pango/pangofc-shape.c b/pango/pangofc-shape.c index 57f70000..a59ca67c 100644 --- a/pango/pangofc-shape.c +++ b/pango/pangofc-shape.c @@ -278,6 +278,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, @@ -306,6 +338,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); @@ -347,6 +380,18 @@ _pango_fc_shape (PangoFont *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_variations (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); hb_direction = PANGO_GRAVITY_IS_VERTICAL (analysis->gravity) ? HB_DIRECTION_TTB : HB_DIRECTION_LTR; -- cgit v1.2.1