]> git.wh0rd.org - fontconfig.git/blob - src/fcpat.c
Add support for user-provided freetype faces to Xft
[fontconfig.git] / src / fcpat.c
1 /*
2 * $XFree86: xc/lib/fontconfig/src/fcpat.c,v 1.5 2002/05/29 22:07:33 keithp Exp $
3 *
4 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
5 *
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.
15 *
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.
23 */
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include "fcint.h"
28
29 FcPattern *
30 FcPatternCreate (void)
31 {
32 FcPattern *p;
33
34 p = (FcPattern *) malloc (sizeof (FcPattern));
35 if (!p)
36 return 0;
37 FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern));
38 p->num = 0;
39 p->size = 0;
40 p->elts = 0;
41 return p;
42 }
43
44 void
45 FcValueDestroy (FcValue v)
46 {
47 switch (v.type) {
48 case FcTypeString:
49 FcStrFree ((FcChar8 *) v.u.s);
50 break;
51 case FcTypeMatrix:
52 FcMatrixFree ((FcMatrix *) v.u.m);
53 break;
54 case FcTypeCharSet:
55 FcCharSetDestroy ((FcCharSet *) v.u.c);
56 break;
57 default:
58 break;
59 }
60 }
61
62 FcValue
63 FcValueSave (FcValue v)
64 {
65 switch (v.type) {
66 case FcTypeString:
67 v.u.s = FcStrCopy (v.u.s);
68 if (!v.u.s)
69 v.type = FcTypeVoid;
70 break;
71 case FcTypeMatrix:
72 v.u.m = FcMatrixCopy (v.u.m);
73 if (!v.u.m)
74 v.type = FcTypeVoid;
75 break;
76 case FcTypeCharSet:
77 v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
78 if (!v.u.c)
79 v.type = FcTypeVoid;
80 break;
81 default:
82 break;
83 }
84 return v;
85 }
86
87 void
88 FcValueListDestroy (FcValueList *l)
89 {
90 FcValueList *next;
91 for (; l; l = next)
92 {
93 switch (l->value.type) {
94 case FcTypeString:
95 FcStrFree ((FcChar8 *) l->value.u.s);
96 break;
97 case FcTypeMatrix:
98 FcMatrixFree ((FcMatrix *) l->value.u.m);
99 break;
100 case FcTypeCharSet:
101 FcCharSetDestroy ((FcCharSet *) l->value.u.c);
102 break;
103 default:
104 break;
105 }
106 next = l->next;
107 FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
108 free (l);
109 }
110 }
111
112 FcBool
113 FcValueEqual (FcValue va, FcValue vb)
114 {
115 if (va.type != vb.type)
116 {
117 if (va.type == FcTypeInteger)
118 {
119 va.type = FcTypeDouble;
120 va.u.d = va.u.i;
121 }
122 if (vb.type == FcTypeInteger)
123 {
124 vb.type = FcTypeDouble;
125 vb.u.d = vb.u.i;
126 }
127 if (va.type != vb.type)
128 return FcFalse;
129 }
130 switch (va.type) {
131 case FcTypeVoid:
132 return FcTrue;
133 case FcTypeInteger:
134 return va.u.i == vb.u.i;
135 case FcTypeDouble:
136 return va.u.d == vb.u.d;
137 case FcTypeString:
138 return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
139 case FcTypeBool:
140 return va.u.b == vb.u.b;
141 case FcTypeMatrix:
142 return FcMatrixEqual (va.u.m, vb.u.m);
143 case FcTypeCharSet:
144 return FcCharSetEqual (va.u.c, vb.u.c);
145 case FcTypeFTFace:
146 return va.u.f == vb.u.f;
147 }
148 return FcFalse;
149 }
150
151 static FcBool
152 FcValueListEqual (FcValueList *la, FcValueList *lb)
153 {
154 while (la && lb)
155 {
156 if (!FcValueEqual (la->value, lb->value))
157 return FcFalse;
158 la = la->next;
159 lb = lb->next;
160 }
161 if (la || lb)
162 return FcFalse;
163 return FcTrue;
164 }
165
166 void
167 FcPatternDestroy (FcPattern *p)
168 {
169 int i;
170
171 for (i = 0; i < p->num; i++)
172 FcValueListDestroy (p->elts[i].values);
173
174 p->num = 0;
175 if (p->elts)
176 {
177 FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
178 free (p->elts);
179 p->elts = 0;
180 }
181 p->size = 0;
182 FcMemFree (FC_MEM_PATTERN, sizeof (FcPattern));
183 free (p);
184 }
185
186 FcPatternElt *
187 FcPatternFind (FcPattern *p, const char *object, FcBool insert)
188 {
189 int i;
190 int s;
191 FcPatternElt *e;
192
193 int low, high;
194
195 /* match existing */
196 low = 0;
197 high = p->num;
198
199 while (low + 1 < high)
200 {
201 i = (low + high) >> 1;
202 s = strcmp (object, p->elts[i].object);
203 if (s == 0)
204 return &p->elts[i];
205 if (s > 0)
206 low = i;
207 else
208 high = i;
209 }
210
211 i = low;
212 while (i < high)
213 {
214 s = strcmp (object, p->elts[i].object);
215 if (s == 0)
216 return &p->elts[i];
217 if (s < 0)
218 break;
219 i++;
220 }
221
222 if (!insert)
223 return 0;
224
225 /* grow array */
226 if (p->num + 1 >= p->size)
227 {
228 s = p->size + 16;
229 if (p->elts)
230 e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt));
231 else
232 e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
233 if (!e)
234 return FcFalse;
235 p->elts = e;
236 if (p->size)
237 FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
238 FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
239 while (p->size < s)
240 {
241 p->elts[p->size].object = 0;
242 p->elts[p->size].values = 0;
243 p->size++;
244 }
245 }
246
247 /* move elts up */
248 memmove (p->elts + i + 1,
249 p->elts + i,
250 sizeof (FcPatternElt) *
251 (p->num - i));
252
253 /* bump count */
254 p->num++;
255
256 p->elts[i].object = object;
257 p->elts[i].values = 0;
258
259 return &p->elts[i];
260 }
261
262 FcBool
263 FcPatternEqual (FcPattern *pa, FcPattern *pb)
264 {
265 int i;
266
267 if (pa->num != pb->num)
268 return FcFalse;
269 for (i = 0; i < pa->num; i++)
270 {
271 if (strcmp (pa->elts[i].object, pb->elts[i].object) != 0)
272 return FcFalse;
273 if (!FcValueListEqual (pa->elts[i].values, pb->elts[i].values))
274 return FcFalse;
275 }
276 return FcTrue;
277 }
278
279 FcBool
280 FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
281 {
282 FcPatternElt *e;
283 FcValueList *new, **prev;
284
285 new = (FcValueList *) malloc (sizeof (FcValueList));
286 if (!new)
287 goto bail0;
288
289 FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
290 /* dup string */
291 value = FcValueSave (value);
292 if (value.type == FcTypeVoid)
293 goto bail1;
294
295 new->value = value;
296 new->next = 0;
297
298 e = FcPatternFind (p, object, FcTrue);
299 if (!e)
300 goto bail2;
301
302 if (append)
303 {
304 for (prev = &e->values; *prev; prev = &(*prev)->next);
305 *prev = new;
306 }
307 else
308 {
309 new->next = e->values;
310 e->values = new;
311 }
312
313 return FcTrue;
314
315 bail2:
316 switch (value.type) {
317 case FcTypeString:
318 FcStrFree ((FcChar8 *) value.u.s);
319 break;
320 case FcTypeMatrix:
321 FcMatrixFree ((FcMatrix *) value.u.m);
322 break;
323 case FcTypeCharSet:
324 FcCharSetDestroy ((FcCharSet *) value.u.c);
325 break;
326 default:
327 break;
328 }
329 bail1:
330 FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
331 free (new);
332 bail0:
333 return FcFalse;
334 }
335
336 FcBool
337 FcPatternDel (FcPattern *p, const char *object)
338 {
339 FcPatternElt *e;
340 int i;
341
342 e = FcPatternFind (p, object, FcFalse);
343 if (!e)
344 return FcFalse;
345
346 i = e - p->elts;
347
348 /* destroy value */
349 FcValueListDestroy (e->values);
350
351 /* shuffle existing ones down */
352 memmove (e, e+1, (p->elts + p->num - (e + 1)) * sizeof (FcPatternElt));
353 p->num--;
354 p->elts[p->num].object = 0;
355 p->elts[p->num].values = 0;
356 return FcTrue;
357 }
358
359 FcBool
360 FcPatternAddInteger (FcPattern *p, const char *object, int i)
361 {
362 FcValue v;
363
364 v.type = FcTypeInteger;
365 v.u.i = i;
366 return FcPatternAdd (p, object, v, FcTrue);
367 }
368
369 FcBool
370 FcPatternAddDouble (FcPattern *p, const char *object, double d)
371 {
372 FcValue v;
373
374 v.type = FcTypeDouble;
375 v.u.d = d;
376 return FcPatternAdd (p, object, v, FcTrue);
377 }
378
379
380 FcBool
381 FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
382 {
383 FcValue v;
384
385 v.type = FcTypeString;
386 v.u.s = s;
387 return FcPatternAdd (p, object, v, FcTrue);
388 }
389
390 FcBool
391 FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
392 {
393 FcValue v;
394
395 v.type = FcTypeMatrix;
396 v.u.m = (FcMatrix *) s;
397 return FcPatternAdd (p, object, v, FcTrue);
398 }
399
400
401 FcBool
402 FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
403 {
404 FcValue v;
405
406 v.type = FcTypeBool;
407 v.u.b = b;
408 return FcPatternAdd (p, object, v, FcTrue);
409 }
410
411 FcBool
412 FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
413 {
414 FcValue v;
415
416 v.type = FcTypeCharSet;
417 v.u.c = (FcCharSet *) c;
418 return FcPatternAdd (p, object, v, FcTrue);
419 }
420
421 FcBool
422 FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
423 {
424 FcValue v;
425
426 v.type = FcTypeFTFace;
427 v.u.f = (void *) f;
428 return FcPatternAdd (p, object, v, FcTrue);
429 }
430
431 FcResult
432 FcPatternGet (FcPattern *p, const char *object, int id, FcValue *v)
433 {
434 FcPatternElt *e;
435 FcValueList *l;
436
437 e = FcPatternFind (p, object, FcFalse);
438 if (!e)
439 return FcResultNoMatch;
440 for (l = e->values; l; l = l->next)
441 {
442 if (!id)
443 {
444 *v = l->value;
445 return FcResultMatch;
446 }
447 id--;
448 }
449 return FcResultNoId;
450 }
451
452 FcResult
453 FcPatternGetInteger (FcPattern *p, const char *object, int id, int *i)
454 {
455 FcValue v;
456 FcResult r;
457
458 r = FcPatternGet (p, object, id, &v);
459 if (r != FcResultMatch)
460 return r;
461 switch (v.type) {
462 case FcTypeDouble:
463 *i = (int) v.u.d;
464 break;
465 case FcTypeInteger:
466 *i = v.u.i;
467 break;
468 default:
469 return FcResultTypeMismatch;
470 }
471 return FcResultMatch;
472 }
473
474 FcResult
475 FcPatternGetDouble (FcPattern *p, const char *object, int id, double *d)
476 {
477 FcValue v;
478 FcResult r;
479
480 r = FcPatternGet (p, object, id, &v);
481 if (r != FcResultMatch)
482 return r;
483 switch (v.type) {
484 case FcTypeDouble:
485 *d = v.u.d;
486 break;
487 case FcTypeInteger:
488 *d = (double) v.u.i;
489 break;
490 default:
491 return FcResultTypeMismatch;
492 }
493 return FcResultMatch;
494 }
495
496 FcResult
497 FcPatternGetString (FcPattern *p, const char *object, int id, FcChar8 ** s)
498 {
499 FcValue v;
500 FcResult r;
501
502 r = FcPatternGet (p, object, id, &v);
503 if (r != FcResultMatch)
504 return r;
505 if (v.type != FcTypeString)
506 return FcResultTypeMismatch;
507 *s = (FcChar8 *) v.u.s;
508 return FcResultMatch;
509 }
510
511 FcResult
512 FcPatternGetMatrix (FcPattern *p, const char *object, int id, FcMatrix **m)
513 {
514 FcValue v;
515 FcResult r;
516
517 r = FcPatternGet (p, object, id, &v);
518 if (r != FcResultMatch)
519 return r;
520 if (v.type != FcTypeMatrix)
521 return FcResultTypeMismatch;
522 *m = (FcMatrix *) v.u.m;
523 return FcResultMatch;
524 }
525
526
527 FcResult
528 FcPatternGetBool (FcPattern *p, const char *object, int id, FcBool *b)
529 {
530 FcValue v;
531 FcResult r;
532
533 r = FcPatternGet (p, object, id, &v);
534 if (r != FcResultMatch)
535 return r;
536 if (v.type != FcTypeBool)
537 return FcResultTypeMismatch;
538 *b = v.u.b;
539 return FcResultMatch;
540 }
541
542 FcResult
543 FcPatternGetCharSet (FcPattern *p, const char *object, int id, FcCharSet **c)
544 {
545 FcValue v;
546 FcResult r;
547
548 r = FcPatternGet (p, object, id, &v);
549 if (r != FcResultMatch)
550 return r;
551 if (v.type != FcTypeCharSet)
552 return FcResultTypeMismatch;
553 *c = (FcCharSet *) v.u.c;
554 return FcResultMatch;
555 }
556
557 FcResult
558 FcPatternGetFTFace (FcPattern *p, const char *object, int id, FT_Face *f)
559 {
560 FcValue v;
561 FcResult r;
562
563 r = FcPatternGet (p, object, id, &v);
564 if (r != FcResultMatch)
565 return r;
566 if (v.type != FcTypeFTFace)
567 return FcResultTypeMismatch;
568 *f = (FT_Face) v.u.f;
569 return FcResultMatch;
570 }
571
572 FcPattern *
573 FcPatternDuplicate (FcPattern *orig)
574 {
575 FcPattern *new;
576 int i;
577 FcValueList *l;
578
579 new = FcPatternCreate ();
580 if (!new)
581 goto bail0;
582
583 for (i = 0; i < orig->num; i++)
584 {
585 for (l = orig->elts[i].values; l; l = l->next)
586 if (!FcPatternAdd (new, orig->elts[i].object, l->value, FcTrue))
587 goto bail1;
588 }
589
590 return new;
591
592 bail1:
593 FcPatternDestroy (new);
594 bail0:
595 return 0;
596 }
597
598 FcPattern *
599 FcPatternVaBuild (FcPattern *orig, va_list va)
600 {
601 FcPattern *ret;
602
603 FcPatternVapBuild (ret, orig, va);
604 return ret;
605 }
606
607 FcPattern *
608 FcPatternBuild (FcPattern *orig, ...)
609 {
610 va_list va;
611
612 va_start (va, orig);
613 FcPatternVapBuild (orig, orig, va);
614 va_end (va);
615 return orig;
616 }