Add strong/weak pattern value binding, add known charsets for automatic

lang computation
This commit is contained in:
Keith Packard 2002-06-29 20:31:02 +00:00
parent 5c7fb8274c
commit 4c0036053a
8 changed files with 2223 additions and 89 deletions

View File

@ -1,5 +1,5 @@
/*
* $XFree86: xc/lib/fontconfig/src/fccfg.c,v 1.14 2002/06/20 03:43:09 keithp Exp $
* $XFree86: xc/lib/fontconfig/src/fccfg.c,v 1.15 2002/06/21 06:14:45 keithp Exp $
*
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
*
@ -926,6 +926,7 @@ FcConfigValues (FcPattern *p, FcExpr *e)
l->value = FcConfigEvaluate (p, e);
l->next = 0;
}
l->binding = FcValueBindingWeak;
while (l && l->value.type == FcTypeVoid)
{
FcValueList *next = l->next;

View File

@ -1,5 +1,5 @@
/*
* $XFree86: xc/lib/fontconfig/src/fccharset.c,v 1.12 2002/06/21 06:14:45 keithp Exp $
* $XFree86: xc/lib/fontconfig/src/fccharset.c,v 1.13 2002/06/26 22:56:51 keithp Exp $
*
* Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
*
@ -858,7 +858,7 @@ static int FcCharLeafTotal;
static int FcCharLeafUsed;
static FcCharLeaf *
FcNameParseBuildLeaf (FcCharLeaf *leaf)
FcCharSetFreezeLeaf (FcCharLeaf *leaf)
{
static FcCharLeafEnt *hashTable[FC_CHAR_LEAF_HASH_SIZE];
FcChar32 hash = FcCharLeafHash (leaf);
@ -915,7 +915,7 @@ static int FcCharSetUsed;
static int FcCharSetTotalEnts, FcCharSetUsedEnts;
static FcCharSet *
FcNameParseBuildSet (FcCharSet *fcs)
FcCharSetFreezeBase (FcCharSet *fcs)
{
static FcCharSetEnt *hashTable[FC_CHAR_SET_HASH_SIZE];
FcChar32 hash = FcCharSetHash (fcs);
@ -967,6 +967,36 @@ FcNameParseBuildSet (FcCharSet *fcs)
return &ent->set;
}
FcCharSet *
FcCharSetFreeze (FcCharSet *fcs)
{
FcCharSet *b;
FcCharSet *n = 0;
FcCharLeaf *l;
int i;
b = FcCharSetCreate ();
if (!b)
goto bail0;
for (i = 0; i < fcs->num; i++)
{
l = FcCharSetFreezeLeaf (fcs->leaves[i]);
if (!l)
goto bail1;
if (!FcCharSetInsertLeaf (b, fcs->numbers[i] << 8, l))
goto bail1;
}
n = FcCharSetFreezeBase (b);
bail1:
if (b->leaves)
free (b->leaves);
if (b->numbers)
free (b->numbers);
free (b);
bail0:
return n;
}
FcCharSet *
FcNameParseCharSet (FcChar8 *string)
{
@ -995,7 +1025,7 @@ FcNameParseCharSet (FcChar8 *string)
}
if (bits)
{
leaf = FcNameParseBuildLeaf (&temp);
leaf = FcCharSetFreezeLeaf (&temp);
if (!leaf)
goto bail1;
if (!FcCharSetInsertLeaf (c, ucs4, leaf))
@ -1023,7 +1053,7 @@ FcNameParseCharSet (FcChar8 *string)
sizeof (FcCharSet) * FcCharSetUsed +
FcCharSetUsedEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)));
#endif
n = FcNameParseBuildSet (c);
n = FcCharSetFreezeBase (c);
bail1:
if (c->leaves)
free (c->leaves);

View File

@ -1,5 +1,5 @@
/*
* $XFree86: $
* $XFree86: xc/lib/fontconfig/src/fcfreetype.c,v 1.4 2002/05/31 23:21:25 keithp Exp $
*
* Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
*
@ -29,13 +29,14 @@
#include <freetype/freetype.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/tttables.h>
#include "fcknownsets.h"
static const struct {
int bit;
FcChar8 *name;
} FcCodePageRange[] = {
{ 0, (FcChar8 *) FC_LANG_LATIN_1 },
{ 1, (FcChar8 *) FC_LANG_LATIN_2_EASTERN_EUROPE },
{ 1, (FcChar8 *) FC_LANG_LATIN_2 },
{ 2, (FcChar8 *) FC_LANG_CYRILLIC },
{ 3, (FcChar8 *) FC_LANG_GREEK },
{ 4, (FcChar8 *) FC_LANG_TURKISH },
@ -75,6 +76,94 @@ static const struct {
#define NUM_CODE_PAGE_RANGE (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
static const struct {
const FcCharSet *set;
FcChar32 size;
FcChar32 missing_tolerance;
FcChar8 *name;
} FcCodePageSet[] = {
{
&fcCharSet_Latin1_1252,
fcCharSet_Latin1_1252_size,
8,
(FcChar8 *) FC_LANG_LATIN_1,
},
{
&fcCharSet_Latin2_1250,
fcCharSet_Latin2_1250_size,
8,
(FcChar8 *) FC_LANG_LATIN_2,
},
{
&fcCharSet_Cyrillic_1251,
fcCharSet_Cyrillic_1251_size,
16,
(FcChar8 *) FC_LANG_CYRILLIC,
},
{
&fcCharSet_Greek_1253,
fcCharSet_Greek_1253_size,
8,
(FcChar8 *) FC_LANG_GREEK,
},
{
&fcCharSet_Turkish_1254,
fcCharSet_Turkish_1254_size,
16,
(FcChar8 *) FC_LANG_TURKISH,
},
{
&fcCharSet_Hebrew_1255,
fcCharSet_Hebrew_1255_size,
16,
(FcChar8 *) FC_LANG_HEBREW,
},
{
&fcCharSet_Arabic_1256,
fcCharSet_Arabic_1256_size,
16,
(FcChar8 *) FC_LANG_ARABIC,
},
{
&fcCharSet_Windows_Baltic_1257,
fcCharSet_Windows_Baltic_1257_size,
16,
(FcChar8 *) FC_LANG_WINDOWS_BALTIC,
},
{
&fcCharSet_Thai_874,
fcCharSet_Thai_874_size,
16,
(FcChar8 *) FC_LANG_THAI,
},
{
&fcCharSet_Japanese_932,
fcCharSet_Japanese_932_size,
500,
(FcChar8 *) FC_LANG_JAPANESE,
},
{
&fcCharSet_SimplifiedChinese_936,
fcCharSet_SimplifiedChinese_936_size,
500,
(FcChar8 *) FC_LANG_SIMPLIFIED_CHINESE,
},
{
&fcCharSet_Korean_949,
fcCharSet_Korean_949_size,
500,
(FcChar8 *) FC_LANG_KOREAN_WANSUNG,
},
{
&fcCharSet_TraditionalChinese_950,
fcCharSet_TraditionalChinese_950_size,
500,
(FcChar8 *) FC_LANG_TRADITIONAL_CHINESE,
},
};
#define NUM_CODE_PAGE_SET (sizeof FcCodePageSet / sizeof FcCodePageSet[0])
FcPattern *
FcFreeTypeQuery (const FcChar8 *file,
int id,
@ -90,6 +179,9 @@ FcFreeTypeQuery (const FcChar8 *file,
FT_Library ftLibrary;
const FcChar8 *family;
TT_OS2 *os2;
FcBool hasLang = FcFalse;
FcChar32 codepoints;
FcBool matchCodePage[NUM_CODE_PAGE_SET];
if (FT_Init_FreeType (&ftLibrary))
return 0;
@ -159,37 +251,6 @@ FcFreeTypeQuery (const FcChar8 *file,
goto bail1;
#endif
cs = FcFreeTypeCharSet (face, blanks);
if (!cs)
goto bail1;
/*
* Skip over PCF fonts that have no encoded characters; they're
* usually just Unicode fonts transcoded to some legacy encoding
*/
if (FcCharSetCount (cs) == 0)
{
if (!strcmp(FT_MODULE_CLASS(&face->driver->root)->module_name, "pcf"))
goto bail2;
}
if (!FcPatternAddCharSet (pat, FC_CHARSET, cs))
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++)
if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
(double) face->available_sizes[i].height))
goto bail1;
if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
goto bail1;
}
/*
* Get the OS/2 table and poke about
*/
@ -215,10 +276,120 @@ FcFreeTypeQuery (const FcChar8 *file,
if (!FcPatternAddString (pat, FC_LANG,
FcCodePageRange[i].name))
goto bail1;
hasLang = FcTrue;
}
}
}
/*
* Compute the unicode coverage for the font
*/
cs = FcFreeTypeCharSet (face, blanks);
if (!cs)
goto bail1;
codepoints = FcCharSetCount (cs);
/*
* Skip over PCF fonts that have no encoded characters; they're
* usually just Unicode fonts transcoded to some legacy encoding
*/
if (codepoints == 0)
{
if (!strcmp(FT_MODULE_CLASS(&face->driver->root)->module_name, "pcf"))
goto bail2;
}
if (!FcPatternAddCharSet (pat, FC_CHARSET, cs))
goto bail2;
if (!hasLang || (FcDebug() & FC_DBG_SCANV))
{
/*
* Use the Unicode coverage to set lang if it wasn't
* set from the OS/2 tables
*/
if (FcDebug() & FC_DBG_SCANV)
printf ("%s: ", family);
for (i = 0; i < NUM_CODE_PAGE_SET; i++)
{
FcChar32 missing;
missing = FcCharSetSubtractCount (FcCodePageSet[i].set,
cs);
matchCodePage[i] = missing <= FcCodePageSet[i].missing_tolerance;
if (FcDebug() & FC_DBG_SCANV)
printf ("%s(%d) ", FcCodePageSet[i].name, missing);
}
if (FcDebug() & FC_DBG_SCANV)
printf ("\n");
if (hasLang)
{
FcChar8 *lang;
int j;
/*
* Validate the lang selections
*/
for (i = 0; FcPatternGetString (pat, FC_LANG, i, &lang) == FcResultMatch; i++)
{
for (j = 0; j < NUM_CODE_PAGE_SET; j++)
if (!strcmp ((char *) FcCodePageSet[j].name,
(char *) lang))
{
if (!matchCodePage[j])
printf ("%s(%s): missing lang %s\n", file, family, lang);
}
}
for (j = 0; j < NUM_CODE_PAGE_SET; j++)
{
if (!matchCodePage[j])
continue;
lang = 0;
for (i = 0; FcPatternGetString (pat, FC_LANG, i, &lang) == FcResultMatch; i++)
{
if (!strcmp ((char *) FcCodePageSet[j].name, (char *) lang))
break;
lang = 0;
}
if (!lang)
printf ("%s(%s): extra lang %s\n", file, family, FcCodePageSet[j].name);
}
}
else
{
/*
* None provided, use the charset derived ones
*/
for (i = 0; i < NUM_CODE_PAGE_SET; i++)
if (matchCodePage[i])
{
if (!FcPatternAddString (pat, FC_LANG,
FcCodePageRange[i].name))
goto bail1;
hasLang = TRUE;
}
}
}
if (!hasLang)
if (!FcPatternAddString (pat, FC_LANG, (FcChar8 *) FC_LANG_UNKNOWN))
goto bail1;
/*
* 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++)
if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
(double) face->available_sizes[i].height))
goto bail1;
if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
goto bail1;
}
FT_Done_Face (face);
FT_Done_FreeType (ftLibrary);
return pat;

View File

@ -41,12 +41,6 @@
#include <config.h>
#endif
typedef struct _FcMatcher {
char *object;
double (*compare) (char *object, FcValue value1, FcValue value2);
int priority;
} FcMatcher;
typedef struct _FcSymbolic {
const char *name;
int value;
@ -67,6 +61,7 @@ typedef struct _FcSymbolic {
#define FC_DBG_CACHEV 32
#define FC_DBG_PARSE 64
#define FC_DBG_SCAN 128
#define FC_DBG_SCANV 256
#define FC_DBG_MEMORY 512
#define FC_MEM_CHARSET 0
@ -87,8 +82,13 @@ typedef struct _FcSymbolic {
#define FC_MEM_STRLIST 15
#define FC_MEM_CONFIG 16
typedef enum _FcValueBinding {
FcValueBindingWeak, FcValueBindingStrong
} FcValueBinding;
typedef struct _FcValueList {
struct _FcValueList *next;
FcValueBinding binding;
FcValue value;
} FcValueList;
@ -356,6 +356,9 @@ FcConfigCompareValue (const FcValue m,
const FcValue v);
/* fccharset.c */
FcCharSet *
FcCharSetFreeze (FcCharSet *cs);
FcBool
FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c);

1895
src/fcknownsets.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* $XFree86: xc/lib/fontconfig/src/fcmatch.c,v 1.13 2002/06/19 20:08:22 keithp Exp $
* $XFree86: xc/lib/fontconfig/src/fcmatch.c,v 1.14 2002/06/19 21:32:18 keithp Exp $
*
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
*
@ -97,50 +97,56 @@ FcCompareSize (char *object, FcValue value1, FcValue value2)
return v;
}
typedef struct _FcMatcher {
char *object;
double (*compare) (char *object, FcValue value1, FcValue value2);
int strong, weak;
} FcMatcher;
/*
* Order is significant, it defines the precedence of
* each value, earlier values are more significant than
* later values
*/
static FcMatcher _FcMatchers [] = {
{ FC_FOUNDRY, FcCompareString, },
#define MATCH_FOUNDRY 0
{ FC_FOUNDRY, FcCompareString, 0, 0 },
#define MATCH_FOUNDRY 0
{ FC_CHARSET, FcCompareCharSet },
#define MATCH_CHARSET 1
{ FC_CHARSET, FcCompareCharSet, 1, 1 },
#define MATCH_CHARSET 1
{ FC_LANG, FcCompareString },
#define MATCH_LANG 2
{ FC_FAMILY, FcCompareString, 2, 4 },
#define MATCH_FAMILY 2
{ FC_FAMILY, FcCompareString, },
#define MATCH_FAMILY 3
{ FC_LANG, FcCompareString, 3, 3 },
#define MATCH_LANG 3
{ FC_SPACING, FcCompareInteger, },
#define MATCH_SPACING 4
{ FC_SPACING, FcCompareInteger, 5, 5 },
#define MATCH_SPACING 4
{ FC_PIXEL_SIZE, FcCompareSize, },
#define MATCH_PIXEL_SIZE 5
{ FC_PIXEL_SIZE, FcCompareSize, 6, 6 },
#define MATCH_PIXEL_SIZE 5
{ FC_STYLE, FcCompareString, },
#define MATCH_STYLE 6
{ FC_STYLE, FcCompareString, 7, 7 },
#define MATCH_STYLE 6
{ FC_SLANT, FcCompareInteger, },
#define MATCH_SLANT 7
{ FC_SLANT, FcCompareInteger, 8, 8 },
#define MATCH_SLANT 7
{ FC_WEIGHT, FcCompareInteger, },
#define MATCH_WEIGHT 8
{ FC_WEIGHT, FcCompareInteger, 9, 9 },
#define MATCH_WEIGHT 8
{ FC_ANTIALIAS, FcCompareBool, },
#define MATCH_ANTIALIAS 9
{ FC_ANTIALIAS, FcCompareBool, 10, 10 },
#define MATCH_ANTIALIAS 9
{ FC_RASTERIZER, FcCompareString, },
#define MATCH_RASTERIZER 10
{ FC_RASTERIZER, FcCompareString, 11, 11 },
#define MATCH_RASTERIZER 10
{ FC_OUTLINE, FcCompareBool, },
#define MATCH_OUTLINE 11
{ FC_OUTLINE, FcCompareBool, 12, 12 },
#define MATCH_OUTLINE 11
};
#define NUM_MATCHER (sizeof _FcMatchers / sizeof _FcMatchers[0])
#define NUM_MATCH_VALUES 13
static FcBool
FcCompareValueList (const char *object,
@ -151,9 +157,9 @@ FcCompareValueList (const char *object,
FcResult *result)
{
FcValueList *v1, *v2;
double v, best;
int j;
double v, best, bestStrong, bestWeak;
int i;
int j;
/*
* Locate the possible matching entry by examining the
@ -217,6 +223,8 @@ FcCompareValueList (const char *object,
}
#endif
best = 1e99;
bestStrong = 1e99;
bestWeak = 1e99;
j = 0;
for (v1 = v1orig; v1; v1 = v1->next)
{
@ -239,6 +247,16 @@ FcCompareValueList (const char *object,
*bestValue = v2->value;
best = v;
}
if (v1->binding == FcValueBindingStrong)
{
if (v < bestStrong)
bestStrong = v;
}
else
{
if (v < bestWeak)
bestWeak = v;
}
}
j++;
}
@ -251,7 +269,17 @@ FcCompareValueList (const char *object,
printf ("\n");
}
if (value)
value[i] += best;
{
int weak = _FcMatchers[i].weak;
int strong = _FcMatchers[i].strong;
if (weak == strong)
value[strong] += best;
else
{
value[weak] += bestWeak;
value[strong] += bestStrong;
}
}
return FcTrue;
}
@ -268,7 +296,7 @@ FcCompare (FcPattern *pat,
{
int i, i1, i2;
for (i = 0; i < NUM_MATCHER; i++)
for (i = 0; i < NUM_MATCH_VALUES; i++)
value[i] = 0.0;
i1 = 0;
@ -330,9 +358,9 @@ FcFontRenderPrepare (FcConfig *config,
if (pe)
{
int j;
double score[NUM_MATCHER];
double score[NUM_MATCH_VALUES];
for (j = 0; j < NUM_MATCHER; j++)
for (j = 0; j < NUM_MATCH_VALUES; j++)
score[j] = 0;
if (!FcCompareValueList (pe->object, pe->values,
fe->values, &v, score, &result))
@ -340,7 +368,7 @@ FcFontRenderPrepare (FcConfig *config,
FcPatternDestroy (new);
return 0;
}
for (j = 0; j < NUM_MATCHER; j++)
for (j = 0; j < NUM_MATCH_VALUES; j++)
if (score[j] >= 100.0)
{
FcValueList *pv;
@ -372,14 +400,14 @@ FcFontSetMatch (FcConfig *config,
FcPattern *p,
FcResult *result)
{
double score[NUM_MATCHER], bestscore[NUM_MATCHER];
double score[NUM_MATCH_VALUES], bestscore[NUM_MATCH_VALUES];
int f;
FcFontSet *s;
FcPattern *best;
int i;
int set;
for (i = 0; i < NUM_MATCHER; i++)
for (i = 0; i < NUM_MATCH_VALUES; i++)
bestscore[i] = 0;
best = 0;
if (FcDebug () & FC_DBG_MATCH)
@ -410,19 +438,19 @@ FcFontSetMatch (FcConfig *config,
if (FcDebug () & FC_DBG_MATCHV)
{
printf ("Score");
for (i = 0; i < NUM_MATCHER; i++)
for (i = 0; i < NUM_MATCH_VALUES; i++)
{
printf (" %g", score[i]);
}
printf ("\n");
}
for (i = 0; i < NUM_MATCHER; i++)
for (i = 0; i < NUM_MATCH_VALUES; i++)
{
if (best && bestscore[i] < score[i])
break;
if (!best || score[i] < bestscore[i])
{
for (i = 0; i < NUM_MATCHER; i++)
for (i = 0; i < NUM_MATCH_VALUES; i++)
bestscore[i] = score[i];
best = s->fonts[f];
break;
@ -433,7 +461,7 @@ FcFontSetMatch (FcConfig *config,
if (FcDebug () & FC_DBG_MATCH)
{
printf ("Best score");
for (i = 0; i < NUM_MATCHER; i++)
for (i = 0; i < NUM_MATCH_VALUES; i++)
printf (" %g", bestscore[i]);
FcPatternPrint (best);
}
@ -469,7 +497,7 @@ FcFontMatch (FcConfig *config,
typedef struct _FcSortNode {
FcPattern *pattern;
double score[NUM_MATCHER];
double score[NUM_MATCH_VALUES];
} FcSortNode;
static int
@ -482,7 +510,7 @@ FcSortCompare (const void *aa, const void *ab)
double ad = 0, bd = 0;
int i;
i = NUM_MATCHER;
i = NUM_MATCH_VALUES;
while (i-- && (ad = *as++) == (bd = *bs++))
;
return ad < bd ? -1 : ad > bd ? 1 : 0;
@ -589,7 +617,7 @@ FcFontSetSort (FcConfig *config,
if (FcDebug () & FC_DBG_MATCHV)
{
printf ("Score");
for (i = 0; i < NUM_MATCHER; i++)
for (i = 0; i < NUM_MATCH_VALUES; i++)
{
printf (" %g", new->score[i]);
}

View File

@ -1,5 +1,5 @@
/*
* $XFree86: xc/lib/fontconfig/src/fcname.c,v 1.8 2002/06/19 20:08:22 keithp Exp $
* $XFree86: xc/lib/fontconfig/src/fcname.c,v 1.9 2002/06/26 22:14:08 keithp Exp $
*
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
*
@ -40,12 +40,17 @@ static const FcObjectType _FcBaseObjectTypes[] = {
{ FC_FOUNDRY, FcTypeString, },
/* { FC_CORE, FcTypeBool, }, */
{ FC_ANTIALIAS, FcTypeBool, },
{ FC_HINTING, FcTypeBool, },
{ FC_VERTICAL_LAYOUT, FcTypeBool, },
{ FC_AUTOHINT, FcTypeBool, },
{ FC_GLOBAL_ADVANCE, FcTypeBool, },
/* { FC_XLFD, FcTypeString, }, */
{ FC_FILE, FcTypeString, },
{ FC_INDEX, FcTypeInteger, },
{ FC_RASTERIZER, FcTypeString, },
{ FC_OUTLINE, FcTypeBool, },
{ FC_SCALABLE, FcTypeBool, },
{ FC_DPI, FcTypeDouble },
{ FC_RGBA, FcTypeInteger, },
{ FC_SCALE, FcTypeDouble, },
/* { FC_RENDER, FcTypeBool, },*/

View File

@ -1,5 +1,5 @@
/*
* $XFree86: xc/lib/fontconfig/src/fcpat.c,v 1.7 2002/06/03 08:31:15 keithp Exp $
* $XFree86: xc/lib/fontconfig/src/fcpat.c,v 1.9 2002/06/19 20:08:22 keithp Exp $
*
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
*
@ -408,6 +408,7 @@ FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
goto bail1;
new->value = value;
new->binding = FcValueBindingStrong;
new->next = 0;
e = FcPatternInsertElt (p, object);