diff options
Diffstat (limited to 'pango')
-rw-r--r-- | pango/fonts.c | 253 | ||||
-rw-r--r-- | pango/pango-font.h | 16 | ||||
-rw-r--r-- | pango/pangox.c | 3 |
3 files changed, 265 insertions, 7 deletions
diff --git a/pango/fonts.c b/pango/fonts.c index 45f1dcac..c6e4cbd8 100644 --- a/pango/fonts.c +++ b/pango/fonts.c @@ -19,6 +19,9 @@ * Boston, MA 02111-1307, USA. */ +#include <stdlib.h> +#include <ctype.h> + #include "pango.h" /** @@ -108,6 +111,256 @@ pango_font_descriptions_free (PangoFontDescription **descs, } } +typedef struct +{ + int value; + const char *str; +} FieldMap; + +FieldMap style_map[] = { + { PANGO_STYLE_NORMAL, NULL }, + { PANGO_STYLE_OBLIQUE, "Oblique" }, + { PANGO_STYLE_ITALIC, "Italic" } +}; + +FieldMap variant_map[] = { + { PANGO_VARIANT_NORMAL, NULL }, + { PANGO_VARIANT_SMALL_CAPS, "Small-Caps" } +}; + +FieldMap weight_map[] = { + { 300, "Light" }, + { PANGO_WEIGHT_NORMAL, NULL }, + { 500, "Medium" }, + { 600, "Semi-Bold" }, + { PANGO_WEIGHT_BOLD, "Bold" } +}; + +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, NULL }, + { PANGO_STRETCH_SEMI_EXPANDED, "Semi-Expanded" }, + { PANGO_STRETCH_EXPANDED, "Expanded" }, + { PANGO_STRETCH_EXTRA_EXPANDED, "Extra-Expanded" }, + { PANGO_STRETCH_ULTRA_EXPANDED, "Ultra-Expanded" } +}; + +static gboolean +find_field (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 && g_strncasecmp (map[i].str, 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) +{ + return (g_strcasecmp (str, "Normal") == 0 || + find_field (style_map, G_N_ELEMENTS (style_map), str, len, + desc ? (int *)&desc->style : NULL) || + find_field (variant_map, G_N_ELEMENTS (variant_map), str, len, + desc ? (int *)&desc->variant : NULL) || + find_field (weight_map, G_N_ELEMENTS (weight_map), str, len, + desc ? (int *)&desc->weight : NULL) || + find_field (stretch_map, G_N_ELEMENTS (stretch_map), str, len, + desc ? (int *)&desc->stretch : NULL)); +} + +static const char * +getword (const char *str, const char *last, size_t *wordlen) +{ + const char *result; + + while (last > str && isspace (*(last - 1))) + last--; + + result = last; + while (result > str && !isspace (*(result - 1))) + result--; + + *wordlen = last - result; + + return result; +} + +/** + * pango_font_description_from_string: + * @str: string reprentation of a font description. + * + * Create 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, or stretch, and SIZE + * is an decimal number (size in points). 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, or %NULL if the + * string could not be parsed. + **/ +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 = g_new (PangoFontDescription, 1); + + desc->family_name = NULL; + desc->style = PANGO_STYLE_NORMAL; + desc->weight = PANGO_WEIGHT_NORMAL; + desc->variant = PANGO_VARIANT_NORMAL; + desc->stretch = PANGO_STRETCH_NORMAL; + + desc->size = 0; + + len = strlen (str); + last = str + len; + p = getword (str, last, &wordlen); + + /* Look for a size at the end of the string + */ + if (wordlen != 0) + { + char *end; + double size = strtod (p, &end); + if (end - p == wordlen) /* word is a valid float */ + { + desc->size = (int)(size * 1000 + 0.5); + 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 && isspace (*(last - 1))) + last--; + + if (last > str && *(last - 1) == ',') + last--; + + while (last > str && isspace (*(last - 1))) + last--; + + while (isspace (*str)) + str++; + + if (str != last) + desc->family_name = g_strndup (str, last - str); + + return desc; +} + +static void +append_field (GString *str, 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) + { + if (str->len != 0) + g_string_append_c (str, ' '); + g_string_append (str, map[i].str); + } + return; + } + } + + if (str->len != 0) + g_string_append_c (str, ' '); + g_string_sprintfa (str, "%d", val); +} + +/** + * pango_font_description_to_string: + * @desc: a #PangoFontDescription + * + * Create 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_string_new (NULL); + char *str; + + if (desc->family_name) + { + const char *p; + size_t wordlen; + + g_string_append (result, desc->family_name); + + p = getword (desc->family_name, desc->family_name + strlen(desc->family_name), &wordlen); + if (wordlen != 0 && find_field_any (p, wordlen, NULL)) + 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 (result->len == 0) + g_string_append (result, "Normal"); + + if (desc->size > 0) + { + if (result->len == 0) + g_string_append_c (result, ' '); + + g_string_sprintfa (result, "%f", desc->size / 1000.); + } + + str = result->str; + g_string_free (result, FALSE); + return str; +} + /** * pango_font_init: * @font: a #PangoFont diff --git a/pango/pango-font.h b/pango/pango-font.h index d6d67d0e..bae83660 100644 --- a/pango/pango-font.h +++ b/pango/pango-font.h @@ -74,12 +74,16 @@ struct _PangoFontDescription int size; }; -PangoFontDescription *pango_font_description_copy (const PangoFontDescription *desc); -gboolean pango_font_description_compare (const PangoFontDescription *desc1, - const PangoFontDescription *desc2); -void pango_font_description_free (PangoFontDescription *desc); -void pango_font_descriptions_free (PangoFontDescription **descs, - int n_descs); +PangoFontDescription *pango_font_description_copy (const PangoFontDescription *desc); +gboolean pango_font_description_compare (const PangoFontDescription *desc1, + const PangoFontDescription *desc2); +void pango_font_description_free (PangoFontDescription *desc); +void pango_font_descriptions_free (PangoFontDescription **descs, + int n_descs); + +PangoFontDescription *pango_font_description_from_string (const char *str); +char * pango_font_description_to_string (const PangoFontDescription *desc); + /* Logical fonts */ diff --git a/pango/pangox.c b/pango/pangox.c index 1adf0603..203ea5d2 100644 --- a/pango/pangox.c +++ b/pango/pangox.c @@ -1081,10 +1081,11 @@ pango_x_insert_font (PangoXFontMap *xfontmap, char *identifier; int i; + description.size = 0; + /* First insert the XLFD into the list of XLFDs for the "identifier" - which * is the 2-4th fields of the XLFD */ - identifier = pango_x_get_identifier (fontname); size_info = g_hash_table_lookup (xfontmap->size_infos, identifier); if (!size_info) |