2 * fontconfig/src/fclist.c
4 * Copyright © 2000 Keith Packard
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
29 FcObjectSetCreate (void)
33 os = (FcObjectSet *) malloc (sizeof (FcObjectSet));
36 FcMemAlloc (FC_MEM_OBJECTSET, sizeof (FcObjectSet));
44 FcObjectSetAdd (FcObjectSet *os, const char *object)
48 int high, low, mid, c;
50 if (os->nobject == os->sobject)
54 objects = (const char **) realloc ((void *) os->objects,
55 s * sizeof (const char *));
57 objects = (const char **) malloc (s * sizeof (const char *));
61 FcMemFree (FC_MEM_OBJECTPTR, os->sobject * sizeof (const char *));
62 FcMemAlloc (FC_MEM_OBJECTPTR, s * sizeof (const char *));
63 os->objects = objects;
66 high = os->nobject - 1;
70 object = (char *)FcStrStaticName ((FcChar8 *)object);
73 mid = (low + high) >> 1;
74 c = os->objects[mid] - object;
84 memmove (os->objects + mid + 1, os->objects + mid,
85 (os->nobject - mid) * sizeof (const char *));
86 os->objects[mid] = object;
92 FcObjectSetDestroy (FcObjectSet *os)
96 FcMemFree (FC_MEM_OBJECTPTR, os->sobject * sizeof (const char *));
97 free ((void *) os->objects);
99 FcMemFree (FC_MEM_OBJECTSET, sizeof (FcObjectSet));
104 FcObjectSetVaBuild (const char *first, va_list va)
108 FcObjectSetVapBuild (ret, first, va);
113 FcObjectSetBuild (const char *first, ...)
118 va_start (va, first);
119 FcObjectSetVapBuild (os, first, va);
125 * Font must have a containing value for every value in the pattern
128 FcListValueListMatchAny (FcValueListPtr patOrig, /* pattern */
129 FcValueListPtr fntOrig) /* font */
131 FcValueListPtr pat, fnt;
133 for (pat = patOrig; pat != NULL; pat = FcValueListNext(pat))
135 for (fnt = fntOrig; fnt != NULL; fnt = FcValueListNext(fnt))
138 * make sure the font 'contains' the pattern.
139 * (OpListing is OpContains except for strings
140 * where it requires an exact match)
142 if (FcConfigCompareValue (&fnt->value,
154 FcListValueListEqual (FcValueListPtr v1orig,
155 FcValueListPtr v2orig)
157 FcValueListPtr v1, v2;
159 for (v1 = v1orig; v1 != NULL; v1 = FcValueListNext(v1))
161 for (v2 = v2orig; v2 != NULL; v2 = FcValueListNext(v2))
162 if (FcValueEqual (FcValueCanonicalize(&(v1)->value),
163 FcValueCanonicalize(&(v2)->value)))
168 for (v2 = v2orig; v2 != NULL; v2 = FcValueListNext(v2))
170 for (v1 = v1orig; v1 != NULL; v1 = FcValueListNext(v1))
171 if (FcValueEqual (FcValueCanonicalize(&v1->value),
172 FcValueCanonicalize(&v2->value)))
181 FcListPatternEqual (FcPattern *p1,
186 FcPatternElt *e1, *e2;
188 for (i = 0; i < os->nobject; i++)
190 e1 = FcPatternObjectFindElt (p1, FcObjectFromName (os->objects[i]));
191 e2 = FcPatternObjectFindElt (p2, FcObjectFromName (os->objects[i]));
196 if (!FcListValueListEqual (FcPatternEltValues(e1),
197 FcPatternEltValues(e2)))
204 * FcTrue iff all objects in "p" match "font"
208 FcListPatternMatchAny (const FcPattern *p,
209 const FcPattern *font)
213 for (i = 0; i < p->num; i++)
215 FcPatternElt *pe = &FcPatternElts(p)[i];
216 FcPatternElt *fe = FcPatternObjectFindElt (font, pe->object);
219 if (!FcListValueListMatchAny (FcPatternEltValues(pe), /* pat elts */
220 FcPatternEltValues(fe))) /* font elts */
227 FcListMatrixHash (const FcMatrix *m)
229 int xx = (int) (m->xx * 100),
230 xy = (int) (m->xy * 100),
231 yx = (int) (m->yx * 100),
232 yy = (int) (m->yy * 100);
234 return ((FcChar32) xx) ^ ((FcChar32) xy) ^ ((FcChar32) yx) ^ ((FcChar32) yy);
238 FcListValueHash (FcValue *value)
240 FcValue v = FcValueCanonicalize(value);
245 return (FcChar32) v.u.i;
247 return (FcChar32) (int) v.u.d;
249 return FcStrHashIgnoreCase (v.u.s);
251 return (FcChar32) v.u.b;
253 return FcListMatrixHash (v.u.m);
255 return FcCharSetCount (v.u.c);
259 return FcLangSetHash (v.u.l);
265 FcListValueListHash (FcValueListPtr list)
271 h = h ^ FcListValueHash (&list->value);
272 list = FcValueListNext(list);
278 FcListPatternHash (FcPattern *font,
285 for (n = 0; n < os->nobject; n++)
287 e = FcPatternObjectFindElt (font, FcObjectFromName (os->objects[n]));
289 h = h ^ FcListValueListHash (FcPatternEltValues(e));
294 typedef struct _FcListBucket {
295 struct _FcListBucket *next;
300 #define FC_LIST_HASH_SIZE 4099
302 typedef struct _FcListHashTable {
304 FcListBucket *buckets[FC_LIST_HASH_SIZE];
308 FcListHashTableInit (FcListHashTable *table)
311 memset (table->buckets, '\0', sizeof (table->buckets));
315 FcListHashTableCleanup (FcListHashTable *table)
318 FcListBucket *bucket, *next;
320 for (i = 0; i < FC_LIST_HASH_SIZE; i++)
322 for (bucket = table->buckets[i]; bucket; bucket = next)
325 FcPatternDestroy (bucket->pattern);
326 FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
329 table->buckets[i] = 0;
335 FcGetDefaultObjectLangIndex (FcPattern *font, FcObject object)
337 FcChar8 *lang = FcGetDefaultLang ();
338 FcPatternElt *e = FcPatternObjectFindElt (font, object);
346 for (v = FcPatternEltValues(e), i = 0; v; v = FcValueListNext(v), ++i)
348 value = FcValueCanonicalize (&v->value);
350 if (value.type == FcTypeString)
352 FcLangResult res = FcLangCompare (value.u.s, lang);
353 if (res == FcLangEqual || (res == FcLangDifferentCountry && idx < 0))
359 return (idx > 0) ? idx : 0;
363 FcListAppend (FcListHashTable *table,
371 FcListBucket **prev, *bucket;
373 int fullnameidx = -1;
378 hash = FcListPatternHash (font, os);
379 for (prev = &table->buckets[hash % FC_LIST_HASH_SIZE];
380 (bucket = *prev); prev = &(bucket->next))
382 if (bucket->hash == hash &&
383 FcListPatternEqual (bucket->pattern, font, os))
386 bucket = (FcListBucket *) malloc (sizeof (FcListBucket));
389 FcMemAlloc (FC_MEM_LISTBUCK, sizeof (FcListBucket));
392 bucket->pattern = FcPatternCreate ();
393 if (!bucket->pattern)
396 for (o = 0; o < os->nobject; o++)
398 if (!strcmp (os->objects[o], FC_FAMILY) || !strcmp (os->objects[o], FC_FAMILYLANG))
401 familyidx = FcGetDefaultObjectLangIndex (font, FC_FAMILYLANG_OBJECT);
404 else if (!strcmp (os->objects[o], FC_FULLNAME) || !strcmp (os->objects[o], FC_FULLNAMELANG))
407 fullnameidx = FcGetDefaultObjectLangIndex (font, FC_FULLNAMELANG_OBJECT);
408 defidx = fullnameidx;
410 else if (!strcmp (os->objects[o], FC_STYLE) || !strcmp (os->objects[o], FC_STYLELANG))
413 styleidx = FcGetDefaultObjectLangIndex (font, FC_STYLELANG_OBJECT);
419 e = FcPatternObjectFindElt (font, FcObjectFromName (os->objects[o]));
422 for (v = FcPatternEltValues(e), idx = 0; v;
423 v = FcValueListNext(v), ++idx)
425 if (!FcPatternAdd (bucket->pattern,
427 FcValueCanonicalize(&v->value), defidx != idx))
438 FcPatternDestroy (bucket->pattern);
440 FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
447 FcFontSetList (FcConfig *config,
457 FcListHashTable table;
459 FcListBucket *bucket;
464 if (!FcInitBringUptoDate ())
467 config = FcConfigGetCurrent ();
471 FcListHashTableInit (&table);
475 os = FcObjectGetSet ();
480 * Walk all available fonts adding those that
481 * match to the hash table
483 for (set = 0; set < nsets; set++)
488 for (f = 0; f < s->nfont; f++)
489 if (FcListPatternMatchAny (p, /* pattern */
490 s->fonts[f])) /* font */
491 if (!FcListAppend (&table, s->fonts[f], os))
500 for (i = 0; i < FC_LIST_HASH_SIZE; i++)
502 if ((bucket = table.buckets[i]))
505 for (; bucket; bucket = bucket->next)
515 printf ("used: %d max: %d avg: %g\n", full, max,
516 (double) ents / FC_LIST_HASH_SIZE);
520 * Walk the hash table and build
523 ret = FcFontSetCreate ();
526 for (i = 0; i < FC_LIST_HASH_SIZE; i++)
527 while ((bucket = table.buckets[i]))
529 if (!FcFontSetAdd (ret, bucket->pattern))
531 table.buckets[i] = bucket->next;
532 FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
539 FcFontSetDestroy (ret);
541 FcListHashTableCleanup (&table);
544 FcObjectSetDestroy (os);
549 FcFontList (FcConfig *config,
558 if (!FcInitBringUptoDate ())
561 config = FcConfigGetCurrent ();
566 if (config->fonts[FcSetSystem])
567 sets[nsets++] = config->fonts[FcSetSystem];
568 if (config->fonts[FcSetApplication])
569 sets[nsets++] = config->fonts[FcSetApplication];
570 return FcFontSetList (config, sets, nsets, p, os);
573 #include "fcaliastail.h"