summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-08-20 23:45:19 -0400
committerMatthias Clasen <mclasen@redhat.com>2020-08-25 12:15:18 -0400
commit9d4e5d0f25dd592316d1728f95f40fe5967b120c (patch)
tree1cfc1ed50cbd605fcf1b9d53a728428169b23f33 /src
parent922168afe8bf48e872dc0a808fadefaa798a42ce (diff)
downloadfontconfig-9d4e5d0f25dd592316d1728f95f40fe5967b120c.tar.gz
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.
Diffstat (limited to 'src')
-rw-r--r--src/fccfg.c464
1 files changed, 250 insertions, 214 deletions
diff --git a/src/fccfg.c b/src/fccfg.c
index cb4d3e0..8e7a682 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -934,35 +934,45 @@ FcConfigAddRule (FcConfig *config,
static FcValue
FcConfigPromote (FcValue v, FcValue u, FcValuePromotionBuffer *buf)
{
- if (v.type == FcTypeInteger)
- {
- v.type = FcTypeDouble;
- v.u.d = (double) v.u.i;
- }
- else if (v.type == FcTypeVoid && 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)
- {
- v.u.l = FcLangSetPromote (NULL, buf);
- v.type = FcTypeLangSet;
- }
- else if (buf && v.type == FcTypeVoid && u.type == FcTypeCharSet)
- {
- v.u.c = FcCharSetPromote (buf);
- v.type = FcTypeCharSet;
- }
- if (buf && v.type == FcTypeDouble && u.type == FcTypeRange)
- {
- v.u.r = FcRangePromote (v.u.d, buf);
- v.type = FcTypeRange;
+ switch (v.type)
+ {
+ case FcTypeInteger:
+ v.type = FcTypeDouble;
+ v.u.d = (double) v.u.i;
+ break;
+ case FcTypeVoid:
+ if (u.type == FcTypeMatrix)
+ {
+ v.u.m = &FcIdentityMatrix;
+ v.type = FcTypeMatrix;
+ }
+ else if (u.type == FcTypeLangSet && buf)
+ {
+ v.u.l = FcLangSetPromote (NULL, buf);
+ v.type = FcTypeLangSet;
+ }
+ else if (u.type == FcTypeCharSet && buf)
+ {
+ v.u.c = FcCharSetPromote (buf);
+ v.type = FcTypeCharSet;
+ }
+ 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;
}
@@ -972,195 +982,221 @@ FcConfigCompareValue (const FcValue *left_o,
unsigned int op_,
const FcValue *right_o)
{
- FcValue left = FcValueCanonicalize(left_o);
- FcValue right = FcValueCanonicalize(right_o);
+ FcValue left = FcValueCanonicalize(left_o);
+ FcValue right = FcValueCanonicalize(right_o);
FcBool ret = FcFalse;
FcOp op = FC_OP_GET_OP (op_);
int flags = FC_OP_GET_FLAGS (op_);
- FcValuePromotionBuffer buf1, buf2;
- left = FcConfigPromote (left, right, &buf1);
- right = FcConfigPromote (right, left, &buf2);
- if (left.type == right.type)
- {
- switch (left.type) {
- case FcTypeUnknown:
- break; /* No way to guess how to compare for this object */
- case FcTypeInteger:
- break; /* FcConfigPromote prevents this from happening */
- case FcTypeDouble:
- switch ((int) op) {
- case FcOpEqual:
- case FcOpContains:
- case FcOpListing:
- ret = left.u.d == right.u.d;
- break;
- case FcOpNotEqual:
- case FcOpNotContains:
- ret = left.u.d != right.u.d;
- break;
- case FcOpLess:
- ret = left.u.d < right.u.d;
- break;
- case FcOpLessEqual:
- ret = left.u.d <= right.u.d;
- break;
- case FcOpMore:
- ret = left.u.d > right.u.d;
- break;
- case FcOpMoreEqual:
- ret = left.u.d >= right.u.d;
- break;
- default:
- break;
- }
- break;
- case FcTypeBool:
- switch ((int) op) {
- case FcOpEqual:
- ret = left.u.b == right.u.b;
- break;
- case FcOpContains:
- case FcOpListing:
- ret = left.u.b == right.u.b || left.u.b >= FcDontCare;
- break;
- case FcOpNotEqual:
- ret = left.u.b != right.u.b;
- break;
- case FcOpNotContains:
- ret = !(left.u.b == right.u.b || left.u.b >= FcDontCare);
- break;
- case FcOpLess:
- ret = left.u.b != right.u.b && right.u.b >= FcDontCare;
- break;
- case FcOpLessEqual:
- ret = left.u.b == right.u.b || right.u.b >= FcDontCare;
- break;
- case FcOpMore:
- ret = left.u.b != right.u.b && left.u.b >= FcDontCare;
- break;
- case FcOpMoreEqual:
- ret = left.u.b == right.u.b || left.u.b >= FcDontCare;
- break;
- default:
- break;
- }
- break;
- case FcTypeString:
- switch ((int) op) {
- case FcOpEqual:
- case FcOpListing:
- if (flags & FcOpFlagIgnoreBlanks)
- ret = FcStrCmpIgnoreBlanksAndCase (left.u.s, right.u.s) == 0;
- else
- ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
- break;
- case FcOpContains:
- ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0;
- break;
- case FcOpNotEqual:
- if (flags & FcOpFlagIgnoreBlanks)
- ret = FcStrCmpIgnoreBlanksAndCase (left.u.s, right.u.s) != 0;
- else
- ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
- break;
- case FcOpNotContains:
- ret = FcStrStrIgnoreCase (left.u.s, right.u.s) == 0;
- break;
- default:
- break;
- }
- break;
- case FcTypeMatrix:
- switch ((int) op) {
- case FcOpEqual:
- case FcOpContains:
- case FcOpListing:
- ret = FcMatrixEqual (left.u.m, right.u.m);
- break;
- case FcOpNotEqual:
- case FcOpNotContains:
- ret = !FcMatrixEqual (left.u.m, right.u.m);
- break;
- default:
- break;
- }
- break;
- case FcTypeCharSet:
- 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);
- break;
- case FcOpNotContains:
- /* left contains right if right is a subset of left */
- ret = !FcCharSetIsSubset (right.u.c, left.u.c);
- break;
- case FcOpEqual:
- ret = FcCharSetEqual (left.u.c, right.u.c);
- break;
- case FcOpNotEqual:
- ret = !FcCharSetEqual (left.u.c, right.u.c);
- break;
- default:
- break;
- }
- break;
- case FcTypeLangSet:
- switch ((int) op) {
- case FcOpContains:
- case FcOpListing:
- ret = FcLangSetContains (left.u.l, right.u.l);
- break;
- case FcOpNotContains:
- ret = !FcLangSetContains (left.u.l, right.u.l);
- break;
- case FcOpEqual:
- ret = FcLangSetEqual (left.u.l, right.u.l);
- break;
- case FcOpNotEqual:
- ret = !FcLangSetEqual (left.u.l, right.u.l);
- break;
- default:
- break;
- }
- break;
- case FcTypeVoid:
- switch ((int) op) {
- case FcOpEqual:
- case FcOpContains:
- case FcOpListing:
- ret = FcTrue;
- break;
- default:
- break;
- }
- break;
- case FcTypeFTFace:
- switch ((int) op) {
- case FcOpEqual:
- case FcOpContains:
- case FcOpListing:
- ret = left.u.f == right.u.f;
- break;
- case FcOpNotEqual:
- case FcOpNotContains:
- ret = left.u.f != right.u.f;
- break;
- default:
- break;
- }
- break;
- case FcTypeRange:
- ret = FcRangeCompare (op, left.u.r, right.u.r);
- break;
- }
- }
- else
- {
- if (op == FcOpNotEqual || op == FcOpNotContains)
- ret = FcTrue;
+ if (left.type != right.type)
+ {
+ FcValuePromotionBuffer buf1, buf2;
+ left = FcConfigPromote (left, right, &buf1);
+ right = FcConfigPromote (right, left, &buf2);
+ 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:
+ 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:
+ case FcOpContains:
+ case FcOpListing:
+ ret = left.u.d == right.u.d;
+ break;
+ case FcOpNotEqual:
+ case FcOpNotContains:
+ ret = left.u.d != right.u.d;
+ break;
+ case FcOpLess:
+ ret = left.u.d < right.u.d;
+ break;
+ case FcOpLessEqual:
+ ret = left.u.d <= right.u.d;
+ break;
+ case FcOpMore:
+ ret = left.u.d > right.u.d;
+ break;
+ case FcOpMoreEqual:
+ ret = left.u.d >= right.u.d;
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeBool:
+ switch ((int) op) {
+ case FcOpEqual:
+ ret = left.u.b == right.u.b;
+ break;
+ case FcOpContains:
+ case FcOpListing:
+ ret = left.u.b == right.u.b || left.u.b >= FcDontCare;
+ break;
+ case FcOpNotEqual:
+ ret = left.u.b != right.u.b;
+ break;
+ case FcOpNotContains:
+ ret = !(left.u.b == right.u.b || left.u.b >= FcDontCare);
+ break;
+ case FcOpLess:
+ ret = left.u.b != right.u.b && right.u.b >= FcDontCare;
+ break;
+ case FcOpLessEqual:
+ ret = left.u.b == right.u.b || right.u.b >= FcDontCare;
+ break;
+ case FcOpMore:
+ ret = left.u.b != right.u.b && left.u.b >= FcDontCare;
+ break;
+ case FcOpMoreEqual:
+ ret = left.u.b == right.u.b || left.u.b >= FcDontCare;
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeString:
+ switch ((int) op) {
+ case FcOpEqual:
+ case FcOpListing:
+ if (flags & FcOpFlagIgnoreBlanks)
+ ret = FcStrCmpIgnoreBlanksAndCase (left.u.s, right.u.s) == 0;
+ else
+ ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
+ break;
+ case FcOpContains:
+ ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0;
+ break;
+ case FcOpNotEqual:
+ if (flags & FcOpFlagIgnoreBlanks)
+ ret = FcStrCmpIgnoreBlanksAndCase (left.u.s, right.u.s) != 0;
+ else
+ ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
+ break;
+ case FcOpNotContains:
+ ret = FcStrStrIgnoreCase (left.u.s, right.u.s) == 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeMatrix:
+ switch ((int) op) {
+ case FcOpEqual:
+ case FcOpContains:
+ case FcOpListing:
+ ret = FcMatrixEqual (left.u.m, right.u.m);
+ break;
+ case FcOpNotEqual:
+ case FcOpNotContains:
+ ret = !FcMatrixEqual (left.u.m, right.u.m);
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeCharSet:
+ 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);
+ break;
+ case FcOpNotContains:
+ /* left contains right if right is a subset of left */
+ ret = !FcCharSetIsSubset (right.u.c, left.u.c);
+ break;
+ case FcOpEqual:
+ ret = FcCharSetEqual (left.u.c, right.u.c);
+ break;
+ case FcOpNotEqual:
+ ret = !FcCharSetEqual (left.u.c, right.u.c);
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeLangSet:
+ switch ((int) op) {
+ case FcOpContains:
+ case FcOpListing:
+ ret = FcLangSetContains (left.u.l, right.u.l);
+ break;
+ case FcOpNotContains:
+ ret = !FcLangSetContains (left.u.l, right.u.l);
+ break;
+ case FcOpEqual:
+ ret = FcLangSetEqual (left.u.l, right.u.l);
+ break;
+ case FcOpNotEqual:
+ ret = !FcLangSetEqual (left.u.l, right.u.l);
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeVoid:
+ switch ((int) op) {
+ case FcOpEqual:
+ case FcOpContains:
+ case FcOpListing:
+ ret = FcTrue;
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeFTFace:
+ switch ((int) op) {
+ case FcOpEqual:
+ case FcOpContains:
+ case FcOpListing:
+ ret = left.u.f == right.u.f;
+ break;
+ case FcOpNotEqual:
+ case FcOpNotContains:
+ ret = left.u.f != right.u.f;
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeRange:
+ ret = FcRangeCompare (op, left.u.r, right.u.r);
+ break;
}
return ret;
}