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