]> git.wh0rd.org - fontconfig.git/blobdiff - src/fcmatch.c
Fix more gcc4 warnings:
[fontconfig.git] / src / fcmatch.c
index ace6d8c1200577b90f5f3775ce2193e6345dddee..a359a8b883b96b5d1fee4937e387b1b581290a51 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * $XFree86: xc/lib/fontconfig/src/fcmatch.c,v 1.14 2002/06/19 21:32:18 keithp Exp $
+ * $RCSId: xc/lib/fontconfig/src/fcmatch.c,v 1.20 2002/08/31 22:17:32 keithp Exp $
  *
- * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
+ * Copyright © 2000 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
 #include <stdio.h>
 
 static double
-FcCompareInteger (char *object, FcValue value1, FcValue value2)
+FcCompareNumber (const char *object, FcValue *value1, FcValue *value2)
 {
-    int        v;
+    double  v1, v2, v;
     
-    if (value2.type != FcTypeInteger || value1.type != FcTypeInteger)
+    switch (value1->type) {
+    case FcTypeInteger:
+       v1 = (double) value1->u.i;
+       break;
+    case FcTypeDouble:
+       v1 = value1->u.d;
+       break;
+    default:
        return -1.0;
-    v = value2.u.i - value1.u.i;
+    }
+    switch (value2->type) {
+    case FcTypeInteger:
+       v2 = (double) value2->u.i;
+       break;
+    case FcTypeDouble:
+       v2 = value2->u.d;
+       break;
+    default:
+       return -1.0;
+    }
+    v = v2 - v1;
     if (v < 0)
        v = -v;
     return (double) v;
 }
 
 static double
-FcCompareString (char *object, FcValue value1, FcValue value2)
+FcCompareString (const char *object, FcValue *v1, FcValue *v2)
 {
+    FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
     if (value2.type != FcTypeString || value1.type != FcTypeString)
        return -1.0;
     return (double) FcStrCmpIgnoreCase (value1.u.s, value2.u.s) != 0;
 }
 
 static double
-FcCompareBool (char *object, FcValue value1, FcValue value2)
+FcCompareFamily (const char *object, FcValue *v1, FcValue *v2)
+{
+    FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
+    if (value2.type != FcTypeString || value1.type != FcTypeString)
+       return -1.0;
+    return (double) FcStrCmpIgnoreBlanksAndCase (value1.u.s, value2.u.s) != 0;
+}
+
+static double
+FcCompareLang (const char *object, FcValue *v1, FcValue *v2)
+{
+    FcLangResult    result;
+    FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
+    
+    switch (value1.type) {
+    case FcTypeLangSet:
+       switch (value2.type) {
+       case FcTypeLangSet:
+           result = FcLangSetCompare (value1.u.l, value2.u.l);
+           break;
+       case FcTypeString:
+           result = FcLangSetHasLang (value1.u.l, 
+                                      value2.u.s);
+           break;
+       default:
+           return -1.0;
+       }
+       break;
+    case FcTypeString:
+       switch (value2.type) {
+       case FcTypeLangSet:
+           result = FcLangSetHasLang (value2.u.l, value1.u.s);
+           break;
+       case FcTypeString:
+           result = FcLangCompare (value1.u.s, 
+                                   value2.u.s);
+           break;
+       default:
+           return -1.0;
+       }
+       break;
+    default:
+       return -1.0;
+    }
+    switch (result) {
+    case FcLangEqual:
+       return 0;
+    case FcLangDifferentCountry:
+       return 1;
+    case FcLangDifferentLang:
+    default:
+       return 2;
+    }
+}
+
+static double
+FcCompareBool (const char *object, FcValue *value1, FcValue *value2)
 {
-    if (value2.type != FcTypeBool || value1.type != FcTypeBool)
+    if (value2->type != FcTypeBool || value1->type != FcTypeBool)
        return -1.0;
-    return (double) value2.u.b != value1.u.b;
+    return (double) value2->u.b != value1->u.b;
 }
 
 static double
-FcCompareCharSet (char *object, FcValue value1, FcValue value2)
+FcCompareCharSet (const char *object, FcValue *v1, FcValue *v2)
 {
+    FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
+    
     if (value2.type != FcTypeCharSet || value1.type != FcTypeCharSet)
        return -1.0;
     return (double) FcCharSetSubtractCount (value1.u.c, value2.u.c);
 }
 
 static double
-FcCompareSize (char *object, FcValue value1, FcValue value2)
+FcCompareSize (const char *object, FcValue *value1, FcValue *value2)
 {
     double  v1, v2, v;
 
-    switch (value1.type) {
+    switch (value1->type) {
     case FcTypeInteger:
-       v1 = value1.u.i;
+       v1 = value1->u.i;
        break;
     case FcTypeDouble:
-       v1 = value1.u.d;
+       v1 = value1->u.d;
        break;
     default:
        return -1;
     }
-    switch (value2.type) {
+    switch (value2->type) {
     case FcTypeInteger:
-       v2 = value2.u.i;
+       v2 = value2->u.i;
        break;
     case FcTypeDouble:
-       v2 = value2.u.d;
+       v2 = value2->u.d;
        break;
     default:
        return -1;
@@ -98,8 +175,8 @@ FcCompareSize (char *object, FcValue value1, FcValue value2)
 }
 
 typedef struct _FcMatcher {
-    char           *object;
-    double         (*compare) (char *object, FcValue value1, FcValue value2);
+    const char     *object;
+    double         (*compare) (const char *object, FcValue *value1, FcValue *value2);
     int                    strong, weak;
 } FcMatcher;
 
@@ -111,52 +188,73 @@ typedef struct _FcMatcher {
 static FcMatcher _FcMatchers [] = {
     { FC_FOUNDRY,      FcCompareString,        0, 0 },
 #define MATCH_FOUNDRY      0
+#define MATCH_FOUNDRY_INDEX 0
     
     { FC_CHARSET,      FcCompareCharSet,       1, 1 },
 #define MATCH_CHARSET      1
+#define MATCH_CHARSET_INDEX 1
     
-    { FC_FAMILY,       FcCompareString,        2, 4 },
+    { FC_FAMILY,       FcCompareFamily,        2, 4 },
 #define MATCH_FAMILY       2
+#define MATCH_FAMILY_STRONG_INDEX   2
+#define MATCH_FAMILY_WEAK_INDEX            4
     
-    { FC_LANG,         FcCompareString,        3, 3 },
+    { FC_LANG,         FcCompareLang,          3, 3 },
 #define MATCH_LANG         3
+#define MATCH_LANG_INDEX    3
     
-    { FC_SPACING,      FcCompareInteger,       5, 5 },
+    { FC_SPACING,      FcCompareNumber,        5, 5 },
 #define MATCH_SPACING      4
+#define MATCH_SPACING_INDEX 5
     
     { FC_PIXEL_SIZE,   FcCompareSize,          6, 6 },
 #define MATCH_PIXEL_SIZE    5
+#define MATCH_PIXEL_SIZE_INDEX 6
     
     { FC_STYLE,                FcCompareString,        7, 7 },
 #define MATCH_STYLE        6
+#define MATCH_STYLE_INDEX   7
     
-    { FC_SLANT,                FcCompareInteger,       8, 8 },
+    { FC_SLANT,                FcCompareNumber,        8, 8 },
 #define MATCH_SLANT        7
+#define MATCH_SLANT_INDEX   8
     
-    { FC_WEIGHT,       FcCompareInteger,       9, 9 },
+    { FC_WEIGHT,       FcCompareNumber,        9, 9 },
 #define MATCH_WEIGHT       8
+#define MATCH_WEIGHT_INDEX  9
     
-    { FC_ANTIALIAS,    FcCompareBool,          10, 10 },
-#define MATCH_ANTIALIAS            9
+    { FC_WIDTH,                FcCompareNumber,        10, 10 },
+#define MATCH_WIDTH        9
+#define MATCH_WIDTH_INDEX   10
     
-    { FC_RASTERIZER,   FcCompareString,        11, 11 },
-#define MATCH_RASTERIZER    10
+    { FC_ANTIALIAS,    FcCompareBool,          11, 11 },
+#define MATCH_ANTIALIAS            10
+#define MATCH_ANTIALIAS_INDEX      11
     
-    { FC_OUTLINE,      FcCompareBool,          12, 12 },
-#define MATCH_OUTLINE      11
+    { FC_RASTERIZER,   FcCompareString,        12, 12 },
+#define MATCH_RASTERIZER    11
+#define MATCH_RASTERIZER_INDEX    12
+
+    { FC_OUTLINE,      FcCompareBool,          13, 13 },
+#define MATCH_OUTLINE      12
+#define MATCH_OUTLINE_INDEX        13
+
+    { FC_FONTVERSION,  FcCompareNumber,        14, 14 },
+#define MATCH_FONTVERSION   13
+#define MATCH_FONTVERSION_INDEX   14
 };
 
-#define NUM_MATCH_VALUES    13
+#define NUM_MATCH_VALUES    15
 
 static FcBool
 FcCompareValueList (const char  *object,
-                   FcValueList *v1orig,        /* pattern */
-                   FcValueList *v2orig,        /* target */
+                   FcValueListPtr v1orig,      /* pattern */
+                   FcValueListPtr v2orig,      /* target */
                    FcValue     *bestValue,
                    double      *value,
                    FcResult    *result)
 {
-    FcValueList    *v1, *v2;
+    FcValueListPtr v1, v2;
     double         v, best, bestStrong, bestWeak;
     int                    i;
     int                    j;
@@ -170,7 +268,13 @@ FcCompareValueList (const char  *object,
     case 'f':
        switch (FcToLower (object[1])) {
        case 'o':
-           i = MATCH_FOUNDRY; break;
+           switch (FcToLower (object[2])) {
+           case 'u':
+               i = MATCH_FOUNDRY; break;
+           case 'n':
+               i = MATCH_FONTVERSION; break;
+           }
+           break;
        case 'a':
            i = MATCH_FAMILY; break;
        }
@@ -194,7 +298,13 @@ FcCompareValueList (const char  *object,
     case 'p':
        i = MATCH_PIXEL_SIZE; break;
     case 'w':
-       i = MATCH_WEIGHT; break;
+       switch (FcToLower (object[1])) {
+       case 'i':
+           i = MATCH_WIDTH; break;
+       case 'e':
+           i = MATCH_WEIGHT; break;
+       }
+       break;
     case 'r':
        i = MATCH_RASTERIZER; break;
     case 'o':
@@ -205,7 +315,7 @@ FcCompareValueList (const char  *object,
                            (FcChar8 *) object) != 0)
     {
        if (bestValue)
-           *bestValue = v2orig->value;
+           *bestValue = FcValueCanonicalize(&FcValueListPtrU(v2orig)->value);
        return FcTrue;
     }
 #if 0
@@ -226,13 +336,15 @@ FcCompareValueList (const char  *object,
     bestStrong = 1e99;
     bestWeak = 1e99;
     j = 0;
-    for (v1 = v1orig; v1; v1 = v1->next)
+    for (v1 = v1orig; FcValueListPtrU(v1); 
+        v1 = FcValueListPtrU(v1)->next)
     {
-       for (v2 = v2orig; v2; v2 = v2->next)
+       for (v2 = v2orig; FcValueListPtrU(v2); 
+            v2 = FcValueListPtrU(v2)->next)
        {
            v = (*_FcMatchers[i].compare) (_FcMatchers[i].object,
-                                           v1->value,
-                                           v2->value);
+                                           &FcValueListPtrU(v1)->value,
+                                           &FcValueListPtrU(v2)->value);
            if (v < 0)
            {
                *result = FcResultTypeMismatch;
@@ -244,10 +356,10 @@ FcCompareValueList (const char  *object,
            if (v < best)
            {
                if (bestValue)
-                   *bestValue = v2->value;
+                   *bestValue = FcValueCanonicalize(&FcValueListPtrU(v2)->value);
                best = v;
            }
-           if (v1->binding == FcValueBindingStrong)
+           if (FcValueListPtrU(v1)->binding == FcValueBindingStrong)
            {
                if (v < bestStrong)
                    bestStrong = v;
@@ -303,16 +415,17 @@ FcCompare (FcPattern      *pat,
     i2 = 0;
     while (i1 < pat->num && i2 < fnt->num)
     {
-       i = strcmp (pat->elts[i1].object, fnt->elts[i2].object);
+       i = FcObjectPtrCompare((FcPatternEltU(pat->elts)+i1)->object,
+                              (FcPatternEltU(fnt->elts)+i2)->object);
        if (i > 0)
            i2++;
        else if (i < 0)
            i1++;
        else
        {
-           if (!FcCompareValueList (pat->elts[i1].object,
-                                    pat->elts[i1].values,
-                                    fnt->elts[i2].values,
+           if (!FcCompareValueList (FcObjectPtrU((FcPatternEltU(pat->elts)+i1)->object),
+                                    (FcPatternEltU(pat->elts)+i1)->values,
+                                    (FcPatternEltU(fnt->elts)+i2)->values,
                                     0,
                                     value,
                                     result))
@@ -353,43 +466,30 @@ FcFontRenderPrepare (FcConfig         *config,
        return 0;
     for (i = 0; i < font->num; i++)
     {
-       fe = &font->elts[i];
-       pe = FcPatternFindElt (pat, fe->object);
+       fe = FcPatternEltU(font->elts)+i;
+       pe = FcPatternFindElt (pat, FcObjectPtrU(fe->object));
        if (pe)
        {
-           int     j;
-           double  score[NUM_MATCH_VALUES];
-
-           for (j = 0; j < NUM_MATCH_VALUES; j++)
-               score[j] = 0;
-           if (!FcCompareValueList (pe->object, pe->values, 
-                                    fe->values, &v, score, &result))
+           if (!FcCompareValueList (FcObjectPtrU(pe->object), pe->values, 
+                                    fe->values, &v, 0, &result))
            {
                FcPatternDestroy (new);
                return 0;
            }
-           for (j = 0; j < NUM_MATCH_VALUES; j++)
-               if (score[j] >= 100.0)
-               {
-                   FcValueList *pv;
-
-                   for (pv = pe->values; pv; pv = pv->next)
-                       FcPatternAdd (new, fe->object, pv->value, FcTrue);
-                   break;
-               }
        }
        else
-           v = fe->values->value;
-       FcPatternAdd (new, fe->object, v, FcFalse);
+           v = FcValueCanonicalize(&FcValueListPtrU(fe->values)->value);
+       FcPatternAdd (new, FcObjectPtrU(fe->object), v, FcFalse);
     }
     for (i = 0; i < pat->num; i++)
     {
-       pe = &pat->elts[i];
-       fe = FcPatternFindElt (font, pe->object);
+       pe = FcPatternEltU(pat->elts)+i;
+       fe = FcPatternFindElt (font, FcObjectPtrU(pe->object));
        if (!fe)
-           FcPatternAdd (new, pe->object, pe->values->value, FcTrue);
+           FcPatternAdd (new, FcObjectPtrU(pe->object), 
+                          FcValueCanonicalize(&FcValueListPtrU(pe->values)->value), FcTrue);
     }
-    FcConfigSubstitute (config, new, FcMatchFont);
+    FcConfigSubstituteWithPat (config, new, pat, FcMatchFont);
     return new;
 }
 
@@ -419,7 +519,10 @@ FcFontSetMatch (FcConfig    *config,
     {
        config = FcConfigGetCurrent ();
        if (!config)
+       {
+           *result = FcResultOutOfMemory;
            return 0;
+       }
     }
     for (set = 0; set < nsets; set++)
     {
@@ -545,6 +648,11 @@ FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **cs, FcBool tri
                    ncs = FcCharSetCopy (ncs);
                *cs = ncs;
                FcPatternReference (node->pattern);
+               if (FcDebug () & FC_DBG_MATCH)
+               {
+                   printf ("Add ");
+                   FcPatternPrint (node->pattern);
+               }
                if (!FcFontSetAdd (fs, node->pattern))
                {
                    FcPatternDestroy (node->pattern);
@@ -581,7 +689,15 @@ FcFontSetSort (FcConfig        *config,
     int                    set;
     int                    f;
     int                    i;
+    int                    nPatternLang;
+    FcBool         *patternLangSat;
+    FcValue        patternLang;
 
+    if (FcDebug () & FC_DBG_MATCH)
+    {
+       printf ("Sort ");
+       FcPatternPrint (p);
+    }
     nnodes = 0;
     for (set = 0; set < nsets; set++)
     {
@@ -592,10 +708,20 @@ FcFontSetSort (FcConfig       *config,
     }
     if (!nnodes)
        goto bail0;
-    nodes = malloc (nnodes * sizeof (FcSortNode) + nnodes * sizeof (FcSortNode *));
+    
+    for (nPatternLang = 0;
+        FcPatternGet (p, FC_LANG, nPatternLang, &patternLang) == FcResultMatch;
+        nPatternLang++)
+       ;
+       
+    /* freed below */
+    nodes = malloc (nnodes * sizeof (FcSortNode) + 
+                   nnodes * sizeof (FcSortNode *) +
+                   nPatternLang * sizeof (FcBool));
     if (!nodes)
        goto bail0;
     nodeps = (FcSortNode **) (nodes + nnodes);
+    patternLangSat = (FcBool *) (nodeps + nnodes);
     
     new = nodes;
     nodep = nodeps;
@@ -633,6 +759,56 @@ FcFontSetSort (FcConfig        *config,
     
     qsort (nodeps, nnodes, sizeof (FcSortNode *),
           FcSortCompare);
+    
+    for (i = 0; i < nPatternLang; i++)
+       patternLangSat[i] = FcFalse;
+    
+    for (f = 0; f < nnodes; f++)
+    {
+       FcBool  satisfies = FcFalse;
+       /*
+        * If this node matches any language, go check
+        * which ones and satisfy those entries
+        */
+       if (nodeps[f]->score[MATCH_LANG_INDEX] < nPatternLang)
+       {
+           for (i = 0; i < nPatternLang; i++)
+           {
+               FcValue     nodeLang;
+               
+               if (!patternLangSat[i] &&
+                   FcPatternGet (p, FC_LANG, i, &patternLang) == FcResultMatch &&
+                   FcPatternGet (nodeps[f]->pattern, FC_LANG, 0, &nodeLang) == FcResultMatch)
+               {
+                   double  compare = FcCompareLang (FC_LANG, &patternLang, 
+                                                    &nodeLang);
+                   if (compare >= 0 && compare < 2)
+                   {
+                       if (FcDebug () & FC_DBG_MATCHV)
+                       {
+                           FcChar8 *family;
+                           FcChar8 *style;
+
+                           if (FcPatternGetString (nodeps[f]->pattern, FC_FAMILY, 0, &family) == FcResultMatch &&
+                               FcPatternGetString (nodeps[f]->pattern, FC_STYLE, 0, &style) == FcResultMatch)
+                               printf ("Font %s:%s matches language %d\n", family, style, i);
+                       }
+                       patternLangSat[i] = FcTrue;
+                       satisfies = FcTrue;
+                       break;
+                   }
+               }
+           }
+       }
+       if (!satisfies)
+           nodeps[f]->score[MATCH_LANG_INDEX] = 1000.0;
+    }
+
+    /*
+     * Re-sort once the language issues have been settled
+     */
+    qsort (nodeps, nnodes, sizeof (FcSortNode *),
+          FcSortCompare);
 
     ret = FcFontSetCreate ();
     if (!ret)