1 /*
2 * Copyright © 2000 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the author(s) not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. The authors make no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
13 *
14 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23 #include "fcint.h"
24 #include "fcftint.h"
25
26 /* Objects MT-safe for readonly access. */
27
28 FcPattern *
FcPatternCreate(void)29 FcPatternCreate (void)
30 {
31 FcPattern *p;
32
33 p = (FcPattern *) malloc (sizeof (FcPattern));
34 if (!p)
35 return 0;
36 memset (p, 0, sizeof (FcPattern));
37 p->num = 0;
38 p->size = 0;
39 p->elts_offset = FcPtrToOffset (p, NULL);
40 FcRefInit (&p->ref, 1);
41 return p;
42 }
43
44 void
FcValueDestroy(FcValue v)45 FcValueDestroy (FcValue v)
46 {
47 switch ((int) v.type) {
48 case FcTypeString:
49 FcFree (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 case FcTypeLangSet:
58 FcLangSetDestroy ((FcLangSet *) v.u.l);
59 break;
60 default:
61 break;
62 }
63 }
64
65 FcValue
FcValueCanonicalize(const FcValue * v)66 FcValueCanonicalize (const FcValue *v)
67 {
68 FcValue new;
69
70 switch ((int) v->type)
71 {
72 case FcTypeString:
73 new.u.s = FcValueString(v);
74 new.type = FcTypeString;
75 break;
76 case FcTypeCharSet:
77 new.u.c = FcValueCharSet(v);
78 new.type = FcTypeCharSet;
79 break;
80 case FcTypeLangSet:
81 new.u.l = FcValueLangSet(v);
82 new.type = FcTypeLangSet;
83 break;
84 default:
85 new = *v;
86 break;
87 }
88 return new;
89 }
90
91 FcValue
FcValueSave(FcValue v)92 FcValueSave (FcValue v)
93 {
94 switch ((int) v.type) {
95 case FcTypeString:
96 v.u.s = FcStrdup (v.u.s);
97 if (!v.u.s)
98 v.type = FcTypeVoid;
99 break;
100 case FcTypeMatrix:
101 v.u.m = FcMatrixCopy (v.u.m);
102 if (!v.u.m)
103 v.type = FcTypeVoid;
104 break;
105 case FcTypeCharSet:
106 v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
107 if (!v.u.c)
108 v.type = FcTypeVoid;
109 break;
110 case FcTypeLangSet:
111 v.u.l = FcLangSetCopy (v.u.l);
112 if (!v.u.l)
113 v.type = FcTypeVoid;
114 break;
115 default:
116 break;
117 }
118 return v;
119 }
120
121 FcValueListPtr
FcValueListCreate(void)122 FcValueListCreate (void)
123 {
124 return calloc (1, sizeof (FcValueList));
125 }
126
127 void
FcValueListDestroy(FcValueListPtr l)128 FcValueListDestroy (FcValueListPtr l)
129 {
130 FcValueListPtr next;
131 for (; l; l = next)
132 {
133 switch ((int) l->value.type) {
134 case FcTypeString:
135 FcFree (l->value.u.s);
136 break;
137 case FcTypeMatrix:
138 FcMatrixFree ((FcMatrix *)l->value.u.m);
139 break;
140 case FcTypeCharSet:
141 FcCharSetDestroy
142 ((FcCharSet *) (l->value.u.c));
143 break;
144 case FcTypeLangSet:
145 FcLangSetDestroy
146 ((FcLangSet *) (l->value.u.l));
147 break;
148 default:
149 break;
150 }
151 next = FcValueListNext(l);
152 free(l);
153 }
154 }
155
156 FcValueListPtr
FcValueListPrepend(FcValueListPtr vallist,FcValue value,FcValueBinding binding)157 FcValueListPrepend (FcValueListPtr vallist,
158 FcValue value,
159 FcValueBinding binding)
160 {
161 FcValueListPtr new;
162
163 if (value.type == FcTypeVoid)
164 return vallist;
165 new = FcValueListCreate ();
166 if (!new)
167 return vallist;
168
169 new->value = FcValueSave (value);
170 new->binding = binding;
171 new->next = vallist;
172
173 return new;
174 }
175
176 FcValueListPtr
FcValueListAppend(FcValueListPtr vallist,FcValue value,FcValueBinding binding)177 FcValueListAppend (FcValueListPtr vallist,
178 FcValue value,
179 FcValueBinding binding)
180 {
181 FcValueListPtr new, last;
182
183 if (value.type == FcTypeVoid)
184 return vallist;
185 new = FcValueListCreate ();
186 if (!new)
187 return vallist;
188
189 new->value = FcValueSave (value);
190 new->binding = binding;
191 new->next = NULL;
192
193 if (vallist)
194 {
195 for (last = vallist; FcValueListNext (last); last = FcValueListNext (last));
196
197 last->next = new;
198 }
199 else
200 vallist = new;
201
202 return vallist;
203 }
204
205 FcValueListPtr
FcValueListDuplicate(FcValueListPtr orig)206 FcValueListDuplicate(FcValueListPtr orig)
207 {
208 FcValueListPtr new = NULL, l, t = NULL;
209 FcValue v;
210
211 for (l = orig; l != NULL; l = FcValueListNext (l))
212 {
213 if (!new)
214 {
215 t = new = FcValueListCreate();
216 }
217 else
218 {
219 t->next = FcValueListCreate();
220 t = FcValueListNext (t);
221 }
222 v = FcValueCanonicalize (&l->value);
223 t->value = FcValueSave (v);
224 t->binding = l->binding;
225 t->next = NULL;
226 }
227
228 return new;
229 }
230
231 FcBool
FcValueEqual(FcValue va,FcValue vb)232 FcValueEqual (FcValue va, FcValue vb)
233 {
234 if (va.type != vb.type)
235 {
236 if (va.type == FcTypeInteger)
237 {
238 va.type = FcTypeDouble;
239 va.u.d = va.u.i;
240 }
241 if (vb.type == FcTypeInteger)
242 {
243 vb.type = FcTypeDouble;
244 vb.u.d = vb.u.i;
245 }
246 if (va.type != vb.type)
247 return FcFalse;
248 }
249 switch (va.type) {
250 case FcTypeUnknown:
251 return FcFalse; /* don't know how to compare this object */
252 case FcTypeVoid:
253 return FcTrue;
254 case FcTypeInteger:
255 return va.u.i == vb.u.i;
256 case FcTypeDouble:
257 return va.u.d == vb.u.d;
258 case FcTypeString:
259 return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
260 case FcTypeBool:
261 return va.u.b == vb.u.b;
262 case FcTypeMatrix:
263 return FcMatrixEqual (va.u.m, vb.u.m);
264 case FcTypeCharSet:
265 return FcCharSetEqual (va.u.c, vb.u.c);
266 case FcTypeFTFace:
267 return va.u.f == vb.u.f;
268 case FcTypeLangSet:
269 return FcLangSetEqual (va.u.l, vb.u.l);
270 }
271 return FcFalse;
272 }
273
274 static FcChar32
FcDoubleHash(double d)275 FcDoubleHash (double d)
276 {
277 if (d < 0)
278 d = -d;
279 if (d > 0xffffffff)
280 d = 0xffffffff;
281 return (FcChar32) d;
282 }
283
284 FcChar32
FcStringHash(const FcChar8 * s)285 FcStringHash (const FcChar8 *s)
286 {
287 FcChar8 c;
288 FcChar32 h = 0;
289
290 if (s)
291 while ((c = *s++))
292 h = ((h << 1) | (h >> 31)) ^ c;
293 return h;
294 }
295
296 static FcChar32
FcValueHash(const FcValue * v)297 FcValueHash (const FcValue *v)
298 {
299 switch (v->type) {
300 case FcTypeUnknown:
301 case FcTypeVoid:
302 return 0;
303 case FcTypeInteger:
304 return (FcChar32) v->u.i;
305 case FcTypeDouble:
306 return FcDoubleHash (v->u.d);
307 case FcTypeString:
308 return FcStringHash (FcValueString(v));
309 case FcTypeBool:
310 return (FcChar32) v->u.b;
311 case FcTypeMatrix:
312 return (FcDoubleHash (v->u.m->xx) ^
313 FcDoubleHash (v->u.m->xy) ^
314 FcDoubleHash (v->u.m->yx) ^
315 FcDoubleHash (v->u.m->yy));
316 case FcTypeCharSet:
317 return (FcChar32) FcValueCharSet(v)->num;
318 case FcTypeFTFace:
319 return FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->family_name) ^
320 FcStringHash ((const FcChar8 *) ((FT_Face) v->u.f)->style_name);
321 case FcTypeLangSet:
322 return FcLangSetHash (FcValueLangSet(v));
323 }
324 return 0;
325 }
326
327 static FcBool
FcValueListEqual(FcValueListPtr la,FcValueListPtr lb)328 FcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
329 {
330 if (la == lb)
331 return FcTrue;
332
333 while (la && lb)
334 {
335 if (!FcValueEqual (la->value, lb->value))
336 return FcFalse;
337 la = FcValueListNext(la);
338 lb = FcValueListNext(lb);
339 }
340 if (la || lb)
341 return FcFalse;
342 return FcTrue;
343 }
344
345 static FcChar32
FcValueListHash(FcValueListPtr l)346 FcValueListHash (FcValueListPtr l)
347 {
348 FcChar32 hash = 0;
349
350 for (; l; l = FcValueListNext(l))
351 {
352 hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
353 }
354 return hash;
355 }
356
357 void
FcPatternDestroy(FcPattern * p)358 FcPatternDestroy (FcPattern *p)
359 {
360 int i;
361 FcPatternElt *elts;
362
363 if (!p)
364 return;
365
366 if (FcRefIsConst (&p->ref))
367 {
368 FcCacheObjectDereference (p);
369 return;
370 }
371
372 if (FcRefDec (&p->ref) != 1)
373 return;
374
375 elts = FcPatternElts (p);
376 for (i = 0; i < p->num; i++)
377 FcValueListDestroy (FcPatternEltValues(&elts[i]));
378
379 free (elts);
380 free (p);
381 }
382
383 static int
FcPatternObjectPosition(const FcPattern * p,FcObject object)384 FcPatternObjectPosition (const FcPattern *p, FcObject object)
385 {
386 int low, high, mid, c;
387 FcPatternElt *elts = FcPatternElts(p);
388
389 low = 0;
390 high = p->num - 1;
391 c = 1;
392 mid = 0;
393 while (low <= high)
394 {
395 mid = (low + high) >> 1;
396 c = elts[mid].object - object;
397 if (c == 0)
398 return mid;
399 if (c < 0)
400 low = mid + 1;
401 else
402 high = mid - 1;
403 }
404 if (c < 0)
405 mid++;
406 return -(mid + 1);
407 }
408
409 FcPatternElt *
FcPatternObjectFindElt(const FcPattern * p,FcObject object)410 FcPatternObjectFindElt (const FcPattern *p, FcObject object)
411 {
412 int i = FcPatternObjectPosition (p, object);
413 if (i < 0)
414 return 0;
415 return &FcPatternElts(p)[i];
416 }
417
418 FcPatternElt *
FcPatternObjectInsertElt(FcPattern * p,FcObject object)419 FcPatternObjectInsertElt (FcPattern *p, FcObject object)
420 {
421 int i;
422 FcPatternElt *e;
423
424 i = FcPatternObjectPosition (p, object);
425 if (i < 0)
426 {
427 i = -i - 1;
428
429 /* reallocate array */
430 if (p->num + 1 >= p->size)
431 {
432 int s = p->size + 16;
433 if (p->size)
434 {
435 FcPatternElt *e0 = FcPatternElts(p);
436 e = (FcPatternElt *) realloc (e0, s * sizeof (FcPatternElt));
437 if (!e) /* maybe it was mmapped */
438 {
439 e = malloc(s * sizeof (FcPatternElt));
440 if (e)
441 memcpy(e, e0, p->num * sizeof (FcPatternElt));
442 }
443 }
444 else
445 e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
446 if (!e)
447 return FcFalse;
448 p->elts_offset = FcPtrToOffset (p, e);
449 while (p->size < s)
450 {
451 e[p->size].object = 0;
452 e[p->size].values = NULL;
453 p->size++;
454 }
455 }
456
457 e = FcPatternElts(p);
458 /* move elts up */
459 memmove (e + i + 1,
460 e + i,
461 sizeof (FcPatternElt) *
462 (p->num - i));
463
464 /* bump count */
465 p->num++;
466
467 e[i].object = object;
468 e[i].values = NULL;
469 }
470
471 return FcPatternElts(p) + i;
472 }
473
474 FcBool
FcPatternEqual(const FcPattern * pa,const FcPattern * pb)475 FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
476 {
477 int i;
478 FcPatternElt *pae, *pbe;
479
480 if (pa == pb)
481 return FcTrue;
482
483 if (pa->num != pb->num)
484 return FcFalse;
485 pae = FcPatternElts(pa);
486 pbe = FcPatternElts(pb);
487 for (i = 0; i < pa->num; i++)
488 {
489 if (pae[i].object != pbe[i].object)
490 return FcFalse;
491 if (!FcValueListEqual (FcPatternEltValues(&pae[i]),
492 FcPatternEltValues(&pbe[i])))
493 return FcFalse;
494 }
495 return FcTrue;
496 }
497
498 FcChar32
FcPatternHash(const FcPattern * p)499 FcPatternHash (const FcPattern *p)
500 {
501 int i;
502 FcChar32 h = 0;
503 FcPatternElt *pe = FcPatternElts(p);
504
505 for (i = 0; i < p->num; i++)
506 {
507 h = (((h << 1) | (h >> 31)) ^
508 pe[i].object ^
509 FcValueListHash (FcPatternEltValues(&pe[i])));
510 }
511 return h;
512 }
513
514 FcBool
FcPatternEqualSubset(const FcPattern * pai,const FcPattern * pbi,const FcObjectSet * os)515 FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
516 {
517 FcPatternElt *ea, *eb;
518 int i;
519
520 for (i = 0; i < os->nobject; i++)
521 {
522 FcObject object = FcObjectFromName (os->objects[i]);
523 ea = FcPatternObjectFindElt (pai, object);
524 eb = FcPatternObjectFindElt (pbi, object);
525 if (ea)
526 {
527 if (!eb)
528 return FcFalse;
529 if (!FcValueListEqual (FcPatternEltValues(ea), FcPatternEltValues(eb)))
530 return FcFalse;
531 }
532 else
533 {
534 if (eb)
535 return FcFalse;
536 }
537 }
538 return FcTrue;
539 }
540
541 FcBool
FcPatternObjectListAdd(FcPattern * p,FcObject object,FcValueListPtr list,FcBool append)542 FcPatternObjectListAdd (FcPattern *p,
543 FcObject object,
544 FcValueListPtr list,
545 FcBool append)
546 {
547 FcPatternElt *e;
548 FcValueListPtr l, *prev;
549
550 if (FcRefIsConst (&p->ref))
551 goto bail0;
552
553 /*
554 * Make sure the stored type is valid for built-in objects
555 */
556 for (l = list; l != NULL; l = FcValueListNext (l))
557 {
558 if (!FcObjectValidType (object, l->value.type))
559 {
560 fprintf (stderr,
561 "Fontconfig warning: FcPattern object %s does not accept value", FcObjectName (object));
562 FcValuePrintFile (stderr, l->value);
563 fprintf (stderr, "\n");
564 goto bail0;
565 }
566 }
567
568 e = FcPatternObjectInsertElt (p, object);
569 if (!e)
570 goto bail0;
571
572 if (append)
573 {
574 for (prev = &e->values; *prev; prev = &(*prev)->next)
575 ;
576 *prev = list;
577 }
578 else
579 {
580 for (prev = &list; *prev; prev = &(*prev)->next)
581 ;
582 *prev = e->values;
583 e->values = list;
584 }
585
586 return FcTrue;
587
588 bail0:
589 return FcFalse;
590 }
591
592 FcBool
FcPatternObjectAddWithBinding(FcPattern * p,FcObject object,FcValue value,FcValueBinding binding,FcBool append)593 FcPatternObjectAddWithBinding (FcPattern *p,
594 FcObject object,
595 FcValue value,
596 FcValueBinding binding,
597 FcBool append)
598 {
599 FcPatternElt *e;
600 FcValueListPtr new, *prev;
601
602 if (FcRefIsConst (&p->ref))
603 goto bail0;
604
605 new = FcValueListCreate ();
606 if (!new)
607 goto bail0;
608
609 value = FcValueSave (value);
610 if (value.type == FcTypeVoid)
611 goto bail1;
612
613 /*
614 * Make sure the stored type is valid for built-in objects
615 */
616 if (!FcObjectValidType (object, value.type))
617 {
618 fprintf (stderr,
619 "Fontconfig warning: FcPattern object %s does not accept value",
620 FcObjectName (object));
621 FcValuePrintFile (stderr, value);
622 fprintf (stderr, "\n");
623 goto bail1;
624 }
625
626 new->value = value;
627 new->binding = binding;
628 new->next = NULL;
629
630 e = FcPatternObjectInsertElt (p, object);
631 if (!e)
632 goto bail2;
633
634 if (append)
635 {
636 for (prev = &e->values; *prev; prev = &(*prev)->next)
637 ;
638 *prev = new;
639 }
640 else
641 {
642 new->next = e->values;
643 e->values = new;
644 }
645
646 return FcTrue;
647
648 bail2:
649 FcValueDestroy (value);
650 bail1:
651 free (new);
652 bail0:
653 return FcFalse;
654 }
655
656 FcBool
FcPatternObjectAdd(FcPattern * p,FcObject object,FcValue value,FcBool append)657 FcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
658 {
659 return FcPatternObjectAddWithBinding (p, object,
660 value, FcValueBindingStrong, append);
661 }
662
663 FcBool
FcPatternAdd(FcPattern * p,const char * object,FcValue value,FcBool append)664 FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
665 {
666 return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
667 value, FcValueBindingStrong, append);
668 }
669
670 FcBool
FcPatternAddWeak(FcPattern * p,const char * object,FcValue value,FcBool append)671 FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append)
672 {
673 return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
674 value, FcValueBindingWeak, append);
675 }
676
677 FcBool
FcPatternObjectDel(FcPattern * p,FcObject object)678 FcPatternObjectDel (FcPattern *p, FcObject object)
679 {
680 FcPatternElt *e;
681
682 e = FcPatternObjectFindElt (p, object);
683 if (!e)
684 return FcFalse;
685
686 /* destroy value */
687 FcValueListDestroy (e->values);
688
689 /* shuffle existing ones down */
690 memmove (e, e+1,
691 (FcPatternElts(p) + p->num - (e + 1)) *
692 sizeof (FcPatternElt));
693 p->num--;
694 e = FcPatternElts(p) + p->num;
695 e->object = 0;
696 e->values = NULL;
697 return FcTrue;
698 }
699
700 FcBool
FcPatternDel(FcPattern * p,const char * object)701 FcPatternDel (FcPattern *p, const char *object)
702 {
703 return FcPatternObjectDel (p, FcObjectFromName (object));
704 }
705
706 FcBool
FcPatternRemove(FcPattern * p,const char * object,int id)707 FcPatternRemove (FcPattern *p, const char *object, int id)
708 {
709 FcPatternElt *e;
710 FcValueListPtr *prev, l;
711
712 e = FcPatternObjectFindElt (p, FcObjectFromName (object));
713 if (!e)
714 return FcFalse;
715 for (prev = &e->values; (l = *prev); prev = &l->next)
716 {
717 if (!id)
718 {
719 *prev = l->next;
720 l->next = NULL;
721 FcValueListDestroy (l);
722 if (!e->values)
723 FcPatternDel (p, object);
724 return FcTrue;
725 }
726 id--;
727 }
728 return FcFalse;
729 }
730
731 FcBool
FcPatternObjectAddInteger(FcPattern * p,FcObject object,int i)732 FcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
733 {
734 FcValue v;
735
736 v.type = FcTypeInteger;
737 v.u.i = i;
738 return FcPatternObjectAdd (p, object, v, FcTrue);
739 }
740
741 FcBool
FcPatternAddInteger(FcPattern * p,const char * object,int i)742 FcPatternAddInteger (FcPattern *p, const char *object, int i)
743 {
744 return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
745 }
746
747 FcBool
FcPatternObjectAddDouble(FcPattern * p,FcObject object,double d)748 FcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
749 {
750 FcValue v;
751
752 v.type = FcTypeDouble;
753 v.u.d = d;
754 return FcPatternObjectAdd (p, object, v, FcTrue);
755 }
756
757
758 FcBool
FcPatternAddDouble(FcPattern * p,const char * object,double d)759 FcPatternAddDouble (FcPattern *p, const char *object, double d)
760 {
761 return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
762 }
763
764 FcBool
FcPatternObjectAddString(FcPattern * p,FcObject object,const FcChar8 * s)765 FcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
766 {
767 FcValue v;
768
769 if (!s)
770 {
771 v.type = FcTypeVoid;
772 v.u.s = 0;
773 return FcPatternObjectAdd (p, object, v, FcTrue);
774 }
775
776 v.type = FcTypeString;
777 v.u.s = s;
778 return FcPatternObjectAdd (p, object, v, FcTrue);
779 }
780
781 FcBool
FcPatternAddString(FcPattern * p,const char * object,const FcChar8 * s)782 FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
783 {
784 return FcPatternObjectAddString (p, FcObjectFromName (object), s);
785 }
786
787 FcBool
FcPatternAddMatrix(FcPattern * p,const char * object,const FcMatrix * s)788 FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
789 {
790 FcValue v;
791
792 v.type = FcTypeMatrix;
793 v.u.m = s;
794 return FcPatternAdd (p, object, v, FcTrue);
795 }
796
797
798 FcBool
FcPatternObjectAddBool(FcPattern * p,FcObject object,FcBool b)799 FcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
800 {
801 FcValue v;
802
803 v.type = FcTypeBool;
804 v.u.b = b;
805 return FcPatternObjectAdd (p, object, v, FcTrue);
806 }
807
808 FcBool
FcPatternAddBool(FcPattern * p,const char * object,FcBool b)809 FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
810 {
811 return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
812 }
813
814 FcBool
FcPatternAddCharSet(FcPattern * p,const char * object,const FcCharSet * c)815 FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
816 {
817 FcValue v;
818
819 v.type = FcTypeCharSet;
820 v.u.c = (FcCharSet *)c;
821 return FcPatternAdd (p, object, v, FcTrue);
822 }
823
824 FcBool
FcPatternAddFTFace(FcPattern * p,const char * object,const FT_Face f)825 FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
826 {
827 FcValue v;
828
829 v.type = FcTypeFTFace;
830 v.u.f = (void *) f;
831 return FcPatternAdd (p, object, v, FcTrue);
832 }
833
834 FcBool
FcPatternAddLangSet(FcPattern * p,const char * object,const FcLangSet * ls)835 FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
836 {
837 FcValue v;
838
839 v.type = FcTypeLangSet;
840 v.u.l = (FcLangSet *)ls;
841 return FcPatternAdd (p, object, v, FcTrue);
842 }
843
844 FcResult
FcPatternObjectGet(const FcPattern * p,FcObject object,int id,FcValue * v)845 FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
846 {
847 FcPatternElt *e;
848 FcValueListPtr l;
849
850 if (!p)
851 return FcResultNoMatch;
852 e = FcPatternObjectFindElt (p, object);
853 if (!e)
854 return FcResultNoMatch;
855 for (l = FcPatternEltValues(e); l; l = FcValueListNext(l))
856 {
857 if (!id)
858 {
859 *v = FcValueCanonicalize(&l->value);
860 return FcResultMatch;
861 }
862 id--;
863 }
864 return FcResultNoId;
865 }
866
867 FcResult
FcPatternGet(const FcPattern * p,const char * object,int id,FcValue * v)868 FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
869 {
870 return FcPatternObjectGet (p, FcObjectFromName (object), id, v);
871 }
872
873 FcResult
FcPatternObjectGetInteger(const FcPattern * p,FcObject object,int id,int * i)874 FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
875 {
876 FcValue v;
877 FcResult r;
878
879 r = FcPatternObjectGet (p, object, id, &v);
880 if (r != FcResultMatch)
881 return r;
882 switch ((int) v.type) {
883 case FcTypeDouble:
884 *i = (int) v.u.d;
885 break;
886 case FcTypeInteger:
887 *i = v.u.i;
888 break;
889 default:
890 return FcResultTypeMismatch;
891 }
892 return FcResultMatch;
893 }
894
895 FcResult
FcPatternGetInteger(const FcPattern * p,const char * object,int id,int * i)896 FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
897 {
898 return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
899 }
900
901
902 FcResult
FcPatternObjectGetDouble(const FcPattern * p,FcObject object,int id,double * d)903 FcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
904 {
905 FcValue v;
906 FcResult r;
907
908 r = FcPatternObjectGet (p, object, id, &v);
909 if (r != FcResultMatch)
910 return r;
911 switch ((int) v.type) {
912 case FcTypeDouble:
913 *d = v.u.d;
914 break;
915 case FcTypeInteger:
916 *d = (double) v.u.i;
917 break;
918 default:
919 return FcResultTypeMismatch;
920 }
921 return FcResultMatch;
922 }
923
924 FcResult
FcPatternGetDouble(const FcPattern * p,const char * object,int id,double * d)925 FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
926 {
927 return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
928 }
929
930 FcResult
FcPatternObjectGetString(const FcPattern * p,FcObject object,int id,FcChar8 ** s)931 FcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 ** s)
932 {
933 FcValue v;
934 FcResult r;
935
936 r = FcPatternObjectGet (p, object, id, &v);
937 if (r != FcResultMatch)
938 return r;
939 if (v.type != FcTypeString)
940 return FcResultTypeMismatch;
941
942 *s = (FcChar8 *) v.u.s;
943 return FcResultMatch;
944 }
945
946 FcResult
FcPatternGetString(const FcPattern * p,const char * object,int id,FcChar8 ** s)947 FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
948 {
949 return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
950 }
951
952 FcResult
FcPatternGetMatrix(const FcPattern * p,const char * object,int id,FcMatrix ** m)953 FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
954 {
955 FcValue v;
956 FcResult r;
957
958 r = FcPatternGet (p, object, id, &v);
959 if (r != FcResultMatch)
960 return r;
961 if (v.type != FcTypeMatrix)
962 return FcResultTypeMismatch;
963 *m = (FcMatrix *)v.u.m;
964 return FcResultMatch;
965 }
966
967
968 FcResult
FcPatternGetBool(const FcPattern * p,const char * object,int id,FcBool * b)969 FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
970 {
971 FcValue v;
972 FcResult r;
973
974 r = FcPatternGet (p, object, id, &v);
975 if (r != FcResultMatch)
976 return r;
977 if (v.type != FcTypeBool)
978 return FcResultTypeMismatch;
979 *b = v.u.b;
980 return FcResultMatch;
981 }
982
983 FcResult
FcPatternGetCharSet(const FcPattern * p,const char * object,int id,FcCharSet ** c)984 FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
985 {
986 FcValue v;
987 FcResult r;
988
989 r = FcPatternGet (p, object, id, &v);
990 if (r != FcResultMatch)
991 return r;
992 if (v.type != FcTypeCharSet)
993 return FcResultTypeMismatch;
994 *c = (FcCharSet *)v.u.c;
995 return FcResultMatch;
996 }
997
998 FcResult
FcPatternGetFTFace(const FcPattern * p,const char * object,int id,FT_Face * f)999 FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
1000 {
1001 FcValue v;
1002 FcResult r;
1003
1004 r = FcPatternGet (p, object, id, &v);
1005 if (r != FcResultMatch)
1006 return r;
1007 if (v.type != FcTypeFTFace)
1008 return FcResultTypeMismatch;
1009 *f = (FT_Face) v.u.f;
1010 return FcResultMatch;
1011 }
1012
1013 FcResult
FcPatternGetLangSet(const FcPattern * p,const char * object,int id,FcLangSet ** ls)1014 FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
1015 {
1016 FcValue v;
1017 FcResult r;
1018
1019 r = FcPatternGet (p, object, id, &v);
1020 if (r != FcResultMatch)
1021 return r;
1022 if (v.type != FcTypeLangSet)
1023 return FcResultTypeMismatch;
1024 *ls = (FcLangSet *)v.u.l;
1025 return FcResultMatch;
1026 }
1027
1028 FcPattern *
FcPatternDuplicate(const FcPattern * orig)1029 FcPatternDuplicate (const FcPattern *orig)
1030 {
1031 FcPattern *new;
1032 FcPatternElt *e;
1033 int i;
1034 FcValueListPtr l;
1035
1036 new = FcPatternCreate ();
1037 if (!new)
1038 goto bail0;
1039
1040 e = FcPatternElts(orig);
1041
1042 for (i = 0; i < orig->num; i++)
1043 {
1044 for (l = FcPatternEltValues(e + i); l; l = FcValueListNext(l))
1045 {
1046 if (!FcPatternObjectAddWithBinding (new, e[i].object,
1047 FcValueCanonicalize(&l->value),
1048 l->binding,
1049 FcTrue))
1050 goto bail1;
1051
1052 }
1053 }
1054
1055 return new;
1056
1057 bail1:
1058 FcPatternDestroy (new);
1059 bail0:
1060 return 0;
1061 }
1062
1063 void
FcPatternReference(FcPattern * p)1064 FcPatternReference (FcPattern *p)
1065 {
1066 if (!FcRefIsConst (&p->ref))
1067 FcRefInc (&p->ref);
1068 else
1069 FcCacheObjectReference (p);
1070 }
1071
1072 FcPattern *
FcPatternVaBuild(FcPattern * p,va_list va)1073 FcPatternVaBuild (FcPattern *p, va_list va)
1074 {
1075 FcPattern *ret;
1076
1077 FcPatternVapBuild (ret, p, va);
1078 return ret;
1079 }
1080
1081 FcPattern *
FcPatternBuild(FcPattern * p,...)1082 FcPatternBuild (FcPattern *p, ...)
1083 {
1084 va_list va;
1085
1086 va_start (va, p);
1087 FcPatternVapBuild (p, p, va);
1088 va_end (va);
1089 return p;
1090 }
1091
1092 /*
1093 * Add all of the elements in 's' to 'p'
1094 */
1095 FcBool
FcPatternAppend(FcPattern * p,FcPattern * s)1096 FcPatternAppend (FcPattern *p, FcPattern *s)
1097 {
1098 int i;
1099 FcPatternElt *e;
1100 FcValueListPtr v;
1101
1102 for (i = 0; i < s->num; i++)
1103 {
1104 e = FcPatternElts(s)+i;
1105 for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
1106 {
1107 if (!FcPatternObjectAddWithBinding (p, e->object,
1108 FcValueCanonicalize(&v->value),
1109 v->binding, FcTrue))
1110 return FcFalse;
1111 }
1112 }
1113 return FcTrue;
1114 }
1115
1116 FcPattern *
FcPatternFilter(FcPattern * p,const FcObjectSet * os)1117 FcPatternFilter (FcPattern *p, const FcObjectSet *os)
1118 {
1119 int i;
1120 FcPattern *ret;
1121 FcPatternElt *e;
1122 FcValueListPtr v;
1123
1124 if (!os)
1125 return FcPatternDuplicate (p);
1126
1127 ret = FcPatternCreate ();
1128 if (!ret)
1129 return NULL;
1130
1131 for (i = 0; i < os->nobject; i++)
1132 {
1133 FcObject object = FcObjectFromName (os->objects[i]);
1134 e = FcPatternObjectFindElt (p, object);
1135 if (e)
1136 {
1137 for (v = FcPatternEltValues(e); v; v = FcValueListNext(v))
1138 {
1139 if (!FcPatternObjectAddWithBinding (ret, e->object,
1140 FcValueCanonicalize(&v->value),
1141 v->binding, FcTrue))
1142 goto bail0;
1143 }
1144 }
1145 }
1146 return ret;
1147
1148 bail0:
1149 FcPatternDestroy (ret);
1150 return NULL;
1151 }
1152
1153
1154 FcBool
FcPatternSerializeAlloc(FcSerialize * serialize,const FcPattern * pat)1155 FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat)
1156 {
1157 int i;
1158 FcPatternElt *elts = FcPatternElts(pat);
1159
1160 if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern)))
1161 return FcFalse;
1162 if (!FcSerializeAlloc (serialize, elts, pat->num * sizeof (FcPatternElt)))
1163 return FcFalse;
1164 for (i = 0; i < pat->num; i++)
1165 if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues(elts+i)))
1166 return FcFalse;
1167 return FcTrue;
1168 }
1169
1170 FcPattern *
FcPatternSerialize(FcSerialize * serialize,const FcPattern * pat)1171 FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
1172 {
1173 FcPattern *pat_serialized;
1174 FcPatternElt *elts = FcPatternElts (pat);
1175 FcPatternElt *elts_serialized;
1176 FcValueList *values_serialized;
1177 int i;
1178
1179 pat_serialized = FcSerializePtr (serialize, pat);
1180 if (!pat_serialized)
1181 return NULL;
1182 *pat_serialized = *pat;
1183 pat_serialized->size = pat->num;
1184 FcRefSetConst (&pat_serialized->ref);
1185
1186 elts_serialized = FcSerializePtr (serialize, elts);
1187 if (!elts_serialized)
1188 return NULL;
1189
1190 pat_serialized->elts_offset = FcPtrToOffset (pat_serialized,
1191 elts_serialized);
1192
1193 for (i = 0; i < pat->num; i++)
1194 {
1195 values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts+i));
1196 if (!values_serialized)
1197 return NULL;
1198 elts_serialized[i].object = elts[i].object;
1199 elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i],
1200 values_serialized,
1201 FcValueList);
1202 }
1203 if (FcDebug() & FC_DBG_CACHEV) {
1204 printf ("Raw pattern:\n");
1205 FcPatternPrint (pat);
1206 printf ("Serialized pattern:\n");
1207 FcPatternPrint (pat_serialized);
1208 printf ("\n");
1209 }
1210 return pat_serialized;
1211 }
1212
1213 FcBool
FcValueListSerializeAlloc(FcSerialize * serialize,const FcValueList * vl)1214 FcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl)
1215 {
1216 while (vl)
1217 {
1218 if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList)))
1219 return FcFalse;
1220 switch ((int) vl->value.type) {
1221 case FcTypeString:
1222 if (!FcStrSerializeAlloc (serialize, vl->value.u.s))
1223 return FcFalse;
1224 break;
1225 case FcTypeCharSet:
1226 if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c))
1227 return FcFalse;
1228 break;
1229 case FcTypeLangSet:
1230 if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l))
1231 return FcFalse;
1232 break;
1233 default:
1234 break;
1235 }
1236 vl = vl->next;
1237 }
1238 return FcTrue;
1239 }
1240
1241 FcValueList *
FcValueListSerialize(FcSerialize * serialize,const FcValueList * vl)1242 FcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
1243 {
1244 FcValueList *vl_serialized;
1245 FcChar8 *s_serialized;
1246 FcCharSet *c_serialized;
1247 FcLangSet *l_serialized;
1248 FcValueList *head_serialized = NULL;
1249 FcValueList *prev_serialized = NULL;
1250
1251 while (vl)
1252 {
1253 vl_serialized = FcSerializePtr (serialize, vl);
1254 if (!vl_serialized)
1255 return NULL;
1256
1257 if (prev_serialized)
1258 prev_serialized->next = FcPtrToEncodedOffset (prev_serialized,
1259 vl_serialized,
1260 FcValueList);
1261 else
1262 head_serialized = vl_serialized;
1263
1264 vl_serialized->next = NULL;
1265 vl_serialized->value.type = vl->value.type;
1266 switch ((int) vl->value.type) {
1267 case FcTypeInteger:
1268 vl_serialized->value.u.i = vl->value.u.i;
1269 break;
1270 case FcTypeDouble:
1271 vl_serialized->value.u.d = vl->value.u.d;
1272 break;
1273 case FcTypeString:
1274 s_serialized = FcStrSerialize (serialize, vl->value.u.s);
1275 if (!s_serialized)
1276 return NULL;
1277 vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value,
1278 s_serialized,
1279 FcChar8);
1280 break;
1281 case FcTypeBool:
1282 vl_serialized->value.u.b = vl->value.u.b;
1283 break;
1284 case FcTypeMatrix:
1285 /* can't happen */
1286 break;
1287 case FcTypeCharSet:
1288 c_serialized = FcCharSetSerialize (serialize, vl->value.u.c);
1289 if (!c_serialized)
1290 return NULL;
1291 vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value,
1292 c_serialized,
1293 FcCharSet);
1294 break;
1295 case FcTypeFTFace:
1296 /* can't happen */
1297 break;
1298 case FcTypeLangSet:
1299 l_serialized = FcLangSetSerialize (serialize, vl->value.u.l);
1300 if (!l_serialized)
1301 return NULL;
1302 vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value,
1303 l_serialized,
1304 FcLangSet);
1305 break;
1306 default:
1307 break;
1308 }
1309 prev_serialized = vl_serialized;
1310 vl = vl->next;
1311 }
1312 return head_serialized;
1313 }
1314
1315 #define __fcpat__
1316 #include "fcaliastail.h"
1317 #include "fcftaliastail.h"
1318 #undef __fcpat__
1319