]>
git.wh0rd.org - fontconfig.git/blob - src/fclist.c
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
= (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
; FcValueListPtrU(pat
);
134 pat
= FcValueListPtrU(pat
)->next
)
136 for (fnt
= fntOrig
; FcValueListPtrU(fnt
);
137 fnt
= FcValueListPtrU(fnt
)->next
)
140 * make sure the font 'contains' the pattern.
141 * (OpListing is OpContains except for strings
142 * where it requires an exact match)
144 if (FcConfigCompareValue (&FcValueListPtrU(fnt
)->value
,
146 &FcValueListPtrU(pat
)->value
))
149 if (!FcValueListPtrU(fnt
))
156 FcListValueListEqual (FcValueListPtr v1orig
,
157 FcValueListPtr v2orig
)
159 FcValueListPtr v1
, v2
;
161 for (v1
= v1orig
; FcValueListPtrU(v1
);
162 v1
= FcValueListPtrU(v1
)->next
)
164 for (v2
= v2orig
; FcValueListPtrU(v2
);
165 v2
= FcValueListPtrU(v2
)->next
)
166 if (FcValueEqual (FcValueCanonicalize(&FcValueListPtrU(v1
)->value
),
167 FcValueCanonicalize(&FcValueListPtrU(v2
)->value
)))
169 if (!FcValueListPtrU(v2
))
172 for (v2
= v2orig
; FcValueListPtrU(v2
);
173 v2
= FcValueListPtrU(v2
)->next
)
175 for (v1
= v1orig
; FcValueListPtrU(v1
);
176 v1
= FcValueListPtrU(v1
)->next
)
177 if (FcValueEqual (FcValueCanonicalize(&FcValueListPtrU(v1
)->value
),
178 FcValueCanonicalize(&FcValueListPtrU(v2
)->value
)))
180 if (!FcValueListPtrU(v1
))
187 FcListPatternEqual (FcPattern
*p1
,
192 FcPatternElt
*e1
, *e2
;
194 for (i
= 0; i
< os
->nobject
; i
++)
196 e1
= FcPatternFindElt (p1
, os
->objects
[i
]);
197 e2
= FcPatternFindElt (p2
, os
->objects
[i
]);
202 if (!FcListValueListEqual (e1
->values
, e2
->values
))
209 * FcTrue iff all objects in "p" match "font"
213 FcListPatternMatchAny (const FcPattern
*p
,
214 const FcPattern
*font
)
219 for (i
= 0; i
< p
->num
; i
++)
221 e
= FcPatternFindElt (font
,
222 FcObjectPtrU((FcPatternEltU(p
->elts
)+i
)->object
));
225 if (!FcListValueListMatchAny ((FcPatternEltU(p
->elts
)+i
)->values
, /* pat elts */
226 e
->values
)) /* font elts */
233 FcListMatrixHash (const FcMatrix
*m
)
235 int xx
= (int) (m
->xx
* 100),
236 xy
= (int) (m
->xy
* 100),
237 yx
= (int) (m
->yx
* 100),
238 yy
= (int) (m
->yy
* 100);
240 return ((FcChar32
) xx
) ^ ((FcChar32
) xy
) ^ ((FcChar32
) yx
) ^ ((FcChar32
) yy
);
244 FcListValueHash (FcValue
*value
)
246 FcValue v
= FcValueCanonicalize(value
);
251 return (FcChar32
) v
.u
.i
;
253 return (FcChar32
) (int) v
.u
.d
;
255 return FcStrHashIgnoreCase (v
.u
.s
);
257 return (FcChar32
) v
.u
.b
;
259 return FcListMatrixHash (v
.u
.m
);
261 return FcCharSetCount (v
.u
.c
);
265 return FcLangSetHash (v
.u
.l
);
271 FcListValueListHash (FcValueListPtr list
)
275 while (FcValueListPtrU(list
))
277 h
= h
^ FcListValueHash (&FcValueListPtrU(list
)->value
);
278 list
= FcValueListPtrU(list
)->next
;
284 FcListPatternHash (FcPattern
*font
,
291 for (n
= 0; n
< os
->nobject
; n
++)
293 e
= FcPatternFindElt (font
, os
->objects
[n
]);
295 h
= h
^ FcListValueListHash (e
->values
);
300 typedef struct _FcListBucket
{
301 struct _FcListBucket
*next
;
306 #define FC_LIST_HASH_SIZE 4099
308 typedef struct _FcListHashTable
{
310 FcListBucket
*buckets
[FC_LIST_HASH_SIZE
];
314 FcListHashTableInit (FcListHashTable
*table
)
317 memset (table
->buckets
, '\0', sizeof (table
->buckets
));
321 FcListHashTableCleanup (FcListHashTable
*table
)
324 FcListBucket
*bucket
, *next
;
326 for (i
= 0; i
< FC_LIST_HASH_SIZE
; i
++)
328 for (bucket
= table
->buckets
[i
]; bucket
; bucket
= next
)
331 FcPatternDestroy (bucket
->pattern
);
332 FcMemFree (FC_MEM_LISTBUCK
, sizeof (FcListBucket
));
335 table
->buckets
[i
] = 0;
341 FcGetDefaultObjectLangIndex (FcPattern
*font
, const char *object
)
343 FcChar8
*lang
= FcGetDefaultLang ();
344 FcPatternElt
*e
= FcPatternFindElt (font
, object
);
352 for (v
= e
->values
, i
= 0; FcValueListPtrU(v
); v
= FcValueListPtrU(v
)->next
, ++i
)
354 value
= FcValueCanonicalize (&FcValueListPtrU (v
)->value
);
356 if (value
.type
== FcTypeString
)
358 FcLangResult res
= FcLangCompare (value
.u
.s
, lang
);
359 if (res
== FcLangEqual
|| (res
== FcLangDifferentCountry
&& idx
< 0))
365 return (idx
> 0) ? idx
: 0;
369 FcListAppend (FcListHashTable
*table
,
377 FcListBucket
**prev
, *bucket
;
379 int fullnameidx
= -1;
384 hash
= FcListPatternHash (font
, os
);
385 for (prev
= &table
->buckets
[hash
% FC_LIST_HASH_SIZE
];
386 (bucket
= *prev
); prev
= &(bucket
->next
))
388 if (bucket
->hash
== hash
&&
389 FcListPatternEqual (bucket
->pattern
, font
, os
))
392 bucket
= (FcListBucket
*) malloc (sizeof (FcListBucket
));
395 FcMemAlloc (FC_MEM_LISTBUCK
, sizeof (FcListBucket
));
398 bucket
->pattern
= FcPatternCreate ();
399 if (!bucket
->pattern
)
402 for (o
= 0; o
< os
->nobject
; o
++)
404 if (!strcmp (os
->objects
[o
], FC_FAMILY
) || !strcmp (os
->objects
[o
], FC_FAMILYLANG
))
407 familyidx
= FcGetDefaultObjectLangIndex (font
, FC_FAMILYLANG
);
410 else if (!strcmp (os
->objects
[o
], FC_FULLNAME
) || !strcmp (os
->objects
[o
], FC_FULLNAMELANG
))
413 fullnameidx
= FcGetDefaultObjectLangIndex (font
, FC_FULLNAMELANG
);
414 defidx
= fullnameidx
;
416 else if (!strcmp (os
->objects
[o
], FC_STYLE
) || !strcmp (os
->objects
[o
], FC_STYLELANG
))
419 styleidx
= FcGetDefaultObjectLangIndex (font
, FC_STYLELANG
);
425 /* Also, copy over the full path info. */
426 if (!strcmp (os
->objects
[o
], FC_FILE
))
427 FcPatternTransferFullFname (bucket
->pattern
, font
);
429 e
= FcPatternFindElt (font
, os
->objects
[o
]);
432 for (v
= e
->values
, idx
= 0; FcValueListPtrU(v
);
433 v
= FcValueListPtrU(v
)->next
, ++idx
)
435 if (!FcPatternAdd (bucket
->pattern
,
437 FcValueCanonicalize(&FcValueListPtrU(v
)->value
), defidx
!= idx
))
448 FcPatternDestroy (bucket
->pattern
);
450 FcMemFree (FC_MEM_LISTBUCK
, sizeof (FcListBucket
));
457 FcFontSetList (FcConfig
*config
,
467 FcListHashTable table
;
469 FcListBucket
*bucket
;
473 if (!FcInitBringUptoDate ())
476 config
= FcConfigGetCurrent ();
480 FcListHashTableInit (&table
);
482 * Walk all available fonts adding those that
483 * match to the hash table
485 for (set
= 0; set
< nsets
; set
++)
490 for (f
= 0; f
< s
->nfont
; f
++)
491 if (FcListPatternMatchAny (p
, /* pattern */
492 s
->fonts
[f
])) /* font */
493 if (!FcListAppend (&table
, s
->fonts
[f
], os
))
502 for (i
= 0; i
< FC_LIST_HASH_SIZE
; i
++)
504 if ((bucket
= table
.buckets
[i
]))
507 for (; bucket
; bucket
= bucket
->next
)
517 printf ("used: %d max: %d avg: %g\n", full
, max
,
518 (double) ents
/ FC_LIST_HASH_SIZE
);
522 * Walk the hash table and build
525 ret
= FcFontSetCreate ();
528 for (i
= 0; i
< FC_LIST_HASH_SIZE
; i
++)
529 while ((bucket
= table
.buckets
[i
]))
531 if (!FcFontSetAdd (ret
, bucket
->pattern
))
533 table
.buckets
[i
] = bucket
->next
;
534 FcMemFree (FC_MEM_LISTBUCK
, sizeof (FcListBucket
));
541 FcFontSetDestroy (ret
);
543 FcListHashTableCleanup (&table
);
549 FcFontList (FcConfig
*config
,
558 config
= FcConfigGetCurrent ();
563 if (config
->fonts
[FcSetSystem
])
564 sets
[nsets
++] = config
->fonts
[FcSetSystem
];
565 if (config
->fonts
[FcSetApplication
])
566 sets
[nsets
++] = config
->fonts
[FcSetApplication
];
567 return FcFontSetList (config
, sets
, nsets
, p
, os
);