/*
- * $RCSId: xc/lib/fontconfig/src/fclang.c,v 1.7 2002/08/26 23:34:31 keithp Exp $
+ * fontconfig/src/fclang.c
*
* Copyright © 2002 Keith Packard
*
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-#include <fcntl.h>
-#include <sys/mman.h>
#include "fcint.h"
+#include "fcftint.h"
typedef struct {
- FcChar8 *lang;
- FcCharSet charset;
+ const FcChar8 lang[8];
+ const FcCharSet charset;
} FcLangCharSet;
typedef struct {
#include "../fc-lang/fclang.h"
struct _FcLangSet {
+ FcStrSet *extra;
+ FcChar32 map_size;
FcChar32 map[NUM_LANG_SET_MAP];
- FcStrSetPtr extra;
};
-#define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
-#define FcLangSetBitGet(ls, id) (((ls)->map[(id)>>5] >> ((id) & 0x1f)) & 1)
+static void
+FcLangSetBitSet (FcLangSet *ls,
+ unsigned int id)
+{
+ int bucket;
+
+ id = fcLangCharSetIndices[id];
+ bucket = id >> 5;
+ if (bucket >= ls->map_size)
+ return; /* shouldn't happen really */
+
+ ls->map[bucket] |= ((FcChar32) 1 << (id & 0x1f));
+}
+
+static FcBool
+FcLangSetBitGet (const FcLangSet *ls,
+ unsigned int id)
+{
+ int bucket;
+
+ id = fcLangCharSetIndices[id];
+ bucket = id >> 5;
+ if (bucket >= ls->map_size)
+ return FcFalse;
+
+ return ((ls->map[bucket] >> (id & 0x1f)) & 1) ? FcTrue : FcFalse;
+}
FcLangSet *
-FcFreeTypeLangSet (const FcCharSet *charset,
+FcFreeTypeLangSet (const FcCharSet *charset,
const FcChar8 *exclusiveLang)
{
int i, j;
FcChar32 missing;
const FcCharSet *exclusiveCharset = 0;
FcLangSet *ls;
-
if (exclusiveLang)
- exclusiveCharset = FcCharSetForLang (exclusiveLang);
+ exclusiveCharset = FcLangGetCharSet (exclusiveLang);
ls = FcLangSetCreate ();
if (!ls)
return 0;
+ if (FcDebug() & FC_DBG_LANGSET)
+ {
+ printf ("font charset");
+ FcCharSetPrint (charset);
+ printf ("\n");
+ }
for (i = 0; i < NUM_LANG_CHAR_SET; i++)
{
+ if (FcDebug() & FC_DBG_LANGSET)
+ {
+ printf ("%s charset", fcLangCharSets[i].lang);
+ FcCharSetPrint (&fcLangCharSets[i].charset);
+ printf ("\n");
+ }
+
/*
* Check for Han charsets to make fonts
* which advertise support for a single language
continue;
for (j = 0; j < fcLangCharSets[i].charset.num; j++)
- if (FcCharSetGetLeaf(&fcLangCharSets[i].charset, j) !=
- FcCharSetGetLeaf(exclusiveCharset, j))
+ if (FcCharSetLeaf(&fcLangCharSets[i].charset, j) !=
+ FcCharSetLeaf(exclusiveCharset, j))
continue;
}
missing = FcCharSetSubtractCount (&fcLangCharSets[i].charset, charset);
{
if (missing && missing < 10)
{
- FcCharSet *missed = FcCharSetSubtract (&fcLangCharSets[i].charset,
+ FcCharSet *missed = FcCharSetSubtract (&fcLangCharSets[i].charset,
charset);
FcChar32 ucs4;
FcChar32 map[FC_CHARSET_MAP_SIZE];
FcChar32 next;
- printf ("\n%s(%d) ", fcLangCharSets[i].lang, missing);
+ printf ("\n%s(%u) ", fcLangCharSets[i].lang, missing);
printf ("{");
for (ucs4 = FcCharSetFirstPage (missed, map, &next);
ucs4 != FC_CHARSET_DONE;
FcCharSetDestroy (missed);
}
else
- printf ("%s(%d) ", fcLangCharSets[i].lang, missing);
+ printf ("%s(%u) ", fcLangCharSets[i].lang, missing);
}
if (!missing)
FcLangSetBitSet (ls, i);
if (FcDebug() & FC_DBG_SCANV)
printf ("\n");
-
-
+
+
return ls;
}
if (c1 != c2)
{
if (FcLangEnd (c1) && FcLangEnd (c2))
- result = FcLangDifferentCountry;
+ result = FcLangDifferentTerritory;
return result;
}
else if (!c1)
return FcLangEqual;
else if (c1 == '-')
- result = FcLangDifferentCountry;
+ result = FcLangDifferentTerritory;
}
}
/*
- * Return FcTrue when super contains sub.
+ * Return FcTrue when super contains sub.
*
* super contains sub if super and sub have the same
* language and either the same country or one
}
const FcCharSet *
-FcCharSetForLang (const FcChar8 *lang)
+FcLangGetCharSet (const FcChar8 *lang)
{
int i;
int country = -1;
+
for (i = 0; i < NUM_LANG_CHAR_SET; i++)
{
switch (FcLangCompare (lang, fcLangCharSets[i].lang)) {
case FcLangEqual:
return &fcLangCharSets[i].charset;
- case FcLangDifferentCountry:
+ case FcLangDifferentTerritory:
if (country == -1)
country = i;
+ case FcLangDifferentLang:
default:
break;
}
}
if (country == -1)
return 0;
- return &fcLangCharSets[i].charset;
+ return &fcLangCharSets[country].charset;
+}
+
+FcStrSet *
+FcGetLangs (void)
+{
+ FcStrSet *langs;
+ int i;
+
+ langs = FcStrSetCreate();
+ if (!langs)
+ return 0;
+
+ for (i = 0; i < NUM_LANG_CHAR_SET; i++)
+ FcStrSetAdd (langs, fcLangCharSets[i].lang);
+
+ return langs;
}
FcLangSet *
return 0;
FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet));
memset (ls->map, '\0', sizeof (ls->map));
- ls->extra = FcStrSetPtrCreateDynamic(0);
+ ls->map_size = NUM_LANG_SET_MAP;
+ ls->extra = 0;
return ls;
}
-void
-FcLangSetPtrDestroy (FcLangSetPtr li)
-{
- if (li.storage == FcStorageDynamic)
- FcLangSetDestroy(FcLangSetPtrU(li));
-}
-
void
FcLangSetDestroy (FcLangSet *ls)
{
- if (FcStrSetPtrU(ls->extra))
- FcStrSetDestroy (FcStrSetPtrU(ls->extra));
+ if (ls->extra)
+ FcStrSetDestroy (ls->extra);
FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet));
free (ls);
}
new = FcLangSetCreate ();
if (!new)
goto bail0;
- memcpy (new->map, ls->map, sizeof (new->map));
- if (FcStrSetPtrU(ls->extra))
+ memset (new->map, '\0', sizeof (new->map));
+ memcpy (new->map, ls->map, FC_MIN (sizeof (new->map), ls->map_size * sizeof (ls->map[0])));
+ if (ls->extra)
{
FcStrList *list;
FcChar8 *extra;
- new->extra = FcStrSetPtrCreateDynamic(FcStrSetCreate ());
- if (!FcStrSetPtrU(new->extra))
+ new->extra = FcStrSetCreate ();
+ if (!new->extra)
goto bail1;
- list = FcStrListCreate (FcStrSetPtrU(ls->extra));
+ list = FcStrListCreate (ls->extra);
if (!list)
goto bail1;
while ((extra = FcStrListNext (list)))
- if (!FcStrSetAdd (FcStrSetPtrU(new->extra), extra))
+ if (!FcStrSetAdd (new->extra, extra))
{
FcStrListDone (list);
goto bail1;
{
int low, high, mid = 0;
int cmp = 0;
- FcChar8 firstChar = FcToLower(lang[0]);
+ FcChar8 firstChar = FcToLower(lang[0]);
FcChar8 secondChar = firstChar ? FcToLower(lang[1]) : '\0';
-
+
if (firstChar < 'a')
{
low = 0;
{ /* 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) */
cmp = fcLangCharSets[mid].lang[1] - secondChar;
- if (cmp == 0 &&
- (fcLangCharSets[mid].lang[2] != '\0' ||
+ if (cmp == 0 &&
+ (fcLangCharSets[mid].lang[2] != '\0' ||
lang[2] != '\0'))
{
- cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang+2,
+ cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang+2,
lang+2);
}
}
FcLangSetBitSet (ls, id);
return FcTrue;
}
- if (!FcStrSetPtrU(ls->extra))
+ if (!ls->extra)
{
- ls->extra = FcStrSetPtrCreateDynamic(FcStrSetCreate ());
- if (!FcStrSetPtrU(ls->extra))
+ ls->extra = FcStrSetCreate ();
+ if (!ls->extra)
return FcFalse;
}
- return FcStrSetAdd (FcStrSetPtrU(ls->extra), lang);
+ return FcStrSetAdd (ls->extra, lang);
}
FcLangResult
if (FcLangSetBitGet (ls, i) && r < best)
best = r;
}
- if (FcStrSetPtrU(ls->extra))
+ if (ls->extra)
{
- FcStrList *list = FcStrListCreate (FcStrSetPtrU(ls->extra));
+ FcStrList *list = FcStrListCreate (ls->extra);
FcChar8 *extra;
- FcLangResult r;
if (list)
{
FcLangResult
FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
{
- int i, j;
+ int i, j, count;
FcLangResult best, r;
- for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ count = FC_MIN (lsa->map_size, lsb->map_size);
+ count = FC_MIN (NUM_LANG_SET_MAP, count);
+ for (i = 0; i < count; i++)
if (lsa->map[i] & lsb->map[i])
return FcLangEqual;
best = FcLangDifferentLang;
for (j = 0; j < NUM_COUNTRY_SET; j++)
- for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ for (i = 0; i < count; i++)
if ((lsa->map[i] & fcLangCountrySets[j][i]) &&
(lsb->map[i] & fcLangCountrySets[j][i]))
{
- best = FcLangDifferentCountry;
+ best = FcLangDifferentTerritory;
break;
}
- if (FcStrSetPtrU(lsa->extra))
+ if (lsa->extra)
{
- r = FcLangSetCompareStrSet (lsb, FcStrSetPtrU(lsa->extra));
+ r = FcLangSetCompareStrSet (lsb, lsa->extra);
if (r < best)
best = r;
}
- if (best > FcLangEqual && FcStrSetPtrU(lsb->extra))
+ if (best > FcLangEqual && lsb->extra)
{
- r = FcLangSetCompareStrSet (lsa, FcStrSetPtrU(lsb->extra));
+ r = FcLangSetCompareStrSet (lsa, lsb->extra);
if (r < best)
best = r;
}
int id;
memset (ls.map, '\0', sizeof (ls.map));
- ls.extra = FcStrSetPtrCreateDynamic(0);
+ ls.extra = 0;
id = FcLangSetIndex (lang);
if (id > 0)
{
}
else
{
- ls.extra = FcStrSetPtrCreateDynamic(&strs);
+ ls.extra = &strs;
strs.num = 1;
strs.size = 1;
- strs.storage = FcStorageDynamic;
- strs.u.strs = &str;
+ strs.strs = &str;
strs.ref = 1;
str = (FcChar8 *) lang;
}
FcLangSetHash (const FcLangSet *ls)
{
FcChar32 h = 0;
- int i;
+ int i, count;
- for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ count = FC_MIN (ls->map_size, NUM_LANG_SET_MAP);
+ for (i = 0; i < count; i++)
h ^= ls->map[i];
- if (FcStrSetPtrU(ls->extra))
- h ^= FcStrSetPtrU(ls->extra)->num;
+ if (ls->extra)
+ h ^= ls->extra->num;
return h;
}
FcLangSet *
FcNameParseLangSet (const FcChar8 *string)
{
- FcChar8 lang[32],c;
+ FcChar8 lang[32], c = 0;
int i;
FcLangSet *ls;
FcBool
FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
{
- int i, bit;
+ int i, bit, count;
FcChar32 bits;
FcBool first = FcTrue;
- for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ count = FC_MIN (ls->map_size, NUM_LANG_SET_MAP);
+ for (i = 0; i < count; i++)
{
if ((bits = ls->map[i]))
{
if (!first)
if (!FcStrBufChar (buf, '|'))
return FcFalse;
- if (!FcStrBufString (buf, fcLangCharSets[id].lang))
+ if (!FcStrBufString (buf, fcLangCharSets[fcLangCharSetIndicesInv[id]].lang))
return FcFalse;
first = FcFalse;
}
}
}
- if (FcStrSetPtrU(ls->extra))
+ if (ls->extra)
{
- FcStrList *list = FcStrListCreate (FcStrSetPtrU(ls->extra));
+ FcStrList *list = FcStrListCreate (ls->extra);
FcChar8 *extra;
if (!list)
{
if (!first)
if (!FcStrBufChar (buf, '|'))
+ {
+ FcStrListDone (list);
return FcFalse;
+ }
if (!FcStrBufString (buf, extra))
- return FcFalse;
+ {
+ FcStrListDone (list);
+ return FcFalse;
+ }
first = FcFalse;
}
+ FcStrListDone (list);
}
return FcTrue;
}
FcBool
FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb)
{
- int i;
+ int i, count;
- for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ count = FC_MIN (lsa->map_size, lsb->map_size);
+ count = FC_MIN (NUM_LANG_SET_MAP, count);
+ for (i = 0; i < count; i++)
{
if (lsa->map[i] != lsb->map[i])
return FcFalse;
}
- if (!FcStrSetPtrU(lsa->extra) && !FcStrSetPtrU(lsb->extra))
+ if (!lsa->extra && !lsb->extra)
return FcTrue;
- if (FcStrSetPtrU(lsa->extra) && FcStrSetPtrU(lsb->extra))
- return FcStrSetEqual (FcStrSetPtrU(lsa->extra), FcStrSetPtrU(lsb->extra));
+ if (lsa->extra && lsb->extra)
+ return FcStrSetEqual (lsa->extra, lsb->extra);
return FcFalse;
}
FcLangContains (fcLangCharSets[i].lang, lang))
return FcTrue;
}
- if (FcStrSetPtrU(ls->extra))
+ if (ls->extra)
{
- FcStrList *list = FcStrListCreate (FcStrSetPtrU(ls->extra));
+ FcStrList *list = FcStrListCreate (ls->extra);
FcChar8 *extra;
if (list)
FcBool
FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
{
- int i, j;
+ int i, j, count;
FcChar32 missing;
if (FcDebug() & FC_DBG_MATCHV)
/*
* check bitmaps for missing language support
*/
- for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ count = FC_MIN (lsa->map_size, lsb->map_size);
+ count = FC_MIN (NUM_LANG_SET_MAP, count);
+ for (i = 0; i < count; i++)
{
missing = lsb->map[i] & ~lsa->map[i];
if (missing)
{
for (j = 0; j < 32; j++)
- if (missing & (1 << j))
+ if (missing & (1 << j))
{
if (!FcLangSetContainsLang (lsa,
- fcLangCharSets[i*32 + j].lang))
+ fcLangCharSets[fcLangCharSetIndicesInv[i*32 + j]].lang))
{
if (FcDebug() & FC_DBG_MATCHV)
- printf ("\tMissing bitmap %s\n", fcLangCharSets[i*32+j].lang);
+ printf ("\tMissing bitmap %s\n", fcLangCharSets[fcLangCharSetIndicesInv[i*32+j]].lang);
return FcFalse;
}
}
}
}
- if (FcStrSetPtrU(lsb->extra))
+ if (lsb->extra)
{
- FcStrList *list = FcStrListCreate (FcStrSetPtrU(lsb->extra));
+ FcStrList *list = FcStrListCreate (lsb->extra);
FcChar8 *extra;
if (list)
return FcTrue;
}
-static FcLangSet * langsets = 0;
-static int langset_ptr = 0, langset_count = 0;
-
-FcLangSet *
-FcLangSetPtrU (FcLangSetPtr li)
-{
- switch (li.storage)
- {
- case FcStorageDynamic:
- return li.u.dyn;
- case FcStorageStatic:
- return &langsets[li.u.stat];
- default:
- return 0;
-
- }
-}
-
-FcLangSetPtr
-FcLangSetPtrCreateDynamic (FcLangSet *li)
+FcBool
+FcLangSetSerializeAlloc (FcSerialize *serialize, const FcLangSet *l)
{
- FcLangSetPtr new;
- new.storage = FcStorageDynamic;
- new.u.dyn = li;
- return new;
+ if (!FcSerializeAlloc (serialize, l, sizeof (FcLangSet)))
+ return FcFalse;
+ return FcTrue;
}
-void
-FcLangSetClearStatic (void)
+FcLangSet *
+FcLangSetSerialize(FcSerialize *serialize, const FcLangSet *l)
{
- FcStrSetClearStatic();
- langset_ptr = 0;
- langset_count = 0;
+ FcLangSet *l_serialize = FcSerializePtr (serialize, l);
+
+ if (!l_serialize)
+ return NULL;
+ memset (l_serialize->map, '\0', sizeof (l_serialize->map));
+ memcpy (l_serialize->map, l->map, FC_MIN (sizeof (l_serialize->map), l->map_size * sizeof (l->map[0])));
+ l_serialize->map_size = NUM_LANG_SET_MAP;
+ l_serialize->extra = NULL; /* We don't serialize ls->extra */
+ return l_serialize;
}
-/* should only write one copy of any particular FcLangSet */
-FcBool
-FcLangSetPrepareSerialize (FcLangSet *l)
+FcStrSet *
+FcLangSetGetLangs (const FcLangSet *ls)
{
- langset_count++;
- if (l && FcStrSetPtrU(l->extra))
- return FcStrSetPrepareSerialize (FcStrSetPtrU(l->extra));
- return FcTrue;
-}
+ FcStrSet *langs;
+ int i;
-FcLangSetPtr
-FcLangSetSerialize(FcLangSet *l)
-{
- FcLangSetPtr new;
- int p = langset_ptr;
+ langs = FcStrSetCreate();
+ if (!langs)
+ return 0;
- if (!l) return FcLangSetPtrCreateDynamic(0);
+ for (i = 0; i < NUM_LANG_CHAR_SET; i++)
+ if (FcLangSetBitGet (ls, i))
+ FcStrSetAdd (langs, fcLangCharSets[i].lang);
- if (!langsets)
+ if (ls->extra)
{
- FcLangSet* t;
- t = (FcLangSet *)malloc(langset_count * sizeof(FcLangSet));
- if (!t)
- return FcLangSetPtrCreateDynamic(0);
- langsets = t;
- langset_ptr = 0;
- }
-
- langsets[langset_ptr] = *l;
- if (FcStrSetPtrU(l->extra))
- langsets[langset_ptr].extra =
- FcStrSetSerialize(FcStrSetPtrU(l->extra));
- else
- langsets[langset_ptr].extra = FcStrSetPtrCreateDynamic(0);
- langset_ptr++;
- new.storage = FcStorageStatic;
- new.u.stat = p;
- return new;
-}
+ FcStrList *list = FcStrListCreate (ls->extra);
+ FcChar8 *extra;
-FcBool
-FcLangSetWrite (int fd, FcCache *metadata)
-{
- metadata->langsets_length = langset_ptr;
- metadata->langsets_offset = FcCacheNextOffset(fd);
+ if (list)
+ {
+ while ((extra = FcStrListNext (list)))
+ FcStrSetAdd (langs, extra);
- if (langset_ptr > 0)
- {
- lseek (fd, metadata->langsets_offset, SEEK_SET);
- return write(fd, langsets,
- metadata->langsets_length * sizeof(FcLangSet)) != -1;
+ FcStrListDone (list);
+ }
}
- return FcTrue;
-}
-FcBool
-FcLangSetRead (int fd, FcCache metadata)
-{
- langsets = mmap(NULL,
- metadata.langsets_length * sizeof (FcLangSet),
- PROT_READ,
- MAP_SHARED, fd, metadata.langsets_offset);
- if (langsets == MAP_FAILED)
- return FcFalse;
- langset_count = langset_ptr = metadata.langsets_length;
- return FcTrue;
+ return langs;
}
+
+#define __fclang__
+#include "fcaliastail.h"
+#include "fcftaliastail.h"
+#undef __fclang__