]> git.wh0rd.org - fontconfig.git/blobdiff - src/fcmatch.c
Revert to original FcFontSetMatch algorithm to avoid losing fonts.
[fontconfig.git] / src / fcmatch.c
index 0af0c8367d68dd50f56a560d8f486e0940ea50cc..739ef3e28d4b8e6593d905d7d33c2be917a75ebd 100644 (file)
@@ -22,9 +22,9 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include "fcint.h"
 #include <string.h>
 #include <ctype.h>
-#include "fcint.h"
 #include <stdio.h>
 
 static double
@@ -495,9 +495,6 @@ FcFontRenderPrepare (FcConfig           *config,
                           FcValueCanonicalize(&FcValueListPtrU(pe->values)->value), FcTrue);
     }
 
-    if (FcPatternFindElt (font, FC_FILE))
-       FcPatternTransferFullFname (new, font);
-
     FcConfigSubstituteWithPat (config, new, pat, FcMatchFont);
     return new;
 }
@@ -509,14 +506,15 @@ FcFontSetMatch (FcConfig    *config,
                FcPattern   *p,
                FcResult    *result)
 {
-    double         score;
-    double         bestscore;
+    double         score[NUM_MATCH_VALUES], bestscore[NUM_MATCH_VALUES];
     int                    f;
     FcFontSet      *s;
     FcPattern      *best;
-    int                    scoring_index;
+    int                    i;
     int                    set;
 
+    for (i = 0; i < NUM_MATCH_VALUES; i++)
+       bestscore[i] = 0;
     best = 0;
     if (FcDebug () & FC_DBG_MATCH)
     {
@@ -527,141 +525,51 @@ FcFontSetMatch (FcConfig    *config,
     {
        config = FcConfigGetCurrent ();
        if (!config)
-       {
-           *result = FcResultOutOfMemory;
            return 0;
-       }
     }
     for (set = 0; set < nsets; set++)
     {
        s = sets[set];
        if (!s)
            continue;
-
-        char* matchBlocked = (char*)calloc(s->nfont, sizeof(FcBool));
-
-       /* The old algorithm checked if each font beat 'best', 
-        * scanning all of the value lists for all of the pattern elts. */
-       /* This algorithm checks each font on a element-by-element basis
-        * and blocks fonts that have already lost on some element from
-        * further consideration from being best.  Basically, we've
-        * swapped the order of loops and short-circuited fonts that
-        * are out of contention right away.
-        * This saves a lot of time! */
-        for (scoring_index = 0; scoring_index < NUM_MATCH_VALUES; 
-            scoring_index++)
-        {
-            int            pat_elt;
-            FcPatternElt    *pat_elts = FcPatternEltU(p->elts);
-           FcMatcher       *match = 0;
-           FcValueListPtr  v1;
-            FcValueList     *v1_ptrU;
-            int            v1_offset = 0;
-
-
-            for (pat_elt = 0; pat_elt < p->num; pat_elt++) 
-            {
-                match = FcObjectPtrToMatcher
-                   ((FcPatternEltU(p->elts)+pat_elt)->object);
-
-               if (match && 
-                    (match->strong == scoring_index ||
-                    match->weak == scoring_index))
-                   break;
-               else
-                   match = 0;
+       for (f = 0; f < s->nfont; f++)
+       {
+           if (FcDebug () & FC_DBG_MATCHV)
+           {
+               printf ("Font %d ", f);
+               FcPatternPrint (s->fonts[f]);
            }
-
-           if (!match)
-               continue;
-
-            bestscore = 1e99;
-
-            
-            for (v1 = pat_elts[pat_elt].values, v1_ptrU = FcValueListPtrU(v1); 
-                v1_ptrU;
-                 v1 = FcValueListPtrU(v1)->next, 
-                    v1_ptrU = FcValueListPtrU(v1), v1_offset++)
-            {
-
-               if (v1_ptrU->binding == FcValueBindingWeak
-                    && scoring_index != match->weak)
-                   continue;
-
-               for (f = 0; f < s->nfont; f++)
-               {
-                   int                 cand_elt;
-                   FcPatternElt        *cand_elts;
-
-                   if (matchBlocked[f])
-                       continue;
-
-                   score = 0.0;
-                   cand_elts = FcPatternEltU(s->fonts[f]->elts);
-                   
-                   /* Look for the appropriate element in this candidate
-                    * pattern 'f' and evaluate its score wrt 'p'. */
-                   for (cand_elt = 0; cand_elt < s->fonts[f]->num; cand_elt++)
-                   {
-                       if (cand_elts[cand_elt].object == 
-                               pat_elts[pat_elt].object)
-                        {
-                           FcValueListPtr  v2;
-                           FcValueList     *v2_ptrU;
-                           double          v2_best_score = 1e99;
-
-                           for (v2 = cand_elts[cand_elt].values, 
-                                    v2_ptrU = FcValueListPtrU(v2);
-                                FcValueListPtrU(v2);
-                                v2 = FcValueListPtrU(v2)->next)
-                           {
-                               double v = (match->compare) 
-                                   (&v1_ptrU->value, &v2_ptrU->value);
-
-                               if (v < 0)
-                               {
-                                   *result = FcResultTypeMismatch;
-                                   return 0;
-                               }
-                               /* I'm actually kind of surprised that
-                                * this isn't v + 100 * v1_offset. -PL */
-                               v = v * 100 + v1_offset;
-                               if (v < v2_best_score)
-                                   v2_best_score = v;
-                           }
-                           score += v2_best_score;
-                       }
-                   }
-
-                   /* If there's a previous champion, and current score
-                    * beats previous best score, on this element, then
-                    * knock out the previous champion and anything
-                    * else that we would have visited previous to f;
-                    * clearly anything previous to f would have been
-                    * less than f on this score. */
-                   if (!best || score < bestscore)
-                   {
-                       if (best) 
-                       {
-                           int b;
-                           for (b = 0; b < f; ++b)
-                               matchBlocked[b] = FcTrue;
-                       }
-
-                       bestscore = score;
-                       best = s->fonts[f];
-                   }
-
-                   /* If f loses, then it's out too. */
-                   if (best && score > bestscore)
-                       matchBlocked[f] = FcTrue;
-
-                   /* Otherwise, f is equal to best on this element.
-                    * Carry on to next pattern element. */
+           if (!FcCompare (p, s->fonts[f], score, result))
+               return 0;
+           if (FcDebug () & FC_DBG_MATCHV)
+           {
+               printf ("Score");
+               for (i = 0; i < NUM_MATCH_VALUES; i++)
+               {
+                   printf (" %g", score[i]);
                }
-           }
-        }
-       free (matchBlocked);
+               printf ("\n");
+           }
+           for (i = 0; i < NUM_MATCH_VALUES; i++)
+           {
+               if (best && bestscore[i] < score[i])
+                   break;
+               if (!best || score[i] < bestscore[i])
+               {
+                   for (i = 0; i < NUM_MATCH_VALUES; i++)
+                       bestscore[i] = score[i];
+                   best = s->fonts[f];
+                   break;
+               }
+           }
+       }
+    }
+    if (FcDebug () & FC_DBG_MATCH)
+    {
+       printf ("Best score");
+       for (i = 0; i < NUM_MATCH_VALUES; i++)
+           printf (" %g", bestscore[i]);
+       FcPatternPrint (best);
     }
     if (!best)
     {
@@ -715,7 +623,7 @@ FcSortCompare (const void *aa, const void *ab)
 }
 
 static FcBool
-FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **cs, FcBool trim)
+FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **cs, FcBool trim, FcBool build_cs)
 {
     FcCharSet  *ncs;
     FcSortNode *node;
@@ -732,16 +640,20 @@ FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **cs, FcBool tri
             */
            if (!trim || !*cs || !FcCharSetIsSubset (ncs, *cs))
            {
-               if (*cs)
-               {
-                   ncs = FcCharSetUnion (ncs, *cs);
-                   if (!ncs)
-                       return FcFalse;
-                   FcCharSetDestroy (*cs);
-               }
-               else
-                   ncs = FcCharSetCopy (ncs);
-               *cs = ncs;
+                if (trim || build_cs)
+                {
+                    if (*cs)
+                    {
+                        ncs = FcCharSetUnion (ncs, *cs);
+                        if (!ncs)
+                            return FcFalse;
+                        FcCharSetDestroy (*cs);
+                    }
+                    else
+                        ncs = FcCharSetCopy (ncs);
+                    *cs = ncs;
+                }
+
                FcPatternReference (node->pattern);
                if (FcDebug () & FC_DBG_MATCH)
                {
@@ -910,13 +822,16 @@ FcFontSetSort (FcConfig       *config,
 
     cs = 0;
 
-    if (!FcSortWalk (nodeps, nnodes, ret, &cs, trim))
+    if (!FcSortWalk (nodeps, nnodes, ret, &cs, trim, (csp!=0)))
        goto bail2;
 
     if (csp)
        *csp = cs;
     else
-       FcCharSetDestroy (cs);
+    {
+        if (cs)
+            FcCharSetDestroy (cs);
+    }
 
     free (nodes);