Speed up FcConfigCompareValue

Avoid FcValueCanonicalize when we can, to avoid
unnecessary copying of FcValue structs.
diff --git a/src/fccfg.c b/src/fccfg.c
index 8e7a682..803cd68 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -982,192 +982,215 @@
 		      unsigned int      op_,
 		      const FcValue	*right_o)
 {
-    FcValue     left = FcValueCanonicalize(left_o);
-    FcValue     right = FcValueCanonicalize(right_o);
+    FcValue     left;
+    FcValue     right;
     FcBool	ret = FcFalse;
     FcOp	op = FC_OP_GET_OP (op_);
     int		flags = FC_OP_GET_FLAGS (op_);
 
-    if (left.type != right.type)
+    if (left_o->type != right_o->type)
     {
+        left = FcValueCanonicalize(left_o);
+        right = FcValueCanonicalize(right_o);
         FcValuePromotionBuffer buf1, buf2;
         left = FcConfigPromote (left, right, &buf1);
         right = FcConfigPromote (right, left, &buf2);
-        if (left.type != right.type)
+        left_o = &left;
+        right_o = &right;
+        if (left_o->type != right_o->type)
         {
 	    if (op == FcOpNotEqual || op == FcOpNotContains)
 	        ret = FcTrue;
             return ret;
         }
     }
-    switch (left.type) {
+    switch (left_o->type) {
     case FcTypeUnknown:
         break;	/* No way to guess how to compare for this object */
-    case FcTypeInteger:
+    case FcTypeInteger: {
+        int l = left_o->u.i;
+        int r = right_o->u.i;
         switch ((int) op) {
         case FcOpEqual:
         case FcOpContains:
         case FcOpListing:
-            ret = left.u.i == right.u.i;
+            ret = l == r;
             break;
         case FcOpNotEqual:
         case FcOpNotContains:
-            ret = left.u.i != right.u.i;
+            ret = l != r;
             break;
         case FcOpLess:
-            ret = left.u.i < right.u.i;
+            ret = l < r;
             break;
         case FcOpLessEqual:
-            ret = left.u.i <= right.u.i;
+            ret = l <= r;
             break;
         case FcOpMore:
-            ret = left.u.i > right.u.i;
+            ret = l > r;
             break;
         case FcOpMoreEqual:
-            ret = left.u.i >= right.u.i;
+            ret = l >= r;
             break;
         default:
             break;
         }
         break;
-    case FcTypeDouble:
+    }
+    case FcTypeDouble: {
+        double l = left_o->u.d;
+        double r = right_o->u.d;
         switch ((int) op) {
         case FcOpEqual:
         case FcOpContains:
         case FcOpListing:
-            ret = left.u.d == right.u.d;
+            ret = l == r;
             break;
         case FcOpNotEqual:
         case FcOpNotContains:
-            ret = left.u.d != right.u.d;
+            ret = l != r;
             break;
         case FcOpLess:
-            ret = left.u.d < right.u.d;
+            ret = l < r;
             break;
         case FcOpLessEqual:
-            ret = left.u.d <= right.u.d;
+            ret = l <= r;
             break;
         case FcOpMore:
-            ret = left.u.d > right.u.d;
+            ret = l > r;
             break;
         case FcOpMoreEqual:
-            ret = left.u.d >= right.u.d;
+            ret = l >= r;
             break;
         default:
             break;
         }
         break;
-    case FcTypeBool:
+    }
+    case FcTypeBool: {
+        FcBool l = left_o->u.b;
+        FcBool r = right_o->u.b;
         switch ((int) op) {
         case FcOpEqual:
-            ret = left.u.b == right.u.b;
+            ret = l == r;
             break;
         case FcOpContains:
         case FcOpListing:
-            ret = left.u.b == right.u.b || left.u.b >= FcDontCare;
+            ret = l == r || l >= FcDontCare;
             break;
         case FcOpNotEqual:
-            ret = left.u.b != right.u.b;
+            ret = l != r;
             break;
         case FcOpNotContains:
-            ret = !(left.u.b == right.u.b || left.u.b >= FcDontCare);
+            ret = !(l == r || l >= FcDontCare);
             break;
         case FcOpLess:
-            ret = left.u.b != right.u.b && right.u.b >= FcDontCare;
+            ret = l != r && r >= FcDontCare;
             break;
         case FcOpLessEqual:
-            ret = left.u.b == right.u.b || right.u.b >= FcDontCare;
+            ret = l == r || r >= FcDontCare;
             break;
         case FcOpMore:
-            ret = left.u.b != right.u.b && left.u.b >= FcDontCare;
+            ret = l != r && l >= FcDontCare;
             break;
         case FcOpMoreEqual:
-            ret = left.u.b == right.u.b || left.u.b >= FcDontCare;
+            ret = l == r || l >= FcDontCare;
             break;
         default:
             break;
         }
         break;
-    case FcTypeString:
+    }
+    case FcTypeString: {
+        const FcChar8 *l = FcValueString (left_o);
+        const FcChar8 *r = FcValueString (right_o);
         switch ((int) op) {
         case FcOpEqual:
         case FcOpListing:
             if (flags & FcOpFlagIgnoreBlanks)
-                ret = FcStrCmpIgnoreBlanksAndCase (left.u.s, right.u.s) == 0;
+                ret = FcStrCmpIgnoreBlanksAndCase (l, r) == 0;
             else
-                ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
+                ret = FcStrCmpIgnoreCase (l, r) == 0;
             break;
         case FcOpContains:
-            ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0;
+            ret = FcStrStrIgnoreCase (l, r) != 0;
             break;
         case FcOpNotEqual:
             if (flags & FcOpFlagIgnoreBlanks)
-                ret = FcStrCmpIgnoreBlanksAndCase (left.u.s, right.u.s) != 0;
+                ret = FcStrCmpIgnoreBlanksAndCase (l, r) != 0;
             else
-                ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
+                ret = FcStrCmpIgnoreCase (l, r) != 0;
             break;
         case FcOpNotContains:
-            ret = FcStrStrIgnoreCase (left.u.s, right.u.s) == 0;
+            ret = FcStrStrIgnoreCase (l, r) == 0;
             break;
         default:
             break;
         }
         break;
-    case FcTypeMatrix:
+    }
+    case FcTypeMatrix: {
         switch ((int) op) {
         case FcOpEqual:
         case FcOpContains:
         case FcOpListing:
-            ret = FcMatrixEqual (left.u.m, right.u.m);
+            ret = FcMatrixEqual (left_o->u.m, right_o->u.m);
             break;
         case FcOpNotEqual:
         case FcOpNotContains:
-            ret = !FcMatrixEqual (left.u.m, right.u.m);
+            ret = !FcMatrixEqual (left_o->u.m, right_o->u.m);
             break;
         default:
             break;
         }
         break;
-    case FcTypeCharSet:
+    }
+    case FcTypeCharSet: {
+        const FcCharSet *l = FcValueCharSet (left_o);
+        const FcCharSet *r = FcValueCharSet (right_o);
         switch ((int) op) {
         case FcOpContains:
         case FcOpListing:
             /* left contains right if right is a subset of left */
-            ret = FcCharSetIsSubset (right.u.c, left.u.c);
+            ret = FcCharSetIsSubset (r, l);
             break;
         case FcOpNotContains:
             /* left contains right if right is a subset of left */
-            ret = !FcCharSetIsSubset (right.u.c, left.u.c);
+            ret = !FcCharSetIsSubset (r, l);
             break;
         case FcOpEqual:
-            ret = FcCharSetEqual (left.u.c, right.u.c);
+            ret = FcCharSetEqual (l, r);
             break;
         case FcOpNotEqual:
-            ret = !FcCharSetEqual (left.u.c, right.u.c);
+            ret = !FcCharSetEqual (l, r);
             break;
         default:
             break;
         }
         break;
-    case FcTypeLangSet:
+    }
+    case FcTypeLangSet: {
+        const FcLangSet *l = FcValueLangSet (left_o);
+        const FcLangSet *r = FcValueLangSet (right_o);
         switch ((int) op) {
         case FcOpContains:
         case FcOpListing:
-            ret = FcLangSetContains (left.u.l, right.u.l);
+            ret = FcLangSetContains (l, r);
             break;
         case FcOpNotContains:
-            ret = !FcLangSetContains (left.u.l, right.u.l);
+            ret = !FcLangSetContains (l, r);
             break;
         case FcOpEqual:
-            ret = FcLangSetEqual (left.u.l, right.u.l);
+            ret = FcLangSetEqual (l, r);
             break;
         case FcOpNotEqual:
-            ret = !FcLangSetEqual (left.u.l, right.u.l);
+            ret = !FcLangSetEqual (l, r);
             break;
         default:
             break;
         }
         break;
+    }
     case FcTypeVoid:
         switch ((int) op) {
         case FcOpEqual:
@@ -1184,20 +1207,23 @@
         case FcOpEqual:
         case FcOpContains:
         case FcOpListing:
-            ret = left.u.f == right.u.f;
+            ret = left_o->u.f == right_o->u.f;
             break;
         case FcOpNotEqual:
         case FcOpNotContains:
-            ret = left.u.f != right.u.f;
+            ret = left_o->u.f != right_o->u.f;
             break;
         default:
             break;
         }
         break;
-    case FcTypeRange:
-        ret = FcRangeCompare (op, left.u.r, right.u.r);
+    case FcTypeRange: {
+        const FcRange *l = FcValueRange (left_o);
+        const FcRange *r = FcValueRange (right_o);
+        ret = FcRangeCompare (op, l, r);
         break;
     }
+    }
     return ret;
 }