]> git.wh0rd.org Git - 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 }