From d420e1df983871ab18b0f07976596fdf0ce78847 Mon Sep 17 00:00:00 2001 From: Akira TAGOH Date: Thu, 4 Jul 2013 19:51:03 +0900 Subject: [PATCH] Rework to apply the intermixed test and edit elements in one-pass --- src/fccfg.c | 367 ++++++++++++++++++++++++---------------------------- src/fcdbg.c | 39 ++++-- src/fcint.h | 29 +++-- src/fcxml.c | 247 ++++++++++++++++------------------- 4 files changed, 331 insertions(+), 351 deletions(-) diff --git a/src/fccfg.c b/src/fccfg.c index 3cf31e8..7ea94b8 100644 --- a/src/fccfg.c +++ b/src/fccfg.c @@ -214,10 +214,8 @@ FcSubstDestroy (FcSubst *s) while (s) { n = s->next; - if (s->test) - FcTestDestroy (s->test); - if (s->edit) - FcEditDestroy (s->edit); + if (s->rule) + FcRuleDestroy (s->rule); free (s); s = n; } @@ -226,8 +224,6 @@ FcSubstDestroy (FcSubst *s) FcExpr * FcConfigAllocExpr (FcConfig *config) { - FcExpr *e; - if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end) { FcExprPage *new_page; @@ -241,10 +237,7 @@ FcConfigAllocExpr (FcConfig *config) config->expr_pool = new_page; } - e = config->expr_pool->next++; - FcRefInit (&e->ref, 1); - - return e; + return config->expr_pool->next++; } FcConfig * @@ -649,15 +642,13 @@ FcConfigSetRescanInverval (FcConfig *config, int rescanInterval) return FcConfigSetRescanInterval (config, rescanInterval); } - FcBool -FcConfigAddEdit (FcConfig *config, - FcTest *test, - FcEdit *edit, +FcConfigAddRule (FcConfig *config, + FcRule *rule, FcMatchKind kind) { FcSubst *subst, **prev; - FcTest *t; + FcRule *r; int num; switch (kind) { @@ -678,15 +669,18 @@ FcConfigAddEdit (FcConfig *config, return FcFalse; for (; *prev; prev = &(*prev)->next); *prev = subst; - subst->next = 0; - subst->test = test; - subst->edit = edit; + subst->next = NULL; + subst->rule = rule; num = 0; - for (t = test; t; t = t->next) + for (r = rule; r; r = r->next) { - if (t->kind == FcMatchDefault) - t->kind = kind; - num++; + if (r->type == FcRuleTest) + { + if (r->u.test && + r->u.test->kind == FcMatchDefault) + r->u.test->kind = kind; + num++; + } } if (config->maxObjects < num) config->maxObjects = num; @@ -1491,13 +1485,12 @@ FcConfigSubstituteWithPat (FcConfig *config, { FcValue v; FcSubst *s; - FcSubState *st; - int i; - FcTest *t; - FcEdit *e; - FcValueList *l; + FcRule *r; + FcValueList *l, *value = NULL; FcPattern *m; FcStrSet *strs; + FcPatternElt *elt = NULL; + FcObject object = FC_INVALID_OBJECT; if (!config) { @@ -1542,10 +1535,6 @@ FcConfigSubstituteWithPat (FcConfig *config, return FcFalse; } - st = (FcSubState *) malloc (config->maxObjects * sizeof (FcSubState)); - if (!st && config->maxObjects) - return FcFalse; - if (FcDebug () & FC_DBG_EDIT) { printf ("FcConfigSubstitute "); @@ -1553,194 +1542,174 @@ FcConfigSubstituteWithPat (FcConfig *config, } for (; s; s = s->next) { - /* - * Check the tests to see if - * they all match the pattern - */ - for (t = s->test, i = 0; t; t = t->next, i++) + r = s->rule; + for (; r; r = r->next) { - if (FcDebug () & FC_DBG_EDIT) - { - printf ("FcConfigSubstitute test "); - FcTestPrint (t); - } - st[i].elt = 0; - if (kind == FcMatchFont && t->kind == FcMatchPattern) - m = p_pat; - else - m = p; - if (m) - st[i].elt = FcPatternObjectFindElt (m, t->object); - else - st[i].elt = 0; - /* - * If there's no such field in the font, - * then FcQualAll matches while FcQualAny does not - */ - if (!st[i].elt) - { - if (t->qual == FcQualAll) + switch (r->type) { + case FcRuleUnknown: + /* shouldn't be reached */ + break; + case FcRuleTest: + /* + * Check the tests to see if + * they all match the pattern + */ + if (FcDebug () & FC_DBG_EDIT) { - st[i].value = 0; - continue; + printf ("FcConfigSubstitute test "); + FcTestPrint (r->u.test); } + if (kind == FcMatchFont && r->u.test->kind == FcMatchPattern) + m = p_pat; else - break; - } - /* - * Check to see if there is a match, mark the location - * to apply match-relative edits - */ - 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) - break; - if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values) - break; - } - if (t) - { - if (FcDebug () & FC_DBG_EDIT) - printf ("No match\n"); - continue; - } - if (FcDebug () & FC_DBG_EDIT) - { - printf ("Substitute "); - FcSubstPrint (s); - } - for (e = s->edit; e; e = e->next) - { - /* - * Evaluate the list of expressions - */ - 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 - * the font - */ - for (t = s->test, i = 0; t; t = t->next, i++) - { - if ((t->kind == FcMatchFont || kind == FcMatchPattern) && - t->object == e->object) - { - /* - * KLUDGE - the pattern may have been reallocated or - * things may have been inserted or deleted above - * this element by other edits. Go back and find - * the element again - */ - if (e != s->edit && st[i].elt) - st[i].elt = FcPatternObjectFindElt (p, t->object); - if (!st[i].elt) - t = 0; - break; - } - } - switch (FC_OP_GET_OP (e->op)) { - case FcOpAssign: + m = p; + if (m) + elt = FcPatternObjectFindElt (m, r->u.test->object); + else + elt = NULL; /* - * If there was a test, then replace the matched - * value with the new list of values + * If there's no such field in the font, + * then FcQualAll matches while FcQualAny does not */ - if (t) + if (!elt) { - FcValueList *thisValue = st[i].value; - FcValueList *nextValue = thisValue; - - /* - * Append the new list of values after the current value - */ - FcConfigAdd (&st[i].elt->values, thisValue, FcTrue, l, e->object); - /* - * Delete the marked value - */ - if (thisValue) - FcConfigDel (&st[i].elt->values, thisValue); - /* - * Adjust any pointers into the value list to ensure - * future edits occur at the same place - */ - for (t = s->test, i = 0; t; t = t->next, i++) + if (r->u.test->qual == FcQualAll) { - if (st[i].value == thisValue) - st[i].value = nextValue; + value = NULL; + continue; } - break; - } - /* fall through ... */ - case FcOpAssignReplace: - /* - * Delete all of the values and insert - * the new set - */ - FcConfigPatternDel (p, e->object); - FcConfigPatternAdd (p, e->object, l, FcTrue); - /* - * Adjust any pointers into the value list as they no - * longer point to anything valid - */ - if (t) - { - FcPatternElt *thisElt = st[i].elt; - for (t = s->test, i = 0; t; t = t->next, i++) + else { - if (st[i].elt == thisElt) - st[i].value = 0; + if (FcDebug () & FC_DBG_EDIT) + printf ("No match\n"); + goto bail; } } - break; - case FcOpPrepend: - if (t) + /* + * Check to see if there is a match, mark the location + * to apply match-relative edits + */ + value = FcConfigMatchValueList (m, p_pat, kind, r->u.test, elt->values); + if (!value || + (r->u.test->qual == FcQualFirst && value != elt->values) || + (r->u.test->qual == FcQualNotFirst && value == elt->values)) { - FcConfigAdd (&st[i].elt->values, st[i].value, FcFalse, l, e->object); - break; + if (FcDebug () & FC_DBG_EDIT) + printf ("No match\n"); + goto bail; } - /* fall through ... */ - case FcOpPrependFirst: - FcConfigPatternAdd (p, e->object, l, FcFalse); + object = r->u.test->object; break; - case FcOpAppend: - if (t) + case FcRuleEdit: + if (FcDebug () & FC_DBG_EDIT) { - FcConfigAdd (&st[i].elt->values, st[i].value, FcTrue, l, e->object); - break; + printf ("Substitute "); + FcEditPrint (r->u.edit); + printf ("\n\n"); } - /* fall through ... */ - case FcOpAppendLast: - FcConfigPatternAdd (p, e->object, l, FcTrue); - break; - case FcOpDelete: - if (t) - { - FcConfigDel (&st[i].elt->values, st[i].value); - break; - } - /* fall through ... */ - case FcOpDeleteAll: - FcConfigPatternDel (p, e->object); - break; - default: - FcValueListDestroy (l); - break; - } - } - /* - * Now go through the pattern and eliminate - * any properties without data - */ - for (e = s->edit; e; e = e->next) - FcConfigPatternCanon (p, e->object); + /* + * Evaluate the list of expressions + */ + l = FcConfigValues (p, p_pat,kind, r->u.edit->expr, r->u.edit->binding); + /* + * Locate any test associated with this field, skipping + * tests associated with the pattern when substituting in + * the font + */ + if (object != r->u.edit->object) + value = NULL; - if (FcDebug () & FC_DBG_EDIT) - { - printf ("FcConfigSubstitute edit"); - FcPatternPrint (p); + switch (FC_OP_GET_OP (r->u.edit->op)) { + case FcOpAssign: + /* + * If there was a test, then replace the matched + * value with the new list of values + */ + if (value) + { + FcValueList *thisValue = value; + FcValueList *nextValue = thisValue; + + /* + * Append the new list of values after the current value + */ + FcConfigAdd (&elt->values, thisValue, FcTrue, l, r->u.edit->object); + /* + * Delete the marked value + */ + if (thisValue) + FcConfigDel (&elt->values, thisValue); + /* + * Adjust a pointer into the value list to ensure + * future edits occur at the same place + */ + value = nextValue; + break; + } + /* fall through ... */ + case FcOpAssignReplace: + /* + * Delete all of the values and insert + * the new set + */ + FcConfigPatternDel (p, r->u.edit->object); + FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue); + /* + * Adjust a pointer into the value list as they no + * longer point to anything valid + */ + value = NULL; + break; + case FcOpPrepend: + if (value) + { + FcConfigAdd (&elt->values, value, FcFalse, l, r->u.edit->object); + break; + } + /* fall through ... */ + case FcOpPrependFirst: + FcConfigPatternAdd (p, r->u.edit->object, l, FcFalse); + break; + case FcOpAppend: + if (value) + { + FcConfigAdd (&elt->values, value, FcTrue, l, r->u.edit->object); + break; + } + /* fall through ... */ + case FcOpAppendLast: + FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue); + break; + case FcOpDelete: + if (value) + { + FcConfigDel (&elt->values, value); + break; + } + /* fall through ... */ + case FcOpDeleteAll: + FcConfigPatternDel (p, r->u.edit->object); + break; + default: + FcValueListDestroy (l); + break; + } + /* + * Now go through the pattern and eliminate + * any properties without data + */ + FcConfigPatternCanon (p, r->u.edit->object); + + if (FcDebug () & FC_DBG_EDIT) + { + printf ("FcConfigSubstitute edit"); + FcPatternPrint (p); + } + break; + } } + bail:; } - free (st); if (FcDebug () & FC_DBG_EDIT) { printf ("FcConfigSubstitute done"); diff --git a/src/fcdbg.c b/src/fcdbg.c index ce64214..d74bc27 100644 --- a/src/fcdbg.c +++ b/src/fcdbg.c @@ -427,21 +427,38 @@ FcEditPrint (const FcEdit *edit) void FcSubstPrint (const FcSubst *subst) { - FcEdit *e; - FcTest *t; + FcRule *r; + FcRuleType last_type = FcRuleUnknown; printf ("match\n"); - for (t = subst->test; t; t = t->next) + for (r = subst->rule; r; r = r->next) { + if (last_type != r->type) + { + switch (r->type) { + case FcRuleTest: + printf ("[test]\n"); + break; + case FcRuleEdit: + printf ("[edit]\n"); + break; + default: + break; + } + last_type = r->type; + } printf ("\t"); - FcTestPrint (t); - } - printf ("edit\n"); - for (e = subst->edit; e; e = e->next) - { - printf ("\t"); - FcEditPrint (e); - printf (";\n"); + switch (r->type) { + case FcRuleTest: + FcTestPrint (r->u.test); + break; + case FcRuleEdit: + FcEditPrint (r->u.edit); + printf (";\n"); + break; + default: + break; + } } printf ("\n"); } diff --git a/src/fcint.h b/src/fcint.h index 9dff033..fe523fb 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -241,7 +241,6 @@ typedef struct _FcExprName { typedef struct _FcExpr { FcOp op; - FcRef ref; union { int ival; double dval; @@ -275,7 +274,6 @@ typedef enum _FcQual { #define FcMatchDefault ((FcMatchKind) -1) typedef struct _FcTest { - struct _FcTest *next; FcMatchKind kind; FcQual qual; FcObject object; @@ -284,17 +282,28 @@ typedef struct _FcTest { } FcTest; typedef struct _FcEdit { - struct _FcEdit *next; FcObject object; FcOp op; FcExpr *expr; FcValueBinding binding; } FcEdit; +typedef enum _FcRuleType { + FcRuleUnknown, FcRuleTest, FcRuleEdit +} FcRuleType; + +typedef struct _FcRule { + struct _FcRule *next; + FcRuleType type; + union { + FcTest *test; + FcEdit *edit; + } u; +} FcRule; + typedef struct _FcSubst { struct _FcSubst *next; - FcTest *test; - FcEdit *edit; + FcRule *rule; } FcSubst; typedef struct _FcCharLeaf { @@ -614,10 +623,9 @@ FcPrivate FcBool FcConfigAddBlank (FcConfig *config, FcChar32 blank); -FcPrivate FcBool -FcConfigAddEdit (FcConfig *config, - FcTest *test, - FcEdit *edit, +FcBool +FcConfigAddRule (FcConfig *config, + FcRule *rule, FcMatchKind kind); FcPrivate void @@ -844,6 +852,9 @@ FcTestDestroy (FcTest *test); FcPrivate void FcEditDestroy (FcEdit *e); +void +FcRuleDestroy (FcRule *rule); + /* fclang.c */ FcPrivate FcLangSet * FcFreeTypeLangSet (const FcCharSet *charset, diff --git a/src/fcxml.c b/src/fcxml.c index 4b8049f..61dc630 100644 --- a/src/fcxml.c +++ b/src/fcxml.c @@ -62,12 +62,28 @@ FcExprDestroy (FcExpr *e); void FcTestDestroy (FcTest *test) { - if (test->next) - FcTestDestroy (test->next); FcExprDestroy (test->expr); free (test); } +void +FcRuleDestroy (FcRule *rule) +{ + if (rule->next) + FcRuleDestroy (rule->next); + switch (rule->type) { + case FcRuleTest: + FcTestDestroy (rule->u.test); + break; + case FcRuleEdit: + FcEditDestroy (rule->u.edit); + break; + default: + break; + } + free (rule); +} + static FcExpr * FcExprCreateInteger (FcConfig *config, int i) { @@ -223,24 +239,11 @@ FcExprCreateOp (FcConfig *config, FcExpr *left, FcOp op, FcExpr *right) return e; } -static FcExpr * -FcExprReference (FcExpr *e) -{ - if (e) - { - FcRefInc (&e->ref); - } - - return e; -} - static void FcExprDestroy (FcExpr *e) { if (!e) return; - if (FcRefDec (&e->ref) != 1) - return; switch (FC_OP_GET_OP (e->op)) { case FcOpInteger: break; @@ -313,8 +316,6 @@ FcExprDestroy (FcExpr *e) void FcEditDestroy (FcEdit *e) { - if (e->next) - FcEditDestroy (e->next); if (e->expr) FcExprDestroy (e->expr); free (e); @@ -727,7 +728,6 @@ FcTestCreate (FcConfigParse *parse, { const FcObjectType *o; - test->next = 0; test->kind = kind; test->qual = qual; test->object = FcObjectFromName ((const char *) field); @@ -740,21 +740,6 @@ FcTestCreate (FcConfigParse *parse, return test; } -static FcTest * -FcTestDuplicate (FcTest *test) -{ - FcTest *retval = (FcTest *) malloc (sizeof (FcTest)); - - if (retval) - { - memcpy (retval, test, sizeof (FcTest)); - retval->next = NULL; - retval->expr = FcExprReference (test->expr); - } - - return retval; -} - static FcEdit * FcEditCreate (FcConfigParse *parse, FcObject object, @@ -768,7 +753,6 @@ FcEditCreate (FcConfigParse *parse, { const FcObjectType *o; - e->next = 0; e->object = object; e->op = op; e->expr = expr; @@ -780,6 +764,34 @@ FcEditCreate (FcConfigParse *parse, return e; } +static FcRule * +FcRuleCreate (FcRuleType type, + void *p) +{ + FcRule *r = (FcRule *) malloc (sizeof (FcRule)); + + if (!r) + return NULL; + + r->next = NULL; + r->type = type; + switch (type) + { + case FcRuleTest: + r->u.test = (FcTest *) p; + break; + case FcRuleEdit: + r->u.edit = (FcEdit *) p; + break; + default: + free (r); + r = NULL; + break; + } + + return r; +} + static FcVStack * FcVStackCreateAndPush (FcConfigParse *parse) { @@ -1685,9 +1697,9 @@ static void FcParseAlias (FcConfigParse *parse) { FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0; - FcEdit *edit = 0, *next; + FcEdit *edit = 0; FcVStack *vstack; - FcTest *test = NULL; + FcRule *rule = NULL, *r; FcValueBinding binding; if (!FcConfigLexBinding (parse, FcConfigGetAttribute (parse, "binding"), &binding)) @@ -1732,8 +1744,14 @@ FcParseAlias (FcConfigParse *parse) vstack->tag = FcVStackNone; break; case FcVStackTest: - vstack->u.test->next = test; - test = vstack->u.test; + if (rule) + { + r = FcRuleCreate (FcRuleTest, vstack->u.test); + r->next = rule; + rule = r; + } + else + rule = FcRuleCreate (FcRuleTest, vstack->u.test); vstack->tag = FcVStackNone; break; default: @@ -1751,8 +1769,35 @@ FcParseAlias (FcConfigParse *parse) FcExprDestroy (accept); if (def) FcExprDestroy (def); + if (rule) + FcRuleDestroy (rule); return; } + if (!prefer && + !accept && + !def) + { + FcExprDestroy (family); + return; + } + else + { + FcTest *t = FcTestCreate (parse, FcMatchPattern, + FcQualAny, + (FcChar8 *) FC_FAMILY, + FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks), + family); + if (rule) + { + for (r = rule; r->next; r = r->next); + r->next = FcRuleCreate (FcRuleTest, t); + r = r->next; + } + else + { + r = rule = FcRuleCreate (FcRuleTest, t); + } + } if (prefer) { edit = FcEditCreate (parse, @@ -1760,60 +1805,46 @@ FcParseAlias (FcConfigParse *parse) FcOpPrepend, prefer, binding); - if (edit) - edit->next = 0; - else + if (!edit) FcExprDestroy (prefer); + else + { + r->next = FcRuleCreate (FcRuleEdit, edit); + r = r->next; + } } if (accept) { - next = edit; edit = FcEditCreate (parse, FC_FAMILY_OBJECT, FcOpAppend, accept, binding); - if (edit) - edit->next = next; - else + if (!edit) FcExprDestroy (accept); + else + { + r->next = FcRuleCreate (FcRuleEdit, edit); + r = r->next; + } } if (def) { - next = edit; edit = FcEditCreate (parse, FC_FAMILY_OBJECT, FcOpAppendLast, def, binding); - if (edit) - edit->next = next; - else + if (!edit) FcExprDestroy (def); - } - if (edit) - { - FcTest *t = FcTestCreate (parse, FcMatchPattern, - FcQualAny, - (FcChar8 *) FC_FAMILY, - FC_OP (FcOpEqual, FcOpFlagIgnoreBlanks), - family); - if (test) - { - FcTest *p = test; - - while (p->next) - p = p->next; - p->next = t; - } else - test = t; - if (test) - if (!FcConfigAddEdit (parse->config, test, edit, FcMatchPattern)) - FcTestDestroy (test); + { + r->next = FcRuleCreate (FcRuleEdit, edit); + r = r->next; + } } - else - FcExprDestroy (family); + if (!FcConfigAddRule (parse->config, rule, FcMatchPattern)) + FcRuleDestroy (rule); } static FcExpr * @@ -2414,22 +2445,14 @@ FcParseEdit (FcConfigParse *parse) FcEditDestroy (edit); } -typedef struct FcSubstStack { - FcTest *test; - FcEdit *edit; -} FcSubstStack; - static void FcParseMatch (FcConfigParse *parse) { const FcChar8 *kind_name; FcMatchKind kind; - FcTest *test = 0; FcEdit *edit = 0; FcVStack *vstack; - FcBool tested = FcFalse; - FcSubstStack *sstack = NULL; - int len, pos = 0, i; + FcRule *rule = NULL, *r; kind_name = FcConfigGetAttribute (parse, "target"); if (!kind_name) @@ -2448,55 +2471,29 @@ FcParseMatch (FcConfigParse *parse) return; } } - len = FcVStackElements(parse); - if (len > 0) - { - sstack = malloc (sizeof (FcSubstStack) * (len + 1)); - if (!sstack) - { - FcConfigMessage (parse, FcSevereError, "out of memory"); - return; - } - } while ((vstack = FcVStackPeek (parse))) { switch ((int) vstack->tag) { case FcVStackTest: - vstack->u.test->next = test; - test = vstack->u.test; + r = FcRuleCreate (FcRuleTest, vstack->u.test); + if (rule) + r->next = rule; + rule = r; vstack->tag = FcVStackNone; - tested = FcTrue; - for (i = 0; i < pos; i++) - { - FcTest *t = FcTestDuplicate(test); - - t->next = sstack[i].test; - sstack[i].test = t; - } break; case FcVStackEdit: - /* due to the reverse traversal, node appears faster than - * node if any. so we have to deal with it here rather than - * the above in FcVStackTest, and put recipes in reverse order. - */ - if (tested) - { - sstack[pos].test = test; - sstack[pos].edit = edit; - pos++; - test = NULL; - edit = NULL; - tested = FcFalse; - } - vstack->u.edit->next = edit; - edit = vstack->u.edit; - vstack->tag = FcVStackNone; - if (kind == FcMatchScan && edit->object > FC_MAX_BASE_OBJECT) + if (kind == FcMatchScan && vstack->u.edit->object > FC_MAX_BASE_OBJECT) { FcConfigMessage (parse, FcSevereError, " cannot edit user-defined object \"%s\"", FcObjectName(edit->object)); + break; } + r = FcRuleCreate (FcRuleEdit, vstack->u.edit); + if (rule) + r->next = rule; + rule = r; + vstack->tag = FcVStackNone; break; default: FcConfigMessage (parse, FcSevereWarning, "invalid match element"); @@ -2504,22 +2501,8 @@ FcParseMatch (FcConfigParse *parse) } FcVStackPopAndDestroy (parse); } - if (!FcConfigAddEdit (parse->config, test, edit, kind)) + if (!FcConfigAddRule (parse->config, rule, kind)) FcConfigMessage (parse, FcSevereError, "out of memory"); - if (sstack) - { - int i; - - for (i = 0; i < pos; i++) - { - if (!FcConfigAddEdit (parse->config, sstack[pos - i - 1].test, sstack[pos - i - 1].edit, kind)) - { - FcConfigMessage (parse, FcSevereError, "out of memory"); - return; - } - } - free (sstack); - } } static void