Fix unary operator parsing. Add floor, ceil, trunc and round unary
operators
This commit is contained in:
parent
52253696cd
commit
3f7653c2ba
|
@ -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
|
||||||
|
|
|
@ -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;)>
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
71
src/fccfg.c
71
src/fccfg.c
|
@ -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;
|
||||||
|
|
20
src/fcdbg.c
20
src/fcdbg.c
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
107
src/fcxml.c
107
src/fcxml.c
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue