Speed up FcConfigCompareValue

Make FcConfigPromote use a switch instead of
an if-else cascade, and avoid calling it when
we can.

Note that we need to add a case for integers
in FcConfigCompareValue, since we are no longer
promoting integers to doubles unconditionally.
This commit is contained in:
Matthias Clasen 2020-08-20 23:45:19 -04:00
parent 922168afe8
commit 9d4e5d0f25
1 changed files with 247 additions and 211 deletions

View File

@ -934,36 +934,46 @@ FcConfigAddRule (FcConfig *config,
static FcValue
FcConfigPromote (FcValue v, FcValue u, FcValuePromotionBuffer *buf)
{
if (v.type == FcTypeInteger)
switch (v.type)
{
case FcTypeInteger:
v.type = FcTypeDouble;
v.u.d = (double) v.u.i;
}
else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
break;
case FcTypeVoid:
if (u.type == FcTypeMatrix)
{
v.u.m = &FcIdentityMatrix;
v.type = FcTypeMatrix;
}
else if (buf && v.type == FcTypeString && u.type == FcTypeLangSet)
{
v.u.l = FcLangSetPromote (v.u.s, buf);
v.type = FcTypeLangSet;
}
else if (buf && v.type == FcTypeVoid && u.type == FcTypeLangSet)
else if (u.type == FcTypeLangSet && buf)
{
v.u.l = FcLangSetPromote (NULL, buf);
v.type = FcTypeLangSet;
}
else if (buf && v.type == FcTypeVoid && u.type == FcTypeCharSet)
else if (u.type == FcTypeCharSet && buf)
{
v.u.c = FcCharSetPromote (buf);
v.type = FcTypeCharSet;
}
if (buf && v.type == FcTypeDouble && u.type == FcTypeRange)
break;
case FcTypeString:
if (u.type == FcTypeLangSet && buf)
{
v.u.l = FcLangSetPromote (v.u.s, buf);
v.type = FcTypeLangSet;
}
break;
case FcTypeDouble:
if (u.type == FcTypeRange && buf)
{
v.u.r = FcRangePromote (v.u.d, buf);
v.type = FcTypeRange;
}
break;
default:
break;
}
return v;
}
@ -977,17 +987,49 @@ FcConfigCompareValue (const FcValue *left_o,
FcBool ret = FcFalse;
FcOp op = FC_OP_GET_OP (op_);
int flags = FC_OP_GET_FLAGS (op_);
FcValuePromotionBuffer buf1, buf2;
if (left.type != right.type)
{
FcValuePromotionBuffer buf1, buf2;
left = FcConfigPromote (left, right, &buf1);
right = FcConfigPromote (right, left, &buf2);
if (left.type == right.type)
if (left.type != right.type)
{
if (op == FcOpNotEqual || op == FcOpNotContains)
ret = FcTrue;
return ret;
}
}
switch (left.type) {
case FcTypeUnknown:
break; /* No way to guess how to compare for this object */
case FcTypeInteger:
break; /* FcConfigPromote prevents this from happening */
switch ((int) op) {
case FcOpEqual:
case FcOpContains:
case FcOpListing:
ret = left.u.i == right.u.i;
break;
case FcOpNotEqual:
case FcOpNotContains:
ret = left.u.i != right.u.i;
break;
case FcOpLess:
ret = left.u.i < right.u.i;
break;
case FcOpLessEqual:
ret = left.u.i <= right.u.i;
break;
case FcOpMore:
ret = left.u.i > right.u.i;
break;
case FcOpMoreEqual:
ret = left.u.i >= right.u.i;
break;
default:
break;
}
break;
case FcTypeDouble:
switch ((int) op) {
case FcOpEqual:
@ -1156,12 +1198,6 @@ FcConfigCompareValue (const FcValue *left_o,
ret = FcRangeCompare (op, left.u.r, right.u.r);
break;
}
}
else
{
if (op == FcOpNotEqual || op == FcOpNotContains)
ret = FcTrue;
}
return ret;
}