mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-06 04:38:04 +02:00
[twin] Reorganize matching code to better reflect the code in Pango
Makes it easier to update later.
This commit is contained in:
parent
2b4044a36f
commit
922c108365
2 changed files with 135 additions and 42 deletions
|
|
@ -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; 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 void
|
||||
parse_field (twin_face_properties_t *props,
|
||||
const char *s,
|
||||
const char *str,
|
||||
int len)
|
||||
{
|
||||
#define MATCH(s1, var, value) \
|
||||
if (field_matches (s1, s, len)) var = value
|
||||
if (field_matches ("Normal", str, len))
|
||||
return;
|
||||
|
||||
if (0) ;
|
||||
#define FIELD(NAME) \
|
||||
if (find_field (STRINGIFY (NAME), NAME##_map, ARRAY_LENGTH (NAME##_map), str, len, \
|
||||
(int *)(void *)&props->NAME)) \
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue