diff options
Diffstat (limited to 'trunk/pango/fonts.c')
-rw-r--r-- | trunk/pango/fonts.c | 1855 |
1 files changed, 1855 insertions, 0 deletions
diff --git a/trunk/pango/fonts.c b/trunk/pango/fonts.c new file mode 100644 index 00000000..0979ba1a --- /dev/null +++ b/trunk/pango/fonts.c @@ -0,0 +1,1855 @@ +/* Pango + * fonts.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 <stdlib.h> +#include <math.h> +#include <string.h> + +#include "pango-types.h" +#include "pango-font.h" +#include "pango-fontmap.h" +#include "pango-impl-utils.h" + +static const char bad_font_warning[] = "%s called with null font argument, expect ugly output"; + +struct _PangoFontDescription +{ + char *family_name; + + PangoStyle style; + PangoVariant variant; + PangoWeight weight; + PangoStretch stretch; + PangoGravity gravity; + + guint16 mask; + guint static_family : 1; + guint size_is_absolute : 1; + + int size; +}; + +GType +pango_font_description_get_type (void) +{ + static GType our_type = 0; + + if (G_UNLIKELY (our_type == 0)) + our_type = g_boxed_type_register_static (I_("PangoFontDescription"), + (GBoxedCopyFunc)pango_font_description_copy, + (GBoxedFreeFunc)pango_font_description_free); + + return our_type; +} + + +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 */ + + 0, /* mask */ + 0, /* static_family */ + FALSE, /* 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 pango_font_description_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. + * + * Like pango_font_description_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 + * pango_font_description_set_family(). + * + * Return value: 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. + **/ +G_CONST_RETURN 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 + * #PangoStyle 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 + * pango_font_description_set_style(). + * + * Return value: the style field for the font description. + * Use pango_font_description_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 #PangoVariant + * 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 + * pango_font_description_set_variant(). + * + * Return value: the variant field for the font description. Use + * pango_font_description_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 #PangoWeight 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 + * pango_font_description_set_weight(). + * + * Return value: the weight field for the font description. Use + * pango_font_description_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 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 pango_font_description_set_stretch(). + * + * Return value: the stretch field for the font description. Use + * pango_font_description_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 pango_font_description_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 pango_font_description_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 pango_font_description_set_size(). + * + * Return value: the size field for the font description in points or device units. + * You must call pango_font_description_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 pango_font_description_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 pango_font_description_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 pango_font_description_set_size() and pango_font_description_set_absolute_size(). + * + * Return value: whether the size for the font description is in + * points or device units. Use pango_font_description_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 + * pango_font_description_set_gravity(). + * + * Return value: the gravity field for the font description. Use + * pango_font_description_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_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: 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. 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. + **/ +void +pango_font_description_merge (PangoFontDescription *desc, + const PangoFontDescription *desc_to_merge, + gboolean replace_existing) +{ + gboolean family_merged; + + g_return_if_fail (desc != NULL); + g_return_if_fail (desc_to_merge != NULL); + + family_merged = desc_to_merge->family_name && (replace_existing || !desc->family_name); + + 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; + } +} + +/** + * 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. + * + * Like pango_font_description_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; + + desc->mask |= new_mask; +} + +static gint +compute_distance (const PangoFontDescription *a, + const PangoFontDescription *b) +{ + if (a->style == b->style) + { + return abs(a->weight - 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 (a->weight - b->weight); + } + else + return G_MAXINT; +} + +/** + * pango_font_description_better_match: + * @desc: a #PangoFontDescription + * @old_match: a #PangoFontDescription, or %NULL + * @new_match: a #PangoFontDescription + * + * Determines if the style attributes of @new_match are a closer match + * for @desc than @old_match, or if @old_match is %NULL, determines if + * @new_match is a match at all. Approximate matching is done for + * weight and style; other attributes must match exactly. + * + * 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: a #PangoFontDescription + * + * Make a copy of a #PangoFontDescription. + * + * Return value: the newly allocated #PangoFontDescription, which should + * be freed with pango_font_description_free(). + **/ +PangoFontDescription * +pango_font_description_copy (const PangoFontDescription *desc) +{ + PangoFontDescription *result; + + g_return_val_if_fail (desc != NULL, NULL); + + result = g_slice_new (PangoFontDescription); + + *result = *desc; + + if (result->family_name) + { + result->family_name = g_strdup (result->family_name); + result->static_family = FALSE; + } + + return result; +} + +/** + * pango_font_description_copy_static: + * @desc: a #PangoFontDescription + * + * Like pango_font_description_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: the newly allocated #PangoFontDescription, which should + * be freed with pango_font_description_free(). + **/ +PangoFontDescription * +pango_font_description_copy_static (const PangoFontDescription *desc) +{ + PangoFontDescription *result; + + g_return_val_if_fail (desc != NULL, NULL); + + result = g_slice_new (PangoFontDescription); + + *result = *desc; + if (result->family_name) + result->static_family = 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)); +} + +#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 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); + 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: a #PangoFontDescription, or %NULL + * + * Frees a font description. + **/ +void +pango_font_description_free (PangoFontDescription *desc) +{ + if (desc) + { + if (desc->family_name && !desc->static_family) + g_free (desc->family_name); + + g_slice_free (PangoFontDescription, desc); + } +} + +/** + * pango_font_descriptions_free: + * @descs: a pointer to an array of #PangoFontDescription, or %NULL + * @n_descs: number of font descriptions in @descs + * + * Frees a list of font descriptions from pango_font_map_list_fonts() + **/ +void +pango_font_descriptions_free (PangoFontDescription **descs, + int n_descs) +{ + int i; + + if (descs) + { + 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_OBLIQUE, "Oblique" }, + { PANGO_STYLE_ITALIC, "Italic" } +}; + +static const FieldMap variant_map[] = { + { PANGO_VARIANT_NORMAL, "" }, + { PANGO_VARIANT_SMALL_CAPS, "Small-Caps" } +}; + +static const FieldMap weight_map[] = { + { PANGO_WEIGHT_ULTRALIGHT, "Ultra-Light" }, + { PANGO_WEIGHT_LIGHT, "Light" }, + { PANGO_WEIGHT_NORMAL, "" }, + { 500, "Medium" }, + { PANGO_WEIGHT_SEMIBOLD, "Semi-Bold" }, + { PANGO_WEIGHT_BOLD, "Bold" }, + { PANGO_WEIGHT_ULTRABOLD, "Ultra-Bold" }, + { PANGO_WEIGHT_HEAVY, "Heavy" } +}; + +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_SOUTH, "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 +find_field (const FieldMap *map, int n_elements, const char *str, int len, int *val) +{ + int i; + + for (i=0; i<n_elements; i++) + { + if (map[i].str[0] && g_ascii_strncasecmp (map[i].str, str, len) == 0 && + map[i].str[len] == '\0') + { + if (val) + *val = map[i].value; + return TRUE; + } + } + + return FALSE; +} + +static gboolean +find_field_any (const char *str, int len, PangoFontDescription *desc) +{ + gboolean found = FALSE; + + if (g_ascii_strcasecmp (str, "Normal") == 0) + return TRUE; + +#define FIELD(NAME, MASK) \ + G_STMT_START { \ + if (find_field (NAME##_map, G_N_ELEMENTS (NAME##_map), str, len, \ + desc ? (int *)&desc->NAME : NULL)) \ + { \ + found = TRUE; \ + if (desc) \ + desc->mask |= MASK; \ + } \ + } G_STMT_END + + FIELD (style, PANGO_FONT_MASK_STYLE); + FIELD (variant, PANGO_FONT_MASK_VARIANT); + FIELD (weight, PANGO_FONT_MASK_WEIGHT); + FIELD (stretch, PANGO_FONT_MASK_STRETCH); + FIELD (gravity, PANGO_FONT_MASK_GRAVITY); + +#undef FIELD + + return found; +} + +static const char * +getword (const char *str, const char *last, size_t *wordlen) +{ + const char *result; + + while (last > str && g_ascii_isspace (*(last - 1))) + last--; + + result = last; + while (result > str && !g_ascii_isspace (*(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; +} + +/** + * pango_font_description_from_string: + * @str: string representation of a font description. + * + * Creates a new font description from a string representation in the + * form "[FAMILY-LIST] [STYLE-OPTIONS] [SIZE]", 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. 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. + * + * 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 a size at the end of the string + */ + 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) + { + desc->family_name = g_strndup (str, last - str); + desc->mask |= PANGO_FONT_MASK_FAMILY; + } + + return desc; +} + +static void +append_field (GString *str, const FieldMap *map, int n_elements, int val) +{ + int i; + for (i=0; i<n_elements; i++) + { + if (map[i].value == val) + { + if (map[i].str && map[i].str[0]) + { + if (str->len > 0 && str->str[str->len -1] != ' ') + g_string_append_c (str, ' '); + g_string_append (str, map[i].str); + } + return; + } + } + + if (str->len > 0 || str->str[str->len -1] != ' ') + g_string_append_c (str, ' '); + g_string_append_printf (str, "%d", val); +} + +/** + * pango_font_description_to_string: + * @desc: a #PangoFontDescription + * + * Creates a string representation of a font description. See + * pango_font_description_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 (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, ','); + } + + append_field (result, weight_map, G_N_ELEMENTS (weight_map), desc->weight); + append_field (result, style_map, G_N_ELEMENTS (style_map), desc->style); + append_field (result, stretch_map, G_N_ELEMENTS (stretch_map), desc->stretch); + append_field (result, variant_map, G_N_ELEMENTS (variant_map), desc->variant); + if (desc->mask & PANGO_FONT_MASK_GRAVITY) + append_field (result, gravity_map, G_N_ELEMENTS (gravity_map), desc->gravity); + + 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"); + } + + 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 + * pango_font_description_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); + + /* XXX This should be rewritten to read char-by-char instead + * of byte-by-byte, to be Unicode safe. + */ + p = result; + while (*p) + { + if (strchr ("-+_.", *p) == NULL && !g_ascii_isalnum (*p)) + *p = '_'; + else + *p = g_ascii_tolower (*p); + p++; + } + + return result; +} + +G_DEFINE_TYPE (PangoFont, pango_font, G_TYPE_OBJECT) + +static void +pango_font_class_init (PangoFontClass *class) +{ +} + +static void +pango_font_init (PangoFont *font) +{ +} + +/** + * pango_font_describe: + * @font: a #PangoFont + * + * Returns a description of the font, with font size set in points. + * Use pango_font_describe_with_absolute_size() if you want the font + * size in device units. + * + * Return value: a newly-allocated #PangoFontDescription object. + **/ +PangoFontDescription * +pango_font_describe (PangoFont *font) +{ + g_return_val_if_fail (font != NULL, NULL); + + return PANGO_FONT_GET_CLASS (font)->describe (font); +} + +/** + * pango_font_describe_with_absolute_size: + * @font: a #PangoFont + * + * Returns a description of the font, with absolute font size set + * (in device units). Use pango_font_describe() if you want the font + * size in points. + * + * Return value: a newly-allocated #PangoFontDescription object. + * + * Since: 1.14 + **/ +PangoFontDescription * +pango_font_describe_with_absolute_size (PangoFont *font) +{ + g_return_val_if_fail (font != NULL, NULL); + + if (G_UNLIKELY (!PANGO_FONT_GET_CLASS (font)->describe_absolute)) + { + g_warning ("describe_absolute not implemented for this font class, report this as a bug"); + return pango_font_describe (font); + } + + return PANGO_FONT_GET_CLASS (font)->describe_absolute (font); +} + +/** + * pango_font_get_coverage: + * @font: a #PangoFont + * @language: the language tag + * + * Computes the coverage map for a given font and language tag. + * + * Return value: a newly-allocated #PangoCoverage object. + **/ +PangoCoverage * +pango_font_get_coverage (PangoFont *font, + PangoLanguage *language) +{ + g_return_val_if_fail (font != NULL, NULL); + + return PANGO_FONT_GET_CLASS (font)->get_coverage (font, language); +} + +/** + * pango_font_find_shaper: + * @font: a #PangoFont + * @language: the language tag + * @ch: a Unicode character. + * + * Finds the best matching shaper for a font for a particular + * language tag and character point. + * + * Return value: the best matching shaper. + **/ +PangoEngineShape * +pango_font_find_shaper (PangoFont *font, + PangoLanguage *language, + guint32 ch) +{ + PangoEngineShape* shaper; + + g_return_val_if_fail (font != NULL, NULL); + + shaper = PANGO_FONT_GET_CLASS (font)->find_shaper (font, language, ch); + + return shaper; +} + +/** + * pango_font_get_glyph_extents: + * @font: a #PangoFont + * @glyph: the glyph index + * @ink_rect: rectangle used to store the extents of the glyph as drawn + * or %NULL to indicate that the result is not needed. + * @logical_rect: rectangle used to store the logical extents of the glyph + * or %NULL to indicate that the result is not needed. + * + * Gets the logical and ink extents of a glyph within a font. The + * coordinate system for each rectangle has its origin at the + * base line and horizontal origin of the character with increasing + * coordinates extending to the right and down. The macros PANGO_ASCENT(), + * PANGO_DESCENT(), PANGO_LBEARING(), and PANGO_RBEARING() can be used to convert + * from the extents rectangle to more traditional font metrics. The units + * of the rectangles are in 1/PANGO_SCALE of a device unit. + **/ +void +pango_font_get_glyph_extents (PangoFont *font, + PangoGlyph glyph, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect) +{ + if (G_UNLIKELY (!font)) + { + + if (!_pango_warning_history.get_glyph_extents) + { + _pango_warning_history.get_glyph_extents = TRUE; + g_warning (bad_font_warning, "pango_font_get_glyph_extents"); + } + if (ink_rect) + { + ink_rect->x = PANGO_SCALE; + ink_rect->y = - (PANGO_UNKNOWN_GLYPH_HEIGHT - 1) * PANGO_SCALE; + ink_rect->height = (PANGO_UNKNOWN_GLYPH_HEIGHT - 2) * PANGO_SCALE; + ink_rect->width = (PANGO_UNKNOWN_GLYPH_WIDTH - 2) * PANGO_SCALE; + } + if (logical_rect) + { + logical_rect->x = logical_rect->y = 0; + logical_rect->y = - PANGO_UNKNOWN_GLYPH_HEIGHT * PANGO_SCALE; + logical_rect->height = PANGO_UNKNOWN_GLYPH_HEIGHT * PANGO_SCALE; + logical_rect->width = PANGO_UNKNOWN_GLYPH_WIDTH * PANGO_SCALE; + } + return; + } + + PANGO_FONT_GET_CLASS (font)->get_glyph_extents (font, glyph, ink_rect, logical_rect); +} + +/** + * pango_font_get_metrics: + * @font: a #PangoFont + * @language: language tag used to determine which script to get the metrics + * for, or %NULL to indicate to get the metrics for the entire + * font. + * + * Gets overall metric information for a font. Since the metrics may be + * substantially different for different scripts, a language tag can + * be provided to indicate that the metrics should be retrieved that + * correspond to the script(s) used by that language. + * + * Return value: a #PangoFontMetrics object. The caller must call pango_font_metrics_unref() + * when finished using the object. + **/ +PangoFontMetrics * +pango_font_get_metrics (PangoFont *font, + PangoLanguage *language) +{ + if (G_UNLIKELY (!font)) + { + PangoFontMetrics *metrics; + + if (!_pango_warning_history.get_metrics) + { + _pango_warning_history.get_metrics = TRUE; + g_warning (bad_font_warning, "pango_font_get_metrics"); + } + metrics = pango_font_metrics_new (); + + metrics->ascent = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_HEIGHT; + metrics->descent = 0; + metrics->approximate_char_width = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_WIDTH; + metrics->approximate_digit_width = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_WIDTH; + metrics->underline_position = -PANGO_SCALE; + metrics->underline_thickness = PANGO_SCALE; + metrics->strikethrough_position = PANGO_SCALE * PANGO_UNKNOWN_GLYPH_HEIGHT / 2; + metrics->strikethrough_thickness = PANGO_SCALE; + + return metrics; + } + + return PANGO_FONT_GET_CLASS (font)->get_metrics (font, language); +} + +/** + * pango_font_get_font_map: + * @font: a #PangoFont + * + * Gets the font map for which the font was created. + * + * Return value: the #PangoFontMap for the font + * + * Since: 1.10 + **/ +PangoFontMap * +pango_font_get_font_map (PangoFont *font) +{ + if (G_UNLIKELY (!font)) + { + + if (!_pango_warning_history.get_font_map) + { + _pango_warning_history.get_font_map = TRUE; + g_warning (bad_font_warning, "pango_font_get_font_map"); + } + return NULL; + } + + if (PANGO_FONT_GET_CLASS (font)->get_font_map) + return PANGO_FONT_GET_CLASS (font)->get_font_map (font); + else + return NULL; +} + +GType +pango_font_metrics_get_type (void) +{ + static GType our_type = 0; + + if (G_UNLIKELY (our_type == 0)) + our_type = g_boxed_type_register_static (I_("PangoFontMetrics"), + (GBoxedCopyFunc)pango_font_metrics_ref, + (GBoxedFreeFunc)pango_font_metrics_unref); + + return our_type; +} + + +/** + * pango_font_metrics_new: + * + * Creates a new #PangoFontMetrics structure. This is only for + * internal use by Pango backends and there is no public way + * to set the fields of the structure. + * + * Return value: a newly-created #PangoFontMetrics structure + * with a reference count of 1. + **/ +PangoFontMetrics * +pango_font_metrics_new (void) +{ + PangoFontMetrics *metrics = g_slice_new0 (PangoFontMetrics); + metrics->ref_count = 1; + + return metrics; +} + +/** + * pango_font_metrics_ref: + * @metrics: a #PangoFontMetrics structure + * + * Increase the reference count of a font metrics structure by one. + * + * Return value: @metrics + **/ +PangoFontMetrics * +pango_font_metrics_ref (PangoFontMetrics *metrics) +{ + if (!metrics) + return NULL; + + metrics->ref_count++; + + return metrics; +} + +/** + * pango_font_metrics_unref: + * @metrics: a #PangoFontMetrics structure + * + * Decrease the reference count of a font metrics structure by one. If + * the result is zero, frees the structure and any associated + * memory. + **/ +void +pango_font_metrics_unref (PangoFontMetrics *metrics) +{ + if (!metrics) + return; + g_return_if_fail (metrics->ref_count > 0 ); + + metrics->ref_count--; + + if (metrics->ref_count == 0) + g_slice_free (PangoFontMetrics, metrics); +} + +/** + * pango_font_metrics_get_ascent: + * @metrics: a #PangoFontMetrics structure + * + * Gets the ascent from a font metrics structure. The ascent is + * the distance from the baseline to the logical top of a line + * of text. (The logical top may be above or below the top of the + * actual drawn ink. It is necessary to lay out the text to figure + * where the ink will be.) + * + * Return value: the ascent, in Pango units. (1 point == %PANGO_SCALE Pango units.) + **/ +int +pango_font_metrics_get_ascent (PangoFontMetrics *metrics) +{ + g_return_val_if_fail (metrics != NULL, 0); + + return metrics->ascent; +} + +/** + * pango_font_metrics_get_descent: + * @metrics: a #PangoFontMetrics structure + * + * Gets the descent from a font metrics structure. The descent is + * the distance from the baseline to the logical bottom of a line + * of text. (The logical bottom may be above or below the bottom of the + * actual drawn ink. It is necessary to lay out the text to figure + * where the ink will be.) + * + * Return value: the descent, in Pango units. (1 point == %PANGO_SCALE Pango units.) + **/ +int +pango_font_metrics_get_descent (PangoFontMetrics *metrics) +{ + g_return_val_if_fail (metrics != NULL, 0); + + return metrics->descent; +} + +/** + * pango_font_metrics_get_approximate_char_width: + * @metrics: a #PangoFontMetrics structure + * + * Gets the approximate character width for a font metrics structure. + * This is merely a representative value useful, for example, for + * determining the initial size for a window. Actual characters in + * text will be wider and narrower than this. + * + * Return value: the character width, in Pango units. (1 point == %PANGO_SCALE Pango units.) + **/ +int +pango_font_metrics_get_approximate_char_width (PangoFontMetrics *metrics) +{ + g_return_val_if_fail (metrics != NULL, 0); + + return metrics->approximate_char_width; +} + +/** + * pango_font_metrics_get_approximate_digit_width: + * @metrics: a #PangoFontMetrics structure + * + * Gets the approximate digit width for a font metrics structure. + * This is merely a representative value useful, for example, for + * determining the initial size for a window. Actual digits in + * text can be wider or narrower than this, though this value + * is generally somewhat more accurate than the result of + * pango_font_metrics_get_approximate_char_width() for digits. + * + * Return value: the digit width, in Pango units. (1 point == %PANGO_SCALE Pango units.) + **/ +int +pango_font_metrics_get_approximate_digit_width (PangoFontMetrics *metrics) +{ + g_return_val_if_fail (metrics != NULL, 0); + + return metrics->approximate_digit_width; +} + +/** + * pango_font_metrics_get_underline_position: + * @metrics: a #PangoFontMetrics structure + * + * Gets the suggested position to draw the underline. + * The value returned is the distance <emphasis>above</emphasis> the + * baseline of the top of the underline. Since most fonts have + * underline positions beneath the baseline, this value is typically + * negative. + * + * Return value: the suggested underline position, in Pango units. + * + * Since: 1.6 + **/ +int +pango_font_metrics_get_underline_position (PangoFontMetrics *metrics) +{ + g_return_val_if_fail (metrics != NULL, 0); + + return metrics->underline_position; +} + +/** + * pango_font_metrics_get_underline_thickness: + * @metrics: a #PangoFontMetrics structure + * + * Gets the suggested thickness to draw for the underline. + * + * Return value: the suggested underline thickness, in Pango units. + * + * Since: 1.6 + **/ +int +pango_font_metrics_get_underline_thickness (PangoFontMetrics *metrics) +{ + g_return_val_if_fail (metrics != NULL, 0); + + return metrics->underline_thickness; +} + +/** + * pango_font_metrics_get_strikethrough_position: + * @metrics: a #PangoFontMetrics structure + * + * Gets the suggested position to draw the strikethrough. + * The value returned is the distance <emphasis>above</emphasis> the + * baseline of the top of the strikethrough. + * + * Return value: the suggested strikethrough position, in Pango units. + * + * Since: 1.6 + **/ +int +pango_font_metrics_get_strikethrough_position (PangoFontMetrics *metrics) +{ + g_return_val_if_fail (metrics != NULL, 0); + + return metrics->strikethrough_position; +} + +/** + * pango_font_metrics_get_strikethrough_thickness: + * @metrics: a #PangoFontMetrics structure + * + * Gets the suggested thickness to draw for the strikethrough. + * + * Return value: the suggested strikethrough thickness, in Pango units. + * + * Since: 1.6 + **/ +int +pango_font_metrics_get_strikethrough_thickness (PangoFontMetrics *metrics) +{ + g_return_val_if_fail (metrics != NULL, 0); + + return metrics->strikethrough_thickness; +} + +/* + * PangoFontFamily + */ + +G_DEFINE_TYPE (PangoFontFamily, pango_font_family, G_TYPE_OBJECT) + +static void +pango_font_family_class_init (PangoFontFamilyClass *class) +{ +} + +static void +pango_font_family_init (PangoFontFamily *family) +{ +} + +/** + * pango_font_family_get_name: + * @family: a #PangoFontFamily + * + * Gets the name of the family. The name is unique among all + * fonts for the font backend and can be used in a #PangoFontDescription + * to specify that a face from this family is desired. + * + * Return value: the name of the family. This string is owned + * by the family object and must not be modified or freed. + **/ +G_CONST_RETURN char * +pango_font_family_get_name (PangoFontFamily *family) +{ + g_return_val_if_fail (PANGO_IS_FONT_FAMILY (family), NULL); + + return PANGO_FONT_FAMILY_GET_CLASS (family)->get_name (family); +} + +/** + * pango_font_family_list_faces: + * @family: a #PangoFontFamily + * @faces: location to store an array of pointers to #PangoFontFace + * objects, or %NULL. This array should be freed with g_free() + * when it is no longer needed. + * @n_faces: location to store number of elements in @faces. + * + * Lists the different font faces that make up @family. The faces + * in a family share a common design, but differ in slant, weight, + * width and other aspects. + **/ +void +pango_font_family_list_faces (PangoFontFamily *family, + PangoFontFace ***faces, + int *n_faces) +{ + g_return_if_fail (PANGO_IS_FONT_FAMILY (family)); + + PANGO_FONT_FAMILY_GET_CLASS (family)->list_faces (family, faces, n_faces); +} + +/** + * pango_font_family_is_monospace: + * @family: a #PangoFontFamily + * + * A monospace font is a font designed for text display where the the + * characters form a regular grid. For Western languages this would + * mean that the advance width of all characters are the same, but + * this categorization also includes Asian fonts which include + * double-width characters: characters that occupy two grid cells. + * g_unichar_iswide() returns a result that indicates whether a + * character is typically double-width in a monospace font. + * + * The best way to find out the grid-cell size is to call + * pango_font_metrics_get_approximate_digit_width(), since the results + * of pango_font_metrics_get_approximate_char_width() may be affected + * by double-width characters. + * + * Return value: %TRUE if the family is monospace. + * + * Since: 1.4 + **/ +gboolean +pango_font_family_is_monospace (PangoFontFamily *family) +{ + g_return_val_if_fail (PANGO_IS_FONT_FAMILY (family), FALSE); + + if (PANGO_FONT_FAMILY_GET_CLASS (family)->is_monospace) + return PANGO_FONT_FAMILY_GET_CLASS (family)->is_monospace (family); + else + return FALSE; +} + +/* + * PangoFontFace + */ + +G_DEFINE_TYPE (PangoFontFace, pango_font_face, G_TYPE_OBJECT) + +static void +pango_font_face_class_init (PangoFontFaceClass *class) +{ +} + +static void +pango_font_face_init (PangoFontFace *face) +{ +} + +/** + * pango_font_face_describe: + * @face: a #PangoFontFace + * + * Returns the family, style, variant, weight and stretch of + * a #PangoFontFace. The size field of the resulting font description + * will be unset. + * + * Return value: a newly-created #PangoFontDescription structure + * holding the description of the face. Use pango_font_description_free() + * to free the result. + **/ +PangoFontDescription * +pango_font_face_describe (PangoFontFace *face) +{ + g_return_val_if_fail (PANGO_IS_FONT_FACE (face), NULL); + + return PANGO_FONT_FACE_GET_CLASS (face)->describe (face); +} + +/** + * pango_font_face_is_synthesized: + * @face: a #PangoFontFace + * + * Returns whether a #PangoFontFace is synthesized by the underlying + * font rendering engine from another face, perhaps by shearing, emboldening, + * or lightening it. + * + * Return value: whether @face is synthesized. + * + * Since: 1.18 + **/ +gboolean +pango_font_face_is_synthesized (PangoFontFace *face) +{ + g_return_val_if_fail (PANGO_IS_FONT_FACE (face), FALSE); + + if (PANGO_FONT_FACE_GET_CLASS (face)->is_synthesized != NULL) + return PANGO_FONT_FACE_GET_CLASS (face)->is_synthesized (face); + else + return FALSE; +} + +/** + * pango_font_face_get_face_name: + * @face: a #PangoFontFace. + * + * Gets a name representing the style of this face among the + * different faces in the #PangoFontFamily for the face. This + * name is unique among all faces in the family and is suitable + * for displaying to users. + * + * Return value: the face name for the face. This string is + * owned by the face object and must not be modified or freed. + **/ +G_CONST_RETURN char * +pango_font_face_get_face_name (PangoFontFace *face) +{ + g_return_val_if_fail (PANGO_IS_FONT_FACE (face), NULL); + + return PANGO_FONT_FACE_GET_CLASS (face)->get_face_name (face); +} + +/** + * pango_font_face_list_sizes: + * @face: a #PangoFontFace. + * @sizes: location to store a pointer to an array of int. This array + * should be freed with g_free(). + * @n_sizes: location to store the number of elements in @sizes + * + * List the available sizes for a font. This is only applicable to bitmap + * fonts. For scalable fonts, stores %NULL at the location pointed to by + * @sizes and 0 at the location pointed to by @n_sizes. The sizes returned + * are in Pango units and are sorted in ascending order. + * + * Since: 1.4 + **/ +void +pango_font_face_list_sizes (PangoFontFace *face, + int **sizes, + int *n_sizes) +{ + g_return_if_fail (PANGO_IS_FONT_FACE (face)); + g_return_if_fail (sizes == NULL || n_sizes != NULL); + + if (n_sizes == NULL) + return; + + if (PANGO_FONT_FACE_GET_CLASS (face)->list_sizes != NULL) + PANGO_FONT_FACE_GET_CLASS (face)->list_sizes (face, sizes, n_sizes); + else + { + if (sizes != NULL) + *sizes = NULL; + *n_sizes = 0; + } +} |