]> git.wh0rd.org - fontconfig.git/blobdiff - src/fclang.c
Bug 44826 - <alias> must contain only a single <family>
[fontconfig.git] / src / fclang.c
index 552253d2dee366db68685f1670e5ea8ab5dc41e3..be42b58c4694f54747c395ab28011a490a7a4dbc 100644 (file)
@@ -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
  */
 
 #include "fcint.h"
+#include "fcftint.h"
 
 typedef struct {
-    const FcChar8      *lang;
+    const FcChar8      lang[8];
     const FcCharSet    charset;
 } FcLangCharSet;
 
@@ -37,17 +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 */
 
-static FcBool langsets_populated = FcFalse;
+  ls->map[bucket] &= ~((FcChar32) 1 << (id & 0x1f));
+}
 
 FcLangSet *
-FcFreeTypeLangSet (const FcCharSet  *charset, 
+FcFreeTypeLangSet (const FcCharSet  *charset,
                   const FcChar8    *exclusiveLang)
 {
     int                    i, j;
@@ -55,19 +94,26 @@ FcFreeTypeLangSet (const FcCharSet  *charset,
     const FcCharSet *exclusiveCharset = 0;
     FcLangSet      *ls;
 
-    if (!langsets_populated)
-    {
-        FcLangCharSetPopulate ();
-        langsets_populated = FcTrue;
-    }
-
     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
@@ -80,8 +126,8 @@ FcFreeTypeLangSet (const FcCharSet  *charset,
                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);
@@ -89,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];
@@ -122,8 +168,8 @@ FcFreeTypeLangSet (const FcCharSet  *charset,
 
     if (FcDebug() & FC_DBG_SCANV)
        printf ("\n");
-    
-    
+
+
     return ls;
 }
 
@@ -145,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
@@ -191,25 +237,20 @@ FcLangContains (const FcChar8 *super, const FcChar8 *sub)
 }
 
 const FcCharSet *
-FcCharSetForLang (const FcChar8 *lang)
+FcLangGetCharSet (const FcChar8 *lang)
 {
     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)) {
        case FcLangEqual:
            return &fcLangCharSets[i].charset;
-       case FcLangDifferentCountry:
+       case FcLangDifferentTerritory:
            if (country == -1)
                country = i;
+       case FcLangDifferentLang:
        default:
            break;
        }
@@ -219,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)
 {
@@ -229,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;
 }
@@ -250,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;
@@ -284,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;
@@ -315,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);
            }
        }
@@ -355,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)
 {
@@ -426,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)
@@ -458,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)
@@ -468,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)
@@ -490,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;
@@ -502,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;
 
@@ -535,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]))
        {
@@ -550,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;
                }
@@ -586,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;
@@ -656,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)
@@ -668,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;
                    }
                }
@@ -710,90 +796,91 @@ FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
     return FcTrue;
 }
 
-static FcLangSet ** langsets = 0;
-static int langset_bank_count = 0, langset_ptr = 0, langset_count = 0;
-
-void
-FcLangSetNewBank (void)
+FcBool
+FcLangSetSerializeAlloc (FcSerialize *serialize, const FcLangSet *l)
 {
-    langset_count = 0;
+    if (!FcSerializeAlloc (serialize, l, sizeof (FcLangSet)))
+       return FcFalse;
+    return FcTrue;
 }
 
-/* ideally, should only write one copy of any particular FcLangSet */
-int
-FcLangSetNeededBytes (const FcLangSet *l)
+FcLangSet *
+FcLangSetSerialize(FcSerialize *serialize, const FcLangSet *l)
 {
-    langset_count++;
-    return sizeof (FcLangSet);
+    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;
 }
 
-int
-FcLangSetNeededBytesAlign (void)
+FcStrSet *
+FcLangSetGetLangs (const FcLangSet *ls)
 {
-    return fc_alignof (FcLangSet);
-}
+    FcStrSet *langs;
+    int              i;
 
-static FcBool
-FcLangSetEnsureBank (int bi)
-{
-    if (!langsets || bi >= langset_bank_count)
+    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)
     {
-       int new_count = langset_bank_count + 2;
-       int i;
-       FcLangSet** tt;
-       tt = realloc(langsets, new_count * sizeof(FcLangSet *));
-       if (!tt)
-           return FcFalse;
+       FcStrList       *list = FcStrListCreate (ls->extra);
+       FcChar8         *extra;
 
-       langsets = tt;
-       for (i = langset_bank_count; i < new_count; i++)
-           langsets[i] = 0; 
-       langset_bank_count = new_count;
+       if (list)
+       {
+           while ((extra = FcStrListNext (list)))
+               FcStrSetAdd (langs, extra);
+
+           FcStrListDone (list);
+       }
     }
 
-    return FcTrue;
+    return langs;
 }
 
-void *
-FcLangSetDistributeBytes (FcCache * metadata, void * block_ptr)
+static FcLangSet *
+FcLangSetOperate(const FcLangSet       *a,
+                const FcLangSet        *b,
+                FcBool                 (*func) (FcLangSet      *ls,
+                                                const FcChar8  *s))
 {
-    int bi = FcCacheBankToIndex(metadata->bank);
-    if (!FcLangSetEnsureBank(bi))
-       return 0;
+    FcLangSet  *langset = FcLangSetCopy (a);
+    FcStrList  *sl = FcStrListCreate (FcLangSetGetLangs (b));
+    FcChar8    *str;
+
+    while ((str = FcStrListNext (sl)))
+    {
+       func (langset, str);
+    }
+    FcStrListDone (sl);
 
-    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;
+    return langset;
 }
 
 FcLangSet *
-FcLangSetSerialize(int bank, FcLangSet *l)
+FcLangSetUnion (const FcLangSet *a, const FcLangSet *b)
 {
-    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];
+    return FcLangSetOperate(a, b, FcLangSetAdd);
 }
 
-void *
-FcLangSetUnserialize (FcCache * metadata, void *block_ptr)
+FcLangSet *
+FcLangSetSubtract (const FcLangSet *a, const FcLangSet *b)
 {
-    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;
+    return FcLangSetOperate(a, b, FcLangSetDel);
 }
+
+#define __fclang__
+#include "fcaliastail.h"
+#include "fcftaliastail.h"
+#undef __fclang__