I changed FcFontSetSort to respect the generic aliases better in the face

of language matching.
What I did was to ammend the strict sort order used by FcFontSort so that
    it 'satisfies' the language specified in the pattern by locating the
    best matching font supporting each pattern language and then ignores
    language in the remaining fonts for purposes of matching.
So, when asking for 'sans:lang=en', you'll get an English font first, and
    then the remaining fonts sorted with respect to the 'sans' alias alone
    -- pushing Kochi fonts ahead of other English-supporting Han fonts.
reviewed by: Owen Taylor <otaylor@redhat.com>
This commit is contained in:
Keith Packard 2004-12-14 00:12:25 +00:00
parent 46a10637cd
commit 5cf8c5364f
2 changed files with 96 additions and 2 deletions

View File

@ -1,3 +1,20 @@
2004-12-13 Keith Packard <keithp@keithp.com>
reviewed by: Owen Taylor <otaylor@redhat.com>
* src/fcmatch.c: (FcFontSetSort):
I changed FcFontSetSort to respect the generic aliases better
in the face of language matching.
What I did was to ammend the strict sort order used by FcFontSort so
that it 'satisfies' the language specified in the pattern by locating
the best matching font supporting each pattern language and then
ignores language in the remaining fonts for purposes of matching.
So, when asking for 'sans:lang=en', you'll get an English font first,
and then the remaining fonts sorted with respect to the 'sans' alias
alone -- pushing Kochi fonts ahead of other English-supporting Han fonts.
2004-12-10 Jakub Pavelek <jakub.pavelek@nokia.com>
reviewed by: Keith Packard <keithp@keithp.com>

View File

@ -181,45 +181,60 @@ typedef struct _FcMatcher {
static FcMatcher _FcMatchers [] = {
{ FC_FOUNDRY, FcCompareString, 0, 0 },
#define MATCH_FOUNDRY 0
#define MATCH_FOUNDRY_INDEX 0
{ FC_CHARSET, FcCompareCharSet, 1, 1 },
#define MATCH_CHARSET 1
#define MATCH_CHARSET_INDEX 1
{ FC_FAMILY, FcCompareFamily, 2, 4 },
#define MATCH_FAMILY 2
#define MATCH_FAMILY_STRONG_INDEX 2
#define MATCH_FAMILY_WEAK_INDEX 4
{ FC_LANG, FcCompareLang, 3, 3 },
#define MATCH_LANG 3
#define MATCH_LANG_INDEX 3
{ FC_SPACING, FcCompareNumber, 5, 5 },
#define MATCH_SPACING 4
#define MATCH_SPACING_INDEX 5
{ FC_PIXEL_SIZE, FcCompareSize, 6, 6 },
#define MATCH_PIXEL_SIZE 5
#define MATCH_PIXEL_SIZE_INDEX 6
{ FC_STYLE, FcCompareString, 7, 7 },
#define MATCH_STYLE 6
#define MATCH_STYLE_INDEX 7
{ FC_SLANT, FcCompareNumber, 8, 8 },
#define MATCH_SLANT 7
#define MATCH_SLANT_INDEX 8
{ FC_WEIGHT, FcCompareNumber, 9, 9 },
#define MATCH_WEIGHT 8
#define MATCH_WEIGHT_INDEX 9
{ FC_WIDTH, FcCompareNumber, 10, 10 },
#define MATCH_WIDTH 9
#define MATCH_WIDTH_INDEX 10
{ FC_ANTIALIAS, FcCompareBool, 11, 11 },
#define MATCH_ANTIALIAS 10
#define MATCH_ANTIALIAS_INDEX 11
{ FC_RASTERIZER, FcCompareString, 12, 12 },
#define MATCH_RASTERIZER 11
#define MATCH_RASTERIZER_INDEX 12
{ FC_OUTLINE, FcCompareBool, 13, 13 },
#define MATCH_OUTLINE 12
#define MATCH_OUTLINE_INDEX 13
{ FC_FONTVERSION, FcCompareNumber, 14, 14 },
#define MATCH_FONTVERSION 13
#define MATCH_FONTVERSION_INDEX 14
};
#define NUM_MATCH_VALUES 15
@ -663,6 +678,9 @@ FcFontSetSort (FcConfig *config,
int set;
int f;
int i;
int nPatternLang;
FcBool *patternLangSat;
FcValue patternLang;
if (FcDebug () & FC_DBG_MATCH)
{
@ -679,11 +697,20 @@ FcFontSetSort (FcConfig *config,
}
if (!nnodes)
goto bail0;
for (nPatternLang = 0;
FcPatternGet (p, FC_LANG, nPatternLang, &patternLang) == FcResultMatch;
nPatternLang++)
;
/* freed below */
nodes = malloc (nnodes * sizeof (FcSortNode) + nnodes * sizeof (FcSortNode *));
nodes = malloc (nnodes * sizeof (FcSortNode) +
nnodes * sizeof (FcSortNode *) +
nPatternLang * sizeof (FcBool));
if (!nodes)
goto bail0;
nodeps = (FcSortNode **) (nodes + nnodes);
patternLangSat = (FcBool *) (nodeps + nnodes);
new = nodes;
nodep = nodeps;
@ -721,6 +748,56 @@ FcFontSetSort (FcConfig *config,
qsort (nodeps, nnodes, sizeof (FcSortNode *),
FcSortCompare);
for (i = 0; i < nPatternLang; i++)
patternLangSat[i] = FcFalse;
for (f = 0; f < nnodes; f++)
{
FcBool satisfies = FcFalse;
/*
* If this node matches any language, go check
* which ones and satisfy those entries
*/
if (nodeps[f]->score[MATCH_LANG_INDEX] < nPatternLang)
{
for (i = 0; i < nPatternLang; i++)
{
FcValue nodeLang;
if (!patternLangSat[i] &&
FcPatternGet (p, FC_LANG, i, &patternLang) == FcResultMatch &&
FcPatternGet (nodeps[f]->pattern, FC_LANG, 0, &nodeLang) == FcResultMatch)
{
double compare = FcCompareLang (FC_LANG, patternLang,
nodeLang);
if (compare >= 0 && compare < 2)
{
if (FcDebug () & FC_DBG_MATCHV)
{
FcChar8 *family;
FcChar8 *style;
if (FcPatternGetString (nodeps[f]->pattern, FC_FAMILY, 0, &family) == FcResultMatch &&
FcPatternGetString (nodeps[f]->pattern, FC_STYLE, 0, &style) == FcResultMatch)
printf ("Font %s:%s matches language %d\n", family, style, i);
}
patternLangSat[i] = FcTrue;
satisfies = FcTrue;
break;
}
}
}
}
if (!satisfies)
nodeps[f]->score[MATCH_LANG_INDEX] = 1000.0;
}
/*
* Re-sort once the language issues have been settled
*/
qsort (nodeps, nnodes, sizeof (FcSortNode *),
FcSortCompare);
ret = FcFontSetCreate ();
if (!ret)