]> git.wh0rd.org - fontconfig.git/blob - src/fcpat.c
Add FcPatternEqualSubset for Pango, clean up some internal FcPattern
[fontconfig.git] / src / fcpat.c
1 /*
2 * $XFree86: xc/lib/fontconfig/src/fcpat.c,v 1.6 2002/05/31 23:21:25 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 static int
187 FcPatternPosition (const FcPattern *p, const char *object)
188 {
189 int low, high, mid, c;
190
191 low = 0;
192 high = p->num - 1;
193 c = 1;
194 mid = 0;
195 while (low <= high)
196 {
197 mid = (low + high) >> 1;
198 c = strcmp (p->elts[mid].object, object);
199 if (c == 0)
200 return mid;
201 if (c < 0)
202 low = mid + 1;
203 else
204 high = mid - 1;
205 }
206 if (c < 0)
207 mid++;
208 return -(mid + 1);
209 }
210
211 FcPatternElt *
212 FcPatternFindElt (const FcPattern *p, const char *object)
213 {
214 int i = FcPatternPosition (p, object);
215 if (i < 0)
216 return 0;
217 return &p->elts[i];
218 }
219
220 FcPatternElt *
221 FcPatternInsertElt (FcPattern *p, const char *object)
222 {
223 int i;
224 FcPatternElt *e;
225
226 i = FcPatternPosition (p, object);
227 if (i < 0)
228 {
229 i = -i - 1;
230
231 /* grow array */
232 if (p->num + 1 >= p->size)
233 {
234 int s = p->size + 16;
235 if (p->elts)
236 e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt));
237 else
238 e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
239 if (!e)
240 return FcFalse;
241 p->elts = e;
242 if (p->size)
243 FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
244 FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
245 while (p->size < s)
246 {
247 p->elts[p->size].object = 0;
248 p->elts[p->size].values = 0;
249 p->size++;
250 }
251 }
252
253 /* move elts up */
254 memmove (p->elts + i + 1,
255 p->elts + i,
256 sizeof (FcPatternElt) *
257 (p->num - i));
258
259 /* bump count */
260 p->num++;
261
262 p->elts[i].object = object;
263 p->elts[i].values = 0;
264 }
265
266 return &p->elts[i];
267 }
268
269 FcBool
270 FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
271 {
272 int i;
273
274 if (pa->num != pb->num)
275 return FcFalse;
276 for (i = 0; i < pa->num; i++)
277 {
278 if (strcmp (pa->elts[i].object, pb->elts[i].object) != 0)
279 return FcFalse;
280 if (!FcValueListEqual (pa->elts[i].values, pb->elts[i].values))
281 return FcFalse;
282 }
283 return FcTrue;
284 }
285
286 FcBool
287 FcPatternEqualSubset (const FcPattern *pa, const FcPattern *pb, const FcObjectSet *os)
288 {
289 FcPatternElt *ea, *eb;
290 int i;
291
292 for (i = 0; i < os->nobject; i++)
293 {
294 ea = FcPatternFindElt (pa, os->objects[i]);
295 eb = FcPatternFindElt (pb, os->objects[i]);
296 if (ea)
297 {
298 if (!eb)
299 return FcFalse;
300 if (!FcValueListEqual (ea->values, eb->values))
301 return FcFalse;
302 }
303 else
304 {
305 if (eb)
306 return FcFalse;
307 }
308 }
309 return FcTrue;
310 }
311
312 FcBool
313 FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
314 {
315 FcPatternElt *e;
316 FcValueList *new, **prev;
317
318 new = (FcValueList *) malloc (sizeof (FcValueList));
319 if (!new)
320 goto bail0;
321
322 FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
323 /* dup string */
324 value = FcValueSave (value);
325 if (value.type == FcTypeVoid)
326 goto bail1;
327
328 new->value = value;
329 new->next = 0;
330
331 e = FcPatternInsertElt (p, object);
332 if (!e)
333 goto bail2;
334
335 if (append)
336 {
337 for (prev = &e->values; *prev; prev = &(*prev)->next);
338 *prev = new;
339 }
340 else
341 {
342 new->next = e->values;
343 e->values = new;
344 }
345
346 return FcTrue;
347
348 bail2:
349 switch (value.type) {
350 case FcTypeString:
351 FcStrFree ((FcChar8 *) value.u.s);
352 break;
353 case FcTypeMatrix:
354 FcMatrixFree ((FcMatrix *) value.u.m);
355 break;
356 case FcTypeCharSet:
357 FcCharSetDestroy ((FcCharSet *) value.u.c);
358 break;
359 default:
360 break;
361 }
362 bail1:
363 FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
364 free (new);
365 bail0:
366 return FcFalse;
367 }
368
369 FcBool
370 FcPatternDel (FcPattern *p, const char *object)
371 {
372 FcPatternElt *e;
373 int i;
374
375 e = FcPatternFindElt (p, object);
376 if (!e)
377 return FcFalse;
378
379 i = e - p->elts;
380
381 /* destroy value */
382 FcValueListDestroy (e->values);
383
384 /* shuffle existing ones down */
385 memmove (e, e+1, (p->elts + p->num - (e + 1)) * sizeof (FcPatternElt));
386 p->num--;
387 p->elts[p->num].object = 0;
388 p->elts[p->num].values = 0;
389 return FcTrue;
390 }
391
392 FcBool
393 FcPatternAddInteger (FcPattern *p, const char *object, int i)
394 {
395 FcValue v;
396
397 v.type = FcTypeInteger;
398 v.u.i = i;
399 return FcPatternAdd (p, object, v, FcTrue);
400 }
401
402 FcBool
403 FcPatternAddDouble (FcPattern *p, const char *object, double d)
404 {
405 FcValue v;
406
407 v.type = FcTypeDouble;
408 v.u.d = d;
409 return FcPatternAdd (p, object, v, FcTrue);
410 }
411
412
413 FcBool
414 FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
415 {
416 FcValue v;
417
418 v.type = FcTypeString;
419 v.u.s = s;
420 return FcPatternAdd (p, object, v, FcTrue);
421 }
422
423 FcBool
424 FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
425 {
426 FcValue v;
427
428 v.type = FcTypeMatrix;
429 v.u.m = (FcMatrix *) s;
430 return FcPatternAdd (p, object, v, FcTrue);
431 }
432
433
434 FcBool
435 FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
436 {
437 FcValue v;
438
439 v.type = FcTypeBool;
440 v.u.b = b;
441 return FcPatternAdd (p, object, v, FcTrue);
442 }
443
444 FcBool
445 FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
446 {
447 FcValue v;
448
449 v.type = FcTypeCharSet;
450 v.u.c = (FcCharSet *) c;
451 return FcPatternAdd (p, object, v, FcTrue);
452 }
453
454 FcBool
455 FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
456 {
457 FcValue v;
458
459 v.type = FcTypeFTFace;
460 v.u.f = (void *) f;
461 return FcPatternAdd (p, object, v, FcTrue);
462 }
463
464 FcResult
465 FcPatternGet (FcPattern *p, const char *object, int id, FcValue *v)
466 {
467 FcPatternElt *e;
468 FcValueList *l;
469
470 e = FcPatternFindElt (p, object);
471 if (!e)
472 return FcResultNoMatch;
473 for (l = e->values; l; l = l->next)
474 {
475 if (!id)
476 {
477 *v = l->value;
478 return FcResultMatch;
479 }
480 id--;
481 }
482 return FcResultNoId;
483 }
484
485 FcResult
486 FcPatternGetInteger (FcPattern *p, const char *object, int id, int *i)
487 {
488 FcValue v;
489 FcResult r;
490
491 r = FcPatternGet (p, object, id, &v);
492 if (r != FcResultMatch)
493 return r;
494 switch (v.type) {
495 case FcTypeDouble:
496 *i = (int) v.u.d;
497 break;
498 case FcTypeInteger:
499 *i = v.u.i;
500 break;
501 default:
502 return FcResultTypeMismatch;
503 }
504 return FcResultMatch;
505 }
506
507 FcResult
508 FcPatternGetDouble (FcPattern *p, const char *object, int id, double *d)
509 {
510 FcValue v;
511 FcResult r;
512
513 r = FcPatternGet (p, object, id, &v);
514 if (r != FcResultMatch)
515 return r;
516 switch (v.type) {
517 case FcTypeDouble:
518 *d = v.u.d;
519 break;
520 case FcTypeInteger:
521 *d = (double) v.u.i;
522 break;
523 default:
524 return FcResultTypeMismatch;
525 }
526 return FcResultMatch;
527 }
528
529 FcResult
530 FcPatternGetString (FcPattern *p, const char *object, int id, FcChar8 ** s)
531 {
532 FcValue v;
533 FcResult r;
534
535 r = FcPatternGet (p, object, id, &v);
536 if (r != FcResultMatch)
537 return r;
538 if (v.type != FcTypeString)
539 return FcResultTypeMismatch;
540 *s = (FcChar8 *) v.u.s;
541 return FcResultMatch;
542 }
543
544 FcResult
545 FcPatternGetMatrix (FcPattern *p, const char *object, int id, FcMatrix **m)
546 {
547 FcValue v;
548 FcResult r;
549
550 r = FcPatternGet (p, object, id, &v);
551 if (r != FcResultMatch)
552 return r;
553 if (v.type != FcTypeMatrix)
554 return FcResultTypeMismatch;
555 *m = (FcMatrix *) v.u.m;
556 return FcResultMatch;
557 }
558
559
560 FcResult
561 FcPatternGetBool (FcPattern *p, const char *object, int id, FcBool *b)
562 {
563 FcValue v;
564 FcResult r;
565
566 r = FcPatternGet (p, object, id, &v);
567 if (r != FcResultMatch)
568 return r;
569 if (v.type != FcTypeBool)
570 return FcResultTypeMismatch;
571 *b = v.u.b;
572 return FcResultMatch;
573 }
574
575 FcResult
576 FcPatternGetCharSet (FcPattern *p, const char *object, int id, FcCharSet **c)
577 {
578 FcValue v;
579 FcResult r;
580
581 r = FcPatternGet (p, object, id, &v);
582 if (r != FcResultMatch)
583 return r;
584 if (v.type != FcTypeCharSet)
585 return FcResultTypeMismatch;
586 *c = (FcCharSet *) v.u.c;
587 return FcResultMatch;
588 }
589
590 FcResult
591 FcPatternGetFTFace (FcPattern *p, const char *object, int id, FT_Face *f)
592 {
593 FcValue v;
594 FcResult r;
595
596 r = FcPatternGet (p, object, id, &v);
597 if (r != FcResultMatch)
598 return r;
599 if (v.type != FcTypeFTFace)
600 return FcResultTypeMismatch;
601 *f = (FT_Face) v.u.f;
602 return FcResultMatch;
603 }
604
605 FcPattern *
606 FcPatternDuplicate (FcPattern *orig)
607 {
608 FcPattern *new;
609 int i;
610 FcValueList *l;
611
612 new = FcPatternCreate ();
613 if (!new)
614 goto bail0;
615
616 for (i = 0; i < orig->num; i++)
617 {
618 for (l = orig->elts[i].values; l; l = l->next)
619 if (!FcPatternAdd (new, orig->elts[i].object, l->value, FcTrue))
620 goto bail1;
621 }
622
623 return new;
624
625 bail1:
626 FcPatternDestroy (new);
627 bail0:
628 return 0;
629 }
630
631 FcPattern *
632 FcPatternVaBuild (FcPattern *orig, va_list va)
633 {
634 FcPattern *ret;
635
636 FcPatternVapBuild (ret, orig, va);
637 return ret;
638 }
639
640 FcPattern *
641 FcPatternBuild (FcPattern *orig, ...)
642 {
643 va_list va;
644
645 va_start (va, orig);
646 FcPatternVapBuild (orig, orig, va);
647 va_end (va);
648 return orig;
649 }