Implement new semantics for Contains and LISTING:
LISTING requires that the font Contain all of the pattern values, where Contain is redefined for strings to mean precise matching (so that Courier 10 Pitch doesn't list Courier fonts) "Contains" for lang means both langs have the same language and either the same country or one is missing the country
This commit is contained in:
parent
26da2bb42f
commit
74a623e02e
79
src/fccfg.c
79
src/fccfg.c
|
@ -514,42 +514,43 @@ FcConfigPromote (FcValue v, FcValue u)
|
||||||
}
|
}
|
||||||
|
|
||||||
FcBool
|
FcBool
|
||||||
FcConfigCompareValue (const FcValue m_o,
|
FcConfigCompareValue (const FcValue left_o,
|
||||||
FcOp op,
|
FcOp op,
|
||||||
const FcValue v_o)
|
const FcValue right_o)
|
||||||
{
|
{
|
||||||
FcValue m = m_o;
|
FcValue left = left_o;
|
||||||
FcValue v = v_o;
|
FcValue right = right_o;
|
||||||
FcBool ret = FcFalse;
|
FcBool ret = FcFalse;
|
||||||
|
|
||||||
m = FcConfigPromote (m, v);
|
left = FcConfigPromote (left, right);
|
||||||
v = FcConfigPromote (v, m);
|
right = FcConfigPromote (right, left);
|
||||||
if (m.type == v.type)
|
if (left.type == right.type)
|
||||||
{
|
{
|
||||||
switch (m.type) {
|
switch (left.type) {
|
||||||
case FcTypeInteger:
|
case FcTypeInteger:
|
||||||
break; /* FcConfigPromote prevents this from happening */
|
break; /* FcConfigPromote prevents this from happening */
|
||||||
case FcTypeDouble:
|
case FcTypeDouble:
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case FcOpEqual:
|
case FcOpEqual:
|
||||||
case FcOpContains:
|
case FcOpContains:
|
||||||
ret = m.u.d == v.u.d;
|
case FcOpListing:
|
||||||
|
ret = left.u.d == right.u.d;
|
||||||
break;
|
break;
|
||||||
case FcOpNotEqual:
|
case FcOpNotEqual:
|
||||||
case FcOpNotContains:
|
case FcOpNotContains:
|
||||||
ret = m.u.d != v.u.d;
|
ret = left.u.d != right.u.d;
|
||||||
break;
|
break;
|
||||||
case FcOpLess:
|
case FcOpLess:
|
||||||
ret = m.u.d < v.u.d;
|
ret = left.u.d < right.u.d;
|
||||||
break;
|
break;
|
||||||
case FcOpLessEqual:
|
case FcOpLessEqual:
|
||||||
ret = m.u.d <= v.u.d;
|
ret = left.u.d <= right.u.d;
|
||||||
break;
|
break;
|
||||||
case FcOpMore:
|
case FcOpMore:
|
||||||
ret = m.u.d > v.u.d;
|
ret = left.u.d > right.u.d;
|
||||||
break;
|
break;
|
||||||
case FcOpMoreEqual:
|
case FcOpMoreEqual:
|
||||||
ret = m.u.d >= v.u.d;
|
ret = left.u.d >= right.u.d;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -559,11 +560,12 @@ FcConfigCompareValue (const FcValue m_o,
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case FcOpEqual:
|
case FcOpEqual:
|
||||||
case FcOpContains:
|
case FcOpContains:
|
||||||
ret = m.u.b == v.u.b;
|
case FcOpListing:
|
||||||
|
ret = left.u.b == right.u.b;
|
||||||
break;
|
break;
|
||||||
case FcOpNotEqual:
|
case FcOpNotEqual:
|
||||||
case FcOpNotContains:
|
case FcOpNotContains:
|
||||||
ret = m.u.b != v.u.b;
|
ret = left.u.b != right.u.b;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -572,16 +574,15 @@ FcConfigCompareValue (const FcValue m_o,
|
||||||
case FcTypeString:
|
case FcTypeString:
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case FcOpEqual:
|
case FcOpEqual:
|
||||||
ret = FcStrCmpIgnoreCase (m.u.s, v.u.s) == 0;
|
case FcOpListing:
|
||||||
|
ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
|
||||||
break;
|
break;
|
||||||
case FcOpContains:
|
case FcOpContains:
|
||||||
ret = FcStrStrIgnoreCase (m.u.s, v.u.s) != 0;
|
ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0;
|
||||||
break;
|
break;
|
||||||
case FcOpNotEqual:
|
case FcOpNotEqual:
|
||||||
ret = FcStrCmpIgnoreCase (m.u.s, v.u.s) != 0;
|
|
||||||
break;
|
|
||||||
case FcOpNotContains:
|
case FcOpNotContains:
|
||||||
ret = FcStrStrIgnoreCase (m.u.s, v.u.s) == 0;
|
ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -591,11 +592,12 @@ FcConfigCompareValue (const FcValue m_o,
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case FcOpEqual:
|
case FcOpEqual:
|
||||||
case FcOpContains:
|
case FcOpContains:
|
||||||
ret = FcMatrixEqual (m.u.m, v.u.m);
|
case FcOpListing:
|
||||||
|
ret = FcMatrixEqual (left.u.m, right.u.m);
|
||||||
break;
|
break;
|
||||||
case FcOpNotEqual:
|
case FcOpNotEqual:
|
||||||
case FcOpNotContains:
|
case FcOpNotContains:
|
||||||
ret = !FcMatrixEqual (m.u.m, v.u.m);
|
ret = !FcMatrixEqual (left.u.m, right.u.m);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -604,18 +606,19 @@ FcConfigCompareValue (const FcValue m_o,
|
||||||
case FcTypeCharSet:
|
case FcTypeCharSet:
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case FcOpContains:
|
case FcOpContains:
|
||||||
/* v contains m if m is a subset of v */
|
case FcOpListing:
|
||||||
ret = FcCharSetIsSubset (m.u.c, v.u.c);
|
/* left contains right if right is a subset of left */
|
||||||
|
ret = FcCharSetIsSubset (right.u.c, left.u.c);
|
||||||
break;
|
break;
|
||||||
case FcOpNotContains:
|
case FcOpNotContains:
|
||||||
/* v contains m if m is a subset of v */
|
/* left contains right if right is a subset of left */
|
||||||
ret = !FcCharSetIsSubset (m.u.c, v.u.c);
|
ret = !FcCharSetIsSubset (right.u.c, left.u.c);
|
||||||
break;
|
break;
|
||||||
case FcOpEqual:
|
case FcOpEqual:
|
||||||
ret = FcCharSetEqual (m.u.c, v.u.c);
|
ret = FcCharSetEqual (left.u.c, right.u.c);
|
||||||
break;
|
break;
|
||||||
case FcOpNotEqual:
|
case FcOpNotEqual:
|
||||||
ret = !FcCharSetEqual (m.u.c, v.u.c);
|
ret = !FcCharSetEqual (left.u.c, right.u.c);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -624,16 +627,17 @@ FcConfigCompareValue (const FcValue m_o,
|
||||||
case FcTypeLangSet:
|
case FcTypeLangSet:
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case FcOpContains:
|
case FcOpContains:
|
||||||
ret = FcLangSetContains (m.u.l, v.u.l);
|
case FcOpListing:
|
||||||
|
ret = FcLangSetContains (left.u.l, right.u.l);
|
||||||
break;
|
break;
|
||||||
case FcOpNotContains:
|
case FcOpNotContains:
|
||||||
ret = FcLangSetContains (m.u.l, v.u.l);
|
ret = FcLangSetContains (left.u.l, right.u.l);
|
||||||
break;
|
break;
|
||||||
case FcOpEqual:
|
case FcOpEqual:
|
||||||
ret = FcLangSetEqual (m.u.l, v.u.l);
|
ret = FcLangSetEqual (left.u.l, right.u.l);
|
||||||
break;
|
break;
|
||||||
case FcOpNotEqual:
|
case FcOpNotEqual:
|
||||||
ret = !FcLangSetEqual (m.u.l, v.u.l);
|
ret = !FcLangSetEqual (left.u.l, right.u.l);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -643,6 +647,7 @@ FcConfigCompareValue (const FcValue m_o,
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case FcOpEqual:
|
case FcOpEqual:
|
||||||
case FcOpContains:
|
case FcOpContains:
|
||||||
|
case FcOpListing:
|
||||||
ret = FcTrue;
|
ret = FcTrue;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -653,11 +658,12 @@ FcConfigCompareValue (const FcValue m_o,
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case FcOpEqual:
|
case FcOpEqual:
|
||||||
case FcOpContains:
|
case FcOpContains:
|
||||||
ret = m.u.f == v.u.f;
|
case FcOpListing:
|
||||||
|
ret = left.u.f == right.u.f;
|
||||||
break;
|
break;
|
||||||
case FcOpNotEqual:
|
case FcOpNotEqual:
|
||||||
case FcOpNotContains:
|
case FcOpNotContains:
|
||||||
ret = m.u.f != v.u.f;
|
ret = left.u.f != right.u.f;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -748,6 +754,7 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
|
||||||
case FcOpMoreEqual:
|
case FcOpMoreEqual:
|
||||||
case FcOpContains:
|
case FcOpContains:
|
||||||
case FcOpNotContains:
|
case FcOpNotContains:
|
||||||
|
case FcOpListing:
|
||||||
vl = FcConfigEvaluate (p, e->u.tree.left);
|
vl = FcConfigEvaluate (p, e->u.tree.left);
|
||||||
vr = FcConfigEvaluate (p, e->u.tree.right);
|
vr = FcConfigEvaluate (p, e->u.tree.right);
|
||||||
v.type = FcTypeBool;
|
v.type = FcTypeBool;
|
||||||
|
@ -952,6 +959,7 @@ FcConfigMatchValueList (FcPattern *p,
|
||||||
|
|
||||||
while (e)
|
while (e)
|
||||||
{
|
{
|
||||||
|
/* Compute the value of the match expression */
|
||||||
if (e->op == FcOpComma)
|
if (e->op == FcOpComma)
|
||||||
{
|
{
|
||||||
value = FcConfigEvaluate (p, e->u.tree.left);
|
value = FcConfigEvaluate (p, e->u.tree.left);
|
||||||
|
@ -965,6 +973,7 @@ FcConfigMatchValueList (FcPattern *p,
|
||||||
|
|
||||||
for (v = values; v; v = v->next)
|
for (v = values; v; v = v->next)
|
||||||
{
|
{
|
||||||
|
/* Compare the pattern value to the match expression value */
|
||||||
if (FcConfigCompareValue (v->value, t->op, value))
|
if (FcConfigCompareValue (v->value, t->op, value))
|
||||||
{
|
{
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
|
|
@ -157,6 +157,7 @@ FcOpPrint (FcOp op)
|
||||||
case FcOpCeil: printf ("Ceil"); break;
|
case FcOpCeil: printf ("Ceil"); break;
|
||||||
case FcOpRound: printf ("Round"); break;
|
case FcOpRound: printf ("Round"); break;
|
||||||
case FcOpTrunc: printf ("Trunc"); break;
|
case FcOpTrunc: printf ("Trunc"); break;
|
||||||
|
case FcOpListing: printf ("Listing"); break;
|
||||||
case FcOpInvalid: printf ("Invalid"); break;
|
case FcOpInvalid: printf ("Invalid"); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,6 +202,7 @@ FcExprPrint (const FcExpr *expr)
|
||||||
case FcOpMore:
|
case FcOpMore:
|
||||||
case FcOpMoreEqual:
|
case FcOpMoreEqual:
|
||||||
case FcOpContains:
|
case FcOpContains:
|
||||||
|
case FcOpListing:
|
||||||
case FcOpNotContains:
|
case FcOpNotContains:
|
||||||
case FcOpPlus:
|
case FcOpPlus:
|
||||||
case FcOpMinus:
|
case FcOpMinus:
|
||||||
|
@ -225,6 +227,7 @@ FcExprPrint (const FcExpr *expr)
|
||||||
case FcOpMore: printf ("More"); break;
|
case FcOpMore: printf ("More"); break;
|
||||||
case FcOpMoreEqual: printf ("MoreEqual"); break;
|
case FcOpMoreEqual: printf ("MoreEqual"); break;
|
||||||
case FcOpContains: printf ("Contains"); break;
|
case FcOpContains: printf ("Contains"); break;
|
||||||
|
case FcOpListing: printf ("Listing"); break;
|
||||||
case FcOpNotContains: printf ("NotContains"); break;
|
case FcOpNotContains: printf ("NotContains"); break;
|
||||||
case FcOpPlus: printf ("Plus"); break;
|
case FcOpPlus: printf ("Plus"); break;
|
||||||
case FcOpMinus: printf ("Minus"); break;
|
case FcOpMinus: printf ("Minus"); break;
|
||||||
|
|
|
@ -132,7 +132,8 @@ typedef enum _FcOp {
|
||||||
FcOpAssign, FcOpAssignReplace,
|
FcOpAssign, FcOpAssignReplace,
|
||||||
FcOpPrependFirst, FcOpPrepend, FcOpAppend, FcOpAppendLast,
|
FcOpPrependFirst, FcOpPrepend, FcOpAppend, FcOpAppendLast,
|
||||||
FcOpQuest,
|
FcOpQuest,
|
||||||
FcOpOr, FcOpAnd, FcOpEqual, FcOpNotEqual, FcOpContains, FcOpNotContains,
|
FcOpOr, FcOpAnd, FcOpEqual, FcOpNotEqual,
|
||||||
|
FcOpContains, FcOpListing, FcOpNotContains,
|
||||||
FcOpLess, FcOpLessEqual, FcOpMore, FcOpMoreEqual,
|
FcOpLess, FcOpLessEqual, FcOpMore, FcOpMoreEqual,
|
||||||
FcOpPlus, FcOpMinus, FcOpTimes, FcOpDivide,
|
FcOpPlus, FcOpMinus, FcOpTimes, FcOpDivide,
|
||||||
FcOpNot, FcOpComma, FcOpFloor, FcOpCeil, FcOpRound, FcOpTrunc,
|
FcOpNot, FcOpComma, FcOpFloor, FcOpCeil, FcOpRound, FcOpTrunc,
|
||||||
|
|
18
src/fclang.c
18
src/fclang.c
|
@ -144,29 +144,33 @@ FcLangCompare (const FcChar8 *s1, const FcChar8 *s2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return FcTrue when s1 contains s2.
|
* Return FcTrue when super contains sub.
|
||||||
*
|
*
|
||||||
* s1 contains s2 if s1 equals s2 or if s1 is a
|
* super contains sub if super and sub have the same
|
||||||
* language with a country and s2 is just a language
|
* language and either the same country or one
|
||||||
|
* is missing the country
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
FcLangContains (const FcChar8 *s1, const FcChar8 *s2)
|
FcLangContains (const FcChar8 *super, const FcChar8 *sub)
|
||||||
{
|
{
|
||||||
FcChar8 c1, c2;
|
FcChar8 c1, c2;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
c1 = *s1++;
|
c1 = *super++;
|
||||||
c2 = *s2++;
|
c2 = *sub++;
|
||||||
|
|
||||||
c1 = FcToLower (c1);
|
c1 = FcToLower (c1);
|
||||||
c2 = FcToLower (c2);
|
c2 = FcToLower (c2);
|
||||||
if (c1 != c2)
|
if (c1 != c2)
|
||||||
{
|
{
|
||||||
/* see if s1 has a country while s2 is mising one */
|
/* see if super has a country while sub is mising one */
|
||||||
if (c1 == '-' && c2 == '\0')
|
if (c1 == '-' && c2 == '\0')
|
||||||
return FcTrue;
|
return FcTrue;
|
||||||
|
/* see if sub has a country while super is mising one */
|
||||||
|
if (c1 == '\0' && c2 == '-')
|
||||||
|
return FcTrue;
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
}
|
}
|
||||||
else if (!c1)
|
else if (!c1)
|
||||||
|
|
36
src/fclist.c
36
src/fclist.c
|
@ -120,18 +120,34 @@ FcObjectSetBuild (const char *first, ...)
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Font must have a containing value for every value in the pattern
|
||||||
|
*/
|
||||||
static FcBool
|
static FcBool
|
||||||
FcListValueListMatchAny (FcValueList *v1orig,
|
FcListValueListMatchAny (FcValueList *patOrig, /* pattern */
|
||||||
FcValueList *v2orig)
|
FcValueList *fntOrig) /* font */
|
||||||
{
|
{
|
||||||
FcValueList *v1, *v2;
|
FcValueList *pat, *fnt;
|
||||||
|
|
||||||
for (v1 = v1orig; v1; v1 = v1->next)
|
for (pat = patOrig; pat; pat = pat->next)
|
||||||
for (v2 = v2orig; v2; v2 = v2->next)
|
{
|
||||||
if (FcConfigCompareValue (v1->value, FcOpContains, v2->value))
|
for (fnt = fntOrig; fnt; fnt = fnt->next)
|
||||||
return FcTrue;
|
{
|
||||||
|
/*
|
||||||
|
* make sure the font 'contains' the pattern.
|
||||||
|
* (OpListing is OpContains except for strings
|
||||||
|
* where it requires an exact match)
|
||||||
|
*/
|
||||||
|
if (FcConfigCompareValue (fnt->value,
|
||||||
|
FcOpListing,
|
||||||
|
pat->value))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!fnt)
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
}
|
}
|
||||||
|
return FcTrue;
|
||||||
|
}
|
||||||
|
|
||||||
static FcBool
|
static FcBool
|
||||||
FcListValueListEqual (FcValueList *v1orig,
|
FcListValueListEqual (FcValueList *v1orig,
|
||||||
|
@ -196,7 +212,8 @@ FcListPatternMatchAny (FcPattern *p,
|
||||||
e = FcPatternFindElt (font, p->elts[i].object);
|
e = FcPatternFindElt (font, p->elts[i].object);
|
||||||
if (!e)
|
if (!e)
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
if (!FcListValueListMatchAny (p->elts[i].values, e->values))
|
if (!FcListValueListMatchAny (p->elts[i].values, /* pat elts */
|
||||||
|
e->values)) /* font elts */
|
||||||
return FcFalse;
|
return FcFalse;
|
||||||
}
|
}
|
||||||
return FcTrue;
|
return FcTrue;
|
||||||
|
@ -415,7 +432,8 @@ FcFontSetList (FcConfig *config,
|
||||||
if (!s)
|
if (!s)
|
||||||
continue;
|
continue;
|
||||||
for (f = 0; f < s->nfont; f++)
|
for (f = 0; f < s->nfont; f++)
|
||||||
if (FcListPatternMatchAny (p, s->fonts[f]))
|
if (FcListPatternMatchAny (p, /* pattern */
|
||||||
|
s->fonts[f])) /* font */
|
||||||
if (!FcListAppend (&table, s->fonts[f], os))
|
if (!FcListAppend (&table, s->fonts[f], os))
|
||||||
goto bail1;
|
goto bail1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,6 +243,7 @@ FcExprDestroy (FcExpr *e)
|
||||||
case FcOpMore:
|
case FcOpMore:
|
||||||
case FcOpMoreEqual:
|
case FcOpMoreEqual:
|
||||||
case FcOpContains:
|
case FcOpContains:
|
||||||
|
case FcOpListing:
|
||||||
case FcOpNotContains:
|
case FcOpNotContains:
|
||||||
case FcOpPlus:
|
case FcOpPlus:
|
||||||
case FcOpMinus:
|
case FcOpMinus:
|
||||||
|
|
Loading…
Reference in New Issue