static FcBool FcListValueListEqual (FcValueListPtr v1orig, FcValueListPtr v2orig) { FcValueListPtr v1, v2; for (v1 = v1orig; v1 != NULL; v1 = FcValueListNext(v1)) { for (v2 = v2orig; v2 != NULL; v2 = FcValueListNext(v2)) if (FcValueEqual (FcValueCanonicalize(&(v1)->value), FcValueCanonicalize(&(v2)->value))) break; if (v2 == NULL) return FcFalse; } for (v2 = v2orig; v2 != NULL; v2 = FcValueListNext(v2)) { for (v1 = v1orig; v1 != NULL; v1 = FcValueListNext(v1)) if (FcValueEqual (FcValueCanonicalize(&v1->value), FcValueCanonicalize(&v2->value))) break; if (v1 == NULL) return FcFalse; } return FcTrue; }
static FcChar32 FcListValueHash (FcValue *value) { FcValue v = FcValueCanonicalize(value); switch (v.type) { case FcTypeVoid: return 0; case FcTypeInteger: return (FcChar32) v.u.i; case FcTypeDouble: return (FcChar32) (int) v.u.d; case FcTypeString: return FcStrHashIgnoreCase (v.u.s); case FcTypeBool: return (FcChar32) v.u.b; case FcTypeMatrix: return FcListMatrixHash (v.u.m); case FcTypeCharSet: return FcCharSetCount (v.u.c); case FcTypeFTFace: return (long) v.u.f; case FcTypeLangSet: return FcLangSetHash (v.u.l); } return 0; }
static int FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object) { FcChar8 *lang = FcGetDefaultLang (); FcPatternElt *e = FcPatternObjectFindElt (font, object); FcValueListPtr v; FcValue value; int idx = -1; int i; if (e) { for (v = FcPatternEltValues(e), i = 0; v; v = FcValueListNext(v), ++i) { value = FcValueCanonicalize (&v->value); if (value.type == FcTypeString) { FcLangResult res = FcLangCompare (value.u.s, lang); if (res == FcLangEqual || (res == FcLangDifferentCountry && idx < 0)) idx = i; } } } return (idx > 0) ? idx : 0; }
FcBool FcNameUnparseValue (FcStrBuf *buf, FcValue *v0, FcChar8 *escape) { FcChar8 temp[1024]; FcValue v = FcValueCanonicalize(v0); switch (v.type) { case FcTypeUnknown: case FcTypeVoid: return FcTrue; case FcTypeInteger: sprintf ((char *) temp, "%d", v.u.i); return FcNameUnparseString (buf, temp, 0); case FcTypeDouble: sprintf ((char *) temp, "%g", v.u.d); return FcNameUnparseString (buf, temp, 0); case FcTypeString: return FcNameUnparseString (buf, v.u.s, escape); case FcTypeBool: return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0); case FcTypeMatrix: sprintf ((char *) temp, "%g %g %g %g", v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy); return FcNameUnparseString (buf, temp, 0); case FcTypeCharSet: return FcNameUnparseCharSet (buf, v.u.c); case FcTypeLangSet: return FcNameUnparseLangSet (buf, v.u.l); case FcTypeFTFace: return FcTrue; } return FcFalse; }
void FcValueListPrintWithPosition(FcValueListPtr l, const FcValueListPtr pos) { for (; l != NULL; l = FcValueListNext(l)) { FcValuePrintWithPosition(FcValueCanonicalize(&l->value), pos != NULL && l == pos); FcValueBindingPrint(l); } if (!pos) printf(" [marker]"); }
static double FcCompareLang (FcValue *v1, FcValue *v2) { FcLangResult result; FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2); switch (value1.type) { case FcTypeLangSet: switch (value2.type) { case FcTypeLangSet: result = FcLangSetCompare (value1.u.l, value2.u.l); break; case FcTypeString: result = FcLangSetHasLang (value1.u.l, value2.u.s); break; default: return -1.0; } break; case FcTypeString: switch (value2.type) { case FcTypeLangSet: result = FcLangSetHasLang (value2.u.l, value1.u.s); break; case FcTypeString: result = FcLangCompare (value1.u.s, value2.u.s); break; default: return -1.0; } break; default: return -1.0; } switch (result) { case FcLangEqual: return 0; case FcLangDifferentCountry: return 1; case FcLangDifferentLang: default: return 2; } }
void FcValueListPrint(FcValueListPtr l) { #ifdef _DEBUG for (; l != NULL; l = FcValueListNext(l)) { FcValuePrint(FcValueCanonicalize(&l->value)); FcValueBindingPrint(l); } #endif }
FcBool FcNameUnparseValue (FcStrBuf *buf, FcValue *v0, FcChar8 *escape) { FcChar8 temp[1024]; FcValue v = FcValueCanonicalize(v0); FcRange r; switch (v.type) { case FcTypeUnknown: case FcTypeVoid: return FcTrue; case FcTypeInteger: sprintf ((char *) temp, "%d", v.u.i); return FcNameUnparseString (buf, temp, 0); case FcTypeDouble: sprintf ((char *) temp, "%g", v.u.d); return FcNameUnparseString (buf, temp, 0); case FcTypeString: return FcNameUnparseString (buf, v.u.s, escape); case FcTypeBool: return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0); case FcTypeMatrix: sprintf ((char *) temp, "%g %g %g %g", v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy); return FcNameUnparseString (buf, temp, 0); case FcTypeCharSet: return FcNameUnparseCharSet (buf, v.u.c); case FcTypeLangSet: return FcNameUnparseLangSet (buf, v.u.l); case FcTypeFTFace: return FcTrue; case FcTypeRange: r = FcRangeCanonicalize (v.u.r); if (!FcDoubleIsZero (r.u.d.begin) || !FcDoubleIsZero (r.u.d.end)) { if (FcDoubleCmpEQ (r.u.d.begin, r.u.d.end)) sprintf ((char *) temp, "%g", r.u.d.begin); else sprintf ((char *) temp, "(%g %g)", r.u.d.begin, r.u.d.end); return FcNameUnparseString (buf, temp, 0); } else return FcTrue; } return FcFalse; }
void FcValueListPrint (FcValueListPtr l) { for (; l != NULL; l = FcValueListNext(l)) { FcValuePrint (FcValueCanonicalize(&l->value)); switch (l->binding) { case FcValueBindingWeak: printf ("(w)"); break; case FcValueBindingStrong: printf ("(s)"); break; case FcValueBindingSame: printf ("(=)"); break; } } }
static int FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object, const FcChar8 *lang) { FcPatternElt *e = FcPatternObjectFindElt (font, object); FcValueListPtr v; FcValue value; int idx = -1; int defidx = -1; int i; if (e) { for (v = FcPatternEltValues(e), i = 0; v; v = FcValueListNext(v), ++i) { value = FcValueCanonicalize (&v->value); if (value.type == FcTypeString) { FcLangResult res = FcLangCompare (value.u.s, lang); if (res == FcLangEqual) return i; if (res == FcLangDifferentCountry && idx < 0) idx = i; if (defidx < 0) { /* workaround for fonts that has non-English value * at the head of values. */ res = FcLangCompare (value.u.s, (FcChar8 *)"en"); if (res == FcLangEqual) defidx = i; } } } } return (idx > 0) ? idx : (defidx > 0) ? defidx : 0; }
static FcBool FcListAppend (FcListHashTable *table, FcPattern *font, FcObjectSet *os, const FcChar8 *lang) { int o; FcPatternElt *e; FcValueListPtr v; FcChar32 hash; FcListBucket **prev, *bucket; int familyidx = -1; int fullnameidx = -1; int styleidx = -1; int defidx = 0; int idx; hash = FcListPatternHash (font, os); for (prev = &table->buckets[hash % FC_LIST_HASH_SIZE]; (bucket = *prev); prev = &(bucket->next)) { if (bucket->hash == hash && FcListPatternEqual (bucket->pattern, font, os)) return FcTrue; } bucket = (FcListBucket *) malloc (sizeof (FcListBucket)); if (!bucket) goto bail0; FcMemAlloc (FC_MEM_LISTBUCK, sizeof (FcListBucket)); bucket->next = 0; bucket->hash = hash; bucket->pattern = FcPatternCreate (); if (!bucket->pattern) goto bail1; for (o = 0; o < os->nobject; o++) { if (!strcmp (os->objects[o], FC_FAMILY) || !strcmp (os->objects[o], FC_FAMILYLANG)) { if (familyidx < 0) familyidx = FcGetDefaultObjectLangIndex (font, FC_FAMILYLANG_OBJECT, lang); defidx = familyidx; } else if (!strcmp (os->objects[o], FC_FULLNAME) || !strcmp (os->objects[o], FC_FULLNAMELANG)) { if (fullnameidx < 0) fullnameidx = FcGetDefaultObjectLangIndex (font, FC_FULLNAMELANG_OBJECT, lang); defidx = fullnameidx; } else if (!strcmp (os->objects[o], FC_STYLE) || !strcmp (os->objects[o], FC_STYLELANG)) { if (styleidx < 0) styleidx = FcGetDefaultObjectLangIndex (font, FC_STYLELANG_OBJECT, lang); defidx = styleidx; } else defidx = 0; e = FcPatternObjectFindElt (font, FcObjectFromName (os->objects[o])); if (e) { for (v = FcPatternEltValues(e), idx = 0; v; v = FcValueListNext(v), ++idx) { if (!FcPatternAdd (bucket->pattern, os->objects[o], FcValueCanonicalize(&v->value), defidx != idx)) goto bail2; } } } *prev = bucket; ++table->entries; return FcTrue; bail2: FcPatternDestroy (bucket->pattern); bail1: FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket)); free (bucket); bail0: return FcFalse; }
void FcValueListPrint(FcValueListPtr l) { for (; l != NULL; l = FcValueListNext(l)) { FcValuePrint(FcValueCanonicalize(&l->value)); FcValueBindingPrint(l); } }
FcBool FcConfigCompareValue (const FcValue *left_o, FcOp op, const FcValue *right_o) { FcValue left = FcValueCanonicalize(left_o); FcValue right = FcValueCanonicalize(right_o); FcBool ret = FcFalse; left = FcConfigPromote (left, right); right = FcConfigPromote (right, left); if (left.type == right.type) { switch (left.type) { case FcTypeInteger: break; /* FcConfigPromote prevents this from happening */ case FcTypeDouble: switch (op) { case FcOpEqual: case FcOpContains: case FcOpListing: ret = left.u.d == right.u.d; break; case FcOpNotEqual: case FcOpNotContains: ret = left.u.d != right.u.d; break; case FcOpLess: ret = left.u.d < right.u.d; break; case FcOpLessEqual: ret = left.u.d <= right.u.d; break; case FcOpMore: ret = left.u.d > right.u.d; break; case FcOpMoreEqual: ret = left.u.d >= right.u.d; break; default: break; } break; case FcTypeBool: switch (op) { case FcOpEqual: case FcOpContains: case FcOpListing: ret = left.u.b == right.u.b; break; case FcOpNotEqual: case FcOpNotContains: ret = left.u.b != right.u.b; break; default: break; } break; case FcTypeString: switch (op) { case FcOpEqual: case FcOpListing: ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0; break; case FcOpContains: ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0; break; case FcOpNotEqual: ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0; break; case FcOpNotContains: ret = FcStrStrIgnoreCase (left.u.s, right.u.s) == 0; break; default: break; } break; case FcTypeMatrix: switch (op) { case FcOpEqual: case FcOpContains: case FcOpListing: ret = FcMatrixEqual (left.u.m, right.u.m); break; case FcOpNotEqual: case FcOpNotContains: ret = !FcMatrixEqual (left.u.m, right.u.m); break; default: break; } break; case FcTypeCharSet: switch (op) { case FcOpContains: case FcOpListing: /* left contains right if right is a subset of left */ ret = FcCharSetIsSubset (right.u.c, left.u.c); break; case FcOpNotContains: /* left contains right if right is a subset of left */ ret = !FcCharSetIsSubset (right.u.c, left.u.c); break; case FcOpEqual: ret = FcCharSetEqual (left.u.c, right.u.c); break; case FcOpNotEqual: ret = !FcCharSetEqual (left.u.c, right.u.c); break; default: break; } break; case FcTypeLangSet: switch (op) { case FcOpContains: case FcOpListing: ret = FcLangSetContains (left.u.l, right.u.l); break; case FcOpNotContains: ret = !FcLangSetContains (left.u.l, right.u.l); break; case FcOpEqual: ret = FcLangSetEqual (left.u.l, right.u.l); break; case FcOpNotEqual: ret = !FcLangSetEqual (left.u.l, right.u.l); break; default: break; } break; case FcTypeVoid: switch (op) { case FcOpEqual: case FcOpContains: case FcOpListing: ret = FcTrue; break; default: break; } break; case FcTypeFTFace: switch (op) { case FcOpEqual: case FcOpContains: case FcOpListing: ret = left.u.f == right.u.f; break; case FcOpNotEqual: case FcOpNotContains: ret = left.u.f != right.u.f; break; default: break; } break; } } else { if (op == FcOpNotEqual || op == FcOpNotContains) ret = FcTrue; } return ret; }
static FcBool FcCompareValueList (FcObject object, const FcMatcher *match, FcValueListPtr v1orig, /* pattern */ FcValueListPtr v2orig, /* target */ FcValue *bestValue, double *value, int *n, FcResult *result) { FcValueListPtr v1, v2; double v, best, bestStrong, bestWeak; int j, k, pos = 0; if (!match) { if (bestValue) *bestValue = FcValueCanonicalize(&v2orig->value); if (n) *n = 0; return FcTrue; } best = 1e99; bestStrong = 1e99; bestWeak = 1e99; j = 1; for (v1 = v1orig; v1; v1 = FcValueListNext(v1)) { for (v2 = v2orig, k = 0; v2; v2 = FcValueListNext(v2), k++) { v = (match->compare) (&v1->value, &v2->value); if (v < 0) { *result = FcResultTypeMismatch; return FcFalse; } v = v * 1000 + j; if (v < best) { if (bestValue) *bestValue = FcValueCanonicalize(&v2->value); best = v; pos = k; } if (v1->binding == FcValueBindingStrong) { if (v < bestStrong) bestStrong = v; } else { if (v < bestWeak) bestWeak = v; } } j++; } if (FcDebug () & FC_DBG_MATCHV) { printf (" %s: %g ", FcObjectName (object), best); FcValueListPrint (v1orig); printf (", "); FcValueListPrint (v2orig); printf ("\n"); } if (value) { int weak = match->weak; int strong = match->strong; if (weak == strong) value[strong] += best; else { value[weak] += bestWeak; value[strong] += bestStrong; } } if (n) *n = pos; return FcTrue; }