/*
* $RCSId: xc/lib/fontconfig/src/fclang.c,v 1.7 2002/08/26 23:34:31 keithp Exp $
*
- * Copyright © 2002 Keith Packard
+ * Copyright © 2002 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
#include "fcint.h"
typedef struct {
- FcChar8 *lang;
- FcCharSet charset;
+ const FcChar8 *lang;
+ const FcCharSet charset;
} FcLangCharSet;
typedef struct {
#define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
#define FcLangSetBitGet(ls, id) (((ls)->map[(id)>>5] >> ((id) & 0x1f)) & 1)
+static FcBool langsets_populated = FcFalse;
+
FcLangSet *
FcFreeTypeLangSet (const FcCharSet *charset,
const FcChar8 *exclusiveLang)
{
- int i;
+ int i, j;
FcChar32 missing;
const FcCharSet *exclusiveCharset = 0;
FcLangSet *ls;
-
+
+ if (!langsets_populated)
+ {
+ FcLangCharSetPopulate ();
+ langsets_populated = FcTrue;
+ }
if (exclusiveLang)
exclusiveCharset = FcCharSetForLang (exclusiveLang);
* not support other Han languages
*/
if (exclusiveCharset &&
- FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang) &&
- fcLangCharSets[i].charset.leaves != exclusiveCharset->leaves)
+ FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang))
{
- continue;
+ if (fcLangCharSets[i].charset.num != exclusiveCharset->num)
+ continue;
+
+ for (j = 0; j < fcLangCharSets[i].charset.num; j++)
+ if (FcCharSetGetLeaf(&fcLangCharSets[i].charset, j) !=
+ FcCharSetGetLeaf(exclusiveCharset, j))
+ continue;
}
missing = FcCharSetSubtractCount (&fcLangCharSets[i].charset, charset);
if (FcDebug() & FC_DBG_SCANV)
}
/*
- * Return FcTrue when s1 contains s2.
+ * Return FcTrue when super contains sub.
*
- * s1 contains s2 if s1 equals s2 or if s1 is a
- * language with a country and s2 is just a language
+ * super contains sub if super and sub have the same
+ * language and either the same country or one
+ * is missing the country
*/
static FcBool
-FcLangContains (const FcChar8 *s1, const FcChar8 *s2)
+FcLangContains (const FcChar8 *super, const FcChar8 *sub)
{
FcChar8 c1, c2;
for (;;)
{
- c1 = *s1++;
- c2 = *s2++;
+ c1 = *super++;
+ c2 = *sub++;
c1 = FcToLower (c1);
c2 = FcToLower (c2);
if (c1 != c2)
{
- /* see if s1 has a country while s2 is mising one */
+ /* see if super has a country while sub is mising one */
if (c1 == '-' && c2 == '\0')
return FcTrue;
+ /* see if sub has a country while super is mising one */
+ if (c1 == '\0' && c2 == '-')
+ return FcTrue;
return FcFalse;
}
else if (!c1)
{
int i;
int country = -1;
+
+ if (!langsets_populated)
+ {
+ FcLangCharSetPopulate ();
+ langsets_populated = FcTrue;
+ }
+
for (i = 0; i < NUM_LANG_CHAR_SET; i++)
{
switch (FcLangCompare (lang, fcLangCharSets[i].lang)) {
static int
FcLangSetIndex (const FcChar8 *lang)
{
- int low, high, mid;
- int cmp;
+ int low, high, mid = 0;
+ int cmp = 0;
FcChar8 firstChar = FcToLower(lang[0]);
+ FcChar8 secondChar = firstChar ? FcToLower(lang[1]) : '\0';
if (firstChar < 'a')
{
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)
+ cmp = fcLangCharSets[mid].lang[1] - secondChar;
+ if (cmp == 0 &&
+ (fcLangCharSets[mid].lang[2] != '\0' ||
+ lang[2] != '\0'))
{
- low = mid + 1;
- continue;
+ cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang+2,
+ lang+2);
}
- 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)
return mid;
FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang)
{
int id;
- FcLangResult r;
int i;
id = FcLangSetIndex (lang);
{
FcStrList *list = FcStrListCreate (ls->extra);
FcChar8 *extra;
- FcLangResult r;
if (list)
{
}
return FcTrue;
}
+
+static FcLangSet ** langsets = 0;
+static int langset_bank_count = 0, langset_ptr = 0, langset_count = 0;
+
+void
+FcLangSetNewBank (void)
+{
+ langset_count = 0;
+}
+
+/* ideally, should only write one copy of any particular FcLangSet */
+int
+FcLangSetNeededBytes (const FcLangSet *l)
+{
+ langset_count++;
+ return sizeof (FcLangSet);
+}
+
+int
+FcLangSetNeededBytesAlign (void)
+{
+ return __alignof__ (FcLangSet);
+}
+
+static FcBool
+FcLangSetEnsureBank (int bi)
+{
+ if (!langsets || bi >= langset_bank_count)
+ {
+ int new_count = langset_bank_count + 2;
+ int i;
+ FcLangSet** tt;
+ tt = realloc(langsets, new_count * sizeof(FcLangSet *));
+ if (!tt)
+ return FcFalse;
+
+ langsets = tt;
+ for (i = langset_bank_count; i < new_count; i++)
+ langsets[i] = 0;
+ langset_bank_count = new_count;
+ }
+
+ return FcTrue;
+}
+
+void *
+FcLangSetDistributeBytes (FcCache * metadata, void * block_ptr)
+{
+ int bi = FcCacheBankToIndex(metadata->bank);
+ if (!FcLangSetEnsureBank(bi))
+ return 0;
+
+ block_ptr = ALIGN(block_ptr, FcLangSet);
+ langsets[bi] = block_ptr;
+ block_ptr = (void *)((char *)block_ptr +
+ langset_count * sizeof(FcLangSet));
+ langset_ptr = 0;
+ metadata->langset_count = langset_count;
+ return block_ptr;
+}
+
+FcLangSet *
+FcLangSetSerialize(int bank, FcLangSet *l)
+{
+ int p = langset_ptr, bi = FcCacheBankToIndex(bank);
+
+ if (!l) return 0;
+
+ langsets[bi][langset_ptr] = *l;
+ langsets[bi][langset_ptr].extra = 0;
+ langset_ptr++;
+ return &langsets[bi][p];
+}
+
+void *
+FcLangSetUnserialize (FcCache metadata, void *block_ptr)
+{
+ int bi = FcCacheBankToIndex(metadata.bank);
+ if (!FcLangSetEnsureBank(bi))
+ return 0;
+
+ FcMemAlloc (FC_MEM_LANGSET, metadata.langset_count * sizeof(FcLangSet));
+ block_ptr = ALIGN(block_ptr, FcLangSet);
+ langsets[bi] = (FcLangSet *)block_ptr;
+ block_ptr = (void *)((char *)block_ptr +
+ metadata.langset_count * sizeof(FcLangSet));
+ return block_ptr;
+}