static FcValueList * FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding) { FcValueList *l; if (!e) return 0; l = (FcValueList *) malloc (sizeof (FcValueList)); if (!l) return 0; FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList)); if (FC_OP_GET_OP (e->op) == FcOpComma) { l->value = FcConfigEvaluate (p, e->u.tree.left); l->next = FcConfigValues (p, e->u.tree.right, binding); } else { l->value = FcConfigEvaluate (p, e); l->next = NULL; } l->binding = binding; if (l->value.type == FcTypeVoid) { FcValueList *next = FcValueListNext(l); FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList)); free (l); l = next; } return l; }
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 (FC_OP_GET_OP (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; }
void FcExprPrint(const FcExpr *expr) { if (!expr) printf("none"); else switch (FC_OP_GET_OP(expr->op)) { case FcOpInteger: printf("%d", expr->u.ival); break; case FcOpDouble: printf("%g", expr->u.dval); break; case FcOpString: printf("\"%s\"", expr->u.sval); break; case FcOpMatrix: printf("["); FcExprPrint(expr->u.mexpr->xx); printf(" "); FcExprPrint(expr->u.mexpr->xy); printf("; "); FcExprPrint(expr->u.mexpr->yx); printf(" "); FcExprPrint(expr->u.mexpr->yy); printf("]"); break; case FcOpRange: break; case FcOpBool: printf("%s", expr->u.bval ? "true" : "false"); break; case FcOpCharSet: printf("charset\n"); break; case FcOpLangSet: printf("langset:"); FcLangSetPrint(expr->u.lval); printf("\n"); break; case FcOpNil: printf("nil\n"); break; case FcOpField: printf("%s ", FcObjectName(expr->u.name.object)); switch ((int)expr->u.name.kind) { case FcMatchPattern: printf("(pattern) "); break; case FcMatchFont: printf("(font) "); break; } break; case FcOpConst: printf("%s", expr->u.constant); break; case FcOpQuest: FcExprPrint(expr->u.tree.left); printf(" quest "); FcExprPrint(expr->u.tree.right->u.tree.left); printf(" colon "); FcExprPrint(expr->u.tree.right->u.tree.right); break; case FcOpAssign: case FcOpAssignReplace: case FcOpPrependFirst: case FcOpPrepend: case FcOpAppend: case FcOpAppendLast: case FcOpOr: case FcOpAnd: case FcOpEqual: case FcOpNotEqual: case FcOpLess: case FcOpLessEqual: case FcOpMore: case FcOpMoreEqual: case FcOpContains: case FcOpListing: case FcOpNotContains: case FcOpPlus: case FcOpMinus: case FcOpTimes: case FcOpDivide: case FcOpComma: FcExprPrint(expr->u.tree.left); printf(" "); switch (FC_OP_GET_OP(expr->op)) { case FcOpAssign: printf("Assign"); break; case FcOpAssignReplace: printf("AssignReplace"); break; case FcOpPrependFirst: printf("PrependFirst"); break; case FcOpPrepend: printf("Prepend"); break; case FcOpAppend: printf("Append"); break; case FcOpAppendLast: printf("AppendLast"); break; case FcOpOr: printf("Or"); break; case FcOpAnd: printf("And"); break; case FcOpEqual: printf("Equal"); FcOpFlagsPrint(expr->op); break; case FcOpNotEqual: printf("NotEqual"); FcOpFlagsPrint(expr->op); break; case FcOpLess: printf("Less"); break; case FcOpLessEqual: printf("LessEqual"); break; case FcOpMore: printf("More"); break; case FcOpMoreEqual: printf("MoreEqual"); break; case FcOpContains: printf("Contains"); break; case FcOpListing: printf("Listing"); FcOpFlagsPrint(expr->op); break; case FcOpNotContains: printf("NotContains"); break; case FcOpPlus: printf("Plus"); break; case FcOpMinus: printf("Minus"); break; case FcOpTimes: printf("Times"); break; case FcOpDivide: printf("Divide"); break; case FcOpComma: printf("Comma"); break; default: break; } printf(" "); FcExprPrint(expr->u.tree.right); break; case FcOpNot: printf("Not "); FcExprPrint(expr->u.tree.left); break; case FcOpFloor: printf("Floor "); FcExprPrint(expr->u.tree.left); break; case FcOpCeil: printf("Ceil "); FcExprPrint(expr->u.tree.left); break; case FcOpRound: printf("Round "); FcExprPrint(expr->u.tree.left); break; case FcOpTrunc: printf("Trunc "); FcExprPrint(expr->u.tree.left); break; case FcOpInvalid: printf("Invalid"); break; } }
void FcOpPrint(FcOp op_) { FcOp op = FC_OP_GET_OP(op_); switch (op) { case FcOpInteger: printf("Integer"); break; case FcOpDouble: printf("Double"); break; case FcOpString: printf("String"); break; case FcOpMatrix: printf("Matrix"); break; case FcOpRange: printf("Range"); break; case FcOpBool: printf("Bool"); break; case FcOpCharSet: printf("CharSet"); break; case FcOpLangSet: printf("LangSet"); break; case FcOpField: printf("Field"); break; case FcOpConst: printf("Const"); break; case FcOpAssign: printf("Assign"); break; case FcOpAssignReplace: printf("AssignReplace"); break; case FcOpPrepend: printf("Prepend"); break; case FcOpPrependFirst: printf("PrependFirst"); break; case FcOpAppend: printf("Append"); break; case FcOpAppendLast: printf("AppendLast"); break; case FcOpDelete: printf("Delete"); break; case FcOpDeleteAll: printf("DeleteAll"); break; case FcOpQuest: printf("Quest"); break; case FcOpOr: printf("Or"); break; case FcOpAnd: printf("And"); break; case FcOpEqual: printf("Equal"); FcOpFlagsPrint(op_); break; case FcOpNotEqual: printf("NotEqual"); FcOpFlagsPrint(op_); break; case FcOpLess: printf("Less"); break; case FcOpLessEqual: printf("LessEqual"); break; case FcOpMore: printf("More"); break; case FcOpMoreEqual: printf("MoreEqual"); break; case FcOpContains: printf("Contains"); break; case FcOpNotContains: printf("NotContains"); break; case FcOpPlus: printf("Plus"); break; case FcOpMinus: printf("Minus"); break; case FcOpTimes: printf("Times"); break; case FcOpDivide: printf("Divide"); break; case FcOpNot: printf("Not"); break; case FcOpNil: printf("Nil"); break; case FcOpComma: printf("Comma"); break; case FcOpFloor: printf("Floor"); break; case FcOpCeil: printf("Ceil"); break; case FcOpRound: printf("Round"); break; case FcOpTrunc: printf("Trunc"); break; case FcOpListing: printf("Listing"); FcOpFlagsPrint(op_); break; case FcOpInvalid: printf("Invalid"); break; } }
static FcValue FcConfigEvaluate (FcPattern *p, FcExpr *e) { FcValue v, vl, vr; FcResult r; FcMatrix *m; FcChar8 *str; FcOp op = FC_OP_GET_OP (e->op); switch (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 FcOpLangSet: v.type = FcTypeLangSet; v.u.l = e->u.lval; 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 (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 (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 (op) { case FcOpPlus: v.type = FcTypeString; str = FcStrPlus (vl.u.s, vr.u.s); v.u.s = FcSharedStr (str); FcStrFree (str); if (!v.u.s) v.type = FcTypeVoid; break; default: v.type = FcTypeVoid; break; } break; case FcTypeMatrix: switch (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; case FcTypeCharSet: switch (op) { case FcOpPlus: v.type = FcTypeCharSet; v.u.c = FcCharSetUnion (vl.u.c, vr.u.c); if (!v.u.c) v.type = FcTypeVoid; break; case FcOpMinus: v.type = FcTypeCharSet; v.u.c = FcCharSetSubtract (vl.u.c, vr.u.c); if (!v.u.c) v.type = FcTypeVoid; break; default: v.type = FcTypeVoid; break; } break; case FcTypeLangSet: switch (op) { case FcOpPlus: v.type = FcTypeLangSet; v.u.l = FcLangSetUnion (vl.u.l, vr.u.l); if (!v.u.l) v.type = FcTypeVoid; break; case FcOpMinus: v.type = FcTypeLangSet; v.u.l = FcLangSetSubtract (vl.u.l, vr.u.l); if (!v.u.l) 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; }
FcBool FcConfigCompareValue (const FcValue *left_o, FcOp op_, const FcValue *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_); left = FcConfigPromote (left, right); right = FcConfigPromote (right, left); if (left.type == right.type) { switch (left.type) { case FcTypeInteger: break; /* FcConfigPromote prevents this from happening */ case FcTypeDouble: switch (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 (op) { case FcOpEqual: case FcOpContains: case FcOpListing: ret = left.u.b == right.u.b; break; case FcOpNotEqual: case FcOpNotContains: ret = left.u.b != right.u.b; break; default: break; } break; case FcTypeString: switch (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 (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 (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 (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 (op) { case FcOpEqual: case FcOpContains: case FcOpListing: ret = FcTrue; break; default: break; } break; case FcTypeFTFace: switch (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; } } else { if (op == FcOpNotEqual || op == FcOpNotContains) ret = FcTrue; } return ret; }