FcBool FcListPatternMatchAny (const FcPattern *p, const FcPattern *font) { int i; for (i = 0; i < p->num; i++) { FcPatternElt *pe = &FcPatternElts(p)[i]; FcPatternElt *fe; if (pe->object == FC_NAMELANG_OBJECT) { /* "namelang" object is the alias object to change "familylang", * "stylelang" and "fullnamelang" object alltogether. it won't be * available on the font pattern. so checking its availability * causes no results. we should ignore it here. */ continue; } fe = FcPatternObjectFindElt (font, pe->object); if (!fe) return FcFalse; if (!FcListValueListMatchAny (FcPatternEltValues(pe), /* pat elts */ FcPatternEltValues(fe))) /* font elts */ return FcFalse; } return FcTrue; }
FcChar8 * FcNameUnparseEscaped (FcPattern *pat, FcBool escape) { FcStrBuf buf, buf2; FcChar8 buf_static[8192], buf2_static[256]; int i; FcPatternElt *e; FcStrBufInit (&buf, buf_static, sizeof (buf_static)); FcStrBufInit (&buf2, buf2_static, sizeof (buf2_static)); e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT); if (e) { if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0)) goto bail0; } e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT); if (e) { FcChar8 *p; if (!FcNameUnparseString (&buf2, (FcChar8 *) "-", 0)) goto bail0; if (!FcNameUnparseValueList (&buf2, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0)) goto bail0; p = FcStrBufDoneStatic (&buf2); FcStrBufDestroy (&buf2); if (strlen ((const char *)p) > 1) if (!FcStrBufString (&buf, p)) goto bail0; } for (i = 0; i < NUM_OBJECT_TYPES; i++) { FcObject id = i + 1; const FcObjectType *o; o = &FcObjects[i]; if (!strcmp (o->object, FC_FAMILY) || !strcmp (o->object, FC_SIZE)) continue; e = FcPatternObjectFindElt (pat, id); if (e) { if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0)) goto bail0; if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0)) goto bail0; if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0)) goto bail0; if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0)) goto bail0; } } return FcStrBufDone (&buf); bail0: FcStrBufDestroy (&buf); return 0; }
FcChar8 * FcNameUnparseEscaped (FcPattern *pat, FcBool escape) { FcStrBuf buf; FcChar8 buf_static[8192]; int i; FcPatternElt *e; const FcObjectTypeList *l; const FcObjectType *o; FcStrBufInit (&buf, buf_static, sizeof (buf_static)); e = FcPatternObjectFindElt (pat, FC_FAMILY_OBJECT); if (e) { if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0)) goto bail0; } e = FcPatternObjectFindElt (pat, FC_SIZE_OBJECT); if (e) { if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0)) goto bail0; if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_FIXED : 0)) goto bail0; } for (l = _FcObjectTypes; l; l = l->next) { for (i = 0; i < l->ntypes; i++) { o = &l->types[i]; if (!strcmp (o->object, FC_FAMILY) || !strcmp (o->object, FC_SIZE) || !strcmp (o->object, FC_FILE)) continue; e = FcPatternObjectFindElt (pat, FcObjectFromName (o->object)); if (e) { if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0)) goto bail0; if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0)) goto bail0; if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0)) goto bail0; if (!FcNameUnparseValueList (&buf, FcPatternEltValues(e), escape ? (FcChar8 *) FC_ESCAPE_VARIABLE : 0)) goto bail0; } } } return FcStrBufDone (&buf); bail0: FcStrBufDestroy (&buf); 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 FcListPatternMatchAny (const FcPattern *p, const FcPattern *font) { int i; for (i = 0; i < p->num; i++) { FcPatternElt *pe = &FcPatternElts(p)[i]; FcPatternElt *fe = FcPatternObjectFindElt (font, pe->object); if (!fe) return FcFalse; if (!FcListValueListMatchAny (FcPatternEltValues(pe), /* pat elts */ FcPatternEltValues(fe))) /* font elts */ return FcFalse; } return FcTrue; }
static FcBool FcListPatternEqual (FcPattern *p1, FcPattern *p2, FcObjectSet *os) { int i; FcPatternElt *e1, *e2; for (i = 0; i < os->nobject; i++) { e1 = FcPatternObjectFindElt (p1, FcObjectFromName (os->objects[i])); e2 = FcPatternObjectFindElt (p2, FcObjectFromName (os->objects[i])); if (!e1 && !e2) continue; if (!e1 || !e2) return FcFalse; if (!FcListValueListEqual (FcPatternEltValues(e1), FcPatternEltValues(e2))) return FcFalse; } return FcTrue; }
static FcBool FcCompare (FcPattern *pat, FcPattern *fnt, double *value, FcResult *result) { int i, i1, i2; for (i = 0; i < NUM_MATCH_VALUES; i++) value[i] = 0.0; i1 = 0; i2 = 0; while (i1 < pat->num && i2 < fnt->num) { FcPatternElt *elt_i1 = &FcPatternElts(pat)[i1]; FcPatternElt *elt_i2 = &FcPatternElts(fnt)[i2]; i = FcObjectCompare(elt_i1->object, elt_i2->object); if (i > 0) i2++; else if (i < 0) i1++; else { const FcMatcher *match = FcObjectToMatcher (elt_i1->object, FcFalse); if (!FcCompareValueList (elt_i1->object, match, FcPatternEltValues(elt_i1), FcPatternEltValues(elt_i2), NULL, value, NULL, result)) return FcFalse; i1++; i2++; } } return FcTrue; }
static FcChar32 FcListPatternHash (FcPattern *font, FcObjectSet *os) { int n; FcPatternElt *e; FcChar32 h = 0; for (n = 0; n < os->nobject; n++) { e = FcPatternObjectFindElt (font, FcObjectFromName (os->objects[n])); if (e) h = h ^ FcListValueListHash (FcPatternEltValues(e)); } return h; }
void FcPatternPrint(const FcPattern *p) { int i; FcPatternElt *e; if (!p) { printf("Null pattern\n"); return; } printf("Pattern has %d elts (size %d)\n", p->num, p->size); for (i = 0; i < p->num; i++) { e = &FcPatternElts(p)[i]; printf("\t%s:", FcObjectName(e->object)); FcValueListPrint(FcPatternEltValues(e)); printf("\n"); } printf("\n"); }
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; }