/* * Font must have a containing value for every value in the pattern */ static FcBool FcListValueListMatchAny (FcValueListPtr patOrig, /* pattern */ FcValueListPtr fntOrig) /* font */ { FcValueListPtr pat, fnt; for (pat = patOrig; pat != NULL; pat = FcValueListNext(pat)) { for (fnt = fntOrig; fnt != NULL; fnt = FcValueListNext(fnt)) { /* * make sure the font 'contains' the pattern. * (OpListing is OpContains except for strings * where it requires an exact match) */ if (FcConfigCompareValue (&fnt->value, FC_OP (FcOpListing, FcOpFlagIgnoreBlanks), &pat->value)) break; } if (fnt == NULL) return FcFalse; } return FcTrue; }
static FcValueList * FcConfigMatchValueList (FcPattern *p, FcTest *t, FcValueList *values) { FcValueList *ret = 0; FcExpr *e = t->expr; FcValue value; FcValueList *v; while (e) { /* Compute the value of the match expression */ if (e->op == FcOpComma) { value = FcConfigEvaluate (p, e->u.tree.left); e = e->u.tree.right; } else { value = FcConfigEvaluate (p, e); e = 0; } for (v = values; v; v = FcValueListNext(v)) { /* Compare the pattern value to the match expression value */ if (FcConfigCompareValue (&v->value, t->op, &value)) { if (!ret) ret = v; } else { if (t->qual == FcQualAll) { ret = 0; break; } } } FcValueDestroy (value); } return ret; }
static FcValue FcConfigEvaluate (FcPattern *p, FcExpr *e) { FcValue v, vl, vr; FcResult r; FcMatrix *m; FcChar8 *str; switch (e->op) { case FcOpInteger: v.type = FcTypeInteger; v.u.i = e->u.ival; break; case FcOpDouble: v.type = FcTypeDouble; v.u.d = e->u.dval; break; case FcOpString: v.type = FcTypeString; v.u.s = e->u.sval; v = FcValueSave (v); break; case FcOpMatrix: v.type = FcTypeMatrix; v.u.m = e->u.mval; v = FcValueSave (v); break; case FcOpCharSet: v.type = FcTypeCharSet; v.u.c = e->u.cval; v = FcValueSave (v); break; case FcOpBool: v.type = FcTypeBool; v.u.b = e->u.bval; break; case FcOpField: r = FcPatternObjectGet (p, e->u.object, 0, &v); if (r != FcResultMatch) v.type = FcTypeVoid; v = FcValueSave (v); break; case FcOpConst: if (FcNameConstant (e->u.constant, &v.u.i)) v.type = FcTypeInteger; else v.type = FcTypeVoid; break; case FcOpQuest: vl = FcConfigEvaluate (p, e->u.tree.left); if (vl.type == FcTypeBool) { if (vl.u.b) v = FcConfigEvaluate (p, e->u.tree.right->u.tree.left); else v = FcConfigEvaluate (p, e->u.tree.right->u.tree.right); } else v.type = FcTypeVoid; FcValueDestroy (vl); break; case FcOpEqual: case FcOpNotEqual: case FcOpLess: case FcOpLessEqual: case FcOpMore: case FcOpMoreEqual: case FcOpContains: case FcOpNotContains: case FcOpListing: vl = FcConfigEvaluate (p, e->u.tree.left); vr = FcConfigEvaluate (p, e->u.tree.right); v.type = FcTypeBool; v.u.b = FcConfigCompareValue (&vl, e->op, &vr); FcValueDestroy (vl); FcValueDestroy (vr); break; case FcOpOr: case FcOpAnd: case FcOpPlus: case FcOpMinus: case FcOpTimes: case FcOpDivide: vl = FcConfigEvaluate (p, e->u.tree.left); vr = FcConfigEvaluate (p, e->u.tree.right); vl = FcConfigPromote (vl, vr); vr = FcConfigPromote (vr, vl); if (vl.type == vr.type) { switch (vl.type) { case FcTypeDouble: switch (e->op) { case FcOpPlus: v.type = FcTypeDouble; v.u.d = vl.u.d + vr.u.d; break; case FcOpMinus: v.type = FcTypeDouble; v.u.d = vl.u.d - vr.u.d; break; case FcOpTimes: v.type = FcTypeDouble; v.u.d = vl.u.d * vr.u.d; break; case FcOpDivide: v.type = FcTypeDouble; v.u.d = vl.u.d / vr.u.d; break; default: v.type = FcTypeVoid; break; } if (v.type == FcTypeDouble && v.u.d == (double) (int) v.u.d) { v.type = FcTypeInteger; v.u.i = (int) v.u.d; } break; case FcTypeBool: switch (e->op) { case FcOpOr: v.type = FcTypeBool; v.u.b = vl.u.b || vr.u.b; break; case FcOpAnd: v.type = FcTypeBool; v.u.b = vl.u.b && vr.u.b; break; default: v.type = FcTypeVoid; break; } break; case FcTypeString: switch (e->op) { case FcOpPlus: v.type = FcTypeString; str = FcStrPlus (vl.u.s, vr.u.s); v.u.s = FcStrStaticName (str); FcStrFree (str); if (!v.u.s) v.type = FcTypeVoid; break; default: v.type = FcTypeVoid; break; } break; case FcTypeMatrix: switch (e->op) { case FcOpTimes: v.type = FcTypeMatrix; m = malloc (sizeof (FcMatrix)); if (m) { FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix)); FcMatrixMultiply (m, vl.u.m, vr.u.m); v.u.m = m; } else { v.type = FcTypeVoid; } break; default: v.type = FcTypeVoid; break; } break; default: v.type = FcTypeVoid; break; } } else v.type = FcTypeVoid; FcValueDestroy (vl); FcValueDestroy (vr); break; case FcOpNot: vl = FcConfigEvaluate (p, e->u.tree.left); switch (vl.type) { case FcTypeBool: v.type = FcTypeBool; v.u.b = !vl.u.b; break; default: v.type = FcTypeVoid; break; } FcValueDestroy (vl); break; case FcOpFloor: vl = FcConfigEvaluate (p, e->u.tree.left); switch (vl.type) { case FcTypeInteger: v = vl; break; case FcTypeDouble: v.type = FcTypeInteger; v.u.i = FcDoubleFloor (vl.u.d); break; default: v.type = FcTypeVoid; break; } FcValueDestroy (vl); break; case FcOpCeil: vl = FcConfigEvaluate (p, e->u.tree.left); switch (vl.type) { case FcTypeInteger: v = vl; break; case FcTypeDouble: v.type = FcTypeInteger; v.u.i = FcDoubleCeil (vl.u.d); break; default: v.type = FcTypeVoid; break; } FcValueDestroy (vl); break; case FcOpRound: vl = FcConfigEvaluate (p, e->u.tree.left); switch (vl.type) { case FcTypeInteger: v = vl; break; case FcTypeDouble: v.type = FcTypeInteger; v.u.i = FcDoubleRound (vl.u.d); break; default: v.type = FcTypeVoid; break; } FcValueDestroy (vl); break; case FcOpTrunc: vl = FcConfigEvaluate (p, e->u.tree.left); switch (vl.type) { case FcTypeInteger: v = vl; break; case FcTypeDouble: v.type = FcTypeInteger; v.u.i = FcDoubleTrunc (vl.u.d); break; default: v.type = FcTypeVoid; break; } FcValueDestroy (vl); break; default: v.type = FcTypeVoid; break; } return v; }