diff --git a/src/cairo-font-face-twin.c b/src/cairo-font-face-twin.c index ca847ce68..712ca0dcd 100644 --- a/src/cairo-font-face-twin.c +++ b/src/cairo-font-face-twin.c @@ -57,6 +57,8 @@ static cairo_user_data_key_t twin_properties_key; /* We synthesize multiple faces from the twin data. Here is the parameters. */ +/* The following tables and matching code are copied from Pango */ + /* CSS weight */ typedef enum { TWIN_WEIGHT_THIN = 100, @@ -85,6 +87,64 @@ typedef enum { TWIN_STRETCH_ULTRA_EXPANDED } twin_face_stretch_t; +typedef struct +{ + int value; + const char str[16]; +} FieldMap; + +static const FieldMap slant_map[] = { + { CAIRO_FONT_SLANT_NORMAL, "" }, + { CAIRO_FONT_SLANT_NORMAL, "Roman" }, + { CAIRO_FONT_SLANT_OBLIQUE, "Oblique" }, + { CAIRO_FONT_SLANT_ITALIC, "Italic" } +}; + +static const FieldMap smallcaps_map[] = { + { FALSE, "" }, + { TRUE, "Small-Caps" } +}; + +static const FieldMap weight_map[] = { + { TWIN_WEIGHT_THIN, "Thin" }, + { TWIN_WEIGHT_ULTRALIGHT, "Ultra-Light" }, + { TWIN_WEIGHT_ULTRALIGHT, "Extra-Light" }, + { TWIN_WEIGHT_LIGHT, "Light" }, + { TWIN_WEIGHT_BOOK, "Book" }, + { TWIN_WEIGHT_NORMAL, "" }, + { TWIN_WEIGHT_NORMAL, "Regular" }, + { TWIN_WEIGHT_MEDIUM, "Medium" }, + { TWIN_WEIGHT_SEMIBOLD, "Semi-Bold" }, + { TWIN_WEIGHT_SEMIBOLD, "Demi-Bold" }, + { TWIN_WEIGHT_BOLD, "Bold" }, + { TWIN_WEIGHT_ULTRABOLD, "Ultra-Bold" }, + { TWIN_WEIGHT_ULTRABOLD, "Extra-Bold" }, + { TWIN_WEIGHT_HEAVY, "Heavy" }, + { TWIN_WEIGHT_HEAVY, "Black" }, + { TWIN_WEIGHT_ULTRAHEAVY, "Ultra-Heavy" }, + { TWIN_WEIGHT_ULTRAHEAVY, "Extra-Heavy" }, + { TWIN_WEIGHT_ULTRAHEAVY, "Ultra-Black" }, + { TWIN_WEIGHT_ULTRAHEAVY, "Extra-Black" } +}; + +static const FieldMap stretch_map[] = { + { TWIN_STRETCH_ULTRA_CONDENSED, "Ultra-Condensed" }, + { TWIN_STRETCH_EXTRA_CONDENSED, "Extra-Condensed" }, + { TWIN_STRETCH_CONDENSED, "Condensed" }, + { TWIN_STRETCH_SEMI_CONDENSED, "Semi-Condensed" }, + { TWIN_STRETCH_NORMAL, "" }, + { TWIN_STRETCH_SEMI_EXPANDED, "Semi-Expanded" }, + { TWIN_STRETCH_EXPANDED, "Expanded" }, + { TWIN_STRETCH_EXTRA_EXPANDED, "Extra-Expanded" }, + { TWIN_STRETCH_ULTRA_EXPANDED, "Ultra-Expanded" } +}; + +static const FieldMap monospace_map[] = { + { FALSE, "" }, + { TRUE, "Mono" }, + { TRUE, "Monospace" } +}; + typedef struct _twin_face_properties { cairo_font_slant_t slant; @@ -124,52 +184,84 @@ field_matches (const char *s1, return len == 0 && *s1 == '\0'; } +static cairo_bool_t +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 cairo_bool_t +find_field (const char *what, + const FieldMap *map, + int n_elements, + const char *str, + int len, + int *val) +{ + int i; + cairo_bool_t 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; iNAME)) \ + return; \ - else MATCH ("Oblique", props->slant, CAIRO_FONT_SLANT_OBLIQUE); - else MATCH ("Italic", props->slant, CAIRO_FONT_SLANT_ITALIC); + FIELD (weight); + FIELD (slant); + FIELD (stretch); + FIELD (smallcaps); + FIELD (monospace); - else MATCH ("Thin", props->weight, TWIN_WEIGHT_THIN); - else MATCH ("Ultra-Light", props->weight, TWIN_WEIGHT_ULTRALIGHT); - else MATCH ("Extra-Light", props->weight, TWIN_WEIGHT_ULTRALIGHT); - else MATCH ("Light", props->weight, TWIN_WEIGHT_LIGHT); - else MATCH ("Book", props->weight, TWIN_WEIGHT_BOOK); - else MATCH ("Regular", props->weight, TWIN_WEIGHT_NORMAL); - else MATCH ("Medium", props->weight, TWIN_WEIGHT_MEDIUM); - else MATCH ("Semi-Bold", props->weight, TWIN_WEIGHT_SEMIBOLD); - else MATCH ("Demi-Bold", props->weight, TWIN_WEIGHT_SEMIBOLD); - else MATCH ("Bold", props->weight, TWIN_WEIGHT_BOLD); - else MATCH ("Ultra-Bold", props->weight, TWIN_WEIGHT_ULTRABOLD); - else MATCH ("Extra-Bold", props->weight, TWIN_WEIGHT_ULTRABOLD); - else MATCH ("Heavy", props->weight, TWIN_WEIGHT_HEAVY); - else MATCH ("Black", props->weight, TWIN_WEIGHT_HEAVY); - else MATCH ("Ultra-Heavy", props->weight, TWIN_WEIGHT_ULTRAHEAVY); - else MATCH ("Extra-Heavy", props->weight, TWIN_WEIGHT_ULTRAHEAVY); - else MATCH ("Ultra-Black", props->weight, TWIN_WEIGHT_ULTRAHEAVY); - else MATCH ("Extra-Black", props->weight, TWIN_WEIGHT_ULTRAHEAVY); - - else MATCH ("Ultra-Condensed", props->stretch, TWIN_STRETCH_ULTRA_CONDENSED); - else MATCH ("Extra-Condensed", props->stretch, TWIN_STRETCH_EXTRA_CONDENSED); - else MATCH ("Condensed", props->stretch, TWIN_STRETCH_CONDENSED); - else MATCH ("Semi-Condensed", props->stretch, TWIN_STRETCH_SEMI_CONDENSED); - else MATCH ("Semi-Expanded", props->stretch, TWIN_STRETCH_SEMI_EXPANDED); - else MATCH ("Expanded", props->stretch, TWIN_STRETCH_EXPANDED); - else MATCH ("Extra-Expanded", props->stretch, TWIN_STRETCH_EXTRA_EXPANDED); - else MATCH ("Ultra-Expanded", props->stretch, TWIN_STRETCH_ULTRA_EXPANDED); - - else MATCH ("Mono", props->monospace, TRUE); - else MATCH ("Monospace", props->monospace, TRUE); - - else MATCH ("Small-Caps", props->smallcaps, TRUE); +#undef FIELD } static void @@ -178,11 +270,8 @@ face_props_parse (twin_face_properties_t *props, { const char *start, *end; -#define ISALPHA(c) \ - (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z')) - for (start = end = s; *end; end++) { - if (ISALPHA (*end) || *end == '-') + if (*end != ' ' && *end != ':') continue; if (start < end) diff --git a/src/cairoint.h b/src/cairoint.h index b93c4a44e..5c4626a6d 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -120,6 +120,10 @@ _cairo_win32_tmpfile (void); #undef ARRAY_LENGTH #define ARRAY_LENGTH(__array) ((int) (sizeof (__array) / sizeof (__array[0]))) +#undef STRINGIFY +#undef STRINGIFY_ARG +#define STRINGIFY(macro_or_string) STRINGIFY_ARG (macro_or_string) +#define STRINGIFY_ARG(contents) #contents /* This has to be updated whenever #cairo_status_t is extended. That's * a bit of a pain, but it should be easy to always catch as long as