Commit d8d73958 authored by Keith Packard's avatar Keith Packard

Reimplement FC_LANG as FcTypeLang, freeze patterns, other cleanup

parent f4fe447f
Mon Aug 19 11:57:27 PDT 2002
Thu Aug 22 00:32:29 PDT 2002 keithp
+ Reimplement FC_LANG as new datatype. Lists of strings
was consuming over a megabyte of memory for 401 fonts.
+ Freeze patterns loaded from cache files. This shares
common value lists and common patterns which saves
considerable memory.
+ Change the denotation of 'constant' charsets to use special
ref value instead of separate boolean.
+ Clean up leak tracing stuff, found several unannoted alloc/free
calls
Tue Aug 20 16:17:37 PDT 2002 keithp
+ Fix memory leak when parsing matrices from XML
Mon Aug 19 11:57:27 PDT 2002 keithp
+ Fix autoconf files to pass FONTCONFIG_PATH on
compile line so that ${prefix} gets substituted
correctly.
......
/*
* $XFree86: xc/lib/fontconfig/fc-lang/fc-lang.c,v 1.1 2002/07/06 23:21:36 keithp Exp $
* $XFree86: xc/lib/fontconfig/fc-lang/fc-lang.c,v 1.2 2002/07/07 19:18:51 keithp Exp $
*
* Copyright 2002 Keith Packard, member of The XFree86 Project, Inc.
*
......@@ -159,9 +159,16 @@ get_lang (char *name)
return lang;
}
static int compare (const void *a, const void *b)
{
const FcChar8 *const *as = a, *const *bs = b;
return FcStrCmpIgnoreCase (*as, *bs);
}
int
main (int argc, char **argv)
{
char *files[1024];
FcCharSet *sets[1024];
int duplicate[1024];
char *names[1024];
......@@ -173,12 +180,17 @@ main (int argc, char **argv)
char line[1024];
while (*++argv)
files[i++] = *argv;
files[i] = 0;
qsort (files, i, sizeof (char *), compare);
i = 0;
while (files[i])
{
f = fopen (*argv, "r");
f = fopen (files[i], "r");
if (!f)
fatal (*argv, 0, strerror (errno));
sets[i] = scan (f, *argv);
names[i] = get_name (*argv);
fatal (files[i], 0, strerror (errno));
sets[i] = scan (f, files[i]);
names[i] = get_name (files[i]);
total_leaves += sets[i]->num;
i++;
fclose (f);
......@@ -304,7 +316,7 @@ main (int argc, char **argv)
if (j < 0)
j = i;
printf (" { (FcChar8 *) \"%s\",\n"
" { 1, FcTrue, %d, "
" { FC_REF_CONSTANT, %d, "
"(FcCharLeaf **) leaves_%s, "
"(FcChar16 *) numbers_%s } },\n",
get_lang(names[i]),
......
This diff is collapsed.
/*
* $XFree86: xc/lib/fontconfig/fontconfig/fcprivate.h,v 1.4 2002/08/11 18:10:41 keithp Exp $
* $XFree86: xc/lib/fontconfig/fontconfig/fcprivate.h,v 1.5 2002/08/19 19:32:04 keithp Exp $
*
* Copyright 2001 Keith Packard, member of The XFree86 Project, Inc.
*
......@@ -73,6 +73,9 @@
case FcTypeFTFace: \
__v__.u.f = va_arg (va, FT_Face); \
break; \
case FcTypeLangSet: \
__v__.u.l = va_arg (va, FcLangSet *); \
break; \
} \
if (!FcPatternAdd (__p__, __o__, __v__, FcTrue)) \
goto _FcPatternVapBuild_bail1; \
......
/*
* $XFree86: xc/lib/fontconfig/fontconfig/fontconfig.h,v 1.25 2002/08/11 18:10:41 keithp Exp $
* $XFree86: xc/lib/fontconfig/fontconfig/fontconfig.h,v 1.26 2002/08/19 19:32:04 keithp Exp $
*
* Copyright 2001 Keith Packard, member of The XFree86 Project, Inc.
*
......@@ -109,7 +109,8 @@ typedef enum _FcType {
FcTypeBool,
FcTypeMatrix,
FcTypeCharSet,
FcTypeFTFace
FcTypeFTFace,
FcTypeLangSet
} FcType;
typedef struct _FcMatrix {
......@@ -143,6 +144,8 @@ typedef enum _FcResult {
typedef struct _FcPattern FcPattern;
typedef struct _FcLangSet FcLangSet;
typedef struct _FcValue {
FcType type;
union {
......@@ -154,6 +157,7 @@ typedef struct _FcValue {
const FcCharSet *c;
void *f;
const FcPattern *p;
const FcLangSet *l;
} u;
} FcValue;
......@@ -173,6 +177,10 @@ typedef enum _FcMatchKind {
FcMatchPattern, FcMatchFont
} FcMatchKind;
typedef enum _FcLangResult {
FcLangEqual, FcLangDifferentCountry, FcLangDifferentLang
} FcLangResult;
typedef enum _FcSetName {
FcSetSystem = 0,
FcSetApplication = 1
......@@ -409,6 +417,31 @@ FcInitReinitialize (void);
FcBool
FcInitBringUptoDate (void);
/* fclang.c */
FcLangSet *
FcLangSetCreate (void);
void
FcLangSetDestroy (FcLangSet *ls);
FcLangSet *
FcLangSetCopy (const FcLangSet *ls);
FcBool
FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang);
FcLangResult
FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang);
FcLangResult
FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb);
FcBool
FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb);
FcChar32
FcLangSetHash (const FcLangSet *ls);
/* fclist.c */
FcObjectSet *
FcObjectSetCreate (void);
......@@ -609,6 +642,9 @@ FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c);
FcBool
FcPatternAddBool (FcPattern *p, const char *object, FcBool b);
FcBool
FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls);
FcResult
FcPatternGetInteger (FcPattern *p, const char *object, int n, int *i);
......@@ -627,6 +663,9 @@ FcPatternGetCharSet (FcPattern *p, const char *object, int n, FcCharSet **c);
FcResult
FcPatternGetBool (FcPattern *p, const char *object, int n, FcBool *b);
FcResult
FcPatternGetLangSet (FcPattern *p, const char *object, int n, FcLangSet **ls);
FcPattern *
FcPatternVaBuild (FcPattern *orig, va_list va);
......@@ -691,6 +730,9 @@ FcStrSetCreate (void);
FcBool
FcStrSetMember (FcStrSet *set, const FcChar8 *s);
FcBool
FcStrSetEqual (FcStrSet *sa, FcStrSet *sb);
FcBool
FcStrSetAdd (FcStrSet *set, const FcChar8 *s);
......
/*
* $XFree86: xc/lib/fontconfig/src/fccache.c,v 1.10 2002/08/06 19:00:43 keithp Exp $
* $XFree86: xc/lib/fontconfig/src/fccache.c,v 1.11 2002/08/19 19:32:05 keithp Exp $
*
* Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
*
......@@ -247,6 +247,7 @@ FcCacheFontSetAdd (FcFontSet *set,
int len;
FcBool ret = FcFalse;
FcPattern *font;
FcPattern *frozen;
path = path_buf;
len = (dir_len + 1 + strlen ((const char *) file) + 1);
......@@ -277,10 +278,15 @@ FcCacheFontSetAdd (FcFontSet *set,
{
if (FcDebug () & FC_DBG_CACHEV)
printf (" dir cache file \"%s\"\n", file);
ret = (FcPatternAddString (font, FC_FILE, path) &&
FcFontSetAdd (set, font));
if (!ret)
FcPatternDestroy (font);
ret = FcPatternAddString (font, FC_FILE, path);
if (ret)
{
frozen = FcPatternFreeze (font);
ret = (frozen != 0);
if (ret)
ret = FcFontSetAdd (set, frozen);
}
FcPatternDestroy (font);
}
}
if (path != path_buf) free (path);
......
/*
* $XFree86: xc/lib/fontconfig/src/fccfg.c,v 1.19 2002/08/11 18:10:42 keithp Exp $
* $XFree86: xc/lib/fontconfig/src/fccfg.c,v 1.20 2002/08/19 19:32:05 keithp Exp $
*
* Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
*
......@@ -473,6 +473,11 @@ FcConfigPromote (FcValue v, FcValue u)
v.u.m = &FcIdentityMatrix;
v.type = FcTypeMatrix;
}
else if (v.type == FcTypeString && u.type == FcTypeLangSet)
{
v.u.l = FcLangSetPromote (v.u.s);
v.type = FcTypeLangSet;
}
return v;
}
......@@ -570,6 +575,21 @@ FcConfigCompareValue (FcValue m,
break;
}
break;
case FcTypeLangSet:
switch (op) {
case FcOpContains:
ret = FcLangSetCompare (v.u.l, m.u.l) != FcLangDifferentLang;
break;
case FcOpEqual:
ret = FcLangSetEqual (v.u.l, m.u.l);
break;
case FcOpNotEqual:
ret = !FcLangSetEqual (v.u.l, m.u.l);
break;
default:
break;
}
break;
case FcTypeVoid:
switch (op) {
case FcOpEqual:
......
/*
* $XFree86: xc/lib/fontconfig/src/fccharset.c,v 1.16 2002/07/09 02:28:29 keithp Exp $
* $XFree86: xc/lib/fontconfig/src/fccharset.c,v 1.17 2002/07/13 05:43:25 keithp Exp $
*
* Copyright 2001 Keith Packard, member of The XFree86 Project, Inc.
*
......@@ -42,7 +42,6 @@ FcCharSetCreate (void)
fcs->num = 0;
fcs->leaves = 0;
fcs->numbers = 0;
fcs->constant = FcFalse;
return fcs;
}
......@@ -59,28 +58,28 @@ FcCharSetNew (void)
void
FcCharSetDestroy (FcCharSet *fcs)
{
if (!fcs->constant && --fcs->ref <= 0)
int i;
if (fcs->ref == FC_REF_CONSTANT)
return;
if (--fcs->ref > 0)
return;
for (i = 0; i < fcs->num; i++)
{
int i;
for (i = 0; i < fcs->num; i++)
{
FcMemFree (FC_MEM_CHARNODE, sizeof (FcCharLeaf));
free (fcs->leaves[i]);
}
if (fcs->leaves)
{
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *));
free (fcs->leaves);
}
if (fcs->numbers)
{
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
free (fcs->numbers);
}
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
free (fcs);
FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
free (fcs->leaves[i]);
}
if (fcs->leaves)
{
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *));
free (fcs->leaves);
}
if (fcs->numbers)
{
FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
free (fcs->numbers);
}
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
free (fcs);
}
/*
......@@ -143,6 +142,7 @@ FcCharSetPutLeaf (FcCharSet *fcs,
leaves = realloc (fcs->leaves, (fcs->num + 1) * sizeof (FcCharLeaf *));
if (!leaves)
return FcFalse;
FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharLeaf *));
fcs->leaves = leaves;
if (!fcs->numbers)
numbers = malloc (sizeof (FcChar16));
......@@ -150,6 +150,7 @@ FcCharSetPutLeaf (FcCharSet *fcs,
numbers = realloc (fcs->numbers, (fcs->num + 1) * sizeof (FcChar16));
if (!numbers)
return FcFalse;
FcMemAlloc (FC_MEM_CHARSET, sizeof (FcChar16));
fcs->numbers = numbers;
memmove (fcs->leaves + pos + 1, fcs->leaves + pos,
......@@ -187,6 +188,7 @@ FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4)
free (leaf);
return 0;
}
FcMemAlloc (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
return leaf;
}
......@@ -198,7 +200,7 @@ FcCharSetInsertLeaf (FcCharSet *fcs, FcChar32 ucs4, FcCharLeaf *leaf)
pos = FcCharSetFindLeafPos (fcs, ucs4);
if (pos >= 0)
{
FcMemAlloc (FC_MEM_CHARNODE, sizeof (FcCharLeaf));
FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
free (fcs->leaves[pos]);
fcs->leaves[pos] = leaf;
return FcTrue;
......@@ -213,7 +215,7 @@ FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4)
FcCharLeaf *leaf;
FcChar32 *b;
if (fcs->constant)
if (fcs->ref == FC_REF_CONSTANT)
return FcFalse;
leaf = FcCharSetFindLeafCreate (fcs, ucs4);
if (!leaf)
......@@ -307,7 +309,8 @@ FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter)
FcCharSet *
FcCharSetCopy (FcCharSet *src)
{
src->ref++;
if (src->ref != FC_REF_CONSTANT)
src->ref++;
return src;
}
......@@ -835,6 +838,7 @@ FcCharLeafEntCreate (void)
block = malloc (FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
if (!block)
return 0;
FcMemAlloc (FC_MEM_CHARLEAF, FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
remain = FC_CHAR_LEAF_BLOCK;
}
remain--;
......@@ -921,6 +925,7 @@ FcCharSetFreezeBase (FcCharSet *fcs)
FcChar32 hash = FcCharSetHash (fcs);
FcCharSetEnt **bucket = &hashTable[hash % FC_CHAR_SET_HASH_SIZE];
FcCharSetEnt *ent;
int size;
FcCharSetTotal++;
FcCharSetTotalEnts += fcs->num;
......@@ -937,16 +942,17 @@ FcCharSetFreezeBase (FcCharSet *fcs)
}
}
ent = malloc (sizeof (FcCharSetEnt) +
fcs->num * sizeof (FcCharLeaf *) +
fcs->num * sizeof (FcChar16));
size = (sizeof (FcCharSetEnt) +
fcs->num * sizeof (FcCharLeaf *) +
fcs->num * sizeof (FcChar16));
ent = malloc (size);
if (!ent)
return 0;
FcMemAlloc (FC_MEM_CHARSET, size);
FcCharSetUsed++;
FcCharSetUsedEnts += fcs->num;
ent->set.ref = 0;
ent->set.constant = FcTrue;
ent->set.ref = FC_REF_CONSTANT;
ent->set.num = fcs->num;
if (fcs->num)
{
......@@ -989,9 +995,16 @@ FcCharSetFreeze (FcCharSet *fcs)
n = FcCharSetFreezeBase (b);
bail1:
if (b->leaves)
{
FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *));
free (b->leaves);
}
if (b->numbers)
{
FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16));
free (b->numbers);
}
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
free (b);
bail0:
return n;
......@@ -1056,9 +1069,16 @@ FcNameParseCharSet (FcChar8 *string)
n = FcCharSetFreezeBase (c);
bail1:
if (c->leaves)
{
FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
free (c->leaves);
}
if (c->numbers)
{
FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
free (c->numbers);
}
FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
free (c);
bail0:
return n;
......
/*
* $XFree86: xc/lib/fontconfig/src/fcdbg.c,v 1.7 2002/08/11 18:10:42 keithp Exp $
* $XFree86: xc/lib/fontconfig/src/fcdbg.c,v 1.8 2002/08/19 19:32:05 keithp Exp $
*
* Copyright 2000 Keith Packard, member of The XFree86 Project, Inc.
*
......@@ -51,6 +51,9 @@ FcValuePrint (const FcValue v)
case FcTypeCharSet: /* XXX */
printf (" set");
break;
case FcTypeLangSet:
printf (" langset");
break;
case FcTypeFTFace:
printf (" face");
break;
......
/*
* $XFree86: xc/lib/fontconfig/src/fcfreetype.c,v 1.8 2002/07/09 02:28:29 keithp Exp $
* $XFree86: xc/lib/fontconfig/src/fcfreetype.c,v 1.9 2002/07/13 05:43:25 keithp Exp $
*
* Copyright 2001 Keith Packard, member of The XFree86 Project, Inc.
*
......@@ -123,6 +123,7 @@ FcFreeTypeQuery (const FcChar8 *file,
int weight;
int i;
FcCharSet *cs;
FcLangSet *ls;
FT_Library ftLibrary;
FcChar8 *family;
FcChar8 *style;
......@@ -526,8 +527,12 @@ FcFreeTypeQuery (const FcChar8 *file,
if (!FcPatternAddCharSet (pat, FC_CHARSET, cs))
goto bail2;
if (!FcFreeTypeSetLang (pat, cs, exclusiveLang))
goto bail2;
ls = FcFreeTypeLangSet (cs, exclusiveLang);
if (!ls)
goto bail2;
if (!FcPatternAddLangSet (pat, FC_LANG, ls))
goto bail2;
/*
* Drop our reference to the charset
......
/*
* $XFree86: xc/lib/fontconfig/src/fcinit.c,v 1.5 2002/05/21 17:48:15 keithp Exp $
* $XFree86: xc/lib/fontconfig/src/fcinit.c,v 1.6 2002/05/23 23:00:46 keithp Exp $
*
* Copyright 2001 Keith Packard, member of The XFree86 Project, Inc.
*
......@@ -102,6 +102,8 @@ FcInit (void)
if (!config)
return FcTrue;
FcConfigSetCurrent (config);
if (FcDebug() & FC_DBG_MEMORY)
FcMemReport ();
return FcTrue;
}
......@@ -153,7 +155,7 @@ static struct {
int free_mem;
} FcInUse[FC_MEM_NUM] = {
{ "charset", 0, 0 },
{ "charnode", 0 ,0 },
{ "charleaf", 0 ,0 },
{ "fontset", 0, 0 },
{ "fontptr", 0, 0 },
{ "objectset", 0, 0 },
......@@ -165,6 +167,10 @@ static struct {
{ "substate", 0, 0 },
{ "string", 0, 0 },
{ "listbuck", 0, 0 },
{ "strset", 0, 0 },
{ "strlist", 0, 0 },
{ "config", 0, 0 },
{ "langset", 0, 0 },
};
static int FcAllocCount, FcAllocMem;
......@@ -174,6 +180,9 @@ static int FcMemNotice = 1*1024*1024;
static int FcAllocNotify, FcFreeNotify;
void
FcValueListReport (void);
void
FcMemReport (void)
{
......@@ -196,6 +205,7 @@ FcMemReport (void)
FcAllocMem - FcFreeMem);
FcAllocNotify = 0;
FcFreeNotify = 0;
FcValueListReport ();
}
void
......
......@@ -65,7 +65,7 @@ typedef struct _FcSymbolic {
#define FC_DBG_MEMORY 512
#define FC_MEM_CHARSET 0
#define FC_MEM_CHARNODE 1
#define FC_MEM_CHARLEAF 1
#define FC_MEM_FONTSET 2
#define FC_MEM_FONTPTR 3
#define FC_MEM_OBJECTSET 4
......@@ -77,10 +77,12 @@ typedef struct _FcSymbolic {
#define FC_MEM_SUBSTATE 10
#define FC_MEM_STRING 11
#define FC_MEM_LISTBUCK 12
#define FC_MEM_NUM 13
#define FC_MEM_STRSET 14
#define FC_MEM_STRLIST 15
#define FC_MEM_CONFIG 16
#define FC_MEM_STRSET 13
#define FC_MEM_STRLIST 14
#define FC_MEM_CONFIG 15
#define FC_MEM_LANGSET 16
#define FC_MEM_NUM 17
typedef enum _FcValueBinding {
FcValueBindingWeak, FcValueBindingStrong
......@@ -97,6 +99,7 @@ typedef struct _FcPatternElt {
FcValueList *values;
} FcPatternElt;
struct _FcPattern {
int num;
int size;
......@@ -167,13 +170,10 @@ typedef struct _FcCharLeaf {
FcChar32 map[256/32];
} FcCharLeaf;
typedef enum _FcLangResult {
FcLangEqual, FcLangDifferentCountry, FcLangDifferentLang
} FcLangResult;
#define FC_REF_CONSTANT -1
struct _FcCharSet {
int ref; /* reference count */
FcBool constant; /* in hash table constant */
int num; /* size of leaves and numbers arrays */
FcCharLeaf **leaves;
FcChar16 *numbers;
......@@ -537,9 +537,8 @@ void
FcMemFree (int kind, int size);
/* fclang.c */
FcBool
FcFreeTypeSetLang (FcPattern *pattern,
FcCharSet *charset,
FcLangSet *
FcFreeTypeLangSet (const FcCharSet *charset,
const FcChar8 *exclusiveLang);
FcLangResult
......@@ -548,6 +547,15 @@ FcLangCompare (const FcChar8 *s1, const FcChar8 *s2);
const FcCharSet *
FcCharSetForLang (const FcChar8 *lang);
FcLangSet *
FcLangSetPromote (const FcChar8 *lang);
FcLangSet *
FcNameParseLangSet (const FcChar8 *string);
FcBool
FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls);
/* fclist.c */
/* fcmatch.c */
......@@ -574,6 +582,9 @@ FcPatternAddWithBinding (FcPattern *p,
FcValueBinding binding,
FcBool append);
FcPattern *
FcPatternFreeze (FcPattern *p);
/* fcrender.c */
/* fcmatrix.c */
......
/*
* $XFree86: xc/lib/fontconfig/src/fclang.c,v 1.3 2002/07/08 07:31:53 keithp Exp $
* $XFree86: xc/lib/fontconfig/src/fclang.c,v 1.4 2002/07/12 21:06:03 keithp Exp $
*
* Copyright 2002 Keith Packard, member of The XFree86 Project, Inc.
*
......@@ -31,20 +31,32 @@ typedef struct {
#include "../fc-lang/fclang.h"
#define NUM_LANG_CHAR_SET (sizeof (fcLangCharSets) / sizeof (fcLangCharSets[0]))
FcBool
FcFreeTypeSetLang (FcPattern *pattern,
FcCharSet *charset,
#define NUM_LANG_CHAR_SET (sizeof (fcLangCharSets) / sizeof (fcLangCharSets[0]))
#define NUM_LANG_SET_MAP ((NUM_LANG_CHAR_SET + 31) / 32)
struct _FcLangSet {
FcChar32 map[NUM_LANG_SET_MAP];
FcStrSet *extra;
};
#define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
#define FcLangSetBitGet(ls, id) (((ls)->map[(id)>>5] >> ((id) & 0x1f)) & 1)
FcLangSet *
FcFreeTypeLangSet (const FcCharSet *charset,
const FcChar8 *exclusiveLang)
{
int i;
FcChar32 missing;
FcBool hasLang = FcFalse;
const FcCharSet *exclusiveCharset = 0;
FcLangSet *ls;
if (exclusiveLang)
exclusiveCharset = FcCharSetForLang (exclusiveLang);
ls = FcLangSetCreate ();
if (!ls)
return 0;
for (i = 0; i < NUM_LANG_CHAR_SET; i++)
{
/*
......@@ -91,76 +103,42 @@ FcFreeTypeSetLang (FcPattern *pattern,
printf ("%s(%d) ", fcLangCharSets[i].lang, missing);
}
if (!missing)
{
if (!FcPatternAddString (pattern, FC_LANG, fcLangCharSets[i].lang))
return FcFalse;
hasLang = FcTrue;
}
FcLangSetBitSet (ls, i);
}
/*
* Make sure it has a lang entry
*/
if (!hasLang)
if (!FcPatternAddString (pattern, FC_LANG, (FcChar8 *) "x-unknown"))
return FcFalse;
if (FcDebug() & FC_DBG_SCANV)
printf ("\n");
return FcTrue;
return ls;
}
#define FcLangEnd(c) ((c) == '-' || (c) == '\0')
FcLangResult
FcLangCompare (const FcChar8 *s1, const FcChar8 *s2)
{
const FcChar8 *orig_s1 = s1;
FcChar8 c1, c2;
FcLangResult result;
/*
* Compare ISO 639 language codes
*/
for (;;)
{
c1 = *s1++;
c2 = *s2++;
if (c1 == '\0' || c1 == '-')
break;
if (c2 == '\0' || c2 == '-')
break;
c1 = FcToLower (c1);
c2 = FcToLower (c2);
if (c1 != c2)
return FcLangDifferentLang; /* mismatching lang code */
}
if (!c1 && !c2)
return FcLangEqual;
/*
* Make x-* mismatch as if the lang part didn't match
*/
result = FcLangDifferentCountry;
if (orig_s1[0] == 'x' && (orig_s1[1] == '\0' || orig_s1[1] == '-'))
result = FcLangDifferentLang;
if (c1 == '\0' || c2 == '\0')
return result;
/*
* Compare ISO 3166 country codes
*/