Fix unary operator parsing. Add floor, ceil, trunc and round unary

operators
This commit is contained in:
Keith Packard 2003-04-15 23:38:06 +00:00
parent 52253696cd
commit 3f7653c2ba
7 changed files with 187 additions and 24 deletions

View File

@ -108,7 +108,9 @@ typedef int FcBool;
#define FC_WEIGHT_SEMIBOLD FC_WEIGHT_DEMIBOLD #define FC_WEIGHT_SEMIBOLD FC_WEIGHT_DEMIBOLD
#define FC_WEIGHT_BOLD 200 #define FC_WEIGHT_BOLD 200
#define FC_WEIGHT_EXTRABOLD 205 #define FC_WEIGHT_EXTRABOLD 205
#define FC_WEIGHT_ULTRABOLD FC_WEIGHT_EXTRABOLD
#define FC_WEIGHT_BLACK 210 #define FC_WEIGHT_BLACK 210
#define FC_WEIGHT_HEAVY FC_WEIGHT_BLACK
#define FC_SLANT_ROMAN 0 #define FC_SLANT_ROMAN 0
#define FC_SLANT_ITALIC 100 #define FC_SLANT_ITALIC 100

View File

@ -91,7 +91,7 @@
<!ENTITY % expr 'int|double|string|matrix|bool|charset <!ENTITY % expr 'int|double|string|matrix|bool|charset
|name|const |name|const
|or|and|eq|not_eq|less|less_eq|more|more_eq|contains|not_contains |or|and|eq|not_eq|less|less_eq|more|more_eq|contains|not_contains
|plus|minus|times|divide|not|if'> |plus|minus|times|divide|not|if|floor|ceil|round|trunc'>
<!-- <!--
Match and edit patterns. Match and edit patterns.
@ -180,3 +180,7 @@
<!ELEMENT divide (%expr;)*> <!ELEMENT divide (%expr;)*>
<!ELEMENT not (%expr;)> <!ELEMENT not (%expr;)>
<!ELEMENT if ((%expr;), (%expr;), (%expr;))> <!ELEMENT if ((%expr;), (%expr;), (%expr;))>
<!ELEMENT floor (%expr;)>
<!ELEMENT ceil (%expr;)>
<!ELEMENT round (%expr;)>
<!ELEMENT trunc (%expr;)>

View File

@ -49,7 +49,7 @@ INCLUDES = \
EXTRA_DIST = fontconfig.def.in EXTRA_DIST = fontconfig.def.in
noinst_HEADERS=fcint.h noinst_HEADERS=fcint.h data.h
libfontconfig_la_SOURCES = \ libfontconfig_la_SOURCES = \
fcatomic.c \ fcatomic.c \

View File

@ -648,6 +648,13 @@ FcConfigCompareValue (const FcValue m_o,
} }
#define _FcDoubleFloor(d) ((int) (d))
#define _FcDoubleCeil(d) ((double) (int) (d) == (d) ? (int) (d) : (int) ((d) + 1))
#define FcDoubleFloor(d) ((d) >= 0 ? _FcDoubleFloor(d) : -_FcDoubleCeil(-(d)))
#define FcDoubleCeil(d) ((d) >= 0 ? _FcDoubleCeil(d) : -_FcDoubleFloor(-(d)))
#define FcDoubleRound(d) FcDoubleFloor ((d) + 0.5)
#define FcDoubleTrunc(d) ((d) >= 0 ? _FcDoubleFloor (d) : -_FcDoubleFloor (-(d)))
static FcValue static FcValue
FcConfigEvaluate (FcPattern *p, FcExpr *e) FcConfigEvaluate (FcPattern *p, FcExpr *e)
{ {
@ -836,6 +843,70 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
} }
FcValueDestroy (vl); FcValueDestroy (vl);
break; 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: default:
v.type = FcTypeVoid; v.type = FcTypeVoid;
break; break;

View File

@ -153,6 +153,10 @@ FcOpPrint (FcOp op)
case FcOpNot: printf ("Not"); break; case FcOpNot: printf ("Not"); break;
case FcOpNil: printf ("Nil"); break; case FcOpNil: printf ("Nil"); break;
case FcOpComma: printf ("Comma"); 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 FcOpInvalid: printf ("Invalid"); break; case FcOpInvalid: printf ("Invalid"); break;
} }
} }
@ -236,6 +240,22 @@ FcExprPrint (const FcExpr *expr)
printf ("Not "); printf ("Not ");
FcExprPrint (expr->u.tree.left); FcExprPrint (expr->u.tree.left);
break; 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; case FcOpInvalid: printf ("Invalid"); break;
} }
} }

View File

@ -135,7 +135,8 @@ typedef enum _FcOp {
FcOpOr, FcOpAnd, FcOpEqual, FcOpNotEqual, FcOpContains, FcOpNotContains, FcOpOr, FcOpAnd, FcOpEqual, FcOpNotEqual, FcOpContains, FcOpNotContains,
FcOpLess, FcOpLessEqual, FcOpMore, FcOpMoreEqual, FcOpLess, FcOpLessEqual, FcOpMore, FcOpMoreEqual,
FcOpPlus, FcOpMinus, FcOpTimes, FcOpDivide, FcOpPlus, FcOpMinus, FcOpTimes, FcOpDivide,
FcOpNot, FcOpComma, FcOpInvalid FcOpNot, FcOpComma, FcOpFloor, FcOpCeil, FcOpRound, FcOpTrunc,
FcOpInvalid
} FcOp; } FcOp;
typedef struct _FcExpr { typedef struct _FcExpr {

View File

@ -203,6 +203,8 @@ FcExprCreateOp (FcExpr *left, FcOp op, FcExpr *right)
void void
FcExprDestroy (FcExpr *e) FcExprDestroy (FcExpr *e)
{ {
if (!e)
return;
switch (e->op) { switch (e->op) {
case FcOpInteger: case FcOpInteger:
break; break;
@ -251,6 +253,10 @@ FcExprDestroy (FcExpr *e)
FcExprDestroy (e->u.tree.right); FcExprDestroy (e->u.tree.right);
/* fall through */ /* fall through */
case FcOpNot: case FcOpNot:
case FcOpFloor:
case FcOpCeil:
case FcOpRound:
case FcOpTrunc:
FcExprDestroy (e->u.tree.left); FcExprDestroy (e->u.tree.left);
break; break;
case FcOpNil: case FcOpNil:
@ -337,6 +343,10 @@ typedef enum _FcElement {
FcElementDivide, FcElementDivide,
FcElementNot, FcElementNot,
FcElementIf, FcElementIf,
FcElementFloor,
FcElementCeil,
FcElementRound,
FcElementTrunc,
FcElementUnknown FcElementUnknown
} FcElement; } FcElement;
@ -389,6 +399,10 @@ FcElementMap (const XML_Char *name)
{ "divide", FcElementDivide }, { "divide", FcElementDivide },
{ "not", FcElementNot }, { "not", FcElementNot },
{ "if", FcElementIf }, { "if", FcElementIf },
{ "floor", FcElementFloor },
{ "ceil", FcElementCeil },
{ "round", FcElementRound },
{ "trunc", FcElementTrunc },
{ 0, 0 } { 0, 0 }
}; };
@ -1292,8 +1306,17 @@ FcPopExpr (FcConfigParse *parse)
return expr; return expr;
} }
/*
* This builds a tree of binary operations. Note
* that every operator is defined so that if only
* a single operand is contained, the value of the
* whole expression is the value of the operand.
*
* This code reduces in that case to returning that
* operand.
*/
static FcExpr * static FcExpr *
FcPopExprs (FcConfigParse *parse, FcOp op) FcPopBinary (FcConfigParse *parse, FcOp op)
{ {
FcExpr *left, *expr = 0, *new; FcExpr *left, *expr = 0, *new;
@ -1318,9 +1341,39 @@ FcPopExprs (FcConfigParse *parse, FcOp op)
} }
static void static void
FcParseExpr (FcConfigParse *parse, FcOp op) FcParseBinary (FcConfigParse *parse, FcOp op)
{ {
FcExpr *expr = FcPopExprs (parse, op); FcExpr *expr = FcPopBinary (parse, op);
if (expr)
FcVStackPushExpr (parse, FcVStackExpr, expr);
}
/*
* This builds a a unary operator, it consumes only
* a single operand
*/
static FcExpr *
FcPopUnary (FcConfigParse *parse, FcOp op)
{
FcExpr *operand, *new = 0;
if ((operand = FcPopExpr (parse)))
{
new = FcExprCreateOp (operand, op, 0);
if (!new)
{
FcExprDestroy (operand);
FcConfigMessage (parse, FcSevereError, "out of memory");
}
}
return new;
}
static void
FcParseUnary (FcConfigParse *parse, FcOp op)
{
FcExpr *expr = FcPopUnary (parse, op);
if (expr) if (expr)
FcVStackPushExpr (parse, FcVStackExpr, expr); FcVStackPushExpr (parse, FcVStackExpr, expr);
} }
@ -1449,7 +1502,7 @@ FcParseTest (FcConfigParse *parse)
return; return;
} }
} }
expr = FcPopExprs (parse, FcOpComma); expr = FcPopBinary (parse, FcOpComma);
if (!expr) if (!expr)
{ {
FcConfigMessage (parse, FcSevereWarning, "missing test expression"); FcConfigMessage (parse, FcSevereWarning, "missing test expression");
@ -1527,7 +1580,7 @@ FcParseEdit (FcConfigParse *parse)
return; return;
} }
} }
expr = FcPopExprs (parse, FcOpComma); expr = FcPopBinary (parse, FcOpComma);
edit = FcEditCreate ((char *) FcStrCopy (name), mode, expr, binding); edit = FcEditCreate ((char *) FcStrCopy (name), mode, expr, binding);
if (!edit) if (!edit)
{ {
@ -1716,52 +1769,64 @@ FcEndElement(void *userData, const XML_Char *name)
FcParseString (parse, FcVStackConstant); FcParseString (parse, FcVStackConstant);
break; break;
case FcElementOr: case FcElementOr:
FcParseExpr (parse, FcOpOr); FcParseBinary (parse, FcOpOr);
break; break;
case FcElementAnd: case FcElementAnd:
FcParseExpr (parse, FcOpAnd); FcParseBinary (parse, FcOpAnd);
break; break;
case FcElementEq: case FcElementEq:
FcParseExpr (parse, FcOpEqual); FcParseBinary (parse, FcOpEqual);
break; break;
case FcElementNotEq: case FcElementNotEq:
FcParseExpr (parse, FcOpNotEqual); FcParseBinary (parse, FcOpNotEqual);
break; break;
case FcElementLess: case FcElementLess:
FcParseExpr (parse, FcOpLess); FcParseBinary (parse, FcOpLess);
break; break;
case FcElementLessEq: case FcElementLessEq:
FcParseExpr (parse, FcOpLessEqual); FcParseBinary (parse, FcOpLessEqual);
break; break;
case FcElementMore: case FcElementMore:
FcParseExpr (parse, FcOpMore); FcParseBinary (parse, FcOpMore);
break; break;
case FcElementMoreEq: case FcElementMoreEq:
FcParseExpr (parse, FcOpMoreEqual); FcParseBinary (parse, FcOpMoreEqual);
break; break;
case FcElementContains: case FcElementContains:
FcParseExpr (parse, FcOpContains); FcParseBinary (parse, FcOpContains);
break; break;
case FcElementNotContains: case FcElementNotContains:
FcParseExpr (parse, FcOpNotContains); FcParseBinary (parse, FcOpNotContains);
break; break;
case FcElementPlus: case FcElementPlus:
FcParseExpr (parse, FcOpPlus); FcParseBinary (parse, FcOpPlus);
break; break;
case FcElementMinus: case FcElementMinus:
FcParseExpr (parse, FcOpMinus); FcParseBinary (parse, FcOpMinus);
break; break;
case FcElementTimes: case FcElementTimes:
FcParseExpr (parse, FcOpTimes); FcParseBinary (parse, FcOpTimes);
break; break;
case FcElementDivide: case FcElementDivide:
FcParseExpr (parse, FcOpDivide); FcParseBinary (parse, FcOpDivide);
break; break;
case FcElementNot: case FcElementNot:
FcParseExpr (parse, FcOpNot); FcParseUnary (parse, FcOpNot);
break; break;
case FcElementIf: case FcElementIf:
FcParseExpr (parse, FcOpQuest); FcParseBinary (parse, FcOpQuest);
break;
case FcElementFloor:
FcParseUnary (parse, FcOpFloor);
break;
case FcElementCeil:
FcParseUnary (parse, FcOpCeil);
break;
case FcElementRound:
FcParseUnary (parse, FcOpRound);
break;
case FcElementTrunc:
FcParseUnary (parse, FcOpTrunc);
break; break;
case FcElementUnknown: case FcElementUnknown:
break; break;