diff options
author | Matthias Clasen <mclasen@redhat.com> | 2022-02-12 10:06:41 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2022-02-17 14:01:45 -0600 |
commit | dcfcde31bffc46892d99a144c3b06a4e9ee08654 (patch) | |
tree | ed8eebf87125bcfeab787764572221c475675843 | |
parent | 0d4a208635f2f3f5fd225c343f46877aac60246b (diff) | |
download | pango-dcfcde31bffc46892d99a144c3b06a4e9ee08654.tar.gz |
Move PangoFontDescription to its own files
-rw-r--r-- | pango/fonts.c | 1657 | ||||
-rw-r--r-- | pango/meson.build | 2 | ||||
-rw-r--r-- | pango/pango-font-description.c | 1684 | ||||
-rw-r--r-- | pango/pango-font-description.h | 324 | ||||
-rw-r--r-- | pango/pango-font.h | 294 | ||||
-rw-r--r-- | pango/pango.h | 1 |
6 files changed, 2012 insertions, 1950 deletions
diff --git a/pango/fonts.c b/pango/fonts.c index 8cc02b48..2a226d89 100644 --- a/pango/fonts.c +++ b/pango/fonts.c @@ -31,1663 +31,6 @@ #include "pango-fontmap.h" #include "pango-impl-utils.h" -struct _PangoFontDescription -{ - char *family_name; - - PangoStyle style; - PangoVariant variant; - PangoWeight weight; - PangoStretch stretch; - PangoGravity gravity; - - char *variations; - - guint16 mask; - guint static_family : 1; - guint static_variations : 1; - guint size_is_absolute : 1; - - int size; -}; - -G_DEFINE_BOXED_TYPE (PangoFontDescription, pango_font_description, - pango_font_description_copy, - pango_font_description_free); - -static const PangoFontDescription pfd_defaults = { - NULL, /* family_name */ - - PANGO_STYLE_NORMAL, /* style */ - PANGO_VARIANT_NORMAL, /* variant */ - PANGO_WEIGHT_NORMAL, /* weight */ - PANGO_STRETCH_NORMAL, /* stretch */ - PANGO_GRAVITY_SOUTH, /* gravity */ - NULL, /* variations */ - - 0, /* mask */ - 0, /* static_family */ - 0, /* static_variations*/ - 0, /* size_is_absolute */ - - 0, /* size */ -}; - -/** - * pango_font_description_new: - * - * Creates a new font description structure with all fields unset. - * - * Return value: the newly allocated `PangoFontDescription`, which - * should be freed using [method@Pango.FontDescription.free]. - */ -PangoFontDescription * -pango_font_description_new (void) -{ - PangoFontDescription *desc = g_slice_new (PangoFontDescription); - - *desc = pfd_defaults; - - return desc; -} - -/** - * pango_font_description_set_family: - * @desc: a `PangoFontDescription`. - * @family: a string representing the family name. - * - * Sets the family name field of a font description. - * - * The family - * name represents a family of related font styles, and will - * resolve to a particular `PangoFontFamily`. In some uses of - * `PangoFontDescription`, it is also possible to use a comma - * separated list of family names for this field. - */ -void -pango_font_description_set_family (PangoFontDescription *desc, - const char *family) -{ - g_return_if_fail (desc != NULL); - - pango_font_description_set_family_static (desc, family ? g_strdup (family) : NULL); - if (family) - desc->static_family = FALSE; -} - -/** - * pango_font_description_set_family_static: - * @desc: a `PangoFontDescription` - * @family: a string representing the family name - * - * Sets the family name field of a font description, without copying the string. - * - * This is like [method@Pango.FontDescription.set_family], except that no - * copy of @family 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 @family is a static - * string such as a C string literal, or if @desc is only needed temporarily. - */ -void -pango_font_description_set_family_static (PangoFontDescription *desc, - const char *family) -{ - g_return_if_fail (desc != NULL); - - if (desc->family_name == family) - return; - - if (desc->family_name && !desc->static_family) - g_free (desc->family_name); - - if (family) - { - desc->family_name = (char *)family; - desc->static_family = TRUE; - desc->mask |= PANGO_FONT_MASK_FAMILY; - } - else - { - desc->family_name = pfd_defaults.family_name; - desc->static_family = pfd_defaults.static_family; - desc->mask &= ~PANGO_FONT_MASK_FAMILY; - } -} - -/** - * pango_font_description_get_family: - * @desc: a `PangoFontDescription`. - * - * Gets the family name field of a font description. - * - * See [method@Pango.FontDescription.set_family]. - * - * Return value: (nullable): the family name 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. - */ -const char * -pango_font_description_get_family (const PangoFontDescription *desc) -{ - g_return_val_if_fail (desc != NULL, NULL); - - return desc->family_name; -} - -/** - * pango_font_description_set_style: - * @desc: a `PangoFontDescription` - * @style: the style for the font description - * - * Sets the style field of a `PangoFontDescription`. - * - * The [enum@Pango.Style] enumeration describes whether the font is - * slanted and the manner in which it is slanted; it can be either - * %PANGO_STYLE_NORMAL, %PANGO_STYLE_ITALIC, or %PANGO_STYLE_OBLIQUE. - * - * Most fonts will either have a italic style or an oblique style, - * but not both, and font matching in Pango will match italic - * specifications with oblique fonts and vice-versa if an exact - * match is not found. - */ -void -pango_font_description_set_style (PangoFontDescription *desc, - PangoStyle style) -{ - g_return_if_fail (desc != NULL); - - desc->style = style; - desc->mask |= PANGO_FONT_MASK_STYLE; -} - -/** - * pango_font_description_get_style: - * @desc: a `PangoFontDescription` - * - * Gets the style field of a `PangoFontDescription`. - * - * See [method@Pango.FontDescription.set_style]. - * - * Return value: the style field for the font description. - * Use [method@Pango.FontDescription.get_set_fields] to - * find out if the field was explicitly set or not. - */ -PangoStyle -pango_font_description_get_style (const PangoFontDescription *desc) -{ - g_return_val_if_fail (desc != NULL, pfd_defaults.style); - - return desc->style; -} - -/** - * pango_font_description_set_variant: - * @desc: a `PangoFontDescription` - * @variant: the variant type for the font description. - * - * Sets the variant field of a font description. - * - * The [enum@Pango.Variant] can either be %PANGO_VARIANT_NORMAL - * or %PANGO_VARIANT_SMALL_CAPS. - */ -void -pango_font_description_set_variant (PangoFontDescription *desc, - PangoVariant variant) -{ - g_return_if_fail (desc != NULL); - - desc->variant = variant; - desc->mask |= PANGO_FONT_MASK_VARIANT; -} - -/** - * pango_font_description_get_variant: - * @desc: a `PangoFontDescription`. - * - * Gets the variant field of a `PangoFontDescription`. - * - * See [method@Pango.FontDescription.set_variant]. - * - * Return value: the variant field for the font description. - * Use [method@Pango.FontDescription.get_set_fields] to find - * out if the field was explicitly set or not. - */ -PangoVariant -pango_font_description_get_variant (const PangoFontDescription *desc) -{ - g_return_val_if_fail (desc != NULL, pfd_defaults.variant); - - return desc->variant; -} - -/** - * pango_font_description_set_weight: - * @desc: a `PangoFontDescription` - * @weight: the weight for the font description. - * - * Sets the weight field of a font description. - * - * The weight field - * specifies how bold or light the font should be. In addition - * to the values of the [enum@Pango.Weight] enumeration, other - * intermediate numeric values are possible. - */ -void -pango_font_description_set_weight (PangoFontDescription *desc, - PangoWeight weight) -{ - g_return_if_fail (desc != NULL); - - desc->weight = weight; - desc->mask |= PANGO_FONT_MASK_WEIGHT; -} - -/** - * pango_font_description_get_weight: - * @desc: a `PangoFontDescription` - * - * Gets the weight field of a font description. - * - * See [method@Pango.FontDescription.set_weight]. - * - * Return value: the weight field for the font description. - * Use [method@Pango.FontDescription.get_set_fields] to find - * out if the field was explicitly set or not. - */ -PangoWeight -pango_font_description_get_weight (const PangoFontDescription *desc) -{ - g_return_val_if_fail (desc != NULL, pfd_defaults.weight); - - return desc->weight; -} - -/** - * pango_font_description_set_stretch: - * @desc: a `PangoFontDescription` - * @stretch: the stretch for the font description - * - * Sets the stretch field of a font description. - * - * The [enum@Pango.Stretch] field specifies how narrow or - * wide the font should be. - */ -void -pango_font_description_set_stretch (PangoFontDescription *desc, - PangoStretch stretch) -{ - g_return_if_fail (desc != NULL); - - desc->stretch = stretch; - desc->mask |= PANGO_FONT_MASK_STRETCH; -} - -/** - * pango_font_description_get_stretch: - * @desc: a `PangoFontDescription`. - * - * Gets the stretch field of a font description. - * - * See [method@Pango.FontDescription.set_stretch]. - * - * Return value: the stretch field for the font description. - * Use [method@Pango.FontDescription.get_set_fields] to find - * out if the field was explicitly set or not. - */ -PangoStretch -pango_font_description_get_stretch (const PangoFontDescription *desc) -{ - g_return_val_if_fail (desc != NULL, pfd_defaults.stretch); - - return desc->stretch; -} - -/** - * pango_font_description_set_size: - * @desc: a `PangoFontDescription` - * @size: the size of the font in points, scaled by %PANGO_SCALE. - * (That is, a @size value of 10 * PANGO_SCALE is a 10 point font. - * The conversion factor between points and device units depends on - * system configuration and the output device. For screen display, a - * logical DPI of 96 is common, in which case a 10 point font corresponds - * to a 10 * (96 / 72) = 13.3 pixel font. - * Use [method@Pango.FontDescription.set_absolute_size] if you need - * a particular size in device units. - * - * Sets the size field of a font description in fractional points. - * - * This is mutually exclusive with - * [method@Pango.FontDescription.set_absolute_size]. - */ -void -pango_font_description_set_size (PangoFontDescription *desc, - gint size) -{ - g_return_if_fail (desc != NULL); - g_return_if_fail (size >= 0); - - desc->size = size; - desc->size_is_absolute = FALSE; - desc->mask |= PANGO_FONT_MASK_SIZE; -} - -/** - * pango_font_description_get_size: - * @desc: a `PangoFontDescription` - * - * Gets the size field of a font description. - * - * See [method@Pango.FontDescription.set_size]. - * - * Return value: the size field for the font description in points - * or device units. You must call - * [method@Pango.FontDescription.get_size_is_absolute] to find out - * which is the case. Returns 0 if the size field has not previously - * been set or it has been set to 0 explicitly. - * Use [method@Pango.FontDescription.get_set_fields] to find out - * if the field was explicitly set or not. - */ -gint -pango_font_description_get_size (const PangoFontDescription *desc) -{ - g_return_val_if_fail (desc != NULL, pfd_defaults.size); - - return desc->size; -} - -/** - * pango_font_description_set_absolute_size: - * @desc: a `PangoFontDescription` - * @size: the new size, in Pango units. There are %PANGO_SCALE Pango units - * in one device unit. For an output backend where a device unit is a pixel, - * a @size value of 10 * PANGO_SCALE gives a 10 pixel font. - * - * Sets the size field of a font description, in device units. - * - * This is mutually exclusive with [method@Pango.FontDescription.set_size] - * which sets the font size in points. - * - * Since: 1.8 - */ -void -pango_font_description_set_absolute_size (PangoFontDescription *desc, - double size) -{ - g_return_if_fail (desc != NULL); - g_return_if_fail (size >= 0); - - desc->size = size; - desc->size_is_absolute = TRUE; - desc->mask |= PANGO_FONT_MASK_SIZE; -} - -/** - * pango_font_description_get_size_is_absolute: - * @desc: a `PangoFontDescription` - * - * Determines whether the size of the font is in points (not absolute) - * or device units (absolute). - * - * See [method@Pango.FontDescription.set_size] - * and [method@Pango.FontDescription.set_absolute_size]. - * - * Return value: whether the size for the font description is in - * points or device units. Use [method@Pango.FontDescription.get_set_fields] - * to find out if the size field of the font description was explicitly - * set or not. - * - * Since: 1.8 - */ -gboolean -pango_font_description_get_size_is_absolute (const PangoFontDescription *desc) -{ - g_return_val_if_fail (desc != NULL, pfd_defaults.size_is_absolute); - - return desc->size_is_absolute; -} - -/** - * pango_font_description_set_gravity: - * @desc: a `PangoFontDescription` - * @gravity: the gravity for the font description. - * - * Sets the gravity field of a font description. - * - * The gravity field - * specifies how the glyphs should be rotated. If @gravity is - * %PANGO_GRAVITY_AUTO, this actually unsets the gravity mask on - * the font description. - * - * This function is seldom useful to the user. Gravity should normally - * be set on a `PangoContext`. - * - * Since: 1.16 - */ -void -pango_font_description_set_gravity (PangoFontDescription *desc, - PangoGravity gravity) -{ - g_return_if_fail (desc != NULL); - - if (gravity == PANGO_GRAVITY_AUTO) - { - pango_font_description_unset_fields (desc, PANGO_FONT_MASK_GRAVITY); - return; - } - - desc->gravity = gravity; - desc->mask |= PANGO_FONT_MASK_GRAVITY; -} - -/** - * pango_font_description_get_gravity: - * @desc: a `PangoFontDescription` - * - * Gets the gravity field of a font description. - * - * See [method@Pango.FontDescription.set_gravity]. - * - * Return value: the gravity field for the font description. - * Use [method@Pango.FontDescription.get_set_fields] to find out - * if the field was explicitly set or not. - * - * Since: 1.16 - */ -PangoGravity -pango_font_description_get_gravity (const PangoFontDescription *desc) -{ - g_return_val_if_fail (desc != NULL, pfd_defaults.gravity); - - return desc->gravity; -} - -/** - * pango_font_description_set_variations_static: - * @desc: a `PangoFontDescription` - * @variations: a string representing the variations - * - * Sets the variations field of a font description. - * - * This is like [method@Pango.FontDescription.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: (nullable): 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 and freetype have API for this. See - * for example [hb_ot_var_get_axis_infos](https://harfbuzz.github.io/harfbuzz-hb-ot-var.html#hb-ot-var-get-axis-infos). - * - * 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 [method@Pango.FontDescription.set_variations]. - * - * 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 - */ -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` - * - * Determines which fields in a font description have been set. - * - * Return value: a bitmask with bits set corresponding to the - * fields in @desc that have been set. - */ -PangoFontMask -pango_font_description_get_set_fields (const PangoFontDescription *desc) -{ - g_return_val_if_fail (desc != NULL, pfd_defaults.mask); - - return desc->mask; -} - -/** - * pango_font_description_unset_fields: - * @desc: a `PangoFontDescription` - * @to_unset: bitmask of fields in the @desc to unset. - * - * Unsets some of the fields in a `PangoFontDescription`. - * - * The unset fields will get back to their default values. - */ -void -pango_font_description_unset_fields (PangoFontDescription *desc, - PangoFontMask to_unset) -{ - PangoFontDescription unset_desc; - - g_return_if_fail (desc != NULL); - - unset_desc = pfd_defaults; - unset_desc.mask = to_unset; - - pango_font_description_merge_static (desc, &unset_desc, TRUE); - - desc->mask &= ~to_unset; -} - -/** - * pango_font_description_merge: - * @desc: a `PangoFontDescription` - * @desc_to_merge: (nullable): the `PangoFontDescription` to merge from, - * or %NULL - * @replace_existing: if %TRUE, replace fields in @desc with the - * corresponding values from @desc_to_merge, even if they - * are already exist. - * - * Merges the fields that are set in @desc_to_merge into the fields in - * @desc. - * - * If @replace_existing is %FALSE, only fields in @desc that - * are not already set are affected. If %TRUE, then fields that are - * already set will be replaced as well. - * - * If @desc_to_merge is %NULL, this function performs nothing. - */ -void -pango_font_description_merge (PangoFontDescription *desc, - const PangoFontDescription *desc_to_merge, - gboolean replace_existing) -{ - gboolean family_merged; - gboolean variations_merged; - - g_return_if_fail (desc != NULL); - - if (desc_to_merge == NULL) - 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); - - if (family_merged) - { - 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; - } -} - -/** - * pango_font_description_merge_static: - * @desc: a `PangoFontDescription` - * @desc_to_merge: the `PangoFontDescription` to merge from - * @replace_existing: if %TRUE, replace fields in @desc with the - * corresponding values from @desc_to_merge, even if they - * are already exist. - * - * Merges the fields that are set in @desc_to_merge into the fields in - * @desc, without copying allocated fields. - * - * This is like [method@Pango.FontDescription.merge], but only a shallow copy - * is made of the family name and other allocated fields. @desc can only - * be used until @desc_to_merge is modified or freed. This is meant to - * be used when the merged font description is only needed temporarily. - */ -void -pango_font_description_merge_static (PangoFontDescription *desc, - const PangoFontDescription *desc_to_merge, - gboolean replace_existing) -{ - PangoFontMask new_mask; - - g_return_if_fail (desc != NULL); - g_return_if_fail (desc_to_merge != NULL); - - if (replace_existing) - new_mask = desc_to_merge->mask; - else - new_mask = desc_to_merge->mask & ~desc->mask; - - if (new_mask & PANGO_FONT_MASK_FAMILY) - pango_font_description_set_family_static (desc, desc_to_merge->family_name); - if (new_mask & PANGO_FONT_MASK_STYLE) - desc->style = desc_to_merge->style; - if (new_mask & PANGO_FONT_MASK_VARIANT) - desc->variant = desc_to_merge->variant; - if (new_mask & PANGO_FONT_MASK_WEIGHT) - desc->weight = desc_to_merge->weight; - if (new_mask & PANGO_FONT_MASK_STRETCH) - desc->stretch = desc_to_merge->stretch; - if (new_mask & PANGO_FONT_MASK_SIZE) - { - desc->size = desc_to_merge->size; - desc->size_is_absolute = desc_to_merge->size_is_absolute; - } - 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; -} - -static gint -compute_distance (const PangoFontDescription *a, - const PangoFontDescription *b) -{ - if (a->style == b->style) - { - return abs((int)(a->weight) - (int)(b->weight)); - } - else if (a->style != PANGO_STYLE_NORMAL && - b->style != PANGO_STYLE_NORMAL) - { - /* Equate oblique and italic, but with a big penalty - */ - return 1000000 + abs ((int)(a->weight) - (int)(b->weight)); - } - else - return G_MAXINT; -} - -/** - * pango_font_description_better_match: - * @desc: a `PangoFontDescription` - * @old_match: (nullable): a `PangoFontDescription`, or %NULL - * @new_match: a `PangoFontDescription` - * - * Determines if the style attributes of @new_match are a closer match - * for @desc than those of @old_match are, or if @old_match is %NULL, - * determines if @new_match is a match at all. - * - * Approximate matching is done for weight and style; other style attributes - * must match exactly. Style attributes are all attributes other than family - * and size-related attributes. Approximate matching for style considers - * %PANGO_STYLE_OBLIQUE and %PANGO_STYLE_ITALIC as matches, but not as good - * a match as when the styles are equal. - * - * Note that @old_match must match @desc. - * - * Return value: %TRUE if @new_match is a better match - */ -gboolean -pango_font_description_better_match (const PangoFontDescription *desc, - const PangoFontDescription *old_match, - const PangoFontDescription *new_match) -{ - g_return_val_if_fail (desc != NULL, G_MAXINT); - g_return_val_if_fail (new_match != NULL, G_MAXINT); - - if (new_match->variant == desc->variant && - new_match->stretch == desc->stretch && - new_match->gravity == desc->gravity) - { - int old_distance = old_match ? compute_distance (desc, old_match) : G_MAXINT; - int new_distance = compute_distance (desc, new_match); - - if (new_distance < old_distance) - return TRUE; - } - - return FALSE; -} - -/** - * pango_font_description_copy: - * @desc: (nullable): a `PangoFontDescription`, may be %NULL - * - * Make a copy of a `PangoFontDescription`. - * - * Return value: (nullable): the newly allocated `PangoFontDescription`, - * which should be freed with [method@Pango.FontDescription.free], - * or %NULL if @desc was %NULL. - */ -PangoFontDescription * -pango_font_description_copy (const PangoFontDescription *desc) -{ - PangoFontDescription *result; - - if (desc == NULL) - return NULL; - - result = g_slice_new (PangoFontDescription); - - *result = *desc; - - if (result->family_name) - { - result->family_name = g_strdup (result->family_name); - result->static_family = FALSE; - } - - result->variations = g_strdup (result->variations); - result->static_variations = FALSE; - - return result; -} - -/** - * pango_font_description_copy_static: - * @desc: (nullable): a `PangoFontDescription`, may be %NULL - * - * Make a copy of a `PangoFontDescription`, but don't duplicate - * allocated fields. - * - * This is like [method@Pango.FontDescription.copy], but only a shallow - * copy is made of the family name and other allocated fields. The result - * can only be used until @desc is modified or freed. This is meant - * to be used when the copy is only needed temporarily. - * - * Return value: (nullable): the newly allocated `PangoFontDescription`, - * which should be freed with [method@Pango.FontDescription.free], - * or %NULL if @desc was %NULL. - */ -PangoFontDescription * -pango_font_description_copy_static (const PangoFontDescription *desc) -{ - PangoFontDescription *result; - - if (desc == NULL) - return NULL; - - result = g_slice_new (PangoFontDescription); - - *result = *desc; - if (result->family_name) - result->static_family = TRUE; - - - if (result->variations) - result->static_variations = TRUE; - - return result; -} - -/** - * pango_font_description_equal: - * @desc1: a `PangoFontDescription` - * @desc2: another `PangoFontDescription` - * - * Compares two font descriptions for equality. - * - * Two font descriptions are considered equal if the fonts they describe - * are provably identical. This means that their masks do not have to match, - * as long as other fields are all the same. (Two font descriptions may - * result in identical fonts being loaded, but still compare %FALSE.) - * - * Return value: %TRUE if the two font descriptions are identical, - * %FALSE otherwise. - */ -gboolean -pango_font_description_equal (const PangoFontDescription *desc1, - const PangoFontDescription *desc2) -{ - g_return_val_if_fail (desc1 != NULL, FALSE); - g_return_val_if_fail (desc2 != NULL, FALSE); - - return desc1->style == desc2->style && - desc1->variant == desc2->variant && - desc1->weight == desc2->weight && - desc1->stretch == desc2->stretch && - desc1->size == desc2->size && - 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)) && - (g_strcmp0 (desc1->variations, desc2->variations) == 0); -} - -#define TOLOWER(c) \ - (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c)) - -static guint -case_insensitive_hash (const char *key) -{ - const char *p = key; - guint h = TOLOWER (*p); - - if (h) - { - for (p += 1; *p != '\0'; p++) - h = (h << 5) - h + TOLOWER (*p); - } - - return h; -} - -/** - * pango_font_description_hash: - * @desc: a `PangoFontDescription` - * - * Computes a hash of a `PangoFontDescription` structure. - * - * This is suitable to be used, for example, as an argument - * to g_hash_table_new(). The hash value is independent of @desc->mask. - * - * Return value: the hash value. - */ -guint -pango_font_description_hash (const PangoFontDescription *desc) -{ - guint hash = 0; - - g_return_val_if_fail (desc != NULL, 0); - - 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; - hash ^= desc->variant << 18; - hash ^= desc->weight << 16; - hash ^= desc->stretch << 26; - hash ^= desc->gravity << 28; - - return hash; -} - -/** - * pango_font_description_free: - * @desc: (nullable): a `PangoFontDescription`, may be %NULL - * - * Frees a font description. - */ -void -pango_font_description_free (PangoFontDescription *desc) -{ - if (desc == NULL) - return; - - 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); -} - -/** - * pango_font_descriptions_free: - * @descs: (nullable) (array length=n_descs) (transfer full): a pointer - * to an array of `PangoFontDescription`, may be %NULL - * @n_descs: number of font descriptions in @descs - * - * Frees an array of font descriptions. - */ -void -pango_font_descriptions_free (PangoFontDescription **descs, - int n_descs) -{ - int i; - - if (descs == NULL) - return; - - for (i = 0; i<n_descs; i++) - pango_font_description_free (descs[i]); - g_free (descs); -} - -typedef struct -{ - int value; - const char str[16]; -} FieldMap; - -static const FieldMap style_map[] = { - { PANGO_STYLE_NORMAL, "" }, - { PANGO_STYLE_NORMAL, "Roman" }, - { PANGO_STYLE_OBLIQUE, "Oblique" }, - { PANGO_STYLE_ITALIC, "Italic" } -}; - -static const FieldMap variant_map[] = { - { PANGO_VARIANT_NORMAL, "" }, - { PANGO_VARIANT_SMALL_CAPS, "Small-Caps" }, - { PANGO_VARIANT_ALL_SMALL_CAPS, "All-Small-Caps" }, - { PANGO_VARIANT_PETITE_CAPS, "Petite-Caps" }, - { PANGO_VARIANT_ALL_PETITE_CAPS, "All-Petite-Caps" }, - { PANGO_VARIANT_UNICASE, "Unicase" }, - { PANGO_VARIANT_TITLE_CAPS, "Title-Caps" } -}; - -static const FieldMap weight_map[] = { - { PANGO_WEIGHT_THIN, "Thin" }, - { PANGO_WEIGHT_ULTRALIGHT, "Ultra-Light" }, - { PANGO_WEIGHT_ULTRALIGHT, "Extra-Light" }, - { PANGO_WEIGHT_LIGHT, "Light" }, - { PANGO_WEIGHT_SEMILIGHT, "Semi-Light" }, - { PANGO_WEIGHT_SEMILIGHT, "Demi-Light" }, - { PANGO_WEIGHT_BOOK, "Book" }, - { PANGO_WEIGHT_NORMAL, "" }, - { PANGO_WEIGHT_NORMAL, "Regular" }, - { PANGO_WEIGHT_MEDIUM, "Medium" }, - { PANGO_WEIGHT_SEMIBOLD, "Semi-Bold" }, - { PANGO_WEIGHT_SEMIBOLD, "Demi-Bold" }, - { PANGO_WEIGHT_BOLD, "Bold" }, - { PANGO_WEIGHT_ULTRABOLD, "Ultra-Bold" }, - { PANGO_WEIGHT_ULTRABOLD, "Extra-Bold" }, - { PANGO_WEIGHT_HEAVY, "Heavy" }, - { PANGO_WEIGHT_HEAVY, "Black" }, - { PANGO_WEIGHT_ULTRAHEAVY, "Ultra-Heavy" }, - { PANGO_WEIGHT_ULTRAHEAVY, "Extra-Heavy" }, - { PANGO_WEIGHT_ULTRAHEAVY, "Ultra-Black" }, - { PANGO_WEIGHT_ULTRAHEAVY, "Extra-Black" } -}; - -static const FieldMap stretch_map[] = { - { PANGO_STRETCH_ULTRA_CONDENSED, "Ultra-Condensed" }, - { PANGO_STRETCH_EXTRA_CONDENSED, "Extra-Condensed" }, - { PANGO_STRETCH_CONDENSED, "Condensed" }, - { PANGO_STRETCH_SEMI_CONDENSED, "Semi-Condensed" }, - { PANGO_STRETCH_NORMAL, "" }, - { PANGO_STRETCH_SEMI_EXPANDED, "Semi-Expanded" }, - { PANGO_STRETCH_EXPANDED, "Expanded" }, - { PANGO_STRETCH_EXTRA_EXPANDED, "Extra-Expanded" }, - { PANGO_STRETCH_ULTRA_EXPANDED, "Ultra-Expanded" } -}; - -static const FieldMap gravity_map[] = { - { PANGO_GRAVITY_SOUTH, "Not-Rotated" }, - { PANGO_GRAVITY_SOUTH, "South" }, - { PANGO_GRAVITY_NORTH, "Upside-Down" }, - { PANGO_GRAVITY_NORTH, "North" }, - { PANGO_GRAVITY_EAST, "Rotated-Left" }, - { PANGO_GRAVITY_EAST, "East" }, - { PANGO_GRAVITY_WEST, "Rotated-Right" }, - { PANGO_GRAVITY_WEST, "West" } -}; - -static gboolean -field_matches (const gchar *s1, - const gchar *s2, - gsize n) -{ - gint c1, c2; - - g_return_val_if_fail (s1 != NULL, 0); - g_return_val_if_fail (s2 != NULL, 0); - - while (n && *s1 && *s2) - { - c1 = (gint)(guchar) TOLOWER (*s1); - c2 = (gint)(guchar) TOLOWER (*s2); - if (c1 != c2) { - if (c1 == '-') { - s1++; - continue; - } - return FALSE; - } - s1++; s2++; - n--; - } - - return n == 0 && *s1 == '\0'; -} - -static gboolean -parse_int (const char *word, - size_t wordlen, - int *out) -{ - char *end; - long val = strtol (word, &end, 10); - int i = val; - - if (end != word && (end == word + wordlen) && val >= 0 && val == i) - { - if (out) - *out = i; - - return TRUE; - } - - return FALSE; -} - -static gboolean -find_field (const char *what, - const FieldMap *map, - int n_elements, - const char *str, - int len, - int *val) -{ - int i; - gboolean had_prefix = FALSE; - - if (what) - { - i = strlen (what); - if (len > i && 0 == strncmp (what, str, i) && str[i] == '=') - { - str += i + 1; - len -= i + 1; - had_prefix = TRUE; - } - } - - for (i=0; i<n_elements; i++) - { - if (map[i].str[0] && field_matches (map[i].str, str, len)) - { - if (val) - *val = map[i].value; - return TRUE; - } - } - - if (!what || had_prefix) - return parse_int (str, len, val); - - return FALSE; -} - -static gboolean -find_field_any (const char *str, int len, PangoFontDescription *desc) -{ - if (field_matches ("Normal", str, len)) - return TRUE; - -#define FIELD(NAME, MASK) \ - G_STMT_START { \ - if (find_field (G_STRINGIFY (NAME), NAME##_map, G_N_ELEMENTS (NAME##_map), str, len, \ - desc ? (int *)(void *)&desc->NAME : NULL)) \ - { \ - if (desc) \ - desc->mask |= MASK; \ - return TRUE; \ - } \ - } G_STMT_END - - FIELD (weight, PANGO_FONT_MASK_WEIGHT); - FIELD (style, PANGO_FONT_MASK_STYLE); - FIELD (stretch, PANGO_FONT_MASK_STRETCH); - FIELD (variant, PANGO_FONT_MASK_VARIANT); - FIELD (gravity, PANGO_FONT_MASK_GRAVITY); - -#undef FIELD - - return FALSE; -} - -static const char * -getword (const char *str, const char *last, size_t *wordlen, const char *stop) -{ - const char *result; - - while (last > str && g_ascii_isspace (*(last - 1))) - last--; - - result = last; - while (result > str && !g_ascii_isspace (*(result - 1)) && !strchr (stop, *(result - 1))) - result--; - - *wordlen = last - result; - - return result; -} - -static gboolean -parse_size (const char *word, - size_t wordlen, - int *pango_size, - gboolean *size_is_absolute) -{ - char *end; - double size = g_ascii_strtod (word, &end); - - if (end != word && - (end == word + wordlen || - (end + 2 == word + wordlen && !strncmp (end, "px", 2)) - ) && size >= 0 && size <= 1000000) /* word is a valid float */ - { - if (pango_size) - *pango_size = (int)(size * PANGO_SCALE + 0.5); - - if (size_is_absolute) - *size_is_absolute = end < word + wordlen; - - return TRUE; - } - - 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. - * - * Creates a new font description from a string representation. - * - * The string must have the form - * - * "\[FAMILY-LIST] \[STYLE-OPTIONS] \[SIZE] \[VARIATIONS]", - * - * where FAMILY-LIST is a comma-separated list of families optionally - * terminated by a comma, STYLE_OPTIONS is a whitespace-separated list - * of words where each word describes one of style, variant, weight, - * stretch, or gravity, and SIZE is a decimal number (size in points) - * or optionally followed by the unit modifier "px" for absolute size. - * VARIATIONS is a comma-separated list of font variation - * specifications of the form "\@axis=value" (the = sign is optional). - * - * The following words are understood as styles: - * "Normal", "Roman", "Oblique", "Italic". - * - * The following words are understood as variants: - * "Small-Caps", "All-Small-Caps", "Petite-Caps", "All-Petite-Caps", - * "Unicase", "Title-Caps". - * - * The following words are understood as weights: - * "Thin", "Ultra-Light", "Extra-Light", "Light", "Semi-Light", - * "Demi-Light", "Book", "Regular", "Medium", "Semi-Bold", "Demi-Bold", - * "Bold", "Ultra-Bold", "Extra-Bold", "Heavy", "Black", "Ultra-Black", - * "Extra-Black". - * - * The following words are understood as stretch values: - * "Ultra-Condensed", "Extra-Condensed", "Condensed", "Semi-Condensed", - * "Semi-Expanded", "Expanded", "Extra-Expanded", "Ultra-Expanded". - * - * The following words are understood as gravity values: - * "Not-Rotated", "South", "Upside-Down", "North", "Rotated-Left", - * "East", "Rotated-Right", "West". - * - * Any one of the options may be absent. If FAMILY-LIST is absent, then - * the family_name field of the resulting font description will be - * initialized to %NULL. If STYLE-OPTIONS is missing, then all style - * options will be set to the default values. If SIZE is missing, the - * size in the resulting font description will be set to 0. - * - * A typical example: - * - * "Cantarell Italic Light 15 \@wght=200" - * - * Return value: a new `PangoFontDescription`. - */ -PangoFontDescription * -pango_font_description_from_string (const char *str) -{ - PangoFontDescription *desc; - const char *p, *last; - size_t len, wordlen; - - g_return_val_if_fail (str != NULL, NULL); - - desc = pango_font_description_new (); - - desc->mask = PANGO_FONT_MASK_STYLE | - PANGO_FONT_MASK_WEIGHT | - PANGO_FONT_MASK_VARIANT | - PANGO_FONT_MASK_STRETCH; - - len = strlen (str); - last = str + len; - 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; - } - } - - p = getword (str, last, &wordlen, ","); - /* Look for a size */ - if (wordlen != 0) - { - gboolean size_is_absolute; - if (parse_size (p, wordlen, &desc->size, &size_is_absolute)) - { - desc->size_is_absolute = size_is_absolute; - desc->mask |= PANGO_FONT_MASK_SIZE; - last = p; - } - } - - /* Now parse style words - */ - p = getword (str, last, &wordlen, ","); - while (wordlen != 0) - { - if (!find_field_any (p, wordlen, desc)) - break; - else - { - last = p; - p = getword (str, last, &wordlen, ","); - } - } - - /* Remainder (str => p) is family list. Trim off trailing commas and leading and trailing white space - */ - - while (last > str && g_ascii_isspace (*(last - 1))) - last--; - - if (last > str && *(last - 1) == ',') - last--; - - while (last > str && g_ascii_isspace (*(last - 1))) - last--; - - while (last > str && g_ascii_isspace (*str)) - str++; - - if (str != last) - { - int i; - char **families; - - desc->family_name = g_strndup (str, last - str); - - /* Now sanitize it to trim space from around individual family names. - * bug #499624 */ - - families = g_strsplit (desc->family_name, ",", -1); - - for (i = 0; families[i]; i++) - g_strstrip (families[i]); - - g_free (desc->family_name); - desc->family_name = g_strjoinv (",", families); - g_strfreev (families); - - desc->mask |= PANGO_FONT_MASK_FAMILY; - } - - return desc; -} - -static void -append_field (GString *str, const char *what, const FieldMap *map, int n_elements, int val) -{ - int i; - for (i=0; i<n_elements; i++) - { - if (map[i].value != val) - continue; - - if (G_LIKELY (map[i].str[0])) - { - if (G_LIKELY (str->len > 0 && str->str[str->len -1] != ' ')) - g_string_append_c (str, ' '); - g_string_append (str, map[i].str); - } - return; - } - - if (G_LIKELY (str->len > 0 || str->str[str->len -1] != ' ')) - g_string_append_c (str, ' '); - g_string_append_printf (str, "%s=%d", what, val); -} - -/** - * pango_font_description_to_string: - * @desc: a `PangoFontDescription` - * - * Creates a string representation of a font description. - * - * See [func@Pango.FontDescription.from_string] for a description - * of the format of the string representation. The family list in - * the string description will only have a terminating comma if - * the last word of the list is a valid style option. - * - * Return value: a new string that must be freed with g_free(). - */ -char * -pango_font_description_to_string (const PangoFontDescription *desc) -{ - GString *result; - - g_return_val_if_fail (desc != NULL, NULL); - - result = g_string_new (NULL); - - if (G_LIKELY (desc->family_name && desc->mask & PANGO_FONT_MASK_FAMILY)) - { - const char *p; - size_t wordlen; - - g_string_append (result, desc->family_name); - - /* We need to add a trailing comma if the family name ends - * 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, ","); - if (wordlen != 0 && - (find_field_any (p, wordlen, NULL) || - (parse_size (p, wordlen, NULL, NULL) && - desc->weight == PANGO_WEIGHT_NORMAL && - desc->style == PANGO_STYLE_NORMAL && - desc->stretch == PANGO_STRETCH_NORMAL && - desc->variant == PANGO_VARIANT_NORMAL && - (desc->mask & (PANGO_FONT_MASK_GRAVITY | PANGO_FONT_MASK_SIZE)) == 0))) - g_string_append_c (result, ','); - } - -#define FIELD(NAME, MASK) \ - append_field (result, G_STRINGIFY (NAME), NAME##_map, G_N_ELEMENTS (NAME##_map), desc->NAME) - - FIELD (weight, PANGO_FONT_MASK_WEIGHT); - FIELD (style, PANGO_FONT_MASK_STYLE); - FIELD (stretch, PANGO_FONT_MASK_STRETCH); - FIELD (variant, PANGO_FONT_MASK_VARIANT); - if (desc->mask & PANGO_FONT_MASK_GRAVITY) - FIELD (gravity, PANGO_FONT_MASK_GRAVITY); - -#undef FIELD - - if (result->len == 0) - g_string_append (result, "Normal"); - - if (desc->mask & PANGO_FONT_MASK_SIZE) - { - char buf[G_ASCII_DTOSTR_BUF_SIZE]; - - if (result->len > 0 || result->str[result->len -1] != ' ') - g_string_append_c (result, ' '); - - g_ascii_dtostr (buf, sizeof (buf), (double)desc->size / PANGO_SCALE); - g_string_append (result, buf); - - if (desc->size_is_absolute) - g_string_append (result, "px"); - } - - if ((desc->variations && desc->mask & PANGO_FONT_MASK_VARIATIONS) && - desc->variations[0] != '\0') - { - g_string_append (result, " @"); - g_string_append (result, desc->variations); - } - - return g_string_free (result, FALSE); -} - -/** - * pango_font_description_to_filename: - * @desc: a `PangoFontDescription` - * - * Creates a filename representation of a font description. - * - * The filename is identical to the result from calling - * [method@Pango.FontDescription.to_string], but with underscores - * instead of characters that are untypical in filenames, and in - * lower case only. - * - * Return value: a new string that must be freed with g_free(). - */ -char * -pango_font_description_to_filename (const PangoFontDescription *desc) -{ - char *result; - char *p; - - g_return_val_if_fail (desc != NULL, NULL); - - result = pango_font_description_to_string (desc); - - p = result; - while (*p) - { - if (G_UNLIKELY ((guchar) *p >= 128)) - /* skip over non-ASCII chars */; - else if (strchr ("-+_.", *p) == NULL && !g_ascii_isalnum (*p)) - *p = '_'; - else - *p = g_ascii_tolower (*p); - p++; - } - - return result; -} - -static gboolean -parse_field (const char *what, - const FieldMap *map, - int n_elements, - const char *str, - int *val, - gboolean warn) -{ - gboolean found; - int len = strlen (str); - - if (G_UNLIKELY (*str == '\0')) - return FALSE; - - if (field_matches ("Normal", str, len)) - { - /* find the map entry with empty string */ - int i; - - for (i = 0; i < n_elements; i++) - if (map[i].str[0] == '\0') - { - *val = map[i].value; - return TRUE; - } - - *val = 0; - return TRUE; - } - - found = find_field (NULL, map, n_elements, str, len, val); - - if (!found && warn) - { - int i; - GString *s = g_string_new (NULL); - - for (i = 0; i < n_elements; i++) - { - if (i) - g_string_append_c (s, '/'); - g_string_append (s, map[i].str[0] == '\0' ? "Normal" : map[i].str); - } - - g_warning ("%s must be one of %s or a number", - what, - s->str); - - g_string_free (s, TRUE); - } - - return found; -} - -#define FIELD(NAME, MASK) \ - parse_field (G_STRINGIFY (NAME), NAME##_map, G_N_ELEMENTS (NAME##_map), str, (int *)(void *)NAME, warn) - -/** - * pango_parse_style: - * @str: a string to parse. - * @style: (out): a `PangoStyle` to store the result in. - * @warn: if %TRUE, issue a g_warning() on bad input. - * - * Parses a font style. - * - * The allowed values are "normal", "italic" and "oblique", case - * variations being - * ignored. - * - * Return value: %TRUE if @str was successfully parsed. - */ -gboolean -pango_parse_style (const char *str, - PangoStyle *style, - gboolean warn) -{ - return FIELD (style, PANGO_FONT_MASK_STYLE); -} - -/** - * pango_parse_variant: - * @str: a string to parse. - * @variant: (out): a `PangoVariant` to store the result in. - * @warn: if %TRUE, issue a g_warning() on bad input. - * - * Parses a font variant. - * - * The allowed values are "normal", "small-caps", "all-small-caps", - * "petite-caps", "all-petite-caps", "unicase" and "title-caps", - * case variations being ignored. - * - * Return value: %TRUE if @str was successfully parsed. - */ -gboolean -pango_parse_variant (const char *str, - PangoVariant *variant, - gboolean warn) -{ - return FIELD (variant, PANGO_FONT_MASK_VARIANT); -} - -/** - * pango_parse_weight: - * @str: a string to parse. - * @weight: (out): a `PangoWeight` to store the result in. - * @warn: if %TRUE, issue a g_warning() on bad input. - * - * Parses a font weight. - * - * The allowed values are "heavy", - * "ultrabold", "bold", "normal", "light", "ultraleight" - * and integers. Case variations are ignored. - * - * Return value: %TRUE if @str was successfully parsed. - */ -gboolean -pango_parse_weight (const char *str, - PangoWeight *weight, - gboolean warn) -{ - return FIELD (weight, PANGO_FONT_MASK_WEIGHT); -} - -/** - * pango_parse_stretch: - * @str: a string to parse. - * @stretch: (out): a `PangoStretch` to store the result in. - * @warn: if %TRUE, issue a g_warning() on bad input. - * - * Parses a font stretch. - * - * The allowed values are - * "ultra_condensed", "extra_condensed", "condensed", - * "semi_condensed", "normal", "semi_expanded", "expanded", - * "extra_expanded" and "ultra_expanded". Case variations are - * ignored and the '_' characters may be omitted. - * - * Return value: %TRUE if @str was successfully parsed. - */ -gboolean -pango_parse_stretch (const char *str, - PangoStretch *stretch, - gboolean warn) -{ - return FIELD (stretch, PANGO_FONT_MASK_STRETCH); -} - /* * PangoFont diff --git a/pango/meson.build b/pango/meson.build index dd5b0a70..d2d628cc 100644 --- a/pango/meson.build +++ b/pango/meson.build @@ -10,6 +10,7 @@ pango_sources = [ 'pango-context.c', 'pango-coverage.c', 'pango-emoji.c', + 'pango-font-description.c', 'pango-fontmap.c', 'pango-fontset.c', 'pango-fontset-simple.c', @@ -40,6 +41,7 @@ pango_headers = [ 'pango-coverage.h', 'pango-direction.h', 'pango-font.h', + 'pango-font-description.h', 'pango-fontmap.h', 'pango-fontset.h', 'pango-fontset-simple.h', diff --git a/pango/pango-font-description.c b/pango/pango-font-description.c new file mode 100644 index 00000000..14d1ef70 --- /dev/null +++ b/pango/pango-font-description.c @@ -0,0 +1,1684 @@ +/* Pango + * pango-font-description.c: + * + * Copyright (C) 1999 Red Hat Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include "pango-font-description.h" + +#include "pango-utils.h" + + +struct _PangoFontDescription +{ + char *family_name; + + PangoStyle style; + PangoVariant variant; + PangoWeight weight; + PangoStretch stretch; + PangoGravity gravity; + + char *variations; + + guint16 mask; + guint static_family : 1; + guint static_variations : 1; + guint size_is_absolute : 1; + + int size; +}; + +G_DEFINE_BOXED_TYPE (PangoFontDescription, pango_font_description, + pango_font_description_copy, + pango_font_description_free); + +static const PangoFontDescription pfd_defaults = { + NULL, /* family_name */ + + PANGO_STYLE_NORMAL, /* style */ + PANGO_VARIANT_NORMAL, /* variant */ + PANGO_WEIGHT_NORMAL, /* weight */ + PANGO_STRETCH_NORMAL, /* stretch */ + PANGO_GRAVITY_SOUTH, /* gravity */ + NULL, /* variations */ + + 0, /* mask */ + 0, /* static_family */ + 0, /* static_variations*/ + 0, /* size_is_absolute */ + + 0, /* size */ +}; + +/** + * pango_font_description_new: + * + * Creates a new font description structure with all fields unset. + * + * Return value: the newly allocated `PangoFontDescription`, which + * should be freed using [method@Pango.FontDescription.free]. + */ +PangoFontDescription * +pango_font_description_new (void) +{ + PangoFontDescription *desc = g_slice_new (PangoFontDescription); + + *desc = pfd_defaults; + + return desc; +} + +/** + * pango_font_description_set_family: + * @desc: a `PangoFontDescription`. + * @family: a string representing the family name. + * + * Sets the family name field of a font description. + * + * The family + * name represents a family of related font styles, and will + * resolve to a particular `PangoFontFamily`. In some uses of + * `PangoFontDescription`, it is also possible to use a comma + * separated list of family names for this field. + */ +void +pango_font_description_set_family (PangoFontDescription *desc, + const char *family) +{ + g_return_if_fail (desc != NULL); + + pango_font_description_set_family_static (desc, family ? g_strdup (family) : NULL); + if (family) + desc->static_family = FALSE; +} + +/** + * pango_font_description_set_family_static: + * @desc: a `PangoFontDescription` + * @family: a string representing the family name + * + * Sets the family name field of a font description, without copying the string. + * + * This is like [method@Pango.FontDescription.set_family], except that no + * copy of @family 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 @family is a static + * string such as a C string literal, or if @desc is only needed temporarily. + */ +void +pango_font_description_set_family_static (PangoFontDescription *desc, + const char *family) +{ + g_return_if_fail (desc != NULL); + + if (desc->family_name == family) + return; + + if (desc->family_name && !desc->static_family) + g_free (desc->family_name); + + if (family) + { + desc->family_name = (char *)family; + desc->static_family = TRUE; + desc->mask |= PANGO_FONT_MASK_FAMILY; + } + else + { + desc->family_name = pfd_defaults.family_name; + desc->static_family = pfd_defaults.static_family; + desc->mask &= ~PANGO_FONT_MASK_FAMILY; + } +} + +/** + * pango_font_description_get_family: + * @desc: a `PangoFontDescription`. + * + * Gets the family name field of a font description. + * + * See [method@Pango.FontDescription.set_family]. + * + * Return value: (nullable): the family name 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. + */ +const char * +pango_font_description_get_family (const PangoFontDescription *desc) +{ + g_return_val_if_fail (desc != NULL, NULL); + + return desc->family_name; +} + +/** + * pango_font_description_set_style: + * @desc: a `PangoFontDescription` + * @style: the style for the font description + * + * Sets the style field of a `PangoFontDescription`. + * + * The [enum@Pango.Style] enumeration describes whether the font is + * slanted and the manner in which it is slanted; it can be either + * %PANGO_STYLE_NORMAL, %PANGO_STYLE_ITALIC, or %PANGO_STYLE_OBLIQUE. + * + * Most fonts will either have a italic style or an oblique style, + * but not both, and font matching in Pango will match italic + * specifications with oblique fonts and vice-versa if an exact + * match is not found. + */ +void +pango_font_description_set_style (PangoFontDescription *desc, + PangoStyle style) +{ + g_return_if_fail (desc != NULL); + + desc->style = style; + desc->mask |= PANGO_FONT_MASK_STYLE; +} + +/** + * pango_font_description_get_style: + * @desc: a `PangoFontDescription` + * + * Gets the style field of a `PangoFontDescription`. + * + * See [method@Pango.FontDescription.set_style]. + * + * Return value: the style field for the font description. + * Use [method@Pango.FontDescription.get_set_fields] to + * find out if the field was explicitly set or not. + */ +PangoStyle +pango_font_description_get_style (const PangoFontDescription *desc) +{ + g_return_val_if_fail (desc != NULL, pfd_defaults.style); + + return desc->style; +} + +/** + * pango_font_description_set_variant: + * @desc: a `PangoFontDescription` + * @variant: the variant type for the font description. + * + * Sets the variant field of a font description. + * + * The [enum@Pango.Variant] can either be %PANGO_VARIANT_NORMAL + * or %PANGO_VARIANT_SMALL_CAPS. + */ +void +pango_font_description_set_variant (PangoFontDescription *desc, + PangoVariant variant) +{ + g_return_if_fail (desc != NULL); + + desc->variant = variant; + desc->mask |= PANGO_FONT_MASK_VARIANT; +} + +/** + * pango_font_description_get_variant: + * @desc: a `PangoFontDescription`. + * + * Gets the variant field of a `PangoFontDescription`. + * + * See [method@Pango.FontDescription.set_variant]. + * + * Return value: the variant field for the font description. + * Use [method@Pango.FontDescription.get_set_fields] to find + * out if the field was explicitly set or not. + */ +PangoVariant +pango_font_description_get_variant (const PangoFontDescription *desc) +{ + g_return_val_if_fail (desc != NULL, pfd_defaults.variant); + + return desc->variant; +} + +/** + * pango_font_description_set_weight: + * @desc: a `PangoFontDescription` + * @weight: the weight for the font description. + * + * Sets the weight field of a font description. + * + * The weight field + * specifies how bold or light the font should be. In addition + * to the values of the [enum@Pango.Weight] enumeration, other + * intermediate numeric values are possible. + */ +void +pango_font_description_set_weight (PangoFontDescription *desc, + PangoWeight weight) +{ + g_return_if_fail (desc != NULL); + + desc->weight = weight; + desc->mask |= PANGO_FONT_MASK_WEIGHT; +} + +/** + * pango_font_description_get_weight: + * @desc: a `PangoFontDescription` + * + * Gets the weight field of a font description. + * + * See [method@Pango.FontDescription.set_weight]. + * + * Return value: the weight field for the font description. + * Use [method@Pango.FontDescription.get_set_fields] to find + * out if the field was explicitly set or not. + */ +PangoWeight +pango_font_description_get_weight (const PangoFontDescription *desc) +{ + g_return_val_if_fail (desc != NULL, pfd_defaults.weight); + + return desc->weight; +} + +/** + * pango_font_description_set_stretch: + * @desc: a `PangoFontDescription` + * @stretch: the stretch for the font description + * + * Sets the stretch field of a font description. + * + * The [enum@Pango.Stretch] field specifies how narrow or + * wide the font should be. + */ +void +pango_font_description_set_stretch (PangoFontDescription *desc, + PangoStretch stretch) +{ + g_return_if_fail (desc != NULL); + + desc->stretch = stretch; + desc->mask |= PANGO_FONT_MASK_STRETCH; +} + +/** + * pango_font_description_get_stretch: + * @desc: a `PangoFontDescription`. + * + * Gets the stretch field of a font description. + * + * See [method@Pango.FontDescription.set_stretch]. + * + * Return value: the stretch field for the font description. + * Use [method@Pango.FontDescription.get_set_fields] to find + * out if the field was explicitly set or not. + */ +PangoStretch +pango_font_description_get_stretch (const PangoFontDescription *desc) +{ + g_return_val_if_fail (desc != NULL, pfd_defaults.stretch); + + return desc->stretch; +} + +/** + * pango_font_description_set_size: + * @desc: a `PangoFontDescription` + * @size: the size of the font in points, scaled by %PANGO_SCALE. + * (That is, a @size value of 10 * PANGO_SCALE is a 10 point font. + * The conversion factor between points and device units depends on + * system configuration and the output device. For screen display, a + * logical DPI of 96 is common, in which case a 10 point font corresponds + * to a 10 * (96 / 72) = 13.3 pixel font. + * Use [method@Pango.FontDescription.set_absolute_size] if you need + * a particular size in device units. + * + * Sets the size field of a font description in fractional points. + * + * This is mutually exclusive with + * [method@Pango.FontDescription.set_absolute_size]. + */ +void +pango_font_description_set_size (PangoFontDescription *desc, + gint size) +{ + g_return_if_fail (desc != NULL); + g_return_if_fail (size >= 0); + + desc->size = size; + desc->size_is_absolute = FALSE; + desc->mask |= PANGO_FONT_MASK_SIZE; +} + +/** + * pango_font_description_get_size: + * @desc: a `PangoFontDescription` + * + * Gets the size field of a font description. + * + * See [method@Pango.FontDescription.set_size]. + * + * Return value: the size field for the font description in points + * or device units. You must call + * [method@Pango.FontDescription.get_size_is_absolute] to find out + * which is the case. Returns 0 if the size field has not previously + * been set or it has been set to 0 explicitly. + * Use [method@Pango.FontDescription.get_set_fields] to find out + * if the field was explicitly set or not. + */ +gint +pango_font_description_get_size (const PangoFontDescription *desc) +{ + g_return_val_if_fail (desc != NULL, pfd_defaults.size); + + return desc->size; +} + +/** + * pango_font_description_set_absolute_size: + * @desc: a `PangoFontDescription` + * @size: the new size, in Pango units. There are %PANGO_SCALE Pango units + * in one device unit. For an output backend where a device unit is a pixel, + * a @size value of 10 * PANGO_SCALE gives a 10 pixel font. + * + * Sets the size field of a font description, in device units. + * + * This is mutually exclusive with [method@Pango.FontDescription.set_size] + * which sets the font size in points. + * + * Since: 1.8 + */ +void +pango_font_description_set_absolute_size (PangoFontDescription *desc, + double size) +{ + g_return_if_fail (desc != NULL); + g_return_if_fail (size >= 0); + + desc->size = size; + desc->size_is_absolute = TRUE; + desc->mask |= PANGO_FONT_MASK_SIZE; +} + +/** + * pango_font_description_get_size_is_absolute: + * @desc: a `PangoFontDescription` + * + * Determines whether the size of the font is in points (not absolute) + * or device units (absolute). + * + * See [method@Pango.FontDescription.set_size] + * and [method@Pango.FontDescription.set_absolute_size]. + * + * Return value: whether the size for the font description is in + * points or device units. Use [method@Pango.FontDescription.get_set_fields] + * to find out if the size field of the font description was explicitly + * set or not. + * + * Since: 1.8 + */ +gboolean +pango_font_description_get_size_is_absolute (const PangoFontDescription *desc) +{ + g_return_val_if_fail (desc != NULL, pfd_defaults.size_is_absolute); + + return desc->size_is_absolute; +} + +/** + * pango_font_description_set_gravity: + * @desc: a `PangoFontDescription` + * @gravity: the gravity for the font description. + * + * Sets the gravity field of a font description. + * + * The gravity field + * specifies how the glyphs should be rotated. If @gravity is + * %PANGO_GRAVITY_AUTO, this actually unsets the gravity mask on + * the font description. + * + * This function is seldom useful to the user. Gravity should normally + * be set on a `PangoContext`. + * + * Since: 1.16 + */ +void +pango_font_description_set_gravity (PangoFontDescription *desc, + PangoGravity gravity) +{ + g_return_if_fail (desc != NULL); + + if (gravity == PANGO_GRAVITY_AUTO) + { + pango_font_description_unset_fields (desc, PANGO_FONT_MASK_GRAVITY); + return; + } + + desc->gravity = gravity; + desc->mask |= PANGO_FONT_MASK_GRAVITY; +} + +/** + * pango_font_description_get_gravity: + * @desc: a `PangoFontDescription` + * + * Gets the gravity field of a font description. + * + * See [method@Pango.FontDescription.set_gravity]. + * + * Return value: the gravity field for the font description. + * Use [method@Pango.FontDescription.get_set_fields] to find out + * if the field was explicitly set or not. + * + * Since: 1.16 + */ +PangoGravity +pango_font_description_get_gravity (const PangoFontDescription *desc) +{ + g_return_val_if_fail (desc != NULL, pfd_defaults.gravity); + + return desc->gravity; +} + +/** + * pango_font_description_set_variations_static: + * @desc: a `PangoFontDescription` + * @variations: a string representing the variations + * + * Sets the variations field of a font description. + * + * This is like [method@Pango.FontDescription.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: (nullable): 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 and freetype have API for this. See + * for example [hb_ot_var_get_axis_infos](https://harfbuzz.github.io/harfbuzz-hb-ot-var.html#hb-ot-var-get-axis-infos). + * + * 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 [method@Pango.FontDescription.set_variations]. + * + * 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 + */ +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` + * + * Determines which fields in a font description have been set. + * + * Return value: a bitmask with bits set corresponding to the + * fields in @desc that have been set. + */ +PangoFontMask +pango_font_description_get_set_fields (const PangoFontDescription *desc) +{ + g_return_val_if_fail (desc != NULL, pfd_defaults.mask); + + return desc->mask; +} + +/** + * pango_font_description_unset_fields: + * @desc: a `PangoFontDescription` + * @to_unset: bitmask of fields in the @desc to unset. + * + * Unsets some of the fields in a `PangoFontDescription`. + * + * The unset fields will get back to their default values. + */ +void +pango_font_description_unset_fields (PangoFontDescription *desc, + PangoFontMask to_unset) +{ + PangoFontDescription unset_desc; + + g_return_if_fail (desc != NULL); + + unset_desc = pfd_defaults; + unset_desc.mask = to_unset; + + pango_font_description_merge_static (desc, &unset_desc, TRUE); + + desc->mask &= ~to_unset; +} + +/** + * pango_font_description_merge: + * @desc: a `PangoFontDescription` + * @desc_to_merge: (nullable): the `PangoFontDescription` to merge from, + * or %NULL + * @replace_existing: if %TRUE, replace fields in @desc with the + * corresponding values from @desc_to_merge, even if they + * are already exist. + * + * Merges the fields that are set in @desc_to_merge into the fields in + * @desc. + * + * If @replace_existing is %FALSE, only fields in @desc that + * are not already set are affected. If %TRUE, then fields that are + * already set will be replaced as well. + * + * If @desc_to_merge is %NULL, this function performs nothing. + */ +void +pango_font_description_merge (PangoFontDescription *desc, + const PangoFontDescription *desc_to_merge, + gboolean replace_existing) +{ + gboolean family_merged; + gboolean variations_merged; + + g_return_if_fail (desc != NULL); + + if (desc_to_merge == NULL) + 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); + + if (family_merged) + { + 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; + } +} + +/** + * pango_font_description_merge_static: + * @desc: a `PangoFontDescription` + * @desc_to_merge: the `PangoFontDescription` to merge from + * @replace_existing: if %TRUE, replace fields in @desc with the + * corresponding values from @desc_to_merge, even if they + * are already exist. + * + * Merges the fields that are set in @desc_to_merge into the fields in + * @desc, without copying allocated fields. + * + * This is like [method@Pango.FontDescription.merge], but only a shallow copy + * is made of the family name and other allocated fields. @desc can only + * be used until @desc_to_merge is modified or freed. This is meant to + * be used when the merged font description is only needed temporarily. + */ +void +pango_font_description_merge_static (PangoFontDescription *desc, + const PangoFontDescription *desc_to_merge, + gboolean replace_existing) +{ + PangoFontMask new_mask; + + g_return_if_fail (desc != NULL); + g_return_if_fail (desc_to_merge != NULL); + + if (replace_existing) + new_mask = desc_to_merge->mask; + else + new_mask = desc_to_merge->mask & ~desc->mask; + + if (new_mask & PANGO_FONT_MASK_FAMILY) + pango_font_description_set_family_static (desc, desc_to_merge->family_name); + if (new_mask & PANGO_FONT_MASK_STYLE) + desc->style = desc_to_merge->style; + if (new_mask & PANGO_FONT_MASK_VARIANT) + desc->variant = desc_to_merge->variant; + if (new_mask & PANGO_FONT_MASK_WEIGHT) + desc->weight = desc_to_merge->weight; + if (new_mask & PANGO_FONT_MASK_STRETCH) + desc->stretch = desc_to_merge->stretch; + if (new_mask & PANGO_FONT_MASK_SIZE) + { + desc->size = desc_to_merge->size; + desc->size_is_absolute = desc_to_merge->size_is_absolute; + } + 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; +} + +static gint +compute_distance (const PangoFontDescription *a, + const PangoFontDescription *b) +{ + if (a->style == b->style) + { + return abs((int)(a->weight) - (int)(b->weight)); + } + else if (a->style != PANGO_STYLE_NORMAL && + b->style != PANGO_STYLE_NORMAL) + { + /* Equate oblique and italic, but with a big penalty + */ + return 1000000 + abs ((int)(a->weight) - (int)(b->weight)); + } + else + return G_MAXINT; +} + +/** + * pango_font_description_better_match: + * @desc: a `PangoFontDescription` + * @old_match: (nullable): a `PangoFontDescription`, or %NULL + * @new_match: a `PangoFontDescription` + * + * Determines if the style attributes of @new_match are a closer match + * for @desc than those of @old_match are, or if @old_match is %NULL, + * determines if @new_match is a match at all. + * + * Approximate matching is done for weight and style; other style attributes + * must match exactly. Style attributes are all attributes other than family + * and size-related attributes. Approximate matching for style considers + * %PANGO_STYLE_OBLIQUE and %PANGO_STYLE_ITALIC as matches, but not as good + * a match as when the styles are equal. + * + * Note that @old_match must match @desc. + * + * Return value: %TRUE if @new_match is a better match + */ +gboolean +pango_font_description_better_match (const PangoFontDescription *desc, + const PangoFontDescription *old_match, + const PangoFontDescription *new_match) +{ + g_return_val_if_fail (desc != NULL, G_MAXINT); + g_return_val_if_fail (new_match != NULL, G_MAXINT); + + if (new_match->variant == desc->variant && + new_match->stretch == desc->stretch && + new_match->gravity == desc->gravity) + { + int old_distance = old_match ? compute_distance (desc, old_match) : G_MAXINT; + int new_distance = compute_distance (desc, new_match); + + if (new_distance < old_distance) + return TRUE; + } + + return FALSE; +} + +/** + * pango_font_description_copy: + * @desc: (nullable): a `PangoFontDescription`, may be %NULL + * + * Make a copy of a `PangoFontDescription`. + * + * Return value: (nullable): the newly allocated `PangoFontDescription`, + * which should be freed with [method@Pango.FontDescription.free], + * or %NULL if @desc was %NULL. + */ +PangoFontDescription * +pango_font_description_copy (const PangoFontDescription *desc) +{ + PangoFontDescription *result; + + if (desc == NULL) + return NULL; + + result = g_slice_new (PangoFontDescription); + + *result = *desc; + + if (result->family_name) + { + result->family_name = g_strdup (result->family_name); + result->static_family = FALSE; + } + + result->variations = g_strdup (result->variations); + result->static_variations = FALSE; + + return result; +} + +/** + * pango_font_description_copy_static: + * @desc: (nullable): a `PangoFontDescription`, may be %NULL + * + * Make a copy of a `PangoFontDescription`, but don't duplicate + * allocated fields. + * + * This is like [method@Pango.FontDescription.copy], but only a shallow + * copy is made of the family name and other allocated fields. The result + * can only be used until @desc is modified or freed. This is meant + * to be used when the copy is only needed temporarily. + * + * Return value: (nullable): the newly allocated `PangoFontDescription`, + * which should be freed with [method@Pango.FontDescription.free], + * or %NULL if @desc was %NULL. + */ +PangoFontDescription * +pango_font_description_copy_static (const PangoFontDescription *desc) +{ + PangoFontDescription *result; + + if (desc == NULL) + return NULL; + + result = g_slice_new (PangoFontDescription); + + *result = *desc; + if (result->family_name) + result->static_family = TRUE; + + + if (result->variations) + result->static_variations = TRUE; + + return result; +} + +/** + * pango_font_description_equal: + * @desc1: a `PangoFontDescription` + * @desc2: another `PangoFontDescription` + * + * Compares two font descriptions for equality. + * + * Two font descriptions are considered equal if the fonts they describe + * are provably identical. This means that their masks do not have to match, + * as long as other fields are all the same. (Two font descriptions may + * result in identical fonts being loaded, but still compare %FALSE.) + * + * Return value: %TRUE if the two font descriptions are identical, + * %FALSE otherwise. + */ +gboolean +pango_font_description_equal (const PangoFontDescription *desc1, + const PangoFontDescription *desc2) +{ + g_return_val_if_fail (desc1 != NULL, FALSE); + g_return_val_if_fail (desc2 != NULL, FALSE); + + return desc1->style == desc2->style && + desc1->variant == desc2->variant && + desc1->weight == desc2->weight && + desc1->stretch == desc2->stretch && + desc1->size == desc2->size && + 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)) && + (g_strcmp0 (desc1->variations, desc2->variations) == 0); +} + +#define TOLOWER(c) \ + (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c)) + +static guint +case_insensitive_hash (const char *key) +{ + const char *p = key; + guint h = TOLOWER (*p); + + if (h) + { + for (p += 1; *p != '\0'; p++) + h = (h << 5) - h + TOLOWER (*p); + } + + return h; +} + +/** + * pango_font_description_hash: + * @desc: a `PangoFontDescription` + * + * Computes a hash of a `PangoFontDescription` structure. + * + * This is suitable to be used, for example, as an argument + * to g_hash_table_new(). The hash value is independent of @desc->mask. + * + * Return value: the hash value. + */ +guint +pango_font_description_hash (const PangoFontDescription *desc) +{ + guint hash = 0; + + g_return_val_if_fail (desc != NULL, 0); + + 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; + hash ^= desc->variant << 18; + hash ^= desc->weight << 16; + hash ^= desc->stretch << 26; + hash ^= desc->gravity << 28; + + return hash; +} + +/** + * pango_font_description_free: + * @desc: (nullable): a `PangoFontDescription`, may be %NULL + * + * Frees a font description. + */ +void +pango_font_description_free (PangoFontDescription *desc) +{ + if (desc == NULL) + return; + + 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); +} + +/** + * pango_font_descriptions_free: + * @descs: (nullable) (array length=n_descs) (transfer full): a pointer + * to an array of `PangoFontDescription`, may be %NULL + * @n_descs: number of font descriptions in @descs + * + * Frees an array of font descriptions. + */ +void +pango_font_descriptions_free (PangoFontDescription **descs, + int n_descs) +{ + int i; + + if (descs == NULL) + return; + + for (i = 0; i<n_descs; i++) + pango_font_description_free (descs[i]); + g_free (descs); +} + +typedef struct +{ + int value; + const char str[16]; +} FieldMap; + +static const FieldMap style_map[] = { + { PANGO_STYLE_NORMAL, "" }, + { PANGO_STYLE_NORMAL, "Roman" }, + { PANGO_STYLE_OBLIQUE, "Oblique" }, + { PANGO_STYLE_ITALIC, "Italic" } +}; + +static const FieldMap variant_map[] = { + { PANGO_VARIANT_NORMAL, "" }, + { PANGO_VARIANT_SMALL_CAPS, "Small-Caps" }, + { PANGO_VARIANT_ALL_SMALL_CAPS, "All-Small-Caps" }, + { PANGO_VARIANT_PETITE_CAPS, "Petite-Caps" }, + { PANGO_VARIANT_ALL_PETITE_CAPS, "All-Petite-Caps" }, + { PANGO_VARIANT_UNICASE, "Unicase" }, + { PANGO_VARIANT_TITLE_CAPS, "Title-Caps" } +}; + +static const FieldMap weight_map[] = { + { PANGO_WEIGHT_THIN, "Thin" }, + { PANGO_WEIGHT_ULTRALIGHT, "Ultra-Light" }, + { PANGO_WEIGHT_ULTRALIGHT, "Extra-Light" }, + { PANGO_WEIGHT_LIGHT, "Light" }, + { PANGO_WEIGHT_SEMILIGHT, "Semi-Light" }, + { PANGO_WEIGHT_SEMILIGHT, "Demi-Light" }, + { PANGO_WEIGHT_BOOK, "Book" }, + { PANGO_WEIGHT_NORMAL, "" }, + { PANGO_WEIGHT_NORMAL, "Regular" }, + { PANGO_WEIGHT_MEDIUM, "Medium" }, + { PANGO_WEIGHT_SEMIBOLD, "Semi-Bold" }, + { PANGO_WEIGHT_SEMIBOLD, "Demi-Bold" }, + { PANGO_WEIGHT_BOLD, "Bold" }, + { PANGO_WEIGHT_ULTRABOLD, "Ultra-Bold" }, + { PANGO_WEIGHT_ULTRABOLD, "Extra-Bold" }, + { PANGO_WEIGHT_HEAVY, "Heavy" }, + { PANGO_WEIGHT_HEAVY, "Black" }, + { PANGO_WEIGHT_ULTRAHEAVY, "Ultra-Heavy" }, + { PANGO_WEIGHT_ULTRAHEAVY, "Extra-Heavy" }, + { PANGO_WEIGHT_ULTRAHEAVY, "Ultra-Black" }, + { PANGO_WEIGHT_ULTRAHEAVY, "Extra-Black" } +}; + +static const FieldMap stretch_map[] = { + { PANGO_STRETCH_ULTRA_CONDENSED, "Ultra-Condensed" }, + { PANGO_STRETCH_EXTRA_CONDENSED, "Extra-Condensed" }, + { PANGO_STRETCH_CONDENSED, "Condensed" }, + { PANGO_STRETCH_SEMI_CONDENSED, "Semi-Condensed" }, + { PANGO_STRETCH_NORMAL, "" }, + { PANGO_STRETCH_SEMI_EXPANDED, "Semi-Expanded" }, + { PANGO_STRETCH_EXPANDED, "Expanded" }, + { PANGO_STRETCH_EXTRA_EXPANDED, "Extra-Expanded" }, + { PANGO_STRETCH_ULTRA_EXPANDED, "Ultra-Expanded" } +}; + +static const FieldMap gravity_map[] = { + { PANGO_GRAVITY_SOUTH, "Not-Rotated" }, + { PANGO_GRAVITY_SOUTH, "South" }, + { PANGO_GRAVITY_NORTH, "Upside-Down" }, + { PANGO_GRAVITY_NORTH, "North" }, + { PANGO_GRAVITY_EAST, "Rotated-Left" }, + { PANGO_GRAVITY_EAST, "East" }, + { PANGO_GRAVITY_WEST, "Rotated-Right" }, + { PANGO_GRAVITY_WEST, "West" } +}; + +static gboolean +field_matches (const gchar *s1, + const gchar *s2, + gsize n) +{ + gint c1, c2; + + g_return_val_if_fail (s1 != NULL, 0); + g_return_val_if_fail (s2 != NULL, 0); + + while (n && *s1 && *s2) + { + c1 = (gint)(guchar) TOLOWER (*s1); + c2 = (gint)(guchar) TOLOWER (*s2); + if (c1 != c2) { + if (c1 == '-') { + s1++; + continue; + } + return FALSE; + } + s1++; s2++; + n--; + } + + return n == 0 && *s1 == '\0'; +} + +static gboolean +parse_int (const char *word, + size_t wordlen, + int *out) +{ + char *end; + long val = strtol (word, &end, 10); + int i = val; + + if (end != word && (end == word + wordlen) && val >= 0 && val == i) + { + if (out) + *out = i; + + return TRUE; + } + + return FALSE; +} + +static gboolean +find_field (const char *what, + const FieldMap *map, + int n_elements, + const char *str, + int len, + int *val) +{ + int i; + gboolean had_prefix = FALSE; + + if (what) + { + i = strlen (what); + if (len > i && 0 == strncmp (what, str, i) && str[i] == '=') + { + str += i + 1; + len -= i + 1; + had_prefix = TRUE; + } + } + + for (i=0; i<n_elements; i++) + { + if (map[i].str[0] && field_matches (map[i].str, str, len)) + { + if (val) + *val = map[i].value; + return TRUE; + } + } + + if (!what || had_prefix) + return parse_int (str, len, val); + + return FALSE; +} + +static gboolean +find_field_any (const char *str, int len, PangoFontDescription *desc) +{ + if (field_matches ("Normal", str, len)) + return TRUE; + +#define FIELD(NAME, MASK) \ + G_STMT_START { \ + if (find_field (G_STRINGIFY (NAME), NAME##_map, G_N_ELEMENTS (NAME##_map), str, len, \ + desc ? (int *)(void *)&desc->NAME : NULL)) \ + { \ + if (desc) \ + desc->mask |= MASK; \ + return TRUE; \ + } \ + } G_STMT_END + + FIELD (weight, PANGO_FONT_MASK_WEIGHT); + FIELD (style, PANGO_FONT_MASK_STYLE); + FIELD (stretch, PANGO_FONT_MASK_STRETCH); + FIELD (variant, PANGO_FONT_MASK_VARIANT); + FIELD (gravity, PANGO_FONT_MASK_GRAVITY); + +#undef FIELD + + return FALSE; +} + +static const char * +getword (const char *str, const char *last, size_t *wordlen, const char *stop) +{ + const char *result; + + while (last > str && g_ascii_isspace (*(last - 1))) + last--; + + result = last; + while (result > str && !g_ascii_isspace (*(result - 1)) && !strchr (stop, *(result - 1))) + result--; + + *wordlen = last - result; + + return result; +} + +static gboolean +parse_size (const char *word, + size_t wordlen, + int *pango_size, + gboolean *size_is_absolute) +{ + char *end; + double size = g_ascii_strtod (word, &end); + + if (end != word && + (end == word + wordlen || + (end + 2 == word + wordlen && !strncmp (end, "px", 2)) + ) && size >= 0 && size <= 1000000) /* word is a valid float */ + { + if (pango_size) + *pango_size = (int)(size * PANGO_SCALE + 0.5); + + if (size_is_absolute) + *size_is_absolute = end < word + wordlen; + + return TRUE; + } + + 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. + * + * Creates a new font description from a string representation. + * + * The string must have the form + * + * "\[FAMILY-LIST] \[STYLE-OPTIONS] \[SIZE] \[VARIATIONS]", + * + * where FAMILY-LIST is a comma-separated list of families optionally + * terminated by a comma, STYLE_OPTIONS is a whitespace-separated list + * of words where each word describes one of style, variant, weight, + * stretch, or gravity, and SIZE is a decimal number (size in points) + * or optionally followed by the unit modifier "px" for absolute size. + * VARIATIONS is a comma-separated list of font variation + * specifications of the form "\@axis=value" (the = sign is optional). + * + * The following words are understood as styles: + * "Normal", "Roman", "Oblique", "Italic". + * + * The following words are understood as variants: + * "Small-Caps", "All-Small-Caps", "Petite-Caps", "All-Petite-Caps", + * "Unicase", "Title-Caps". + * + * The following words are understood as weights: + * "Thin", "Ultra-Light", "Extra-Light", "Light", "Semi-Light", + * "Demi-Light", "Book", "Regular", "Medium", "Semi-Bold", "Demi-Bold", + * "Bold", "Ultra-Bold", "Extra-Bold", "Heavy", "Black", "Ultra-Black", + * "Extra-Black". + * + * The following words are understood as stretch values: + * "Ultra-Condensed", "Extra-Condensed", "Condensed", "Semi-Condensed", + * "Semi-Expanded", "Expanded", "Extra-Expanded", "Ultra-Expanded". + * + * The following words are understood as gravity values: + * "Not-Rotated", "South", "Upside-Down", "North", "Rotated-Left", + * "East", "Rotated-Right", "West". + * + * Any one of the options may be absent. If FAMILY-LIST is absent, then + * the family_name field of the resulting font description will be + * initialized to %NULL. If STYLE-OPTIONS is missing, then all style + * options will be set to the default values. If SIZE is missing, the + * size in the resulting font description will be set to 0. + * + * A typical example: + * + * "Cantarell Italic Light 15 \@wght=200" + * + * Return value: a new `PangoFontDescription`. + */ +PangoFontDescription * +pango_font_description_from_string (const char *str) +{ + PangoFontDescription *desc; + const char *p, *last; + size_t len, wordlen; + + g_return_val_if_fail (str != NULL, NULL); + + desc = pango_font_description_new (); + + desc->mask = PANGO_FONT_MASK_STYLE | + PANGO_FONT_MASK_WEIGHT | + PANGO_FONT_MASK_VARIANT | + PANGO_FONT_MASK_STRETCH; + + len = strlen (str); + last = str + len; + 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; + } + } + + p = getword (str, last, &wordlen, ","); + /* Look for a size */ + if (wordlen != 0) + { + gboolean size_is_absolute; + if (parse_size (p, wordlen, &desc->size, &size_is_absolute)) + { + desc->size_is_absolute = size_is_absolute; + desc->mask |= PANGO_FONT_MASK_SIZE; + last = p; + } + } + + /* Now parse style words + */ + p = getword (str, last, &wordlen, ","); + while (wordlen != 0) + { + if (!find_field_any (p, wordlen, desc)) + break; + else + { + last = p; + p = getword (str, last, &wordlen, ","); + } + } + + /* Remainder (str => p) is family list. Trim off trailing commas and leading and trailing white space + */ + + while (last > str && g_ascii_isspace (*(last - 1))) + last--; + + if (last > str && *(last - 1) == ',') + last--; + + while (last > str && g_ascii_isspace (*(last - 1))) + last--; + + while (last > str && g_ascii_isspace (*str)) + str++; + + if (str != last) + { + int i; + char **families; + + desc->family_name = g_strndup (str, last - str); + + /* Now sanitize it to trim space from around individual family names. + * bug #499624 */ + + families = g_strsplit (desc->family_name, ",", -1); + + for (i = 0; families[i]; i++) + g_strstrip (families[i]); + + g_free (desc->family_name); + desc->family_name = g_strjoinv (",", families); + g_strfreev (families); + + desc->mask |= PANGO_FONT_MASK_FAMILY; + } + + return desc; +} + +static void +append_field (GString *str, const char *what, const FieldMap *map, int n_elements, int val) +{ + int i; + for (i=0; i<n_elements; i++) + { + if (map[i].value != val) + continue; + + if (G_LIKELY (map[i].str[0])) + { + if (G_LIKELY (str->len > 0 && str->str[str->len -1] != ' ')) + g_string_append_c (str, ' '); + g_string_append (str, map[i].str); + } + return; + } + + if (G_LIKELY (str->len > 0 || str->str[str->len -1] != ' ')) + g_string_append_c (str, ' '); + g_string_append_printf (str, "%s=%d", what, val); +} + +/** + * pango_font_description_to_string: + * @desc: a `PangoFontDescription` + * + * Creates a string representation of a font description. + * + * See [func@Pango.FontDescription.from_string] for a description + * of the format of the string representation. The family list in + * the string description will only have a terminating comma if + * the last word of the list is a valid style option. + * + * Return value: a new string that must be freed with g_free(). + */ +char * +pango_font_description_to_string (const PangoFontDescription *desc) +{ + GString *result; + + g_return_val_if_fail (desc != NULL, NULL); + + result = g_string_new (NULL); + + if (G_LIKELY (desc->family_name && desc->mask & PANGO_FONT_MASK_FAMILY)) + { + const char *p; + size_t wordlen; + + g_string_append (result, desc->family_name); + + /* We need to add a trailing comma if the family name ends + * 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, ","); + if (wordlen != 0 && + (find_field_any (p, wordlen, NULL) || + (parse_size (p, wordlen, NULL, NULL) && + desc->weight == PANGO_WEIGHT_NORMAL && + desc->style == PANGO_STYLE_NORMAL && + desc->stretch == PANGO_STRETCH_NORMAL && + desc->variant == PANGO_VARIANT_NORMAL && + (desc->mask & (PANGO_FONT_MASK_GRAVITY | PANGO_FONT_MASK_SIZE)) == 0))) + g_string_append_c (result, ','); + } + +#define FIELD(NAME, MASK) \ + append_field (result, G_STRINGIFY (NAME), NAME##_map, G_N_ELEMENTS (NAME##_map), desc->NAME) + + FIELD (weight, PANGO_FONT_MASK_WEIGHT); + FIELD (style, PANGO_FONT_MASK_STYLE); + FIELD (stretch, PANGO_FONT_MASK_STRETCH); + FIELD (variant, PANGO_FONT_MASK_VARIANT); + if (desc->mask & PANGO_FONT_MASK_GRAVITY) + FIELD (gravity, PANGO_FONT_MASK_GRAVITY); + +#undef FIELD + + if (result->len == 0) + g_string_append (result, "Normal"); + + if (desc->mask & PANGO_FONT_MASK_SIZE) + { + char buf[G_ASCII_DTOSTR_BUF_SIZE]; + + if (result->len > 0 || result->str[result->len -1] != ' ') + g_string_append_c (result, ' '); + + g_ascii_dtostr (buf, sizeof (buf), (double)desc->size / PANGO_SCALE); + g_string_append (result, buf); + + if (desc->size_is_absolute) + g_string_append (result, "px"); + } + + if ((desc->variations && desc->mask & PANGO_FONT_MASK_VARIATIONS) && + desc->variations[0] != '\0') + { + g_string_append (result, " @"); + g_string_append (result, desc->variations); + } + + return g_string_free (result, FALSE); +} + +/** + * pango_font_description_to_filename: + * @desc: a `PangoFontDescription` + * + * Creates a filename representation of a font description. + * + * The filename is identical to the result from calling + * [method@Pango.FontDescription.to_string], but with underscores + * instead of characters that are untypical in filenames, and in + * lower case only. + * + * Return value: a new string that must be freed with g_free(). + */ +char * +pango_font_description_to_filename (const PangoFontDescription *desc) +{ + char *result; + char *p; + + g_return_val_if_fail (desc != NULL, NULL); + + result = pango_font_description_to_string (desc); + + p = result; + while (*p) + { + if (G_UNLIKELY ((guchar) *p >= 128)) + /* skip over non-ASCII chars */; + else if (strchr ("-+_.", *p) == NULL && !g_ascii_isalnum (*p)) + *p = '_'; + else + *p = g_ascii_tolower (*p); + p++; + } + + return result; +} + +static gboolean +parse_field (const char *what, + const FieldMap *map, + int n_elements, + const char *str, + int *val, + gboolean warn) +{ + gboolean found; + int len = strlen (str); + + if (G_UNLIKELY (*str == '\0')) + return FALSE; + + if (field_matches ("Normal", str, len)) + { + /* find the map entry with empty string */ + int i; + + for (i = 0; i < n_elements; i++) + if (map[i].str[0] == '\0') + { + *val = map[i].value; + return TRUE; + } + + *val = 0; + return TRUE; + } + + found = find_field (NULL, map, n_elements, str, len, val); + + if (!found && warn) + { + int i; + GString *s = g_string_new (NULL); + + for (i = 0; i < n_elements; i++) + { + if (i) + g_string_append_c (s, '/'); + g_string_append (s, map[i].str[0] == '\0' ? "Normal" : map[i].str); + } + + g_warning ("%s must be one of %s or a number", + what, + s->str); + + g_string_free (s, TRUE); + } + + return found; +} + +#define FIELD(NAME, MASK) \ + parse_field (G_STRINGIFY (NAME), NAME##_map, G_N_ELEMENTS (NAME##_map), str, (int *)(void *)NAME, warn) + +/** + * pango_parse_style: + * @str: a string to parse. + * @style: (out): a `PangoStyle` to store the result in. + * @warn: if %TRUE, issue a g_warning() on bad input. + * + * Parses a font style. + * + * The allowed values are "normal", "italic" and "oblique", case + * variations being + * ignored. + * + * Return value: %TRUE if @str was successfully parsed. + */ +gboolean +pango_parse_style (const char *str, + PangoStyle *style, + gboolean warn) +{ + return FIELD (style, PANGO_FONT_MASK_STYLE); +} + +/** + * pango_parse_variant: + * @str: a string to parse. + * @variant: (out): a `PangoVariant` to store the result in. + * @warn: if %TRUE, issue a g_warning() on bad input. + * + * Parses a font variant. + * + * The allowed values are "normal", "small-caps", "all-small-caps", + * "petite-caps", "all-petite-caps", "unicase" and "title-caps", + * case variations being ignored. + * + * Return value: %TRUE if @str was successfully parsed. + */ +gboolean +pango_parse_variant (const char *str, + PangoVariant *variant, + gboolean warn) +{ + return FIELD (variant, PANGO_FONT_MASK_VARIANT); +} + +/** + * pango_parse_weight: + * @str: a string to parse. + * @weight: (out): a `PangoWeight` to store the result in. + * @warn: if %TRUE, issue a g_warning() on bad input. + * + * Parses a font weight. + * + * The allowed values are "heavy", + * "ultrabold", "bold", "normal", "light", "ultraleight" + * and integers. Case variations are ignored. + * + * Return value: %TRUE if @str was successfully parsed. + */ +gboolean +pango_parse_weight (const char *str, + PangoWeight *weight, + gboolean warn) +{ + return FIELD (weight, PANGO_FONT_MASK_WEIGHT); +} + +/** + * pango_parse_stretch: + * @str: a string to parse. + * @stretch: (out): a `PangoStretch` to store the result in. + * @warn: if %TRUE, issue a g_warning() on bad input. + * + * Parses a font stretch. + * + * The allowed values are + * "ultra_condensed", "extra_condensed", "condensed", + * "semi_condensed", "normal", "semi_expanded", "expanded", + * "extra_expanded" and "ultra_expanded". Case variations are + * ignored and the '_' characters may be omitted. + * + * Return value: %TRUE if @str was successfully parsed. + */ +gboolean +pango_parse_stretch (const char *str, + PangoStretch *stretch, + gboolean warn) +{ + return FIELD (stretch, PANGO_FONT_MASK_STRETCH); +} diff --git a/pango/pango-font-description.h b/pango/pango-font-description.h new file mode 100644 index 00000000..5be1f334 --- /dev/null +++ b/pango/pango-font-description.h @@ -0,0 +1,324 @@ +/* Pango + * pango-font-description.h: Font descriptors + * + * Copyright (C) 2000 Red Hat Software + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#pragma once + +#include <pango/pango-coverage.h> +#include <pango/pango-types.h> + +#include <glib-object.h> +#include <hb.h> + +G_BEGIN_DECLS + +/** + * PangoFontDescription: + * + * A `PangoFontDescription` describes a font in an implementation-independent + * manner. + * + * `PangoFontDescription` structures are used both to list what fonts are + * available on the system and also for specifying the characteristics of + * a font to load. + */ +typedef struct _PangoFontDescription PangoFontDescription; + +/** + * PangoStyle: + * @PANGO_STYLE_NORMAL: the font is upright. + * @PANGO_STYLE_OBLIQUE: the font is slanted, but in a roman style. + * @PANGO_STYLE_ITALIC: the font is slanted in an italic style. + * + * An enumeration specifying the various slant styles possible for a font. + **/ +typedef enum { + PANGO_STYLE_NORMAL, + PANGO_STYLE_OBLIQUE, + PANGO_STYLE_ITALIC +} PangoStyle; + +/** + * PangoVariant: + * @PANGO_VARIANT_NORMAL: A normal font. + * @PANGO_VARIANT_SMALL_CAPS: A font with the lower case characters + * replaced by smaller variants of the capital characters. + * @PANGO_VARIANT_ALL_SMALL_CAPS: A font with all characters + * replaced by smaller variants of the capital characters. Since: 1.50 + * @PANGO_VARIANT_PETITE_CAPS: A font with the lower case characters + * replaced by smaller variants of the capital characters. + * Petite Caps can be even smaller than Small Caps. Since: 1.50 + * @PANGO_VARIANT_ALL_PETITE_CAPS: A font with all characters + * replaced by smaller variants of the capital characters. + * Petite Caps can be even smaller than Small Caps. Since: 1.50 + * @PANGO_VARIANT_UNICASE: A font with the upper case characters + * replaced by smaller variants of the capital letters. Since: 1.50 + * @PANGO_VARIANT_TITLE_CAPS: A font with capital letters that + * are more suitable for all-uppercase titles. Since: 1.50 + * + * An enumeration specifying capitalization variant of the font. + */ +typedef enum { + PANGO_VARIANT_NORMAL, + PANGO_VARIANT_SMALL_CAPS, + PANGO_VARIANT_ALL_SMALL_CAPS, + PANGO_VARIANT_PETITE_CAPS, + PANGO_VARIANT_ALL_PETITE_CAPS, + PANGO_VARIANT_UNICASE, + PANGO_VARIANT_TITLE_CAPS +} PangoVariant; + +/** + * PangoWeight: + * @PANGO_WEIGHT_THIN: the thin weight (= 100) Since: 1.24 + * @PANGO_WEIGHT_ULTRALIGHT: the ultralight weight (= 200) + * @PANGO_WEIGHT_LIGHT: the light weight (= 300) + * @PANGO_WEIGHT_SEMILIGHT: the semilight weight (= 350) Since: 1.36.7 + * @PANGO_WEIGHT_BOOK: the book weight (= 380) Since: 1.24) + * @PANGO_WEIGHT_NORMAL: the default weight (= 400) + * @PANGO_WEIGHT_MEDIUM: the normal weight (= 500) Since: 1.24 + * @PANGO_WEIGHT_SEMIBOLD: the semibold weight (= 600) + * @PANGO_WEIGHT_BOLD: the bold weight (= 700) + * @PANGO_WEIGHT_ULTRABOLD: the ultrabold weight (= 800) + * @PANGO_WEIGHT_HEAVY: the heavy weight (= 900) + * @PANGO_WEIGHT_ULTRAHEAVY: the ultraheavy weight (= 1000) Since: 1.24 + * + * An enumeration specifying the weight (boldness) of a font. + * + * Weight is specified as a numeric value ranging from 100 to 1000. + * This enumeration simply provides some common, predefined values. + */ +typedef enum { + PANGO_WEIGHT_THIN = 100, + PANGO_WEIGHT_ULTRALIGHT = 200, + PANGO_WEIGHT_LIGHT = 300, + PANGO_WEIGHT_SEMILIGHT = 350, + PANGO_WEIGHT_BOOK = 380, + PANGO_WEIGHT_NORMAL = 400, + PANGO_WEIGHT_MEDIUM = 500, + PANGO_WEIGHT_SEMIBOLD = 600, + PANGO_WEIGHT_BOLD = 700, + PANGO_WEIGHT_ULTRABOLD = 800, + PANGO_WEIGHT_HEAVY = 900, + PANGO_WEIGHT_ULTRAHEAVY = 1000 +} PangoWeight; + +/** + * PangoStretch: + * @PANGO_STRETCH_ULTRA_CONDENSED: ultra condensed width + * @PANGO_STRETCH_EXTRA_CONDENSED: extra condensed width + * @PANGO_STRETCH_CONDENSED: condensed width + * @PANGO_STRETCH_SEMI_CONDENSED: semi condensed width + * @PANGO_STRETCH_NORMAL: the normal width + * @PANGO_STRETCH_SEMI_EXPANDED: semi expanded width + * @PANGO_STRETCH_EXPANDED: expanded width + * @PANGO_STRETCH_EXTRA_EXPANDED: extra expanded width + * @PANGO_STRETCH_ULTRA_EXPANDED: ultra expanded width + * + * An enumeration specifying the width of the font relative to other designs + * within a family. + */ +typedef enum { + PANGO_STRETCH_ULTRA_CONDENSED, + PANGO_STRETCH_EXTRA_CONDENSED, + PANGO_STRETCH_CONDENSED, + PANGO_STRETCH_SEMI_CONDENSED, + PANGO_STRETCH_NORMAL, + PANGO_STRETCH_SEMI_EXPANDED, + PANGO_STRETCH_EXPANDED, + PANGO_STRETCH_EXTRA_EXPANDED, + PANGO_STRETCH_ULTRA_EXPANDED +} PangoStretch; + +/** + * PangoFontMask: + * @PANGO_FONT_MASK_FAMILY: the font family is specified. + * @PANGO_FONT_MASK_STYLE: the font style is specified. + * @PANGO_FONT_MASK_VARIANT: the font variant is specified. + * @PANGO_FONT_MASK_WEIGHT: the font weight is specified. + * @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 the set fields in a + * `PangoFontDescription`. + */ +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_VARIATIONS = 1 << 7, +} PangoFontMask; + +/* CSS scale factors (1.2 factor between each size) */ +/** + * PANGO_SCALE_XX_SMALL: + * + * The scale factor for three shrinking steps (1 / (1.2 * 1.2 * 1.2)). + */ +/** + * PANGO_SCALE_X_SMALL: + * + * The scale factor for two shrinking steps (1 / (1.2 * 1.2)). + */ +/** + * PANGO_SCALE_SMALL: + * + * The scale factor for one shrinking step (1 / 1.2). + */ +/** + * PANGO_SCALE_MEDIUM: + * + * The scale factor for normal size (1.0). + */ +/** + * PANGO_SCALE_LARGE: + * + * The scale factor for one magnification step (1.2). + */ +/** + * PANGO_SCALE_X_LARGE: + * + * The scale factor for two magnification steps (1.2 * 1.2). + */ +/** + * PANGO_SCALE_XX_LARGE: + * + * The scale factor for three magnification steps (1.2 * 1.2 * 1.2). + */ +#define PANGO_SCALE_XX_SMALL ((double)0.5787037037037) +#define PANGO_SCALE_X_SMALL ((double)0.6944444444444) +#define PANGO_SCALE_SMALL ((double)0.8333333333333) +#define PANGO_SCALE_MEDIUM ((double)1.0) +#define PANGO_SCALE_LARGE ((double)1.2) +#define PANGO_SCALE_X_LARGE ((double)1.44) +#define PANGO_SCALE_XX_LARGE ((double)1.728) + + +#define PANGO_TYPE_FONT_DESCRIPTION (pango_font_description_get_type ()) + +PANGO_AVAILABLE_IN_ALL +GType pango_font_description_get_type (void) G_GNUC_CONST; +PANGO_AVAILABLE_IN_ALL +PangoFontDescription *pango_font_description_new (void); +PANGO_AVAILABLE_IN_ALL +PangoFontDescription *pango_font_description_copy (const PangoFontDescription *desc); +PANGO_AVAILABLE_IN_ALL +PangoFontDescription *pango_font_description_copy_static (const PangoFontDescription *desc); +PANGO_AVAILABLE_IN_ALL +guint pango_font_description_hash (const PangoFontDescription *desc) G_GNUC_PURE; +PANGO_AVAILABLE_IN_ALL +gboolean pango_font_description_equal (const PangoFontDescription *desc1, + const PangoFontDescription *desc2) G_GNUC_PURE; +PANGO_AVAILABLE_IN_ALL +void pango_font_description_free (PangoFontDescription *desc); +PANGO_AVAILABLE_IN_ALL +void pango_font_descriptions_free (PangoFontDescription **descs, + int n_descs); + +PANGO_AVAILABLE_IN_ALL +void pango_font_description_set_family (PangoFontDescription *desc, + const char *family); +PANGO_AVAILABLE_IN_ALL +void pango_font_description_set_family_static (PangoFontDescription *desc, + const char *family); +PANGO_AVAILABLE_IN_ALL +const char *pango_font_description_get_family (const PangoFontDescription *desc) G_GNUC_PURE; +PANGO_AVAILABLE_IN_ALL +void pango_font_description_set_style (PangoFontDescription *desc, + PangoStyle style); +PANGO_AVAILABLE_IN_ALL +PangoStyle pango_font_description_get_style (const PangoFontDescription *desc) G_GNUC_PURE; +PANGO_AVAILABLE_IN_ALL +void pango_font_description_set_variant (PangoFontDescription *desc, + PangoVariant variant); +PANGO_AVAILABLE_IN_ALL +PangoVariant pango_font_description_get_variant (const PangoFontDescription *desc) G_GNUC_PURE; +PANGO_AVAILABLE_IN_ALL +void pango_font_description_set_weight (PangoFontDescription *desc, + PangoWeight weight); +PANGO_AVAILABLE_IN_ALL +PangoWeight pango_font_description_get_weight (const PangoFontDescription *desc) G_GNUC_PURE; +PANGO_AVAILABLE_IN_ALL +void pango_font_description_set_stretch (PangoFontDescription *desc, + PangoStretch stretch); +PANGO_AVAILABLE_IN_ALL +PangoStretch pango_font_description_get_stretch (const PangoFontDescription *desc) G_GNUC_PURE; +PANGO_AVAILABLE_IN_ALL +void pango_font_description_set_size (PangoFontDescription *desc, + gint size); +PANGO_AVAILABLE_IN_ALL +gint pango_font_description_get_size (const PangoFontDescription *desc) G_GNUC_PURE; +PANGO_AVAILABLE_IN_1_8 +void pango_font_description_set_absolute_size (PangoFontDescription *desc, + double size); +PANGO_AVAILABLE_IN_1_8 +gboolean pango_font_description_get_size_is_absolute (const PangoFontDescription *desc) G_GNUC_PURE; +PANGO_AVAILABLE_IN_1_16 +void pango_font_description_set_gravity (PangoFontDescription *desc, + PangoGravity gravity); +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 *variations); +PANGO_AVAILABLE_IN_1_42 +void pango_font_description_set_variations (PangoFontDescription *desc, + const char *variations); +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 +void pango_font_description_unset_fields (PangoFontDescription *desc, + PangoFontMask to_unset); + +PANGO_AVAILABLE_IN_ALL +void pango_font_description_merge (PangoFontDescription *desc, + const PangoFontDescription *desc_to_merge, + gboolean replace_existing); +PANGO_AVAILABLE_IN_ALL +void pango_font_description_merge_static (PangoFontDescription *desc, + const PangoFontDescription *desc_to_merge, + gboolean replace_existing); + +PANGO_AVAILABLE_IN_ALL +gboolean pango_font_description_better_match (const PangoFontDescription *desc, + const PangoFontDescription *old_match, + const PangoFontDescription *new_match) G_GNUC_PURE; + +PANGO_AVAILABLE_IN_ALL +PangoFontDescription *pango_font_description_from_string (const char *str); +PANGO_AVAILABLE_IN_ALL +char * pango_font_description_to_string (const PangoFontDescription *desc); +PANGO_AVAILABLE_IN_ALL +char * pango_font_description_to_filename (const PangoFontDescription *desc); + + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoFontDescription, pango_font_description_free) + +G_END_DECLS diff --git a/pango/pango-font.h b/pango/pango-font.h index ca55d1cf..3776b2d0 100644 --- a/pango/pango-font.h +++ b/pango/pango-font.h @@ -24,6 +24,7 @@ #include <pango/pango-coverage.h> #include <pango/pango-types.h> +#include <pango/pango-font-description.h> #include <glib-object.h> #include <hb.h> @@ -31,18 +32,6 @@ G_BEGIN_DECLS /** - * PangoFontDescription: - * - * A `PangoFontDescription` describes a font in an implementation-independent - * manner. - * - * `PangoFontDescription` structures are used both to list what fonts are - * available on the system and also for specifying the characteristics of - * a font to load. - */ -typedef struct _PangoFontDescription PangoFontDescription; - -/** * PangoFontMetrics: * * A `PangoFontMetrics` structure holds the overall metric information @@ -63,286 +52,6 @@ typedef struct _PangoFontDescription PangoFontDescription; */ typedef struct _PangoFontMetrics PangoFontMetrics; -/** - * PangoStyle: - * @PANGO_STYLE_NORMAL: the font is upright. - * @PANGO_STYLE_OBLIQUE: the font is slanted, but in a roman style. - * @PANGO_STYLE_ITALIC: the font is slanted in an italic style. - * - * An enumeration specifying the various slant styles possible for a font. - **/ -typedef enum { - PANGO_STYLE_NORMAL, - PANGO_STYLE_OBLIQUE, - PANGO_STYLE_ITALIC -} PangoStyle; - -/** - * PangoVariant: - * @PANGO_VARIANT_NORMAL: A normal font. - * @PANGO_VARIANT_SMALL_CAPS: A font with the lower case characters - * replaced by smaller variants of the capital characters. - * @PANGO_VARIANT_ALL_SMALL_CAPS: A font with all characters - * replaced by smaller variants of the capital characters. Since: 1.50 - * @PANGO_VARIANT_PETITE_CAPS: A font with the lower case characters - * replaced by smaller variants of the capital characters. - * Petite Caps can be even smaller than Small Caps. Since: 1.50 - * @PANGO_VARIANT_ALL_PETITE_CAPS: A font with all characters - * replaced by smaller variants of the capital characters. - * Petite Caps can be even smaller than Small Caps. Since: 1.50 - * @PANGO_VARIANT_UNICASE: A font with the upper case characters - * replaced by smaller variants of the capital letters. Since: 1.50 - * @PANGO_VARIANT_TITLE_CAPS: A font with capital letters that - * are more suitable for all-uppercase titles. Since: 1.50 - * - * An enumeration specifying capitalization variant of the font. - */ -typedef enum { - PANGO_VARIANT_NORMAL, - PANGO_VARIANT_SMALL_CAPS, - PANGO_VARIANT_ALL_SMALL_CAPS, - PANGO_VARIANT_PETITE_CAPS, - PANGO_VARIANT_ALL_PETITE_CAPS, - PANGO_VARIANT_UNICASE, - PANGO_VARIANT_TITLE_CAPS -} PangoVariant; - -/** - * PangoWeight: - * @PANGO_WEIGHT_THIN: the thin weight (= 100) Since: 1.24 - * @PANGO_WEIGHT_ULTRALIGHT: the ultralight weight (= 200) - * @PANGO_WEIGHT_LIGHT: the light weight (= 300) - * @PANGO_WEIGHT_SEMILIGHT: the semilight weight (= 350) Since: 1.36.7 - * @PANGO_WEIGHT_BOOK: the book weight (= 380) Since: 1.24) - * @PANGO_WEIGHT_NORMAL: the default weight (= 400) - * @PANGO_WEIGHT_MEDIUM: the normal weight (= 500) Since: 1.24 - * @PANGO_WEIGHT_SEMIBOLD: the semibold weight (= 600) - * @PANGO_WEIGHT_BOLD: the bold weight (= 700) - * @PANGO_WEIGHT_ULTRABOLD: the ultrabold weight (= 800) - * @PANGO_WEIGHT_HEAVY: the heavy weight (= 900) - * @PANGO_WEIGHT_ULTRAHEAVY: the ultraheavy weight (= 1000) Since: 1.24 - * - * An enumeration specifying the weight (boldness) of a font. - * - * Weight is specified as a numeric value ranging from 100 to 1000. - * This enumeration simply provides some common, predefined values. - */ -typedef enum { - PANGO_WEIGHT_THIN = 100, - PANGO_WEIGHT_ULTRALIGHT = 200, - PANGO_WEIGHT_LIGHT = 300, - PANGO_WEIGHT_SEMILIGHT = 350, - PANGO_WEIGHT_BOOK = 380, - PANGO_WEIGHT_NORMAL = 400, - PANGO_WEIGHT_MEDIUM = 500, - PANGO_WEIGHT_SEMIBOLD = 600, - PANGO_WEIGHT_BOLD = 700, - PANGO_WEIGHT_ULTRABOLD = 800, - PANGO_WEIGHT_HEAVY = 900, - PANGO_WEIGHT_ULTRAHEAVY = 1000 -} PangoWeight; - -/** - * PangoStretch: - * @PANGO_STRETCH_ULTRA_CONDENSED: ultra condensed width - * @PANGO_STRETCH_EXTRA_CONDENSED: extra condensed width - * @PANGO_STRETCH_CONDENSED: condensed width - * @PANGO_STRETCH_SEMI_CONDENSED: semi condensed width - * @PANGO_STRETCH_NORMAL: the normal width - * @PANGO_STRETCH_SEMI_EXPANDED: semi expanded width - * @PANGO_STRETCH_EXPANDED: expanded width - * @PANGO_STRETCH_EXTRA_EXPANDED: extra expanded width - * @PANGO_STRETCH_ULTRA_EXPANDED: ultra expanded width - * - * An enumeration specifying the width of the font relative to other designs - * within a family. - */ -typedef enum { - PANGO_STRETCH_ULTRA_CONDENSED, - PANGO_STRETCH_EXTRA_CONDENSED, - PANGO_STRETCH_CONDENSED, - PANGO_STRETCH_SEMI_CONDENSED, - PANGO_STRETCH_NORMAL, - PANGO_STRETCH_SEMI_EXPANDED, - PANGO_STRETCH_EXPANDED, - PANGO_STRETCH_EXTRA_EXPANDED, - PANGO_STRETCH_ULTRA_EXPANDED -} PangoStretch; - -/** - * PangoFontMask: - * @PANGO_FONT_MASK_FAMILY: the font family is specified. - * @PANGO_FONT_MASK_STYLE: the font style is specified. - * @PANGO_FONT_MASK_VARIANT: the font variant is specified. - * @PANGO_FONT_MASK_WEIGHT: the font weight is specified. - * @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 the set fields in a - * `PangoFontDescription`. - */ -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_VARIATIONS = 1 << 7, -} PangoFontMask; - -/* CSS scale factors (1.2 factor between each size) */ -/** - * PANGO_SCALE_XX_SMALL: - * - * The scale factor for three shrinking steps (1 / (1.2 * 1.2 * 1.2)). - */ -/** - * PANGO_SCALE_X_SMALL: - * - * The scale factor for two shrinking steps (1 / (1.2 * 1.2)). - */ -/** - * PANGO_SCALE_SMALL: - * - * The scale factor for one shrinking step (1 / 1.2). - */ -/** - * PANGO_SCALE_MEDIUM: - * - * The scale factor for normal size (1.0). - */ -/** - * PANGO_SCALE_LARGE: - * - * The scale factor for one magnification step (1.2). - */ -/** - * PANGO_SCALE_X_LARGE: - * - * The scale factor for two magnification steps (1.2 * 1.2). - */ -/** - * PANGO_SCALE_XX_LARGE: - * - * The scale factor for three magnification steps (1.2 * 1.2 * 1.2). - */ -#define PANGO_SCALE_XX_SMALL ((double)0.5787037037037) -#define PANGO_SCALE_X_SMALL ((double)0.6944444444444) -#define PANGO_SCALE_SMALL ((double)0.8333333333333) -#define PANGO_SCALE_MEDIUM ((double)1.0) -#define PANGO_SCALE_LARGE ((double)1.2) -#define PANGO_SCALE_X_LARGE ((double)1.44) -#define PANGO_SCALE_XX_LARGE ((double)1.728) - -/* - * PangoFontDescription - */ - -#define PANGO_TYPE_FONT_DESCRIPTION (pango_font_description_get_type ()) - -PANGO_AVAILABLE_IN_ALL -GType pango_font_description_get_type (void) G_GNUC_CONST; -PANGO_AVAILABLE_IN_ALL -PangoFontDescription *pango_font_description_new (void); -PANGO_AVAILABLE_IN_ALL -PangoFontDescription *pango_font_description_copy (const PangoFontDescription *desc); -PANGO_AVAILABLE_IN_ALL -PangoFontDescription *pango_font_description_copy_static (const PangoFontDescription *desc); -PANGO_AVAILABLE_IN_ALL -guint pango_font_description_hash (const PangoFontDescription *desc) G_GNUC_PURE; -PANGO_AVAILABLE_IN_ALL -gboolean pango_font_description_equal (const PangoFontDescription *desc1, - const PangoFontDescription *desc2) G_GNUC_PURE; -PANGO_AVAILABLE_IN_ALL -void pango_font_description_free (PangoFontDescription *desc); -PANGO_AVAILABLE_IN_ALL -void pango_font_descriptions_free (PangoFontDescription **descs, - int n_descs); - -PANGO_AVAILABLE_IN_ALL -void pango_font_description_set_family (PangoFontDescription *desc, - const char *family); -PANGO_AVAILABLE_IN_ALL -void pango_font_description_set_family_static (PangoFontDescription *desc, - const char *family); -PANGO_AVAILABLE_IN_ALL -const char *pango_font_description_get_family (const PangoFontDescription *desc) G_GNUC_PURE; -PANGO_AVAILABLE_IN_ALL -void pango_font_description_set_style (PangoFontDescription *desc, - PangoStyle style); -PANGO_AVAILABLE_IN_ALL -PangoStyle pango_font_description_get_style (const PangoFontDescription *desc) G_GNUC_PURE; -PANGO_AVAILABLE_IN_ALL -void pango_font_description_set_variant (PangoFontDescription *desc, - PangoVariant variant); -PANGO_AVAILABLE_IN_ALL -PangoVariant pango_font_description_get_variant (const PangoFontDescription *desc) G_GNUC_PURE; -PANGO_AVAILABLE_IN_ALL -void pango_font_description_set_weight (PangoFontDescription *desc, - PangoWeight weight); -PANGO_AVAILABLE_IN_ALL -PangoWeight pango_font_description_get_weight (const PangoFontDescription *desc) G_GNUC_PURE; -PANGO_AVAILABLE_IN_ALL -void pango_font_description_set_stretch (PangoFontDescription *desc, - PangoStretch stretch); -PANGO_AVAILABLE_IN_ALL -PangoStretch pango_font_description_get_stretch (const PangoFontDescription *desc) G_GNUC_PURE; -PANGO_AVAILABLE_IN_ALL -void pango_font_description_set_size (PangoFontDescription *desc, - gint size); -PANGO_AVAILABLE_IN_ALL -gint pango_font_description_get_size (const PangoFontDescription *desc) G_GNUC_PURE; -PANGO_AVAILABLE_IN_1_8 -void pango_font_description_set_absolute_size (PangoFontDescription *desc, - double size); -PANGO_AVAILABLE_IN_1_8 -gboolean pango_font_description_get_size_is_absolute (const PangoFontDescription *desc) G_GNUC_PURE; -PANGO_AVAILABLE_IN_1_16 -void pango_font_description_set_gravity (PangoFontDescription *desc, - PangoGravity gravity); -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 *variations); -PANGO_AVAILABLE_IN_1_42 -void pango_font_description_set_variations (PangoFontDescription *desc, - const char *variations); -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 -void pango_font_description_unset_fields (PangoFontDescription *desc, - PangoFontMask to_unset); - -PANGO_AVAILABLE_IN_ALL -void pango_font_description_merge (PangoFontDescription *desc, - const PangoFontDescription *desc_to_merge, - gboolean replace_existing); -PANGO_AVAILABLE_IN_ALL -void pango_font_description_merge_static (PangoFontDescription *desc, - const PangoFontDescription *desc_to_merge, - gboolean replace_existing); - -PANGO_AVAILABLE_IN_ALL -gboolean pango_font_description_better_match (const PangoFontDescription *desc, - const PangoFontDescription *old_match, - const PangoFontDescription *new_match) G_GNUC_PURE; - -PANGO_AVAILABLE_IN_ALL -PangoFontDescription *pango_font_description_from_string (const char *str); -PANGO_AVAILABLE_IN_ALL -char * pango_font_description_to_string (const PangoFontDescription *desc); -PANGO_AVAILABLE_IN_ALL -char * pango_font_description_to_filename (const PangoFontDescription *desc); - /* * PangoFontMetrics */ @@ -558,7 +267,6 @@ PangoFont * pango_font_deserialize (PangoContext *context, G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoFontFamily, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoFontFace, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoFont, g_object_unref) -G_DEFINE_AUTOPTR_CLEANUP_FUNC(PangoFontDescription, pango_font_description_free) G_END_DECLS diff --git a/pango/pango.h b/pango/pango.h index 39d59455..8f16bbc1 100644 --- a/pango/pango.h +++ b/pango/pango.h @@ -31,6 +31,7 @@ #include <pango/pango-enum-types.h> #include <pango/pango-features.h> #include <pango/pango-font.h> +#include <pango/pango-font-description.h> #include <pango/pango-fontmap.h> #include <pango/pango-fontset.h> #include <pango/pango-fontset-simple.h> |