Fix wrong edit position

This commit is contained in:
Akira TAGOH 2013-08-05 20:04:13 +09:00
parent 338ffe6b88
commit a51d2767ce
3 changed files with 72 additions and 35 deletions

View File

@ -674,12 +674,21 @@ FcConfigAddRule (FcConfig *config,
num = 0; num = 0;
for (r = rule; r; r = r->next) for (r = rule; r; r = r->next)
{ {
if (r->type == FcRuleTest) switch (r->type)
{ {
case FcRuleTest:
if (r->u.test && if (r->u.test &&
r->u.test->kind == FcMatchDefault) r->u.test->kind == FcMatchDefault)
r->u.test->kind = kind; r->u.test->kind = kind;
num++; if (r->u.test->object > FC_MAX_BASE_OBJECT)
num++;
break;
case FcRuleEdit:
if (r->u.edit->object > FC_MAX_BASE_OBJECT)
num++;
break;
default:
break;
} }
} }
if (config->maxObjects < num) if (config->maxObjects < num)
@ -1486,11 +1495,15 @@ FcConfigSubstituteWithPat (FcConfig *config,
FcValue v; FcValue v;
FcSubst *s; FcSubst *s;
FcRule *r; FcRule *r;
FcValueList *l, *value = NULL; FcValueList *l, **value = NULL;
FcPattern *m; FcPattern *m;
FcStrSet *strs; FcStrSet *strs;
FcPatternElt *elt = NULL;
FcObject object = FC_INVALID_OBJECT; FcObject object = FC_INVALID_OBJECT;
FcPatternElt **elt = NULL;
int i, nobjs;
FcBool retval = FcTrue;
#define FC_OBJ_ID(_n_) ((_n_) > FC_MAX_BASE_OBJECT ? ((_n_) - FC_EXT_OBJ_INDEX) : (_n_))
if (!config) if (!config)
{ {
@ -1535,6 +1548,20 @@ FcConfigSubstituteWithPat (FcConfig *config,
return FcFalse; return FcFalse;
} }
nobjs = FC_MAX_BASE_OBJECT + config->maxObjects + 2;
value = (FcValueList **) malloc (SIZEOF_VOID_P * nobjs);
if (!value)
{
retval = FcFalse;
goto bail1;
}
elt = (FcPatternElt **) malloc (SIZEOF_VOID_P * nobjs);
if (!elt)
{
retval = FcFalse;
goto bail1;
}
if (FcDebug () & FC_DBG_EDIT) if (FcDebug () & FC_DBG_EDIT)
{ {
printf ("FcConfigSubstitute "); printf ("FcConfigSubstitute ");
@ -1543,6 +1570,11 @@ FcConfigSubstituteWithPat (FcConfig *config,
for (; s; s = s->next) for (; s; s = s->next)
{ {
r = s->rule; r = s->rule;
for (i = 0; i < nobjs; i++)
{
elt[i] = NULL;
value[i] = NULL;
}
for (; r; r = r->next) for (; r; r = r->next)
{ {
switch (r->type) { switch (r->type) {
@ -1550,6 +1582,7 @@ FcConfigSubstituteWithPat (FcConfig *config,
/* shouldn't be reached */ /* shouldn't be reached */
break; break;
case FcRuleTest: case FcRuleTest:
object = FC_OBJ_ID (r->u.test->object);
/* /*
* Check the tests to see if * Check the tests to see if
* they all match the pattern * they all match the pattern
@ -1564,18 +1597,16 @@ FcConfigSubstituteWithPat (FcConfig *config,
else else
m = p; m = p;
if (m) if (m)
elt = FcPatternObjectFindElt (m, r->u.test->object); elt[object] = FcPatternObjectFindElt (m, r->u.test->object);
else
elt = NULL;
/* /*
* If there's no such field in the font, * If there's no such field in the font,
* then FcQualAll matches while FcQualAny does not * then FcQualAll matches while FcQualAny does not
*/ */
if (!elt) if (!elt[object])
{ {
if (r->u.test->qual == FcQualAll) if (r->u.test->qual == FcQualAll)
{ {
value = NULL; value[object] = NULL;
continue; continue;
} }
else else
@ -1589,18 +1620,18 @@ 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
*/ */
value = FcConfigMatchValueList (m, p_pat, kind, r->u.test, elt->values); value[object] = FcConfigMatchValueList (m, p_pat, kind, r->u.test, elt[object]->values);
if (!value || if (!value[object] ||
(r->u.test->qual == FcQualFirst && value != elt->values) || (r->u.test->qual == FcQualFirst && value[object] != elt[object]->values) ||
(r->u.test->qual == FcQualNotFirst && value == elt->values)) (r->u.test->qual == FcQualNotFirst && value[object] == elt[object]->values))
{ {
if (FcDebug () & FC_DBG_EDIT) if (FcDebug () & FC_DBG_EDIT)
printf ("No match\n"); printf ("No match\n");
goto bail; goto bail;
} }
object = r->u.test->object;
break; break;
case FcRuleEdit: case FcRuleEdit:
object = FC_OBJ_ID (r->u.edit->object);
if (FcDebug () & FC_DBG_EDIT) if (FcDebug () & FC_DBG_EDIT)
{ {
printf ("Substitute "); printf ("Substitute ");
@ -1611,13 +1642,6 @@ FcConfigSubstituteWithPat (FcConfig *config,
* Evaluate the list of expressions * Evaluate the list of expressions
*/ */
l = FcConfigValues (p, p_pat,kind, r->u.edit->expr, r->u.edit->binding); 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;
switch (FC_OP_GET_OP (r->u.edit->op)) { switch (FC_OP_GET_OP (r->u.edit->op)) {
case FcOpAssign: case FcOpAssign:
@ -1625,25 +1649,25 @@ FcConfigSubstituteWithPat (FcConfig *config,
* If there was a test, then replace the matched * If there was a test, then replace the matched
* value with the new list of values * value with the new list of values
*/ */
if (value) if (value[object])
{ {
FcValueList *thisValue = value; FcValueList *thisValue = value[object];
FcValueList *nextValue = thisValue; FcValueList *nextValue = thisValue;
/* /*
* Append the new list of values after the current value * Append the new list of values after the current value
*/ */
FcConfigAdd (&elt->values, thisValue, FcTrue, l, r->u.edit->object); FcConfigAdd (&elt[object]->values, thisValue, FcTrue, l, r->u.edit->object);
/* /*
* Delete the marked value * Delete the marked value
*/ */
if (thisValue) if (thisValue)
FcConfigDel (&elt->values, thisValue); FcConfigDel (&elt[object]->values, thisValue);
/* /*
* Adjust a pointer into the value list to ensure * Adjust a pointer into the value list to ensure
* future edits occur at the same place * future edits occur at the same place
*/ */
value = nextValue; value[object] = nextValue;
break; break;
} }
/* fall through ... */ /* fall through ... */
@ -1658,12 +1682,12 @@ FcConfigSubstituteWithPat (FcConfig *config,
* Adjust a pointer into the value list as they no * Adjust a pointer into the value list as they no
* longer point to anything valid * longer point to anything valid
*/ */
value = NULL; value[object] = NULL;
break; break;
case FcOpPrepend: case FcOpPrepend:
if (value) if (value[object])
{ {
FcConfigAdd (&elt->values, value, FcFalse, l, r->u.edit->object); FcConfigAdd (&elt[object]->values, value[object], FcFalse, l, r->u.edit->object);
break; break;
} }
/* fall through ... */ /* fall through ... */
@ -1671,9 +1695,9 @@ FcConfigSubstituteWithPat (FcConfig *config,
FcConfigPatternAdd (p, r->u.edit->object, l, FcFalse); FcConfigPatternAdd (p, r->u.edit->object, l, FcFalse);
break; break;
case FcOpAppend: case FcOpAppend:
if (value) if (value[object])
{ {
FcConfigAdd (&elt->values, value, FcTrue, l, r->u.edit->object); FcConfigAdd (&elt[object]->values, value[object], FcTrue, l, r->u.edit->object);
break; break;
} }
/* fall through ... */ /* fall through ... */
@ -1681,9 +1705,9 @@ FcConfigSubstituteWithPat (FcConfig *config,
FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue); FcConfigPatternAdd (p, r->u.edit->object, l, FcTrue);
break; break;
case FcOpDelete: case FcOpDelete:
if (value) if (value[object])
{ {
FcConfigDel (&elt->values, value); FcConfigDel (&elt[object]->values, value[object]);
break; break;
} }
/* fall through ... */ /* fall through ... */
@ -1715,7 +1739,15 @@ FcConfigSubstituteWithPat (FcConfig *config,
printf ("FcConfigSubstitute done"); printf ("FcConfigSubstitute done");
FcPatternPrint (p); FcPatternPrint (p);
} }
return FcTrue; bail1:
if (elt)
free (elt);
if (value)
free (value);
#undef FC_OBJ_ID
return retval;
} }
FcBool FcBool

View File

@ -174,6 +174,11 @@ typedef struct _FcValueList {
typedef int FcObject; typedef int FcObject;
/* The 1000 is to leave some room for future added internal objects, such
* that caches from newer fontconfig can still be used with older fontconfig
* without getting confused. */
#define FC_EXT_OBJ_INDEX 1000
typedef struct _FcPatternElt *FcPatternEltPtr; typedef struct _FcPatternElt *FcPatternEltPtr;
/* /*

View File

@ -37,7 +37,7 @@ FcObjectTypeLookup (register const char *str, register unsigned int len);
/* The 1000 is to leave some room for future added internal objects, such /* The 1000 is to leave some room for future added internal objects, such
* that caches from newer fontconfig can still be used with older fontconfig * that caches from newer fontconfig can still be used with older fontconfig
* without getting confused. */ * without getting confused. */
static fc_atomic_int_t next_id = FC_MAX_BASE_OBJECT + 1000; static fc_atomic_int_t next_id = FC_MAX_BASE_OBJECT + FC_EXT_OBJ_INDEX;
struct FcObjectOtherTypeInfo { struct FcObjectOtherTypeInfo {
struct FcObjectOtherTypeInfo *next; struct FcObjectOtherTypeInfo *next;
FcObjectType object; FcObjectType object;