]> git.wh0rd.org - fontconfig.git/blobdiff - src/fclang.c
Revert "Fix FcNameUnparseLangSet()" and redo it
[fontconfig.git] / src / fclang.c
index 1fa4dd66bf87b1a2c0a4df0a5bfafc8b650182c9..ab7ae5381b6d020da2305594d3dd543e491088b4 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * $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
+ * 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
@@ -13,9 +13,9 @@
  * 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 {
-    FcChar8    *lang;
-    FcCharSet  charset;
+    const FcChar8      lang[8];
+    const FcCharSet    charset;
 } FcLangCharSet;
 
 typedef struct {
@@ -41,36 +42,53 @@ struct _FcLangSet {
     FcStrSet   *extra;
 };
 
-#define FcLangSetBitSet(ls, id)        ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
-#define FcLangSetBitGet(ls, id) (((ls)->map[(id)>>5] >> ((id) & 0x1f)) & 1)
+#define FcLangSetBitSet(ls, id)        ((ls)->map[(fcLangCharSetIndices[id])>>5] |= ((FcChar32) 1 << ((fcLangCharSetIndices[id]) & 0x1f)))
+#define FcLangSetBitGet(ls, id) (((ls)->map[(fcLangCharSetIndices[id])>>5] >> ((fcLangCharSetIndices[id]) & 0x1f)) & 1)
 
 FcLangSet *
 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)
@@ -83,7 +101,7 @@ FcFreeTypeLangSet (const FcCharSet  *charset,
                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 +120,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);
@@ -133,40 +151,44 @@ 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 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)
@@ -175,16 +197,17 @@ FcLangContains (const FcChar8 *s1, const FcChar8 *s2)
 }
 
 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;
        default:
@@ -193,7 +216,23 @@ FcCharSetForLang (const FcChar8 *lang)
     }
     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 *
@@ -259,9 +298,10 @@ bail0:
 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')
     {
@@ -290,22 +330,14 @@ FcLangSetIndex (const FcChar8 *lang)
        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 */
+           cmp = fcLangCharSets[mid].lang[1] - secondChar;
+           if (cmp == 0 && 
+               (fcLangCharSets[mid].lang[2] != '\0' || 
+                lang[2] != '\0'))
            {
-               high = mid - 1;
-               continue;
+               cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang+2, 
+                                        lang+2);
            }
-           else if (fcLangCharSets[mid].lang[1] < secondChar)
-           {
-               low = mid + 1;
-               continue;
-           }
-           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;
@@ -372,7 +404,6 @@ FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang)
     {
        FcStrList       *list = FcStrListCreate (ls->extra);
        FcChar8         *extra;
-       FcLangResult    r;
        
        if (list)
        {
@@ -423,7 +454,7 @@ FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
            if ((lsa->map[i] & fcLangCountrySets[j][i]) &&
                (lsb->map[i] & fcLangCountrySets[j][i]))
            {
-               best = FcLangDifferentCountry;
+               best = FcLangDifferentTerritory;
                break;
            }
     if (lsa->extra)
@@ -535,7 +566,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;
                }
@@ -552,11 +583,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;
 }
@@ -582,7 +620,6 @@ static FcBool
 FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang)
 {
     int                    id;
-    FcLangResult    r;
     int                    i;
 
     id = FcLangSetIndex (lang);
@@ -613,7 +650,6 @@ FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang)
     {
        FcStrList       *list = FcStrListCreate (ls->extra);
        FcChar8         *extra;
-       FcLangResult    r;
        
        if (list)
        {
@@ -657,10 +693,10 @@ FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
                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;
                    }
                }
@@ -689,3 +725,58 @@ 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;
+    *l_serialize = *l;
+    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;
+}
+
+#define __fclang__
+#include "fcaliastail.h"
+#include "fcftaliastail.h"
+#undef __fclang__