2 * $RCSId: xc/lib/fontconfig/src/fclist.c,v 1.11tsi Exp $
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 = FcObjectStaticName (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 (FcValueList *patOrig, /* pattern */
129 FcValueList *fntOrig) /* font */
131 FcValueList *pat, *fnt;
133 for (pat = patOrig; pat; pat = pat->next)
135 for (fnt = fntOrig; fnt; fnt = fnt->next)
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 (FcValueList *v1orig,
157 FcValueList *v1, *v2;
159 for (v1 = v1orig; v1; v1 = v1->next)
161 for (v2 = v2orig; v2; v2 = v2->next)
162 if (FcValueEqual (v1->value, v2->value))
167 for (v2 = v2orig; v2; v2 = v2->next)
169 for (v1 = v1orig; v1; v1 = v1->next)
170 if (FcValueEqual (v1->value, v2->value))
179 FcListPatternEqual (FcPattern *p1,
184 FcPatternElt *e1, *e2;
186 for (i = 0; i < os->nobject; i++)
188 e1 = FcPatternFindElt (p1, os->objects[i]);
189 e2 = FcPatternFindElt (p2, os->objects[i]);
194 if (!FcListValueListEqual (e1->values, e2->values))
201 * FcTrue iff all objects in "p" match "font"
205 FcListPatternMatchAny (const FcPattern *p,
206 const FcPattern *font)
211 for (i = 0; i < p->num; i++)
213 e = FcPatternFindElt (font, p->elts[i].object);
216 if (!FcListValueListMatchAny (p->elts[i].values, /* pat elts */
217 e->values)) /* font elts */
224 FcListMatrixHash (const FcMatrix *m)
226 int xx = (int) (m->xx * 100),
227 xy = (int) (m->xy * 100),
228 yx = (int) (m->yx * 100),
229 yy = (int) (m->yy * 100);
231 return ((FcChar32) xx) ^ ((FcChar32) xy) ^ ((FcChar32) yx) ^ ((FcChar32) yy);
235 FcListValueHash (FcValue v)
241 return (FcChar32) v.u.i;
243 return (FcChar32) (int) v.u.d;
245 return FcStrHashIgnoreCase (v.u.s);
247 return (FcChar32) v.u.b;
249 return FcListMatrixHash (v.u.m);
251 return FcCharSetCount (v.u.c);
255 return FcLangSetHash (v.u.l);
261 FcListValueListHash (FcValueList *list)
267 h = h ^ FcListValueHash (list->value);
274 FcListPatternHash (FcPattern *font,
281 for (n = 0; n < os->nobject; n++)
283 e = FcPatternFindElt (font, os->objects[n]);
285 h = h ^ FcListValueListHash (e->values);
290 typedef struct _FcListBucket {
291 struct _FcListBucket *next;
296 #define FC_LIST_HASH_SIZE 4099
298 typedef struct _FcListHashTable {
300 FcListBucket *buckets[FC_LIST_HASH_SIZE];
304 FcListHashTableInit (FcListHashTable *table)
307 memset (table->buckets, '\0', sizeof (table->buckets));
311 FcListHashTableCleanup (FcListHashTable *table)
314 FcListBucket *bucket, *next;
316 for (i = 0; i < FC_LIST_HASH_SIZE; i++)
318 for (bucket = table->buckets[i]; bucket; bucket = next)
321 FcPatternDestroy (bucket->pattern);
322 FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
325 table->buckets[i] = 0;
331 FcListAppend (FcListHashTable *table,
339 FcListBucket **prev, *bucket;
341 hash = FcListPatternHash (font, os);
342 for (prev = &table->buckets[hash % FC_LIST_HASH_SIZE];
343 (bucket = *prev); prev = &(bucket->next))
345 if (bucket->hash == hash &&
346 FcListPatternEqual (bucket->pattern, font, os))
349 bucket = (FcListBucket *) malloc (sizeof (FcListBucket));
352 FcMemAlloc (FC_MEM_LISTBUCK, sizeof (FcListBucket));
355 bucket->pattern = FcPatternCreate ();
356 if (!bucket->pattern)
359 for (o = 0; o < os->nobject; o++)
361 e = FcPatternFindElt (font, os->objects[o]);
364 for (v = e->values; v; v = v->next)
366 if (!FcPatternAdd (bucket->pattern,
379 FcPatternDestroy (bucket->pattern);
381 FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
388 FcFontSetList (FcConfig *config,
398 FcListHashTable table;
400 FcListBucket *bucket;
404 if (!FcInitBringUptoDate ())
407 config = FcConfigGetCurrent ();
411 FcListHashTableInit (&table);
413 * Walk all available fonts adding those that
414 * match to the hash table
416 for (set = 0; set < nsets; set++)
421 for (f = 0; f < s->nfont; f++)
422 if (FcListPatternMatchAny (p, /* pattern */
423 s->fonts[f])) /* font */
424 if (!FcListAppend (&table, s->fonts[f], os))
433 for (i = 0; i < FC_LIST_HASH_SIZE; i++)
435 if ((bucket = table.buckets[i]))
438 for (; bucket; bucket = bucket->next)
448 printf ("used: %d max: %d avg: %g\n", full, max,
449 (double) ents / FC_LIST_HASH_SIZE);
453 * Walk the hash table and build
456 ret = FcFontSetCreate ();
459 for (i = 0; i < FC_LIST_HASH_SIZE; i++)
460 while ((bucket = table.buckets[i]))
462 if (!FcFontSetAdd (ret, bucket->pattern))
464 table.buckets[i] = bucket->next;
465 FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
472 FcFontSetDestroy (ret);
474 FcListHashTableCleanup (&table);
480 FcFontList (FcConfig *config,
489 config = FcConfigGetCurrent ();
494 if (config->fonts[FcSetSystem])
495 sets[nsets++] = config->fonts[FcSetSystem];
496 if (config->fonts[FcSetApplication])
497 sets[nsets++] = config->fonts[FcSetApplication];
498 return FcFontSetList (config, sets, nsets, p, os);