From 11fec41c0e4211ca4cdcd0b63fb8ef8257e2bd0c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 May 2003 01:11:53 +0000 Subject: [PATCH] Grub through style to find weight/slant/width values when other techniques fail --- src/fcfreetype.c | 228 +++++++++++++++++++++++++++++++---------------- src/fcint.h | 6 ++ src/fcstr.c | 74 +++++++++++++++ 3 files changed, 233 insertions(+), 75 deletions(-) diff --git a/src/fcfreetype.c b/src/fcfreetype.c index f46e139..eef7081 100644 --- a/src/fcfreetype.c +++ b/src/fcfreetype.c @@ -255,6 +255,87 @@ FcVendorFoundry(const char *vendor) return 0; } +typedef struct _FcStringConst { + const char *name; + int value; +} FcStringConst; + +static int +FcStringIsConst (const FcChar8 *string, + const FcStringConst *c, + int nc) +{ + int i; + + for (i = 0; i < nc; i++) + if (FcStrCmpIgnoreBlanksAndCase (string, c[i].name) == 0) + return c[i].value; + return -1; +} + +static int +FcStringContainsConst (const FcChar8 *string, + const FcStringConst *c, + int nc) +{ + int i; + + for (i = 0; i < nc; i++) + if (FcStrContainsIgnoreBlanksAndCase (string, c[i].name)) + return c[i].value; + return -1; +} + +static const FcStringConst weightConsts[] = { + { "thin", FC_WEIGHT_THIN }, + { "extralight", FC_WEIGHT_EXTRALIGHT }, + { "ultralight", FC_WEIGHT_ULTRALIGHT }, + { "light", FC_WEIGHT_LIGHT }, + { "book", FC_WEIGHT_BOOK }, + { "regular", FC_WEIGHT_REGULAR }, + { "normal", FC_WEIGHT_NORMAL }, + { "medium", FC_WEIGHT_MEDIUM }, + { "demibold", FC_WEIGHT_DEMIBOLD }, + { "demi", FC_WEIGHT_DEMIBOLD }, + { "semibold", FC_WEIGHT_SEMIBOLD }, + { "bold", FC_WEIGHT_BOLD }, + { "extrabold", FC_WEIGHT_EXTRABOLD }, + { "ultrabold", FC_WEIGHT_ULTRABOLD }, + { "black", FC_WEIGHT_BLACK }, + { "heavy", FC_WEIGHT_HEAVY }, +}; + +#define NUM_WEIGHT_CONSTS (sizeof (weightConsts) / sizeof (weightConsts[0])) + +#define FcIsWeight(s) FcStringIsConst(s,weightConsts,NUM_WEIGHT_CONSTS) +#define FcContainsWeight(s) FcStringContainsConst (s,weightConsts,NUM_WEIGHT_CONSTS) + +static const FcStringConst widthConsts[] = { + { "ultracondensed", FC_WIDTH_ULTRACONDENSED }, + { "extracondensed", FC_WIDTH_EXTRACONDENSED }, + { "semicondensed", FC_WIDTH_SEMICONDENSED }, + { "condensed", FC_WIDTH_CONDENSED }, /* must be after *condensed */ + { "normal", FC_WIDTH_NORMAL }, + { "semiexpanded", FC_WIDTH_SEMIEXPANDED }, + { "extraexpanded", FC_WIDTH_EXTRAEXPANDED }, + { "ultraexpanded", FC_WIDTH_ULTRAEXPANDED }, + { "expanded", FC_WIDTH_EXPANDED }, /* must be after *expanded */ +}; + +#define NUM_WIDTH_CONSTS (sizeof (widthConsts) / sizeof (widthConsts[0])) + +#define FcIsWidth(s) FcStringIsConst(s,widthConsts,NUM_WIDTH_CONSTS) +#define FcContainsWidth(s) FcStringContainsConst (s,widthConsts,NUM_WIDTH_CONSTS) + +static const FcStringConst slantConsts[] = { + { "italic", FC_SLANT_ITALIC }, + { "oblique", FC_SLANT_OBLIQUE }, +}; + +#define NUM_SLANT_CONSTS (sizeof (slantConsts) / sizeof (slantConsts[0])) + +#define FcIsSlant(s) FcStringIsConst(s,slantConsts,NUM_SLANT_CONSTS) +#define FcContainsSlant(s) FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS) FcPattern * FcFreeTypeQuery (const FcChar8 *file, @@ -264,8 +345,8 @@ FcFreeTypeQuery (const FcChar8 *file, { FT_Face face; FcPattern *pat; - int slant; - int weight; + int slant = -1; + int weight = -1; int width = -1; int i; FcCharSet *cs; @@ -307,15 +388,6 @@ FcFreeTypeQuery (const FcChar8 *file, goto bail1; - slant = FC_SLANT_ROMAN; - if (face->style_flags & FT_STYLE_FLAG_ITALIC) - slant = FC_SLANT_ITALIC; - - - weight = FC_WEIGHT_MEDIUM; - if (face->style_flags & FT_STYLE_FLAG_BOLD) - weight = FC_WEIGHT_BOLD; - /* * Get the OS/2 table */ @@ -598,30 +670,15 @@ FcFreeTypeQuery (const FcChar8 *file, } if (FcDebug() & FC_DBG_SCAN) - printf ("\"%s\" \"%s\" ", family, style ? style : (FcChar8 *) ""); + printf ("\n\"%s\" \"%s\"\n", family, style ? style : (FcChar8 *) ""); if (!FcPatternAddString (pat, FC_FAMILY, family)) - { - if (family_allocated) - free (family); - if (style_allocated) - free (style); goto bail1; - } - - if (family_allocated) - free (family); if (style) { if (!FcPatternAddString (pat, FC_STYLE, style)) - { - if (style_allocated) - free (style); goto bail1; - } - if (style_allocated) - free (style); } if (!FcPatternAddString (pat, FC_FILE, file)) @@ -695,7 +752,7 @@ FcFreeTypeQuery (const FcChar8 *file, if (os2 && os2->version != 0xffff) { if (os2->usWeightClass == 0) - weight = -1; + ; else if (os2->usWeightClass < 150) weight = FC_WEIGHT_THIN; else if (os2->usWeightClass < 250) @@ -714,8 +771,6 @@ FcFreeTypeQuery (const FcChar8 *file, weight = FC_WEIGHT_EXTRABOLD; else if (os2->usWeightClass < 950) weight = FC_WEIGHT_BLACK; - else - weight = FC_WEIGHT_MEDIUM; switch (os2->usWidthClass) { case 1: width = FC_WIDTH_ULTRACONDENSED; break; @@ -737,44 +792,15 @@ FcFreeTypeQuery (const FcChar8 *file, if (FT_Get_PS_Font_Info(face, &psfontinfo) == 0) { - if (psfontinfo.weight) +#if 0 + if (weight == -1 && psfontinfo.weight) { - static struct { - char *name; - int value; - } ps_weights[] = { - { "thin", FC_WEIGHT_THIN }, - { "extralight", FC_WEIGHT_EXTRALIGHT }, - { "ultralight", FC_WEIGHT_ULTRALIGHT }, - { "light", FC_WEIGHT_LIGHT }, - { "book", FC_WEIGHT_BOOK }, - { "regular", FC_WEIGHT_REGULAR }, - { "normal", FC_WEIGHT_NORMAL }, - { "medium", FC_WEIGHT_MEDIUM }, - { "demibold", FC_WEIGHT_DEMIBOLD }, - { "demi", FC_WEIGHT_DEMIBOLD }, - { "semibold", FC_WEIGHT_SEMIBOLD }, - { "bold", FC_WEIGHT_BOLD }, - { "extrabold", FC_WEIGHT_EXTRABOLD }, - { "ultrabold", FC_WEIGHT_ULTRABOLD }, - { "black", FC_WEIGHT_BLACK }, - { "heavy", FC_WEIGHT_HEAVY }, - }; -#define NUM_PS_WEIGHTS (sizeof (ps_weights) / sizeof (ps_weights[0])) - int w; - for (w = 0; w < NUM_PS_WEIGHTS; w++) - if (!FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) ps_weights[w].name, - (FcChar8 *) psfontinfo.weight)) - { - weight = ps_weights[w].value; - break; - } - if (FcDebug () & FC_DBG_SCANV) - { - if (w == NUM_PS_WEIGHTS) - printf ("\tunknown PS weight name %s\n", psfontinfo.weight); - } + weight = FcIsWeight (psfontinfo.weight); + if (FcDebug() & FC_DBG_SCANV) + printf ("\tType1 weight %s maps to %d\n", + psfontinfo.weight, weight); } +#endif #if 0 /* @@ -838,14 +864,11 @@ FcFreeTypeQuery (const FcChar8 *file, FcChar8 *width_name; int width; } FcSetWidths[] = { - { "Condensed", FC_WIDTH_CONDENSED }, - { "SemiCondensed", FC_WIDTH_SEMICONDENSED }, - { "Normal", FC_WIDTH_NORMAL }, }; int i; if (FcDebug () & FC_DBG_SCANV) - printf ("\nsetwidth: %s\n", prop.u.atom); + printf ("\tsetwidth: %s\n", prop.u.atom); for (i = 0; i < sizeof (FcSetWidths) / sizeof (FcSetWidths[0]); i++) if (!FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) prop.u.atom, FcSetWidths[i].width_name)) @@ -858,6 +881,48 @@ FcFreeTypeQuery (const FcChar8 *file, #endif + /* + * Look for weight, width and slant names in the style value + */ + if (style) + { + if (weight == -1) + { + weight = FcContainsWeight (style); + if (FcDebug() & FC_DBG_SCANV) + printf ("\tStyle %s maps to weight %d\n", style, weight); + } + if (width == -1) + { + width = FcContainsWidth (style); + if (FcDebug() & FC_DBG_SCANV) + printf ("\tStyle %s maps to width %d\n", style, width); + } + if (slant == -1) + { + slant = FcContainsSlant (style); + if (FcDebug() & FC_DBG_SCANV) + printf ("\tStyle %s maps to slant %d\n", style, slant); + } + } + /* + * Pull default values from the FreeType flags if more + * specific values not found above + */ + if (slant == -1) + { + slant = FC_SLANT_ROMAN; + if (face->style_flags & FT_STYLE_FLAG_ITALIC) + slant = FC_SLANT_ITALIC; + } + + if (weight == -1) + { + weight = FC_WEIGHT_MEDIUM; + if (face->style_flags & FT_STYLE_FLAG_BOLD) + weight = FC_WEIGHT_BOLD; + } + if (!FcPatternAddInteger (pat, FC_SLANT, slant)) goto bail1; @@ -905,11 +970,6 @@ FcFreeTypeQuery (const FcChar8 *file, if (!FcPatternAddInteger (pat, FC_SPACING, spacing)) goto bail2; - /* - * Drop our reference to the charset - */ - FcCharSetDestroy (cs); - if (!(face->face_flags & FT_FACE_FLAG_SCALABLE)) { for (i = 0; i < face->num_fixed_sizes; i++) @@ -920,6 +980,20 @@ FcFreeTypeQuery (const FcChar8 *file, goto bail1; } + /* + * Drop our reference to the charset + */ + FcCharSetDestroy (cs); + + /* + * Deallocate family/style values + */ + + if (family_allocated) + free (family); + if (style_allocated) + free (style); + FT_Done_Face (face); FT_Done_FreeType (ftLibrary); return pat; @@ -928,6 +1002,10 @@ bail2: FcCharSetDestroy (cs); bail1: FcPatternDestroy (pat); + if (family_allocated) + free (family); + if (style_allocated) + free (style); bail0: FT_Done_Face (face); bail: diff --git a/src/fcint.h b/src/fcint.h index 7ffc3a6..9b469b7 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -653,6 +653,12 @@ FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len); int FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2); +const FcChar8 * +FcStrContainsIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2); + +const FcChar8 * +FcStrContainsIgnoreCase (const FcChar8 *s1, const FcChar8 *s2); + FcBool FcStrUsesHome (const FcChar8 *s); diff --git a/src/fcstr.c b/src/fcstr.c index 5b75f0e..ecbfd29 100644 --- a/src/fcstr.c +++ b/src/fcstr.c @@ -114,6 +114,80 @@ FcStrCmp (const FcChar8 *s1, const FcChar8 *s2) return (int) c1 - (int) c2; } +/* + * Is the head of s1 equal to s2? + */ + +static FcBool +FcStrIsAtIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2) +{ + FcChar8 c1, c2; + + for (;;) + { + do + c1 = *s1++; + while (c1 == ' '); + do + c2 = *s2++; + while (c2 == ' '); + if (!c1 || (c1 != c2 && (c1 = FcToLower(c1)) != (c2 = FcToLower(c2)))) + break; + } + return c1 == c2 || !c2; +} + +/* + * Does s1 contain an instance of s2 (ignoring blanks and case)? + */ + +const FcChar8 * +FcStrContainsIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2) +{ + while (*s1) + { + if (FcStrIsAtIgnoreBlanksAndCase (s1, s2)) + return s1; + s1++; + } + return 0; +} + +/* + * Is the head of s1 equal to s2? + */ + +static FcBool +FcStrIsAtIgnoreCase (const FcChar8 *s1, const FcChar8 *s2) +{ + FcChar8 c1, c2; + + for (;;) + { + c1 = *s1++; + c2 = *s2++; + if (!c1 || (c1 != c2 && (c1 = FcToLower(c1)) != (c2 = FcToLower(c2)))) + break; + } + return c1 == c2 || !c2; +} + +/* + * Does s1 contain an instance of s2 (ignoring blanks and case)? + */ + +const FcChar8 * +FcStrContainsIgnoreCase (const FcChar8 *s1, const FcChar8 *s2) +{ + while (*s1) + { + if (FcStrIsAtIgnoreCase (s1, s2)) + return s1; + s1++; + } + return 0; +} + int FcUtf8ToUcs4 (const FcChar8 *src_orig, FcChar32 *dst,