Allow target="font/pattern/default" in <name> elements

Based on idea from Raimund Steger.

For example, one can do something like this:

<match target="font">
  <test name="scalable" compare="eq">
    <bool>false</bool>
  </test>
  <edit name="pixelsizefixupfactor" mode="assign">
    <divide>
      <name target="pattern">pixelsize</name>
      <name target="font"   >pixelsize</name>
    </divide>
  </edit>
  <edit name="matrix" mode="assign">
    <times>
      <name>matrix</name>
      <matrix>
        <name>pixelsizefixupfactor</name> <double>0</double>
        <double>0</double> <name>pixelsizefixupfactor</name>
       </matrix>
    </times>
  </edit>
</match>

Part of work to make bitmap font scaling possible.  See thread
discussion:

http://lists.freedesktop.org/archives/fontconfig/2012-December/004498.html
This commit is contained in:
Behdad Esfahbod 2012-12-29 23:58:38 -05:00
parent d7e1965aa0
commit 51b0044648
5 changed files with 118 additions and 41 deletions

View File

@ -207,7 +207,8 @@
<!ELEMENT range (int,int)> <!ELEMENT range (int,int)>
<!ELEMENT langset (string)*> <!ELEMENT langset (string)*>
<!ELEMENT name (#PCDATA)> <!ELEMENT name (#PCDATA)>
<!ATTLIST name xml:space (default|preserve) 'preserve'> <!ATTLIST name xml:space (default|preserve) 'preserve'
target (default|font|pattern) 'default'>
<!ELEMENT const (#PCDATA)> <!ELEMENT const (#PCDATA)>
<!ATTLIST const xml:space (default|preserve) 'preserve'> <!ATTLIST const xml:space (default|preserve) 'preserve'>
<!ELEMENT or (%expr;)*> <!ELEMENT or (%expr;)*>

View File

@ -867,7 +867,7 @@ FcConfigCompareValue (const FcValue *left_o,
#define FcDoubleTrunc(d) ((d) >= 0 ? _FcDoubleFloor (d) : -_FcDoubleFloor (-(d))) #define FcDoubleTrunc(d) ((d) >= 0 ? _FcDoubleFloor (d) : -_FcDoubleFloor (-(d)))
static FcValue static FcValue
FcConfigEvaluate (FcPattern *p, FcExpr *e) FcConfigEvaluate (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e)
{ {
FcValue v, vl, vr; FcValue v, vl, vr;
FcResult r; FcResult r;
@ -894,10 +894,10 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
FcMatrix m; FcMatrix m;
FcValue xx, xy, yx, yy; FcValue xx, xy, yx, yy;
v.type = FcTypeMatrix; v.type = FcTypeMatrix;
xx = FcConfigPromote (FcConfigEvaluate (p, e->u.mexpr->xx), v); xx = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->xx), v);
xy = FcConfigPromote (FcConfigEvaluate (p, e->u.mexpr->xy), v); xy = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->xy), v);
yx = FcConfigPromote (FcConfigEvaluate (p, e->u.mexpr->yx), v); yx = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->yx), v);
yy = FcConfigPromote (FcConfigEvaluate (p, e->u.mexpr->yy), v); yy = FcConfigPromote (FcConfigEvaluate (p, p_pat, kind, e->u.mexpr->yy), v);
if (xx.type == FcTypeDouble && xy.type == FcTypeDouble && if (xx.type == FcTypeDouble && xy.type == FcTypeDouble &&
yx.type == FcTypeDouble && yy.type == FcTypeDouble) yx.type == FcTypeDouble && yy.type == FcTypeDouble)
{ {
@ -927,7 +927,10 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
v.u.b = e->u.bval; v.u.b = e->u.bval;
break; break;
case FcOpField: case FcOpField:
r = FcPatternObjectGet (p, e->u.object, 0, &v); if (kind == FcMatchFont && e->u.name.kind == FcMatchPattern)
r = FcPatternObjectGet (p_pat, e->u.name.object, 0, &v);
else
r = FcPatternObjectGet (p, e->u.name.object, 0, &v);
if (r != FcResultMatch) if (r != FcResultMatch)
v.type = FcTypeVoid; v.type = FcTypeVoid;
v = FcValueSave (v); v = FcValueSave (v);
@ -939,13 +942,13 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
v.type = FcTypeVoid; v.type = FcTypeVoid;
break; break;
case FcOpQuest: case FcOpQuest:
vl = FcConfigEvaluate (p, e->u.tree.left); vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
if (vl.type == FcTypeBool) if (vl.type == FcTypeBool)
{ {
if (vl.u.b) if (vl.u.b)
v = FcConfigEvaluate (p, e->u.tree.right->u.tree.left); v = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right->u.tree.left);
else else
v = FcConfigEvaluate (p, e->u.tree.right->u.tree.right); v = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right->u.tree.right);
} }
else else
v.type = FcTypeVoid; v.type = FcTypeVoid;
@ -960,8 +963,8 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
case FcOpContains: case FcOpContains:
case FcOpNotContains: case FcOpNotContains:
case FcOpListing: case FcOpListing:
vl = FcConfigEvaluate (p, e->u.tree.left); vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
vr = FcConfigEvaluate (p, e->u.tree.right); vr = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right);
v.type = FcTypeBool; v.type = FcTypeBool;
v.u.b = FcConfigCompareValue (&vl, e->op, &vr); v.u.b = FcConfigCompareValue (&vl, e->op, &vr);
FcValueDestroy (vl); FcValueDestroy (vl);
@ -973,8 +976,8 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
case FcOpMinus: case FcOpMinus:
case FcOpTimes: case FcOpTimes:
case FcOpDivide: case FcOpDivide:
vl = FcConfigEvaluate (p, e->u.tree.left); vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
vr = FcConfigEvaluate (p, e->u.tree.right); vr = FcConfigEvaluate (p, p_pat, kind, e->u.tree.right);
vl = FcConfigPromote (vl, vr); vl = FcConfigPromote (vl, vr);
vr = FcConfigPromote (vr, vl); vr = FcConfigPromote (vr, vl);
if (vl.type == vr.type) if (vl.type == vr.type)
@ -1109,7 +1112,7 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
FcValueDestroy (vr); FcValueDestroy (vr);
break; break;
case FcOpNot: case FcOpNot:
vl = FcConfigEvaluate (p, e->u.tree.left); vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
switch ((int) vl.type) { switch ((int) vl.type) {
case FcTypeBool: case FcTypeBool:
v.type = FcTypeBool; v.type = FcTypeBool;
@ -1122,7 +1125,7 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
FcValueDestroy (vl); FcValueDestroy (vl);
break; break;
case FcOpFloor: case FcOpFloor:
vl = FcConfigEvaluate (p, e->u.tree.left); vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
switch ((int) vl.type) { switch ((int) vl.type) {
case FcTypeInteger: case FcTypeInteger:
v = vl; v = vl;
@ -1138,7 +1141,7 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
FcValueDestroy (vl); FcValueDestroy (vl);
break; break;
case FcOpCeil: case FcOpCeil:
vl = FcConfigEvaluate (p, e->u.tree.left); vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
switch ((int) vl.type) { switch ((int) vl.type) {
case FcTypeInteger: case FcTypeInteger:
v = vl; v = vl;
@ -1154,7 +1157,7 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
FcValueDestroy (vl); FcValueDestroy (vl);
break; break;
case FcOpRound: case FcOpRound:
vl = FcConfigEvaluate (p, e->u.tree.left); vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
switch ((int) vl.type) { switch ((int) vl.type) {
case FcTypeInteger: case FcTypeInteger:
v = vl; v = vl;
@ -1170,7 +1173,7 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
FcValueDestroy (vl); FcValueDestroy (vl);
break; break;
case FcOpTrunc: case FcOpTrunc:
vl = FcConfigEvaluate (p, e->u.tree.left); vl = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
switch ((int) vl.type) { switch ((int) vl.type) {
case FcTypeInteger: case FcTypeInteger:
v = vl; v = vl;
@ -1194,6 +1197,8 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
static FcValueList * static FcValueList *
FcConfigMatchValueList (FcPattern *p, FcConfigMatchValueList (FcPattern *p,
FcPattern *p_pat,
FcMatchKind kind,
FcTest *t, FcTest *t,
FcValueList *values) FcValueList *values)
{ {
@ -1207,12 +1212,12 @@ FcConfigMatchValueList (FcPattern *p,
/* Compute the value of the match expression */ /* Compute the value of the match expression */
if (FC_OP_GET_OP (e->op) == FcOpComma) if (FC_OP_GET_OP (e->op) == FcOpComma)
{ {
value = FcConfigEvaluate (p, e->u.tree.left); value = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
e = e->u.tree.right; e = e->u.tree.right;
} }
else else
{ {
value = FcConfigEvaluate (p, e); value = FcConfigEvaluate (p, p_pat, kind, e);
e = 0; e = 0;
} }
@ -1239,7 +1244,7 @@ FcConfigMatchValueList (FcPattern *p,
} }
static FcValueList * static FcValueList *
FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding) FcConfigValues (FcPattern *p, FcPattern *p_pat, FcMatchKind kind, FcExpr *e, FcValueBinding binding)
{ {
FcValueList *l; FcValueList *l;
@ -1250,12 +1255,12 @@ FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding)
return 0; return 0;
if (FC_OP_GET_OP (e->op) == FcOpComma) if (FC_OP_GET_OP (e->op) == FcOpComma)
{ {
l->value = FcConfigEvaluate (p, e->u.tree.left); l->value = FcConfigEvaluate (p, p_pat, kind, e->u.tree.left);
l->next = FcConfigValues (p, e->u.tree.right, binding); l->next = FcConfigValues (p, p_pat, kind, e->u.tree.right, binding);
} }
else else
{ {
l->value = FcConfigEvaluate (p, e); l->value = FcConfigEvaluate (p, p_pat, kind, e);
l->next = NULL; l->next = NULL;
} }
l->binding = binding; l->binding = binding;
@ -1503,7 +1508,7 @@ FcConfigSubstituteWithPat (FcConfig *config,
* Check to see if there is a match, mark the location * Check to see if there is a match, mark the location
* to apply match-relative edits * to apply match-relative edits
*/ */
st[i].value = FcConfigMatchValueList (m, t, st[i].elt->values); st[i].value = FcConfigMatchValueList (m, p_pat, kind, t, st[i].elt->values);
if (!st[i].value) if (!st[i].value)
break; break;
if (t->qual == FcQualFirst && st[i].value != st[i].elt->values) if (t->qual == FcQualFirst && st[i].value != st[i].elt->values)
@ -1527,7 +1532,7 @@ FcConfigSubstituteWithPat (FcConfig *config,
/* /*
* Evaluate the list of expressions * Evaluate the list of expressions
*/ */
l = FcConfigValues (p, e->expr, e->binding); l = FcConfigValues (p, p_pat,kind, e->expr, e->binding);
/* /*
* Locate any test associated with this field, skipping * Locate any test associated with this field, skipping
* tests associated with the pattern when substituting in * tests associated with the pattern when substituting in

View File

@ -43,10 +43,10 @@ _FcValuePrint (const FcValue v)
printf ("\"%s\"", v.u.s); printf ("\"%s\"", v.u.s);
break; break;
case FcTypeBool: case FcTypeBool:
printf ("%s", v.u.b ? "FcTrue" : "FcFalse"); printf ("%s", v.u.b ? "True" : "False");
break; break;
case FcTypeMatrix: case FcTypeMatrix:
printf ("(%f %f; %f %f)", v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy); printf ("[%g %g; %g %g]", v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
break; break;
case FcTypeCharSet: /* XXX */ case FcTypeCharSet: /* XXX */
FcCharSetPrint (v.u.c); FcCharSetPrint (v.u.c);
@ -254,10 +254,10 @@ FcExprPrint (const FcExpr *expr)
FcExprPrint (expr->u.mexpr->xx); FcExprPrint (expr->u.mexpr->xx);
printf (" "); printf (" ");
FcExprPrint (expr->u.mexpr->xy); FcExprPrint (expr->u.mexpr->xy);
printf (" "); printf ("; ");
FcExprPrint (expr->u.mexpr->yx); FcExprPrint (expr->u.mexpr->yx);
printf (" "); printf (" ");
FcExprPrint (expr->u.mexpr->yx); FcExprPrint (expr->u.mexpr->yy);
printf ("]"); printf ("]");
break; break;
case FcOpRange: break; case FcOpRange: break;
@ -269,7 +269,16 @@ FcExprPrint (const FcExpr *expr)
printf ("\n"); printf ("\n");
break; break;
case FcOpNil: printf ("nil\n"); break; case FcOpNil: printf ("nil\n"); break;
case FcOpField: printf ("%s", FcObjectName(expr->u.object)); 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 FcOpConst: printf ("%s", expr->u.constant); break;
case FcOpQuest: case FcOpQuest:
FcExprPrint (expr->u.tree.left); FcExprPrint (expr->u.tree.left);

View File

@ -227,6 +227,12 @@ typedef struct _FcExprMatrix {
struct _FcExpr *xx, *xy, *yx, *yy; struct _FcExpr *xx, *xy, *yx, *yy;
} FcExprMatrix; } FcExprMatrix;
typedef struct _FcExprName {
FcObject object;
FcMatchKind kind;
} FcExprName;
typedef struct _FcExpr { typedef struct _FcExpr {
FcOp op; FcOp op;
union { union {
@ -237,7 +243,8 @@ typedef struct _FcExpr {
FcBool bval; FcBool bval;
FcCharSet *cval; FcCharSet *cval;
FcLangSet *lval; FcLangSet *lval;
FcObject object;
FcExprName name;
const FcChar8 *constant; const FcChar8 *constant;
struct { struct {
struct _FcExpr *left, *right; struct _FcExpr *left, *right;

View File

@ -187,13 +187,13 @@ FcExprCreateLangSet (FcConfig *config, FcLangSet *langset)
} }
static FcExpr * static FcExpr *
FcExprCreateField (FcConfig *config, const char *field) FcExprCreateName (FcConfig *config, FcExprName name)
{ {
FcExpr *e = FcConfigAllocExpr (config); FcExpr *e = FcConfigAllocExpr (config);
if (e) if (e)
{ {
e->op = FcOpField; e->op = FcOpField;
e->u.object = FcObjectFromName (field); e->u.name = name;
} }
return e; return e;
} }
@ -453,9 +453,9 @@ typedef enum _FcVStackTag {
FcVStackString, FcVStackString,
FcVStackFamily, FcVStackFamily,
FcVStackField,
FcVStackConstant, FcVStackConstant,
FcVStackGlob, FcVStackGlob,
FcVStackName,
FcVStackPattern, FcVStackPattern,
FcVStackPrefer, FcVStackPrefer,
@ -489,6 +489,7 @@ typedef struct _FcVStack {
FcBool bool_; FcBool bool_;
FcCharSet *charset; FcCharSet *charset;
FcLangSet *langset; FcLangSet *langset;
FcExprName name;
FcTest *test; FcTest *test;
FcQual qual; FcQual qual;
@ -631,7 +632,7 @@ FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type)
case FcOpNil: case FcOpNil:
break; break;
case FcOpField: case FcOpField:
o = FcNameGetObjectType (FcObjectName (expr->u.object)); o = FcNameGetObjectType (FcObjectName (expr->u.name.object));
if (o) if (o)
FcTypecheckValue (parse, o->type, type); FcTypecheckValue (parse, o->type, type);
break; break;
@ -864,6 +865,18 @@ FcVStackPushLangSet (FcConfigParse *parse, FcLangSet *langset)
return FcTrue; return FcTrue;
} }
static FcBool
FcVStackPushName (FcConfigParse *parse, FcMatchKind kind, FcObject object)
{
FcVStack *vstack = FcVStackCreateAndPush (parse);
if (!vstack)
return FcFalse;
vstack->u.name.object = object;
vstack->u.name.kind = kind;
vstack->tag = FcVStackName;
return FcTrue;
}
static FcBool static FcBool
FcVStackPushTest (FcConfigParse *parse, FcTest *test) FcVStackPushTest (FcConfigParse *parse, FcTest *test)
{ {
@ -938,10 +951,11 @@ FcVStackPopAndDestroy (FcConfigParse *parse)
switch (vstack->tag) { switch (vstack->tag) {
case FcVStackNone: case FcVStackNone:
break; break;
case FcVStackName:
break;
case FcVStackFamily: case FcVStackFamily:
break; break;
case FcVStackString: case FcVStackString:
case FcVStackField:
case FcVStackConstant: case FcVStackConstant:
case FcVStackGlob: case FcVStackGlob:
FcStrFree (vstack->u.string); FcStrFree (vstack->u.string);
@ -1321,6 +1335,47 @@ FcParseString (FcConfigParse *parse, FcVStackTag tag)
FcStrFree (s); FcStrFree (s);
} }
static void
FcParseName (FcConfigParse *parse)
{
const FcChar8 *kind_string;
FcMatchKind kind;
FcChar8 *s;
FcObject object;
kind_string = FcConfigGetAttribute (parse, "target");
if (!kind_string)
kind = FcMatchDefault;
else
{
if (!strcmp ((char *) kind_string, "pattern"))
kind = FcMatchPattern;
else if (!strcmp ((char *) kind_string, "font"))
kind = FcMatchFont;
else if (!strcmp ((char *) kind_string, "default"))
kind = FcMatchDefault;
else
{
FcConfigMessage (parse, FcSevereWarning, "invalid name target \"%s\"", kind_string);
return;
}
}
if (!parse->pstack)
return;
s = FcStrBufDone (&parse->pstack->str);
if (!s)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
return;
}
object = FcObjectFromName ((const char *) s);
FcVStackPushName (parse, kind, object);
FcStrFree (s);
}
static void static void
FcParseMatrix (FcConfigParse *parse) FcParseMatrix (FcConfigParse *parse)
{ {
@ -1722,8 +1777,8 @@ FcPopExpr (FcConfigParse *parse)
case FcVStackFamily: case FcVStackFamily:
expr = FcExprCreateString (parse->config, vstack->u.string); expr = FcExprCreateString (parse->config, vstack->u.string);
break; break;
case FcVStackField: case FcVStackName:
expr = FcExprCreateField (parse->config, (char *) vstack->u.string); expr = FcExprCreateName (parse->config, vstack->u.name);
break; break;
case FcVStackConstant: case FcVStackConstant:
expr = FcExprCreateConst (parse->config, vstack->u.string); expr = FcExprCreateConst (parse->config, vstack->u.string);
@ -2619,7 +2674,7 @@ FcEndElement(void *userData, const XML_Char *name FC_UNUSED)
FcParsePatelt (parse); FcParsePatelt (parse);
break; break;
case FcElementName: case FcElementName:
FcParseString (parse, FcVStackField); FcParseName (parse);
break; break;
case FcElementConst: case FcElementConst:
FcParseString (parse, FcVStackConstant); FcParseString (parse, FcVStackConstant);