diff options
Diffstat (limited to 'pango/fonts.c')
-rw-r--r-- | pango/fonts.c | 172 |
1 files changed, 162 insertions, 10 deletions
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 */ }; @@ -480,6 +485,98 @@ pango_font_description_get_gravity (const PangoFontDescription *desc) } /** + * 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); } |