Grub through style to find weight/slant/width values when other techniques
fail
This commit is contained in:
parent
1f71c4d878
commit
11fec41c0e
228
src/fcfreetype.c
228
src/fcfreetype.c
|
@ -255,6 +255,87 @@ FcVendorFoundry(const char *vendor)
|
||||||
return 0;
|
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 *
|
FcPattern *
|
||||||
FcFreeTypeQuery (const FcChar8 *file,
|
FcFreeTypeQuery (const FcChar8 *file,
|
||||||
|
@ -264,8 +345,8 @@ FcFreeTypeQuery (const FcChar8 *file,
|
||||||
{
|
{
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
FcPattern *pat;
|
FcPattern *pat;
|
||||||
int slant;
|
int slant = -1;
|
||||||
int weight;
|
int weight = -1;
|
||||||
int width = -1;
|
int width = -1;
|
||||||
int i;
|
int i;
|
||||||
FcCharSet *cs;
|
FcCharSet *cs;
|
||||||
|
@ -307,15 +388,6 @@ FcFreeTypeQuery (const FcChar8 *file,
|
||||||
goto bail1;
|
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
|
* Get the OS/2 table
|
||||||
*/
|
*/
|
||||||
|
@ -598,30 +670,15 @@ FcFreeTypeQuery (const FcChar8 *file,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FcDebug() & FC_DBG_SCAN)
|
if (FcDebug() & FC_DBG_SCAN)
|
||||||
printf ("\"%s\" \"%s\" ", family, style ? style : (FcChar8 *) "<none>");
|
printf ("\n\"%s\" \"%s\"\n", family, style ? style : (FcChar8 *) "<none>");
|
||||||
|
|
||||||
if (!FcPatternAddString (pat, FC_FAMILY, family))
|
if (!FcPatternAddString (pat, FC_FAMILY, family))
|
||||||
{
|
|
||||||
if (family_allocated)
|
|
||||||
free (family);
|
|
||||||
if (style_allocated)
|
|
||||||
free (style);
|
|
||||||
goto bail1;
|
goto bail1;
|
||||||
}
|
|
||||||
|
|
||||||
if (family_allocated)
|
|
||||||
free (family);
|
|
||||||
|
|
||||||
if (style)
|
if (style)
|
||||||
{
|
{
|
||||||
if (!FcPatternAddString (pat, FC_STYLE, style))
|
if (!FcPatternAddString (pat, FC_STYLE, style))
|
||||||
{
|
|
||||||
if (style_allocated)
|
|
||||||
free (style);
|
|
||||||
goto bail1;
|
goto bail1;
|
||||||
}
|
|
||||||
if (style_allocated)
|
|
||||||
free (style);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FcPatternAddString (pat, FC_FILE, file))
|
if (!FcPatternAddString (pat, FC_FILE, file))
|
||||||
|
@ -695,7 +752,7 @@ FcFreeTypeQuery (const FcChar8 *file,
|
||||||
if (os2 && os2->version != 0xffff)
|
if (os2 && os2->version != 0xffff)
|
||||||
{
|
{
|
||||||
if (os2->usWeightClass == 0)
|
if (os2->usWeightClass == 0)
|
||||||
weight = -1;
|
;
|
||||||
else if (os2->usWeightClass < 150)
|
else if (os2->usWeightClass < 150)
|
||||||
weight = FC_WEIGHT_THIN;
|
weight = FC_WEIGHT_THIN;
|
||||||
else if (os2->usWeightClass < 250)
|
else if (os2->usWeightClass < 250)
|
||||||
|
@ -714,8 +771,6 @@ FcFreeTypeQuery (const FcChar8 *file,
|
||||||
weight = FC_WEIGHT_EXTRABOLD;
|
weight = FC_WEIGHT_EXTRABOLD;
|
||||||
else if (os2->usWeightClass < 950)
|
else if (os2->usWeightClass < 950)
|
||||||
weight = FC_WEIGHT_BLACK;
|
weight = FC_WEIGHT_BLACK;
|
||||||
else
|
|
||||||
weight = FC_WEIGHT_MEDIUM;
|
|
||||||
|
|
||||||
switch (os2->usWidthClass) {
|
switch (os2->usWidthClass) {
|
||||||
case 1: width = FC_WIDTH_ULTRACONDENSED; break;
|
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 (FT_Get_PS_Font_Info(face, &psfontinfo) == 0)
|
||||||
{
|
{
|
||||||
if (psfontinfo.weight)
|
#if 0
|
||||||
|
if (weight == -1 && psfontinfo.weight)
|
||||||
{
|
{
|
||||||
static struct {
|
weight = FcIsWeight (psfontinfo.weight);
|
||||||
char *name;
|
if (FcDebug() & FC_DBG_SCANV)
|
||||||
int value;
|
printf ("\tType1 weight %s maps to %d\n",
|
||||||
} ps_weights[] = {
|
psfontinfo.weight, weight);
|
||||||
{ "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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
|
@ -838,14 +864,11 @@ FcFreeTypeQuery (const FcChar8 *file,
|
||||||
FcChar8 *width_name;
|
FcChar8 *width_name;
|
||||||
int width;
|
int width;
|
||||||
} FcSetWidths[] = {
|
} FcSetWidths[] = {
|
||||||
{ "Condensed", FC_WIDTH_CONDENSED },
|
|
||||||
{ "SemiCondensed", FC_WIDTH_SEMICONDENSED },
|
|
||||||
{ "Normal", FC_WIDTH_NORMAL },
|
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (FcDebug () & FC_DBG_SCANV)
|
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++)
|
for (i = 0; i < sizeof (FcSetWidths) / sizeof (FcSetWidths[0]); i++)
|
||||||
if (!FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) prop.u.atom,
|
if (!FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) prop.u.atom,
|
||||||
FcSetWidths[i].width_name))
|
FcSetWidths[i].width_name))
|
||||||
|
@ -858,6 +881,48 @@ FcFreeTypeQuery (const FcChar8 *file,
|
||||||
|
|
||||||
#endif
|
#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))
|
if (!FcPatternAddInteger (pat, FC_SLANT, slant))
|
||||||
goto bail1;
|
goto bail1;
|
||||||
|
|
||||||
|
@ -905,11 +970,6 @@ FcFreeTypeQuery (const FcChar8 *file,
|
||||||
if (!FcPatternAddInteger (pat, FC_SPACING, spacing))
|
if (!FcPatternAddInteger (pat, FC_SPACING, spacing))
|
||||||
goto bail2;
|
goto bail2;
|
||||||
|
|
||||||
/*
|
|
||||||
* Drop our reference to the charset
|
|
||||||
*/
|
|
||||||
FcCharSetDestroy (cs);
|
|
||||||
|
|
||||||
if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
|
if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
|
||||||
{
|
{
|
||||||
for (i = 0; i < face->num_fixed_sizes; i++)
|
for (i = 0; i < face->num_fixed_sizes; i++)
|
||||||
|
@ -920,6 +980,20 @@ FcFreeTypeQuery (const FcChar8 *file,
|
||||||
goto bail1;
|
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_Face (face);
|
||||||
FT_Done_FreeType (ftLibrary);
|
FT_Done_FreeType (ftLibrary);
|
||||||
return pat;
|
return pat;
|
||||||
|
@ -928,6 +1002,10 @@ bail2:
|
||||||
FcCharSetDestroy (cs);
|
FcCharSetDestroy (cs);
|
||||||
bail1:
|
bail1:
|
||||||
FcPatternDestroy (pat);
|
FcPatternDestroy (pat);
|
||||||
|
if (family_allocated)
|
||||||
|
free (family);
|
||||||
|
if (style_allocated)
|
||||||
|
free (style);
|
||||||
bail0:
|
bail0:
|
||||||
FT_Done_Face (face);
|
FT_Done_Face (face);
|
||||||
bail:
|
bail:
|
||||||
|
|
|
@ -653,6 +653,12 @@ FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len);
|
||||||
int
|
int
|
||||||
FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2);
|
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
|
FcBool
|
||||||
FcStrUsesHome (const FcChar8 *s);
|
FcStrUsesHome (const FcChar8 *s);
|
||||||
|
|
||||||
|
|
74
src/fcstr.c
74
src/fcstr.c
|
@ -114,6 +114,80 @@ FcStrCmp (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
return (int) c1 - (int) c2;
|
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
|
int
|
||||||
FcUtf8ToUcs4 (const FcChar8 *src_orig,
|
FcUtf8ToUcs4 (const FcChar8 *src_orig,
|
||||||
FcChar32 *dst,
|
FcChar32 *dst,
|
||||||
|
|
Loading…
Reference in New Issue