X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=src%2Ffclang.c;h=be42b58c4694f54747c395ab28011a490a7a4dbc;hb=HEAD;hp=13f0ca21fb932c232c58a4eecc5ec17b6e769072;hpb=e85789a99770dbd1a4abe9da3eadb355c19f5216;p=fontconfig.git diff --git a/src/fclang.c b/src/fclang.c index 13f0ca2..be42b58 100644 --- a/src/fclang.c +++ b/src/fclang.c @@ -1,5 +1,5 @@ /* - * $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 * @@ -7,15 +7,15 @@ * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting - * documentation, and that the name of Keith Packard not be used in + * documentation, and that the name of the author(s) not be used in * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Keith Packard makes no + * specific, written prior permission. The authors make no * 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 @@ -23,6 +23,7 @@ */ #include "fcint.h" +#include "fcftint.h" typedef struct { const FcChar8 lang[8]; @@ -37,15 +38,55 @@ typedef struct { #include "../fc-lang/fclang.h" struct _FcLangSet { - FcChar32 map[NUM_LANG_SET_MAP]; FcStrSet *extra; + FcChar32 map_size; + FcChar32 map[NUM_LANG_SET_MAP]; }; -#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; +} + +static void +FcLangSetBitReset (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)); +} FcLangSet * -FcFreeTypeLangSet (const FcCharSet *charset, +FcFreeTypeLangSet (const FcCharSet *charset, const FcChar8 *exclusiveLang) { int i, j; @@ -54,21 +95,21 @@ FcFreeTypeLangSet (const FcCharSet *charset, FcLangSet *ls; if (exclusiveLang) - exclusiveCharset = FcCharSetForLang (exclusiveLang); + exclusiveCharset = FcLangGetCharSet (exclusiveLang); ls = FcLangSetCreate (); if (!ls) return 0; - if (FcDebug() & FC_DBG_LANGSET) + if (FcDebug() & FC_DBG_LANGSET) { - printf ("font charset\n"); + printf ("font charset"); FcCharSetPrint (charset); printf ("\n"); } for (i = 0; i < NUM_LANG_CHAR_SET; i++) { - if (FcDebug() & FC_DBG_LANGSET) + if (FcDebug() & FC_DBG_LANGSET) { - printf ("%s charset\n", fcLangCharSets[i].lang); + printf ("%s charset", fcLangCharSets[i].lang); FcCharSetPrint (&fcLangCharSets[i].charset); printf ("\n"); } @@ -85,7 +126,7 @@ FcFreeTypeLangSet (const FcCharSet *charset, continue; for (j = 0; j < fcLangCharSets[i].charset.num; j++) - if (FcCharSetLeaf(&fcLangCharSets[i].charset, j) != + if (FcCharSetLeaf(&fcLangCharSets[i].charset, j) != FcCharSetLeaf(exclusiveCharset, j)) continue; } @@ -94,7 +135,7 @@ FcFreeTypeLangSet (const FcCharSet *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]; @@ -127,8 +168,8 @@ FcFreeTypeLangSet (const FcCharSet *charset, if (FcDebug() & FC_DBG_SCANV) printf ("\n"); - - + + return ls; } @@ -150,18 +191,18 @@ FcLangCompare (const FcChar8 *s1, const FcChar8 *s2) 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 @@ -196,7 +237,7 @@ FcLangContains (const FcChar8 *super, const FcChar8 *sub) } const FcCharSet * -FcCharSetForLang (const FcChar8 *lang) +FcLangGetCharSet (const FcChar8 *lang) { int i; int country = -1; @@ -206,9 +247,10 @@ FcCharSetForLang (const FcChar8 *lang) 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; } @@ -218,6 +260,22 @@ FcCharSetForLang (const FcChar8 *lang) 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 * FcLangSetCreate (void) { @@ -228,6 +286,7 @@ FcLangSetCreate (void) return 0; FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet)); memset (ls->map, '\0', sizeof (ls->map)); + ls->map_size = NUM_LANG_SET_MAP; ls->extra = 0; return ls; } @@ -249,7 +308,8 @@ FcLangSetCopy (const FcLangSet *ls) new = FcLangSetCreate (); if (!new) goto bail0; - memcpy (new->map, ls->map, sizeof (new->map)); + 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; @@ -283,9 +343,9 @@ FcLangSetIndex (const FcChar8 *lang) { 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; @@ -314,11 +374,11 @@ FcLangSetIndex (const FcChar8 *lang) { /* 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); } } @@ -354,6 +414,23 @@ FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang) return FcStrSetAdd (ls->extra, lang); } +FcBool +FcLangSetDel (FcLangSet *ls, const FcChar8 *lang) +{ + int id; + + id = FcLangSetIndex (lang); + if (id >= 0) + { + FcLangSetBitReset (ls, id); + } + else if (ls->extra) + { + FcStrSetDel (ls->extra, lang); + } + return FcTrue; +} + FcLangResult FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang) { @@ -425,19 +502,21 @@ FcLangSetCompareStrSet (const FcLangSet *ls, FcStrSet *set) 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 (lsa->extra) @@ -457,6 +536,7 @@ FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb) /* * Used in computing values -- mustn't allocate any storage + * XXX Not thread-safe */ FcLangSet * FcLangSetPromote (const FcChar8 *lang) @@ -467,6 +547,7 @@ FcLangSetPromote (const FcChar8 *lang) int id; memset (ls.map, '\0', sizeof (ls.map)); + ls.map_size = NUM_LANG_SET_MAP; ls.extra = 0; id = FcLangSetIndex (lang); if (id > 0) @@ -489,9 +570,10 @@ FcChar32 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 (ls->extra) h ^= ls->extra->num; @@ -501,7 +583,7 @@ FcLangSetHash (const FcLangSet *ls) FcLangSet * FcNameParseLangSet (const FcChar8 *string) { - FcChar8 lang[32],c; + FcChar8 lang[32], c = 0; int i; FcLangSet *ls; @@ -534,11 +616,12 @@ bail0: 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])) { @@ -549,7 +632,7 @@ FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls) if (!first) if (!FcStrBufChar (buf, '|')) return FcFalse; - if (!FcStrBufString (buf, fcLangCharSets[id].lang)) + if (!FcStrBufString (buf, fcLangCharSets[fcLangCharSetIndicesInv[id]].lang)) return FcFalse; first = FcFalse; } @@ -585,9 +668,11 @@ FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls) 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; @@ -655,7 +740,7 @@ FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang) FcBool FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb) { - int i, j; + int i, j, count; FcChar32 missing; if (FcDebug() & FC_DBG_MATCHV) @@ -667,19 +752,21 @@ FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb) /* * 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; } } @@ -724,9 +811,76 @@ FcLangSetSerialize(FcSerialize *serialize, const FcLangSet *l) if (!l_serialize) return NULL; - *l_serialize = *l; + 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; } + +FcStrSet * +FcLangSetGetLangs (const FcLangSet *ls) +{ + FcStrSet *langs; + int i; + + langs = FcStrSetCreate(); + if (!langs) + return 0; + + for (i = 0; i < NUM_LANG_CHAR_SET; i++) + if (FcLangSetBitGet (ls, i)) + FcStrSetAdd (langs, fcLangCharSets[i].lang); + + if (ls->extra) + { + FcStrList *list = FcStrListCreate (ls->extra); + FcChar8 *extra; + + if (list) + { + while ((extra = FcStrListNext (list))) + FcStrSetAdd (langs, extra); + + FcStrListDone (list); + } + } + + return langs; +} + +static FcLangSet * +FcLangSetOperate(const FcLangSet *a, + const FcLangSet *b, + FcBool (*func) (FcLangSet *ls, + const FcChar8 *s)) +{ + FcLangSet *langset = FcLangSetCopy (a); + FcStrList *sl = FcStrListCreate (FcLangSetGetLangs (b)); + FcChar8 *str; + + while ((str = FcStrListNext (sl))) + { + func (langset, str); + } + FcStrListDone (sl); + + return langset; +} + +FcLangSet * +FcLangSetUnion (const FcLangSet *a, const FcLangSet *b) +{ + return FcLangSetOperate(a, b, FcLangSetAdd); +} + +FcLangSet * +FcLangSetSubtract (const FcLangSet *a, const FcLangSet *b) +{ + return FcLangSetOperate(a, b, FcLangSetDel); +} + #define __fclang__ #include "fcaliastail.h" +#include "fcftaliastail.h" #undef __fclang__