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 langset (string)*>
<!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)>
<!ATTLIST const xml:space (default|preserve) 'preserve'>
<!ELEMENT or (%expr;)*>

View File

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

View File

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

View File

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

View File

@ -187,13 +187,13 @@ FcExprCreateLangSet (FcConfig *config, FcLangSet *langset)
}
static FcExpr *
FcExprCreateField (FcConfig *config, const char *field)
FcExprCreateName (FcConfig *config, FcExprName name)
{
FcExpr *e = FcConfigAllocExpr (config);
if (e)
{
e->op = FcOpField;
e->u.object = FcObjectFromName (field);
e->u.name = name;
}
return e;
}
@ -453,9 +453,9 @@ typedef enum _FcVStackTag {
FcVStackString,
FcVStackFamily,
FcVStackField,
FcVStackConstant,
FcVStackGlob,
FcVStackName,
FcVStackPattern,
FcVStackPrefer,
@ -489,6 +489,7 @@ typedef struct _FcVStack {
FcBool bool_;
FcCharSet *charset;
FcLangSet *langset;
FcExprName name;
FcTest *test;
FcQual qual;
@ -631,7 +632,7 @@ FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type)
case FcOpNil:
break;
case FcOpField:
o = FcNameGetObjectType (FcObjectName (expr->u.object));
o = FcNameGetObjectType (FcObjectName (expr->u.name.object));
if (o)
FcTypecheckValue (parse, o->type, type);
break;
@ -864,6 +865,18 @@ FcVStackPushLangSet (FcConfigParse *parse, FcLangSet *langset)
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
FcVStackPushTest (FcConfigParse *parse, FcTest *test)
{
@ -938,10 +951,11 @@ FcVStackPopAndDestroy (FcConfigParse *parse)
switch (vstack->tag) {
case FcVStackNone:
break;
case FcVStackName:
break;
case FcVStackFamily:
break;
case FcVStackString:
case FcVStackField:
case FcVStackConstant:
case FcVStackGlob:
FcStrFree (vstack->u.string);
@ -1321,6 +1335,47 @@ FcParseString (FcConfigParse *parse, FcVStackTag tag)
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
FcParseMatrix (FcConfigParse *parse)
{
@ -1722,8 +1777,8 @@ FcPopExpr (FcConfigParse *parse)
case FcVStackFamily:
expr = FcExprCreateString (parse->config, vstack->u.string);
break;
case FcVStackField:
expr = FcExprCreateField (parse->config, (char *) vstack->u.string);
case FcVStackName:
expr = FcExprCreateName (parse->config, vstack->u.name);
break;
case FcVStackConstant:
expr = FcExprCreateConst (parse->config, vstack->u.string);
@ -2619,7 +2674,7 @@ FcEndElement(void *userData, const XML_Char *name FC_UNUSED)
FcParsePatelt (parse);
break;
case FcElementName:
FcParseString (parse, FcVStackField);
FcParseName (parse);
break;
case FcElementConst:
FcParseString (parse, FcVStackConstant);