Bug 72380 - Never drop first font when trimming
[platform/upstream/fontconfig.git] / src / fcmatch.c
index 23f985a..93e013f 100644 (file)
@@ -77,6 +77,24 @@ FcCompareFamily (FcValue *v1, FcValue *v2)
 }
 
 static double
+FcComparePostScript (FcValue *v1, FcValue *v2)
+{
+    const FcChar8 *v1_string = FcValueString (v1);
+    const FcChar8 *v2_string = FcValueString (v2);
+    int n;
+    size_t len;
+
+    if (FcToLower (*v1_string) != FcToLower (*v2_string) &&
+       *v1_string != ' ' && *v2_string != ' ')
+       return 1.0;
+
+    n = FcStrMatchIgnoreCaseAndDelims (v1_string, v2_string, (const FcChar8 *)" -");
+    len = strlen ((const char *)v1_string);
+
+    return (double)(len - n) / (double)len;
+}
+
+static double
 FcCompareLang (FcValue *v1, FcValue *v2)
 {
     FcLangResult    result;
@@ -173,17 +191,26 @@ FcCompareSize (FcValue *value1, FcValue *value2)
 static double
 FcCompareFilename (FcValue *v1, FcValue *v2)
 {
-       const FcChar8 *s1 = FcValueString (v1), *s2 = FcValueString (v2);
-       if (FcStrCmp (s1, s2) == 0)
-           return 0.0;
-       else if (FcStrCmpIgnoreCase (s1, s2) == 0)
-           return 1.0;
-       else if (FcStrRegexCmp (s2, s1))
-           return 2.0;
-       else if (FcStrRegexCmpIgnoreCase (s2, s1))
-           return 3.0;
-       else
-           return 4.0;
+    const FcChar8 *s1 = FcValueString (v1), *s2 = FcValueString (v2);
+    if (FcStrCmp (s1, s2) == 0)
+       return 0.0;
+    else if (FcStrCmpIgnoreCase (s1, s2) == 0)
+       return 1.0;
+    else if (FcStrGlobMatch (s1, s2))
+       return 2.0;
+    else
+       return 3.0;
+}
+
+static double
+FcCompareHash (FcValue *v1, FcValue *v2)
+{
+    const FcChar8 *s1 = FcValueString (v1), *s2 = FcValueString (v2);
+
+    /* Do not match an empty string */
+    if (!s1 || !s2 || !s1[0] || !s2[0])
+       return 1.0;
+    return FcCompareString (v1, v2);
 }
 
 #define PRI_NULL(n)                            \
@@ -198,6 +225,8 @@ FcCompareFilename (FcValue *v1, FcValue *v2)
 #define PRI_FcCompareFilename(n)       PRI1(n)
 #define PRI_FcCompareCharSet(n)                PRI1(n)
 #define PRI_FcCompareLang(n)           PRI1(n)
+#define PRI_FcComparePostScript(n)     PRI1(n)
+#define PRI_FcCompareHash(n)           PRI1(n)
 
 #define FC_OBJECT(NAME, Type, Cmp)     PRI_##Cmp(NAME)
 
@@ -208,19 +237,23 @@ typedef enum _FcMatcherPriorityDummy {
 #undef FC_OBJECT
 
 #undef PRI1
-#define PRI1(n)                        \
-    PRI_ ## n ## _STRONG,      \
-    PRI_ ## n ## _WEAK
+#define PRI1(n)                                        \
+    PRI_ ## n,                                 \
+    PRI_ ## n ## _STRONG = PRI_ ## n,          \
+    PRI_ ## n ## _WEAK = PRI_ ## n
 
 typedef enum _FcMatcherPriority {
     PRI1(HASH),
     PRI1(FILE),
+    PRI1(FONTFORMAT),
+    PRI1(SCALABLE),
     PRI1(FOUNDRY),
     PRI1(CHARSET),
     PRI_FAMILY_STRONG,
-    PRI_LANG_STRONG,
-    PRI_LANG_WEAK,
+    PRI_POSTSCRIPT_NAME_STRONG,
+    PRI1(LANG),
     PRI_FAMILY_WEAK,
+    PRI_POSTSCRIPT_NAME_WEAK,
     PRI1(SPACING),
     PRI1(PIXEL_SIZE),
     PRI1(STYLE),
@@ -519,20 +552,25 @@ FcFontRenderPrepare (FcConfig         *config,
 
                continue;
            }
+           FcPatternObjectAdd (new, fe->object, v, FcFalse);
        }
        else
        {
            if (fel)
                goto copy_lang;
-           v = FcValueCanonicalize(&FcPatternEltValues (fe)->value);
+           FcPatternObjectListAdd (new, fe->object,
+                                   FcValueListDuplicate (FcPatternEltValues (fe)),
+                                   FcTrue);
        }
-       FcPatternObjectAdd (new, fe->object, v, FcFalse);
     }
     for (i = 0; i < pat->num; i++)
     {
        pe = &FcPatternElts(pat)[i];
        fe = FcPatternObjectFindElt (font, pe->object);
-       if (!fe)
+       if (!fe &&
+           pe->object != FC_FAMILYLANG_OBJECT &&
+           pe->object != FC_STYLELANG_OBJECT &&
+           pe->object != FC_FULLNAMELANG_OBJECT)
        {
            FcPatternObjectListAdd (new, pe->object,
                                    FcValueListDuplicate (FcPatternEltValues(pe)),
@@ -705,6 +743,7 @@ FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **csp, FcBool tr
 {
     FcBool ret = FcFalse;
     FcCharSet *cs;
+    int i;
 
     cs = 0;
     if (trim || csp)
@@ -714,7 +753,7 @@ FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **csp, FcBool tr
            goto bail;
     }
 
-    while (nnode--)
+    for (i = 0; i < nnode; i++)
     {
        FcSortNode      *node = *n++;
        FcBool          adds_chars = FcFalse;
@@ -738,7 +777,7 @@ FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **csp, FcBool tr
         * If this font isn't a subset of the previous fonts,
         * add it to the list
         */
-       if (!trim || adds_chars)
+       if (!i || !trim || adds_chars)
        {
            FcPatternReference (node->pattern);
            if (FcDebug () & FC_DBG_MATCHV)
@@ -886,8 +925,7 @@ FcFontSetSort (FcConfig         *config FC_UNUSED,
         * If this node matches any language, go check
         * which ones and satisfy those entries
         */
-       if (nodeps[f]->score[PRI_LANG_STRONG] < 2000 ||
-           nodeps[f]->score[PRI_LANG_WEAK] < 2000)
+       if (nodeps[f]->score[PRI_LANG] < 2000)
        {
            for (i = 0; i < nPatternLang; i++)
            {
@@ -911,13 +949,6 @@ FcFontSetSort (FcConfig        *config FC_UNUSED,
                        }
                        patternLangSat[i] = FcTrue;
                        satisfies = FcTrue;
-                       /* adjust score to ensure it's not more than 10000.0
-                        * which would means the lang didn't satisfy the requirements
-                        */
-                       if (nodeps[f]->score[PRI_LANG_STRONG] > 10000.0)
-                           nodeps[f]->score[PRI_LANG_STRONG] = 10000.0;
-                       if (nodeps[f]->score[PRI_LANG_WEAK] > 10000.0)
-                           nodeps[f]->score[PRI_LANG_WEAK] = 10000.0;
                        break;
                    }
                }
@@ -925,8 +956,7 @@ FcFontSetSort (FcConfig         *config FC_UNUSED,
        }
        if (!satisfies)
        {
-           nodeps[f]->score[PRI_LANG_STRONG] = 10000.0;
-           nodeps[f]->score[PRI_LANG_WEAK] = 10000.0;
+           nodeps[f]->score[PRI_LANG] = 10000.0;
        }
     }