Parse matrices of expressions

Previously a <matrix> element could only accept four <double> literals.
It now accepts full expressions, which can in turn poke into the
pattern, do math, etc.
This commit is contained in:
Behdad Esfahbod 2012-12-29 21:39:06 -05:00
parent 927dd3ddb5
commit 4f6767470f
5 changed files with 94 additions and 51 deletions

View File

@ -201,7 +201,7 @@
<!ATTLIST double xml:space (default|preserve) 'preserve'> <!ATTLIST double xml:space (default|preserve) 'preserve'>
<!ELEMENT string (#PCDATA)> <!ELEMENT string (#PCDATA)>
<!ATTLIST string xml:space (default|preserve) 'preserve'> <!ATTLIST string xml:space (default|preserve) 'preserve'>
<!ELEMENT matrix (double,double,double,double)> <!ELEMENT matrix ((%expr;), (%expr;), (%expr;), (%expr;))>
<!ELEMENT bool (#PCDATA)> <!ELEMENT bool (#PCDATA)>
<!ELEMENT charset (int|range)*> <!ELEMENT charset (int|range)*>
<!ELEMENT range (int,int)> <!ELEMENT range (int,int)>

View File

@ -897,9 +897,27 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
v = FcValueSave (v); v = FcValueSave (v);
break; break;
case FcOpMatrix: case FcOpMatrix:
v.type = FcTypeMatrix; {
v.u.m = e->u.mval; FcMatrix m;
v = FcValueSave (v); v.type = FcTypeMatrix;
FcValue xx, xy, yx, yy;
xx = FcConfigPromote (FcConfigEvaluate (p, e->u.mexpr->xx), v);
xy = FcConfigPromote (FcConfigEvaluate (p, e->u.mexpr->xy), v);
yx = FcConfigPromote (FcConfigEvaluate (p, e->u.mexpr->yx), v);
yy = FcConfigPromote (FcConfigEvaluate (p, e->u.mexpr->yy), v);
if (xx.type == FcTypeDouble && xy.type == FcTypeDouble &&
yx.type == FcTypeDouble && yy.type == FcTypeDouble)
{
m.xx = xx.u.d;
m.xy = xy.u.d;
m.yx = yx.u.d;
m.yy = yy.u.d;
v.u.m = &m;
}
else
v.type = FcTypeVoid;
v = FcValueSave (v);
}
break; break;
case FcOpCharSet: case FcOpCharSet:
v.type = FcTypeCharSet; v.type = FcTypeCharSet;

View File

@ -249,11 +249,17 @@ FcExprPrint (const FcExpr *expr)
case FcOpInteger: printf ("%d", expr->u.ival); break; case FcOpInteger: printf ("%d", expr->u.ival); break;
case FcOpDouble: printf ("%g", expr->u.dval); break; case FcOpDouble: printf ("%g", expr->u.dval); break;
case FcOpString: printf ("\"%s\"", expr->u.sval); break; case FcOpString: printf ("\"%s\"", expr->u.sval); break;
case FcOpMatrix: printf ("[%g %g %g %g]", case FcOpMatrix:
expr->u.mval->xx, printf ("[");
expr->u.mval->xy, FcExprPrint (expr->u.mexpr->xx);
expr->u.mval->yx, printf (" ");
expr->u.mval->yy); break; FcExprPrint (expr->u.mexpr->xy);
printf (" ");
FcExprPrint (expr->u.mexpr->yx);
printf (" ");
FcExprPrint (expr->u.mexpr->yx);
printf ("]");
break;
case FcOpRange: break; case FcOpRange: break;
case FcOpBool: printf ("%s", expr->u.bval ? "true" : "false"); break; case FcOpBool: printf ("%s", expr->u.bval ? "true" : "false"); break;
case FcOpCharSet: printf ("charset\n"); break; case FcOpCharSet: printf ("charset\n"); break;

View File

@ -251,13 +251,17 @@ typedef enum _FcOpFlags {
#define FC_OP_GET_FLAGS(_x_) (((_x_) & 0xffff0000) >> 16) #define FC_OP_GET_FLAGS(_x_) (((_x_) & 0xffff0000) >> 16)
#define FC_OP(_x_,_f_) (FC_OP_GET_OP (_x_) | ((_f_) << 16)) #define FC_OP(_x_,_f_) (FC_OP_GET_OP (_x_) | ((_f_) << 16))
typedef struct _FcExprMatrix {
struct _FcExpr *xx, *xy, *yx, *yy;
} FcExprMatrix;
typedef struct _FcExpr { typedef struct _FcExpr {
FcOp op; FcOp op;
union { union {
int ival; int ival;
double dval; double dval;
const FcChar8 *sval; const FcChar8 *sval;
FcMatrix *mval; FcExprMatrix *mexpr;
FcBool bval; FcBool bval;
FcCharSet *cval; FcCharSet *cval;
FcLangSet *lval; FcLangSet *lval;

View File

@ -105,14 +105,48 @@ FcExprCreateString (FcConfig *config, const FcChar8 *s)
return e; return e;
} }
static FcExprMatrix *
FcExprMatrixCopyShallow (const FcExprMatrix *matrix)
{
FcExprMatrix *m = malloc (sizeof (FcExprMatrix));
if (m)
{
*m = *matrix;
}
return m;
}
static void
FcExprMatrixFreeShallow (FcExprMatrix *m)
{
if (!m)
return;
free (m);
}
static void
FcExprMatrixFree (FcExprMatrix *m)
{
if (!m)
return;
FcExprDestroy (m->xx);
FcExprDestroy (m->xy);
FcExprDestroy (m->yx);
FcExprDestroy (m->yy);
free (m);
}
static FcExpr * static FcExpr *
FcExprCreateMatrix (FcConfig *config, const FcMatrix *m) FcExprCreateMatrix (FcConfig *config, const FcExprMatrix *matrix)
{ {
FcExpr *e = FcConfigAllocExpr (config); FcExpr *e = FcConfigAllocExpr (config);
if (e) if (e)
{ {
e->op = FcOpMatrix; e->op = FcOpMatrix;
e->u.mval = FcMatrixCopy (m); e->u.mexpr = FcExprMatrixCopyShallow (matrix);
} }
return e; return e;
} }
@ -204,7 +238,7 @@ FcExprDestroy (FcExpr *e)
FcSharedStrFree (e->u.sval); FcSharedStrFree (e->u.sval);
break; break;
case FcOpMatrix: case FcOpMatrix:
FcMatrixFree (e->u.mval); FcExprMatrixFree (e->u.mexpr);
break; break;
case FcOpRange: case FcOpRange:
break; break;
@ -451,7 +485,7 @@ typedef struct _FcVStack {
int integer; int integer;
double _double; double _double;
FcMatrix *matrix; FcExprMatrix *matrix;
FcRange range; FcRange range;
FcBool bool_; FcBool bool_;
FcCharSet *charset; FcCharSet *charset;
@ -516,6 +550,10 @@ FcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, const char *fmt,
} }
static FcExpr *
FcPopExpr (FcConfigParse *parse);
static const char * static const char *
FcTypeName (FcType type) FcTypeName (FcType type)
{ {
@ -767,16 +805,13 @@ FcVStackPushDouble (FcConfigParse *parse, double _double)
} }
static FcBool static FcBool
FcVStackPushMatrix (FcConfigParse *parse, FcMatrix *matrix) FcVStackPushMatrix (FcConfigParse *parse, FcExprMatrix *matrix)
{ {
FcVStack *vstack; FcVStack *vstack;
matrix = FcMatrixCopy (matrix);
if (!matrix)
return FcFalse;
vstack = FcVStackCreateAndPush (parse); vstack = FcVStackCreateAndPush (parse);
if (!vstack) if (!vstack)
return FcFalse; return FcFalse;
vstack->u.matrix = matrix; vstack->u.matrix = FcExprMatrixCopyShallow (matrix);
vstack->tag = FcVStackMatrix; vstack->tag = FcVStackMatrix;
return FcTrue; return FcTrue;
} }
@ -921,7 +956,7 @@ FcVStackPopAndDestroy (FcConfigParse *parse)
case FcVStackDouble: case FcVStackDouble:
break; break;
case FcVStackMatrix: case FcVStackMatrix:
FcMatrixFree (vstack->u.matrix); FcExprMatrixFreeShallow (vstack->u.matrix);
break; break;
case FcVStackRange: case FcVStackRange:
case FcVStackBool: case FcVStackBool:
@ -1304,38 +1339,18 @@ static void
FcParseMatrix (FcConfigParse *parse) FcParseMatrix (FcConfigParse *parse)
{ {
FcVStack *vstack; FcVStack *vstack;
enum { m_done, m_xx, m_xy, m_yx, m_yy } matrix_state = m_yy; FcExprMatrix m;
FcMatrix m; int i;
while ((vstack = FcVStackPeek (parse))) m.yy = FcPopExpr (parse);
{ m.yx = FcPopExpr (parse);
double v; m.xy = FcPopExpr (parse);
switch (vstack->tag) { m.xx = FcPopExpr (parse);
case FcVStackInteger:
v = vstack->u.integer; if (FcPopExpr (parse))
break; FcConfigMessage (parse, FcSevereError, "wrong number of matrix elements");
case FcVStackDouble:
v = vstack->u._double;
break;
default:
FcConfigMessage (parse, FcSevereError, "non-double matrix element");
v = 1.0;
break;
}
switch (matrix_state) {
case m_xx: m.xx = v; break;
case m_xy: m.xy = v; break;
case m_yx: m.yx = v; break;
case m_yy: m.yy = v; break;
default: break;
}
FcVStackPopAndDestroy (parse);
matrix_state--;
}
if (matrix_state != m_done)
FcConfigMessage (parse, FcSevereError, "wrong number of matrix elements");
else else
FcVStackPushMatrix (parse, &m); FcVStackPushMatrix (parse, &m);
} }
static void static void
@ -2426,7 +2441,7 @@ FcPopValue (FcConfigParse *parse)
value.type = FcTypeDouble; value.type = FcTypeDouble;
break; break;
case FcVStackMatrix: case FcVStackMatrix:
value.u.m = FcMatrixCopy (vstack->u.matrix); value.u.m = FcExprMatrixCopyShallow (vstack->u.matrix);
if (value.u.m) if (value.u.m)
value.type = FcTypeMatrix; value.type = FcTypeMatrix;
break; break;