AddFcLangSetContains for font listing, add first-letter table for language
lookups, change RCS tag
This commit is contained in:
parent
4bd4418ab5
commit
793e946c2f
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* $XFree86: xc/lib/fontconfig/src/fccfg.c,v 1.23 2002/08/31 22:17:32 keithp Exp $
|
* $RCSId: xc/lib/fontconfig/src/fccfg.c,v 1.23 2002/08/31 22:17:32 keithp Exp $
|
||||||
*
|
*
|
||||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
* Copyright © 2000 Keith Packard
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
@ -590,10 +590,10 @@ FcConfigCompareValue (const FcValue m_o,
|
||||||
case FcTypeLangSet:
|
case FcTypeLangSet:
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case FcOpContains:
|
case FcOpContains:
|
||||||
ret = FcLangSetCompare (v.u.l, m.u.l) != FcLangDifferentLang;
|
ret = FcLangSetContains (v.u.l, m.u.l);
|
||||||
break;
|
break;
|
||||||
case FcOpNotContains:
|
case FcOpNotContains:
|
||||||
ret = FcLangSetCompare (v.u.l, m.u.l) == FcLangDifferentLang;
|
ret = FcLangSetContains (v.u.l, m.u.l);
|
||||||
break;
|
break;
|
||||||
case FcOpEqual:
|
case FcOpEqual:
|
||||||
ret = FcLangSetEqual (v.u.l, m.u.l);
|
ret = FcLangSetEqual (v.u.l, m.u.l);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* $XFree86: xc/lib/fontconfig/src/fcint.h,v 1.27 2002/08/31 22:17:32 keithp Exp $
|
* $RCSId: xc/lib/fontconfig/src/fcint.h,v 1.27 2002/08/31 22:17:32 keithp Exp $
|
||||||
*
|
*
|
||||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
* Copyright © 2000 Keith Packard
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
@ -446,6 +446,9 @@ FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4);
|
||||||
void
|
void
|
||||||
FcValueListPrint (const FcValueList *l);
|
FcValueListPrint (const FcValueList *l);
|
||||||
|
|
||||||
|
void
|
||||||
|
FcLangSetPrint (const FcLangSet *ls);
|
||||||
|
|
||||||
void
|
void
|
||||||
FcOpPrint (FcOp op);
|
FcOpPrint (FcOp op);
|
||||||
|
|
||||||
|
|
221
src/fclang.c
221
src/fclang.c
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* $XFree86: xc/lib/fontconfig/src/fclang.c,v 1.7 2002/08/26 23:34:31 keithp Exp $
|
* $RCSId: xc/lib/fontconfig/src/fclang.c,v 1.7 2002/08/26 23:34:31 keithp Exp $
|
||||||
*
|
*
|
||||||
* Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
|
* Copyright © 2002 Keith Packard
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
@ -29,6 +29,11 @@ typedef struct {
|
||||||
FcCharSet charset;
|
FcCharSet charset;
|
||||||
} FcLangCharSet;
|
} FcLangCharSet;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int begin;
|
||||||
|
int end;
|
||||||
|
} FcLangCharSetRange;
|
||||||
|
|
||||||
#include "../fc-lang/fclang.h"
|
#include "../fc-lang/fclang.h"
|
||||||
|
|
||||||
struct _FcLangSet {
|
struct _FcLangSet {
|
||||||
|
@ -138,6 +143,37 @@ FcLangCompare (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return FcTrue when s1 contains s2.
|
||||||
|
*
|
||||||
|
* s1 contains s2 if s1 equals s2 or if s1 is a
|
||||||
|
* language with a country and s2 is just a language
|
||||||
|
*/
|
||||||
|
|
||||||
|
static FcBool
|
||||||
|
FcLangContains (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
|
{
|
||||||
|
FcChar8 c1, c2;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
c1 = *s1++;
|
||||||
|
c2 = *s2++;
|
||||||
|
|
||||||
|
c1 = FcToLower (c1);
|
||||||
|
c2 = FcToLower (c2);
|
||||||
|
if (c1 != c2)
|
||||||
|
{
|
||||||
|
/* see if s1 has a country while s2 is mising one */
|
||||||
|
if (c1 == '-' && c2 == '\0')
|
||||||
|
return FcTrue;
|
||||||
|
return FcFalse;
|
||||||
|
}
|
||||||
|
else if (!c1)
|
||||||
|
return FcTrue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const FcCharSet *
|
const FcCharSet *
|
||||||
FcCharSetForLang (const FcChar8 *lang)
|
FcCharSetForLang (const FcChar8 *lang)
|
||||||
{
|
{
|
||||||
|
@ -225,13 +261,52 @@ FcLangSetIndex (const FcChar8 *lang)
|
||||||
{
|
{
|
||||||
int low, high, mid;
|
int low, high, mid;
|
||||||
int cmp;
|
int cmp;
|
||||||
|
FcChar8 firstChar = FcToLower(lang[0]);
|
||||||
|
|
||||||
|
if (firstChar < 'a')
|
||||||
|
{
|
||||||
low = 0;
|
low = 0;
|
||||||
|
high = fcLangCharSetRanges[0].begin;
|
||||||
|
}
|
||||||
|
else if(firstChar > 'z')
|
||||||
|
{
|
||||||
|
low = fcLangCharSetRanges[25].begin;
|
||||||
high = NUM_LANG_CHAR_SET - 1;
|
high = NUM_LANG_CHAR_SET - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
low = fcLangCharSetRanges[firstChar - 'a'].begin;
|
||||||
|
high = fcLangCharSetRanges[firstChar - 'a'].end;
|
||||||
|
/* no matches */
|
||||||
|
if (low > high)
|
||||||
|
return -low; /* next entry after where it would be */
|
||||||
|
}
|
||||||
|
|
||||||
while (low <= high)
|
while (low <= high)
|
||||||
{
|
{
|
||||||
mid = (high + low) >> 1;
|
mid = (high + low) >> 1;
|
||||||
cmp = FcStrCmpIgnoreCase (fcLangCharSets[mid].lang, lang);
|
if(fcLangCharSets[mid].lang[0] != firstChar)
|
||||||
|
cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang, lang);
|
||||||
|
else
|
||||||
|
{ /* fast path for resolving 2-letter languages (by far the most common) after
|
||||||
|
* finding the first char (probably already true because of the hash table) */
|
||||||
|
FcChar8 secondChar = FcToLower(lang[1]);
|
||||||
|
if (fcLangCharSets[mid].lang[1] > secondChar) // check second chars
|
||||||
|
{
|
||||||
|
high = mid - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (fcLangCharSets[mid].lang[1] < secondChar)
|
||||||
|
{
|
||||||
|
low = mid + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (fcLangCharSets[mid].lang[2] == '\0' && lang[2] == '\0')
|
||||||
|
return mid;
|
||||||
|
|
||||||
|
else /* identical through the first two charcters, but at least one string didn't end there */
|
||||||
|
cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang+2, lang+2);
|
||||||
|
}
|
||||||
if (cmp == 0)
|
if (cmp == 0)
|
||||||
return mid;
|
return mid;
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
|
@ -412,32 +487,28 @@ FcLangSetHash (const FcLangSet *ls)
|
||||||
FcLangSet *
|
FcLangSet *
|
||||||
FcNameParseLangSet (const FcChar8 *string)
|
FcNameParseLangSet (const FcChar8 *string)
|
||||||
{
|
{
|
||||||
FcChar8 lang[32];
|
FcChar8 lang[32],c;
|
||||||
const FcChar8 *end, *next;
|
int i;
|
||||||
FcLangSet *ls;
|
FcLangSet *ls;
|
||||||
|
|
||||||
ls = FcLangSetCreate ();
|
ls = FcLangSetCreate ();
|
||||||
if (!ls)
|
if (!ls)
|
||||||
goto bail0;
|
goto bail0;
|
||||||
|
|
||||||
while (string && *string)
|
for(;;)
|
||||||
{
|
{
|
||||||
end = (FcChar8 *) strchr ((char *) string, '|');
|
for(i = 0; i < 31;i++)
|
||||||
if (!end)
|
|
||||||
{
|
{
|
||||||
end = string + strlen ((char *) string);
|
c = *string++;
|
||||||
next = end;
|
if(c == '\0' || c == '|')
|
||||||
|
break; /* end of this code */
|
||||||
|
lang[i] = c;
|
||||||
}
|
}
|
||||||
else
|
lang[i] = '\0';
|
||||||
next = end + 1;
|
|
||||||
if (end - string < sizeof (lang) - 1)
|
|
||||||
{
|
|
||||||
strncpy ((char *) lang, (char *) string, end - string);
|
|
||||||
lang[end-string] = '\0';
|
|
||||||
if (!FcLangSetAdd (ls, lang))
|
if (!FcLangSetAdd (ls, lang))
|
||||||
goto bail1;
|
goto bail1;
|
||||||
}
|
if(c == '\0')
|
||||||
string = next;
|
break;
|
||||||
}
|
}
|
||||||
return ls;
|
return ls;
|
||||||
bail1:
|
bail1:
|
||||||
|
@ -482,7 +553,7 @@ FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
|
||||||
if (!first)
|
if (!first)
|
||||||
if (!FcStrBufChar (buf, '|'))
|
if (!FcStrBufChar (buf, '|'))
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
if (!FcStrBufString (buf, extra));
|
if (!FcStrBufString (buf, extra))
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
first = FcFalse;
|
first = FcFalse;
|
||||||
}
|
}
|
||||||
|
@ -506,3 +577,115 @@ FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb)
|
||||||
return FcStrSetEqual (lsa->extra, lsb->extra);
|
return FcStrSetEqual (lsa->extra, lsb->extra);
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FcBool
|
||||||
|
FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang)
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
FcLangResult r;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
id = FcLangSetIndex (lang);
|
||||||
|
if (id < 0)
|
||||||
|
id = -id - 1;
|
||||||
|
else if (FcLangSetBitGet (ls, id))
|
||||||
|
return FcTrue;
|
||||||
|
/*
|
||||||
|
* search up and down among equal languages for a match
|
||||||
|
*/
|
||||||
|
for (i = id - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (FcLangCompare (fcLangCharSets[i].lang, lang) == FcLangDifferentLang)
|
||||||
|
break;
|
||||||
|
if (FcLangSetBitGet (ls, i) &&
|
||||||
|
FcLangContains (fcLangCharSets[i].lang, lang))
|
||||||
|
return FcTrue;
|
||||||
|
}
|
||||||
|
for (i = id; i < NUM_LANG_CHAR_SET; i++)
|
||||||
|
{
|
||||||
|
if (FcLangCompare (fcLangCharSets[i].lang, lang) == FcLangDifferentLang)
|
||||||
|
break;
|
||||||
|
if (FcLangSetBitGet (ls, i) &&
|
||||||
|
FcLangContains (fcLangCharSets[i].lang, lang))
|
||||||
|
return FcTrue;
|
||||||
|
}
|
||||||
|
if (ls->extra)
|
||||||
|
{
|
||||||
|
FcStrList *list = FcStrListCreate (ls->extra);
|
||||||
|
FcChar8 *extra;
|
||||||
|
FcLangResult r;
|
||||||
|
|
||||||
|
if (list)
|
||||||
|
{
|
||||||
|
while ((extra = FcStrListNext (list)))
|
||||||
|
{
|
||||||
|
if (FcLangContains (extra, lang))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FcStrListDone (list);
|
||||||
|
if (extra)
|
||||||
|
return FcTrue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FcFalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return FcTrue if lsa contains every language in lsb
|
||||||
|
*/
|
||||||
|
FcBool
|
||||||
|
FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
FcChar32 missing;
|
||||||
|
|
||||||
|
if (FcDebug() & FC_DBG_MATCHV)
|
||||||
|
{
|
||||||
|
printf ("FcLangSet "); FcLangSetPrint (lsa);
|
||||||
|
printf (" contains "); FcLangSetPrint (lsb);
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* check bitmaps for missing language support
|
||||||
|
*/
|
||||||
|
for (i = 0; i < NUM_LANG_SET_MAP; i++)
|
||||||
|
{
|
||||||
|
missing = lsb->map[i] & ~lsa->map[i];
|
||||||
|
if (missing)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 32; j++)
|
||||||
|
if (missing & (1 << j))
|
||||||
|
{
|
||||||
|
if (!FcLangSetContainsLang (lsa,
|
||||||
|
fcLangCharSets[i*32 + j].lang))
|
||||||
|
{
|
||||||
|
if (FcDebug() & FC_DBG_MATCHV)
|
||||||
|
printf ("\tMissing bitmap %s\n", fcLangCharSets[i*32+j].lang);
|
||||||
|
return FcFalse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lsb->extra)
|
||||||
|
{
|
||||||
|
FcStrList *list = FcStrListCreate (lsb->extra);
|
||||||
|
FcChar8 *extra;
|
||||||
|
|
||||||
|
if (list)
|
||||||
|
{
|
||||||
|
while ((extra = FcStrListNext (list)))
|
||||||
|
{
|
||||||
|
if (!FcLangSetContainsLang (lsa, extra))
|
||||||
|
{
|
||||||
|
if (FcDebug() & FC_DBG_MATCHV)
|
||||||
|
printf ("\tMissing string %s\n", extra);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FcStrListDone (list);
|
||||||
|
if (extra)
|
||||||
|
return FcFalse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FcTrue;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* $XFree86: xc/lib/fontconfig/src/fclist.c,v 1.11tsi Exp $
|
* $RCSId: xc/lib/fontconfig/src/fclist.c,v 1.11tsi Exp $
|
||||||
*
|
*
|
||||||
* Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
|
* Copyright © 2000 Keith Packard
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
@ -128,7 +128,7 @@ FcListValueListMatchAny (FcValueList *v1orig,
|
||||||
|
|
||||||
for (v1 = v1orig; v1; v1 = v1->next)
|
for (v1 = v1orig; v1; v1 = v1->next)
|
||||||
for (v2 = v2orig; v2; v2 = v2->next)
|
for (v2 = v2orig; v2; v2 = v2->next)
|
||||||
if (FcConfigCompareValue (v2->value, FcOpContains, v1->value))
|
if (FcConfigCompareValue (v1->value, FcOpContains, v2->value))
|
||||||
return FcTrue;
|
return FcTrue;
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue