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:
parent
927dd3ddb5
commit
4f6767470f
|
@ -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)>
|
||||||
|
|
24
src/fccfg.c
24
src/fccfg.c
|
@ -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;
|
||||||
|
|
16
src/fcdbg.c
16
src/fcdbg.c
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
97
src/fcxml.c
97
src/fcxml.c
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue