X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=src%2Ffclang.c;h=be42b58c4694f54747c395ab28011a490a7a4dbc;hb=HEAD;hp=fabf36a15d7c15584e9a0840c2dbf5948c57c5ed;hpb=46b51147d10db21a4d5992074bcdc9022f45856b;p=fontconfig.git diff --git a/src/fclang.c b/src/fclang.c index fabf36a..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,10 +23,11 @@ */ #include "fcint.h" +#include "fcftint.h" typedef struct { - FcChar8 *lang; - FcCharSet charset; + const FcChar8 lang[8]; + const FcCharSet charset; } FcLangCharSet; typedef struct { @@ -37,53 +38,110 @@ 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; + 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 * 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 (FcCharSetLeaf(&fcLangCharSets[i].charset, j) != + FcCharSetLeaf(exclusiveCharset, j)) + continue; } missing = FcCharSetSubtractCount (&fcLangCharSets[i].charset, charset); if (FcDebug() & FC_DBG_SCANV) { 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; @@ -102,7 +160,7 @@ FcFreeTypeLangSet (const FcCharSet *charset, FcCharSetDestroy (missed); } else - printf ("%s(%d) ", fcLangCharSets[i].lang, missing); + printf ("%s(%u) ", fcLangCharSets[i].lang, missing); } if (!missing) FcLangSetBitSet (ls, i); @@ -110,8 +168,8 @@ FcFreeTypeLangSet (const FcCharSet *charset, if (FcDebug() & FC_DBG_SCANV) printf ("\n"); - - + + return ls; } @@ -133,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 @@ -179,25 +237,43 @@ FcLangContains (const FcChar8 *super, const FcChar8 *sub) } 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 * @@ -210,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; } @@ -231,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; @@ -265,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; @@ -296,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); } } @@ -336,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) { @@ -369,7 +464,6 @@ FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang) { FcStrList *list = FcStrListCreate (ls->extra); FcChar8 *extra; - FcLangResult r; if (list) { @@ -408,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) @@ -440,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) @@ -450,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) @@ -472,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; @@ -484,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; @@ -517,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])) { @@ -532,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; } @@ -549,11 +649,18 @@ FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls) { 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; } @@ -561,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; @@ -631,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) @@ -643,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; } } @@ -684,3 +795,92 @@ FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb) } return FcTrue; } + +FcBool +FcLangSetSerializeAlloc (FcSerialize *serialize, const FcLangSet *l) +{ + if (!FcSerializeAlloc (serialize, l, sizeof (FcLangSet))) + return FcFalse; + return FcTrue; +} + +FcLangSet * +FcLangSetSerialize(FcSerialize *serialize, const FcLangSet *l) +{ + 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; +} + +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__