Allow target="font/pattern/default" in <name> elements
authorBehdad Esfahbod <behdad@behdad.org>
Sun, 30 Dec 2012 04:58:38 +0000 (23:58 -0500)
committerBehdad Esfahbod <behdad@behdad.org>
Mon, 31 Dec 2012 01:01:23 +0000 (19:01 -0600)
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

fonts.dtd
src/fccfg.c
src/fcdbg.c
src/fcint.h
src/fcxml.c

index 6b33e75..def8c21 100644 (file)
--- a/fonts.dtd
+++ b/fonts.dtd
 <!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;)*>
index 97345be..1454f33 100644 (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
index 5b8d3da..20fc6c8 100644 (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);
index 652f52d..68074f0 100644 (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;
index 21666d0..d31caf5 100644 (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;
@@ -865,6 +866,18 @@ FcVStackPushLangSet (FcConfigParse *parse, FcLangSet *langset)
 }
 
 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)
 {
     FcVStack    *vstack = FcVStackCreateAndPush (parse);
@@ -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);
@@ -1322,6 +1336,47 @@ FcParseString (FcConfigParse *parse, FcVStackTag tag)
 }
 
 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)
 {
     FcExprMatrix m;
@@ -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);