summaryrefslogtreecommitdiff
path: root/pango/fonts.c
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2000-02-29 00:51:29 +0000
committerOwen Taylor <otaylor@src.gnome.org>2000-02-29 00:51:29 +0000
commit6278d373c1a564ae4233a2e4b6d428a9f6202728 (patch)
tree831ea6ce3ce84ab59e040cc7d176067962b33d5d /pango/fonts.c
parentabacca30f29df84d9818cd1395449eff0e4ee171 (diff)
downloadpango-6278d373c1a564ae4233a2e4b6d428a9f6202728.tar.gz
Add functions to convert font descriptions to and from human-readable
Mon Feb 28 19:46:35 2000 Owen Taylor <otaylor@redhat.com> * libpango/fonts.c libpango/pango-fonts.h: Add functions to convert font descriptions to and from human-readable strings. * examples/viewer.c: Use functions from libpango instead of rolling our own font-description conversion functions.
Diffstat (limited to 'pango/fonts.c')
-rw-r--r--pango/fonts.c253
1 files changed, 253 insertions, 0 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