source: trunk/poppler/fontconfig-2.3.2-os2/src/fcpat.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

File size: 25.0 KB
Line 
1/*
2 * $RCSId: xc/lib/fontconfig/src/fcpat.c,v 1.18 2002/09/18 17:11:46 tsi Exp $
3 *
4 * Copyright © 2000 Keith Packard
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 <assert.h>
28#include "fcint.h"
29
30FcPattern *
31FcPatternCreate (void)
32{
33    FcPattern   *p;
34
35    p = (FcPattern *) malloc (sizeof (FcPattern));
36    if (!p)
37        return 0;
38    FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern));
39    p->num = 0;
40    p->size = 0;
41    p->elts = 0;
42    p->ref = 1;
43    return p;
44}
45
46void
47FcValueDestroy (FcValue v)
48{
49    switch (v.type) {
50    case FcTypeString:
51        FcStrFree ((FcChar8 *) v.u.s);
52        break;
53    case FcTypeMatrix:
54        FcMatrixFree ((FcMatrix *) v.u.m);
55        break;
56    case FcTypeCharSet:
57        FcCharSetDestroy ((FcCharSet *) v.u.c);
58        break;
59    case FcTypeLangSet:
60        FcLangSetDestroy ((FcLangSet *) v.u.l);
61        break;
62    default:
63        break;
64    }
65}
66
67FcValue
68FcValueSave (FcValue v)
69{
70    switch (v.type) {
71    case FcTypeString:
72        v.u.s = FcStrCopy (v.u.s);
73        if (!v.u.s)
74            v.type = FcTypeVoid;
75        break;
76    case FcTypeMatrix:
77        v.u.m = FcMatrixCopy (v.u.m);
78        if (!v.u.m)
79            v.type = FcTypeVoid;
80        break;
81    case FcTypeCharSet:
82        v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
83        if (!v.u.c)
84            v.type = FcTypeVoid;
85        break;
86    case FcTypeLangSet:
87        v.u.l = FcLangSetCopy (v.u.l);
88        if (!v.u.l)
89            v.type = FcTypeVoid;
90        break;
91    default:
92        break;
93    }
94    return v;
95}
96
97void
98FcValueListDestroy (FcValueList *l)
99{
100    FcValueList    *next;
101    for (; l; l = next)
102    {
103        switch (l->value.type) {
104        case FcTypeString:
105            FcStrFree ((FcChar8 *) l->value.u.s);
106            break;
107        case FcTypeMatrix:
108            FcMatrixFree ((FcMatrix *) l->value.u.m);
109            break;
110        case FcTypeCharSet:
111            FcCharSetDestroy ((FcCharSet *) l->value.u.c);
112            break;
113        case FcTypeLangSet:
114            FcLangSetDestroy ((FcLangSet *) l->value.u.l);
115            break;
116        default:
117            break;
118        }
119        next = l->next;
120        FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
121        free (l);
122    }
123}
124
125FcBool
126FcValueEqual (FcValue va, FcValue vb)
127{
128    if (va.type != vb.type)
129    {
130        if (va.type == FcTypeInteger)
131        {
132            va.type = FcTypeDouble;
133            va.u.d = va.u.i;
134        }
135        if (vb.type == FcTypeInteger)
136        {
137            vb.type = FcTypeDouble;
138            vb.u.d = vb.u.i;
139        }
140        if (va.type != vb.type)
141            return FcFalse;
142    }
143    switch (va.type) {
144    case FcTypeVoid:
145        return FcTrue;
146    case FcTypeInteger:
147        return va.u.i == vb.u.i;
148    case FcTypeDouble:
149        return va.u.d == vb.u.d;
150    case FcTypeString:
151        return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
152    case FcTypeBool:
153        return va.u.b == vb.u.b;
154    case FcTypeMatrix:
155        return FcMatrixEqual (va.u.m, vb.u.m);
156    case FcTypeCharSet:
157        return FcCharSetEqual (va.u.c, vb.u.c);
158    case FcTypeFTFace:
159        return va.u.f == vb.u.f;
160    case FcTypeLangSet:
161        return FcLangSetEqual (va.u.l, vb.u.l);
162    }
163    return FcFalse;
164}
165
166static FcChar32
167FcDoubleHash (double d)
168{
169    if (d < 0)
170        d = -d;
171    if (d > 0xffffffff)
172        d = 0xffffffff;
173    return (FcChar32) d;
174}
175
176static FcChar32
177FcStringHash (const FcChar8 *s)
178{
179    FcChar8     c;
180    FcChar32    h = 0;
181   
182    if (s)
183        while ((c = *s++))
184            h = ((h << 1) | (h >> 31)) ^ c;
185    return h;
186}
187
188static FcChar32
189FcValueHash (FcValue v)
190{
191    switch (v.type) {
192    case FcTypeVoid:
193        return 0;
194    case FcTypeInteger:
195        return (FcChar32) v.u.i;
196    case FcTypeDouble:
197        return FcDoubleHash (v.u.d);
198    case FcTypeString:
199        return FcStringHash (v.u.s);
200    case FcTypeBool:
201        return (FcChar32) v.u.b;
202    case FcTypeMatrix:
203        return (FcDoubleHash (v.u.m->xx) ^ 
204                FcDoubleHash (v.u.m->xy) ^ 
205                FcDoubleHash (v.u.m->yx) ^ 
206                FcDoubleHash (v.u.m->yy));
207    case FcTypeCharSet:
208        return (FcChar32) v.u.c->num;
209    case FcTypeFTFace:
210        return FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->family_name) ^
211               FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->style_name);
212    case FcTypeLangSet:
213        return FcLangSetHash (v.u.l);
214    }
215    return FcFalse;
216}
217
218static FcBool
219FcValueListEqual (FcValueList *la, FcValueList *lb)
220{
221    if (la == lb)
222        return FcTrue;
223
224    while (la && lb)
225    {
226        if (!FcValueEqual (la->value, lb->value))
227            return FcFalse;
228        la = la->next;
229        lb = lb->next;
230    }
231    if (la || lb)
232        return FcFalse;
233    return FcTrue;
234}
235
236static FcChar32
237FcValueListHash (FcValueList *l)
238{
239    FcChar32    hash = 0;
240   
241    while (l)
242    {
243        hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (l->value);
244        l = l->next;
245    }
246    return hash;
247}
248
249void
250FcPatternDestroy (FcPattern *p)
251{
252    int             i;
253   
254    if (p->ref == FC_REF_CONSTANT || --p->ref > 0)
255        return;
256
257    for (i = 0; i < p->num; i++)
258        FcValueListDestroy (p->elts[i].values);
259
260    p->num = 0;
261    if (p->elts)
262    {
263        FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
264        free (p->elts);
265        p->elts = 0;
266    }
267    p->size = 0;
268    FcMemFree (FC_MEM_PATTERN, sizeof (FcPattern));
269    free (p);
270}
271
272#define FC_VALUE_LIST_HASH_SIZE     257
273#define FC_PATTERN_HASH_SIZE        67
274
275typedef struct _FcValueListEnt FcValueListEnt;
276
277struct _FcValueListEnt {
278    FcValueListEnt  *next;
279    FcValueList     *list;
280    FcChar32        hash, pad;
281};
282
283typedef union _FcValueListAlign {
284    FcValueListEnt  ent;
285    FcValueList     list;
286} FcValueListAlign;
287
288static int          FcValueListFrozenCount[FcTypeLangSet + 1];
289static int          FcValueListFrozenBytes[FcTypeLangSet + 1];
290static char         *FcValueListFrozenName[] = {
291    "Void", 
292    "Integer", 
293    "Double", 
294    "String", 
295    "Bool",
296    "Matrix",
297    "CharSet",
298    "FTFace",
299    "LangSet"
300};
301
302void
303FcValueListReport (void);
304   
305void
306FcValueListReport (void)
307{
308    FcType  t;
309
310    printf ("Fc Frozen Values:\n");
311    printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
312    for (t = FcTypeVoid; t <= FcTypeLangSet; t++)
313        printf ("\t%8s %9d %9d\n", FcValueListFrozenName[t],
314                FcValueListFrozenCount[t], FcValueListFrozenBytes[t]);
315}
316
317static FcValueListEnt *
318FcValueListEntCreate (FcValueList *h)
319{
320    FcValueListAlign    *ea;
321    FcValueListEnt  *e;
322    FcValueList     *l, *new;
323    int             n;
324    int             size;
325
326    n = 0;
327    for (l = h; l; l = l->next)
328        n++;
329    size = sizeof (FcValueListAlign) + n * sizeof (FcValueList);
330    FcValueListFrozenCount[h->value.type]++;
331    FcValueListFrozenBytes[h->value.type] += size;
332    ea = malloc (size);
333    if (!ea)
334        return 0;
335    FcMemAlloc (FC_MEM_VALLIST, size);
336    e = &ea->ent;
337    e->list = (FcValueList *) (ea + 1);
338    new = e->list;
339    for (l = h; l; l = l->next, new++)
340    {
341        if (l->value.type == FcTypeString)
342        {
343            new->value.type = FcTypeString;
344            new->value.u.s = FcObjectStaticName (l->value.u.s);
345        }
346        else
347        {
348            new->value = FcValueSave (l->value);
349        }
350        new->binding = l->binding;
351        if (l->next)
352            new->next = new + 1;
353        else
354            new->next = 0;
355    }
356    return e;
357}
358
359static void
360FcValueListEntDestroy (FcValueListEnt *e)
361{
362    FcValueList *l;
363
364    FcValueListFrozenCount[e->list->value.type]--;
365
366    /* XXX: We should perform these two operations with "size" as
367       computed in FcValueListEntCreate, but we don't have access to
368       that value here. Without this, the FcValueListFrozenBytes
369       values will be wrong as will the FcMemFree counts.
370
371       FcValueListFrozenBytes[e->list->value.type] -= size;
372       FcMemFree (FC_MEM_VALLIST, size);
373    */
374
375    for (l = e->list; l; l = l->next)
376    {
377        if (l->value.type != FcTypeString)
378            FcValueDestroy (l->value);
379    }
380    /* XXX: Are we being too chummy with the implementation here to
381       free(e) when it was actually the enclosing FcValueListAlign
382       that was allocated? */
383    free (e);
384}
385
386static int      FcValueListTotal;
387static int      FcValueListUsed;
388
389static FcValueListEnt   *FcValueListHashTable[FC_VALUE_LIST_HASH_SIZE];
390
391static FcValueList *
392FcValueListFreeze (FcValueList *l)
393{
394    FcChar32                hash = FcValueListHash (l);
395    FcValueListEnt          **bucket = &FcValueListHashTable[hash % FC_VALUE_LIST_HASH_SIZE];
396    FcValueListEnt          *ent;
397
398    FcValueListTotal++;
399    for (ent = *bucket; ent; ent = ent->next)
400    {
401        if (ent->hash == hash && FcValueListEqual (ent->list, l))
402            return ent->list;
403    }
404
405    ent = FcValueListEntCreate (l);
406    if (!ent)
407        return 0;
408
409    FcValueListUsed++;
410    ent->hash = hash;
411    ent->next = *bucket;
412    *bucket = ent;
413    return ent->list;
414}
415
416static void
417FcValueListThawAll (void)
418{
419    int i;
420    FcValueListEnt      *ent, *next;
421
422    for (i = 0; i < FC_VALUE_LIST_HASH_SIZE; i++)
423    {
424        for (ent = FcValueListHashTable[i]; ent; ent = next)
425        {
426            next = ent->next;
427            FcValueListEntDestroy (ent);
428        }
429        FcValueListHashTable[i] = 0;
430    }
431
432    FcValueListTotal = 0;
433    FcValueListUsed = 0;
434}
435
436static FcChar32
437FcPatternBaseHash (FcPattern *b)
438{
439    FcChar32    hash = b->num;
440    int         i;
441
442    for (i = 0; i < b->num; i++)
443        hash = ((hash << 1) | (hash >> 31)) ^ ((long) b->elts[i].values);
444    return hash;
445}
446
447typedef struct _FcPatternEnt FcPatternEnt;
448
449struct _FcPatternEnt {
450    FcPatternEnt    *next;
451    FcChar32        hash;
452    FcPattern       pattern;
453};
454
455static int      FcPatternTotal;
456static int      FcPatternUsed;
457
458static FcPatternEnt     *FcPatternHashTable[FC_VALUE_LIST_HASH_SIZE];
459
460static FcPattern *
461FcPatternBaseFreeze (FcPattern *b)
462{
463    FcChar32            hash = FcPatternBaseHash (b);
464    FcPatternEnt        **bucket = &FcPatternHashTable[hash % FC_VALUE_LIST_HASH_SIZE];
465    FcPatternEnt        *ent;
466    int                 i;
467    int                 size;
468
469    FcPatternTotal++;
470    for (ent = *bucket; ent; ent = ent->next)
471    {
472        if (ent->hash == hash && b->num == ent->pattern.num)
473        {
474            for (i = 0; i < b->num; i++)
475            {
476                if (b->elts[i].object != ent->pattern.elts[i].object)
477                    break;
478                if (b->elts[i].values != ent->pattern.elts[i].values)
479                    break;
480            }
481            if (i == b->num)
482                return &ent->pattern;
483        }
484    }
485
486    /*
487     * Compute size of pattern + elts
488     */
489    size = sizeof (FcPatternEnt) + b->num*sizeof (FcPatternElt);
490    ent = malloc (size);
491    if (!ent)
492        return 0;
493
494    FcMemAlloc (FC_MEM_PATTERN, size);
495    FcPatternUsed++;
496
497    ent->pattern.elts = (FcPatternElt *) (ent + 1);
498    ent->pattern.num = b->num;
499    ent->pattern.size = b->num;
500    ent->pattern.ref = FC_REF_CONSTANT;
501
502    for (i = 0; i < b->num; i++)
503    {
504        ent->pattern.elts[i].values = b->elts[i].values;
505        ent->pattern.elts[i].object = b->elts[i].object;
506    }
507
508    ent->hash = hash;
509    ent->next = *bucket;
510    *bucket = ent;
511    return &ent->pattern;
512}
513
514static void
515FcPatternBaseThawAll (void)
516{
517    int i;
518    FcPatternEnt        *ent, *next;
519
520    for (i = 0; i < FC_VALUE_LIST_HASH_SIZE; i++)
521    {
522        for (ent = FcPatternHashTable[i]; ent; ent = next)
523        {
524            next = ent->next;
525            free (ent);
526        }
527        FcPatternHashTable[i] = 0;
528    }
529
530    FcPatternTotal = 0;
531    FcPatternUsed = 0;
532}
533
534FcPattern *
535FcPatternFreeze (FcPattern *p)
536{
537    FcPattern   *b, *n = 0;
538    int         size;
539    int         i;
540   
541    if (p->ref == FC_REF_CONSTANT)
542       return p;
543
544    size = sizeof (FcPattern) + p->num * sizeof (FcPatternElt);
545    b = (FcPattern *) malloc (size);
546    if (!b)
547        return 0;
548    FcMemAlloc (FC_MEM_PATTERN, size);
549    b->num = p->num;
550    b->size = b->num;
551    b->ref = 1;
552    b->elts = (FcPatternElt *) (b + 1);
553    /*
554     * Freeze object lists
555     */
556    for (i = 0; i < p->num; i++)
557    {
558        b->elts[i].object = p->elts[i].object;
559        b->elts[i].values = FcValueListFreeze (p->elts[i].values);
560        if (!b->elts[i].values)
561            goto bail;
562    }
563    /*
564     * Freeze base
565     */
566    n = FcPatternBaseFreeze (b);
567#ifdef CHATTY
568    if (FcDebug() & FC_DBG_MEMORY)
569    {
570        printf ("ValueLists: total %9d used %9d\n", FcValueListTotal, FcValueListUsed);
571        printf ("Patterns:   total %9d used %9d\n", FcPatternTotal, FcPatternUsed);
572    }
573#endif
574bail:
575    free (b);
576#ifdef DEBUG
577    assert (FcPatternEqual (n, p));
578#endif
579    return n;
580}
581
582void
583FcPatternThawAll (void)
584{
585    FcPatternBaseThawAll ();
586    FcValueListThawAll ();
587}
588
589static int
590FcPatternPosition (const FcPattern *p, const char *object)
591{
592    int     low, high, mid, c;
593
594    object = FcObjectStaticName(object);
595    low = 0;
596    high = p->num - 1;
597    c = 1;
598    mid = 0;
599    while (low <= high)
600    {
601        mid = (low + high) >> 1;
602        c = p->elts[mid].object - object;
603        if (c == 0)
604            return mid;
605        if (c < 0)
606            low = mid + 1;
607        else
608            high = mid - 1;
609    }
610    if (c < 0)
611        mid++;
612    return -(mid + 1);
613}
614
615FcPatternElt *
616FcPatternFindElt (const FcPattern *p, const char *object)
617{
618    int     i = FcPatternPosition (p, object);
619    if (i < 0)
620        return 0;
621    return &p->elts[i];
622}
623
624FcPatternElt *
625FcPatternInsertElt (FcPattern *p, const char *object)
626{
627    int             i;
628    FcPatternElt   *e;
629   
630    i = FcPatternPosition (p, object);
631    if (i < 0)
632    {
633        i = -i - 1;
634   
635        /* grow array */
636        if (p->num + 1 >= p->size)
637        {
638            int s = p->size + 16;
639            if (p->elts)
640                e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt));
641            else
642                e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
643            if (!e)
644                return FcFalse;
645            p->elts = e;
646            if (p->size)
647                FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
648            FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
649            while (p->size < s)
650            {
651                p->elts[p->size].object = 0;
652                p->elts[p->size].values = 0;
653                p->size++;
654            }
655        }
656       
657        /* move elts up */
658        memmove (p->elts + i + 1,
659                 p->elts + i,
660                 sizeof (FcPatternElt) *
661                 (p->num - i));
662                 
663        /* bump count */
664        p->num++;
665       
666        p->elts[i].object = FcObjectStaticName (object);
667        p->elts[i].values = 0;
668    }
669   
670    return &p->elts[i];
671}
672
673FcBool
674FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
675{
676    int i;
677
678    if (pa == pb)
679        return FcTrue;
680
681    if (pa->num != pb->num)
682        return FcFalse;
683    for (i = 0; i < pa->num; i++)
684    {
685        if (pa->elts[i].object != pb->elts[i].object)
686            return FcFalse;
687        if (!FcValueListEqual (pa->elts[i].values, pb->elts[i].values))
688            return FcFalse;
689    }
690    return FcTrue;
691}
692
693FcChar32
694FcPatternHash (const FcPattern *p)
695{
696    int         i;
697    FcChar32    h = 0;
698
699    for (i = 0; i < p->num; i++)
700    {
701        h = (((h << 1) | (h >> 31)) ^ 
702             FcStringHash ((const FcChar8 *) p->elts[i].object) ^
703             FcValueListHash (p->elts[i].values));
704    }
705    return h;
706}
707
708FcBool
709FcPatternEqualSubset (const FcPattern *pa, const FcPattern *pb, const FcObjectSet *os)
710{
711    FcPatternElt    *ea, *eb;
712    int             i;
713   
714    for (i = 0; i < os->nobject; i++)
715    {
716        ea = FcPatternFindElt (pa, os->objects[i]);
717        eb = FcPatternFindElt (pb, os->objects[i]);
718        if (ea)
719        {
720            if (!eb)
721                return FcFalse;
722            if (!FcValueListEqual (ea->values, eb->values))
723                return FcFalse;
724        }
725        else
726        {
727            if (eb)
728                return FcFalse;
729        }
730    }
731    return FcTrue;
732}
733
734FcBool
735FcPatternAddWithBinding  (FcPattern         *p,
736                          const char        *object,
737                          FcValue           value,
738                          FcValueBinding    binding,
739                          FcBool            append)
740{
741    FcPatternElt   *e;
742    FcValueList    *new, **prev;
743
744    if (p->ref == FC_REF_CONSTANT)
745        goto bail0;
746
747    new = (FcValueList *) malloc (sizeof (FcValueList));
748    if (!new)
749        goto bail0;
750
751    FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
752    /* dup string */
753    value = FcValueSave (value);
754    if (value.type == FcTypeVoid)
755        goto bail1;
756
757    new->value = value;
758    new->binding = binding;
759    new->next = 0;
760   
761    e = FcPatternInsertElt (p, object);
762    if (!e)
763        goto bail2;
764   
765    if (append)
766    {
767        for (prev = &e->values; *prev; prev = &(*prev)->next);
768        *prev = new;
769    }
770    else
771    {
772        new->next = e->values;
773        e->values = new;
774    }
775   
776    return FcTrue;
777
778bail2:   
779    switch (value.type) {
780    case FcTypeString:
781        FcStrFree ((FcChar8 *) value.u.s);
782        break;
783    case FcTypeMatrix:
784        FcMatrixFree ((FcMatrix *) value.u.m);
785        break;
786    case FcTypeCharSet:
787        FcCharSetDestroy ((FcCharSet *) value.u.c);
788        break;
789    case FcTypeLangSet:
790        FcLangSetDestroy ((FcLangSet *) value.u.l);
791        break;
792    default:
793        break;
794    }
795bail1:
796    FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
797    free (new);
798bail0:
799    return FcFalse;
800}
801
802FcBool
803FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
804{
805    return FcPatternAddWithBinding (p, object, value, FcValueBindingStrong, append);
806}
807
808FcBool
809FcPatternAddWeak  (FcPattern *p, const char *object, FcValue value, FcBool append)
810{
811    return FcPatternAddWithBinding (p, object, value, FcValueBindingWeak, append);
812}
813
814FcBool
815FcPatternDel (FcPattern *p, const char *object)
816{
817    FcPatternElt   *e;
818    int             i;
819
820    e = FcPatternFindElt (p, object);
821    if (!e)
822        return FcFalse;
823
824    i = e - p->elts;
825   
826    /* destroy value */
827    FcValueListDestroy (e->values);
828   
829    /* shuffle existing ones down */
830    memmove (e, e+1, (p->elts + p->num - (e + 1)) * sizeof (FcPatternElt));
831    p->num--;
832    p->elts[p->num].object = 0;
833    p->elts[p->num].values = 0;
834    return FcTrue;
835}
836
837FcBool
838FcPatternRemove (FcPattern *p, const char *object, int id)
839{
840    FcPatternElt   *e;
841    FcValueList    **prev, *l;
842
843    e = FcPatternFindElt (p, object);
844    if (!e)
845        return FcFalse;
846    for (prev = &e->values; (l = *prev); prev = &l->next)
847    {
848        if (!id)
849        {
850            *prev = l->next;
851            l->next = 0;
852            FcValueListDestroy (l);
853            if (!e->values)
854                FcPatternDel (p, object);
855            return FcTrue;
856        }
857        id--;
858    }
859    return FcFalse;
860}
861
862FcBool
863FcPatternAddInteger (FcPattern *p, const char *object, int i)
864{
865    FcValue     v;
866
867    v.type = FcTypeInteger;
868    v.u.i = i;
869    return FcPatternAdd (p, object, v, FcTrue);
870}
871
872FcBool
873FcPatternAddDouble (FcPattern *p, const char *object, double d)
874{
875    FcValue     v;
876
877    v.type = FcTypeDouble;
878    v.u.d = d;
879    return FcPatternAdd (p, object, v, FcTrue);
880}
881
882
883FcBool
884FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
885{
886    FcValue     v;
887
888    v.type = FcTypeString;
889    v.u.s = s;
890    return FcPatternAdd (p, object, v, FcTrue);
891}
892
893FcBool
894FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
895{
896    FcValue     v;
897
898    v.type = FcTypeMatrix;
899    v.u.m = (FcMatrix *) s;
900    return FcPatternAdd (p, object, v, FcTrue);
901}
902
903
904FcBool
905FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
906{
907    FcValue     v;
908
909    v.type = FcTypeBool;
910    v.u.b = b;
911    return FcPatternAdd (p, object, v, FcTrue);
912}
913
914FcBool
915FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
916{
917    FcValue     v;
918
919    v.type = FcTypeCharSet;
920    v.u.c = (FcCharSet *) c;
921    return FcPatternAdd (p, object, v, FcTrue);
922}
923
924FcBool
925FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
926{
927    FcValue     v;
928
929    v.type = FcTypeFTFace;
930    v.u.f = (void *) f;
931    return FcPatternAdd (p, object, v, FcTrue);
932}
933
934FcBool
935FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
936{
937    FcValue     v;
938
939    v.type = FcTypeLangSet;
940    v.u.l = (FcLangSet *) ls;
941    return FcPatternAdd (p, object, v, FcTrue);
942}
943
944FcResult
945FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
946{
947    FcPatternElt   *e;
948    FcValueList    *l;
949
950    e = FcPatternFindElt (p, object);
951    if (!e)
952        return FcResultNoMatch;
953    for (l = e->values; l; l = l->next)
954    {
955        if (!id)
956        {
957            *v = l->value;
958            return FcResultMatch;
959        }
960        id--;
961    }
962    return FcResultNoId;
963}
964
965FcResult
966FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
967{
968    FcValue     v;
969    FcResult    r;
970
971    r = FcPatternGet (p, object, id, &v);
972    if (r != FcResultMatch)
973        return r;
974    switch (v.type) {
975    case FcTypeDouble:
976        *i = (int) v.u.d;
977        break;
978    case FcTypeInteger:
979        *i = v.u.i;
980        break;
981    default:
982        return FcResultTypeMismatch;
983    }
984    return FcResultMatch;
985}
986
987FcResult
988FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
989{
990    FcValue     v;
991    FcResult    r;
992
993    r = FcPatternGet (p, object, id, &v);
994    if (r != FcResultMatch)
995        return r;
996    switch (v.type) {
997    case FcTypeDouble:
998        *d = v.u.d;
999        break;
1000    case FcTypeInteger:
1001        *d = (double) v.u.i;
1002        break;
1003    default:
1004        return FcResultTypeMismatch;
1005    }
1006    return FcResultMatch;
1007}
1008
1009FcResult
1010FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
1011{
1012    FcValue     v;
1013    FcResult    r;
1014
1015    r = FcPatternGet (p, object, id, &v);
1016    if (r != FcResultMatch)
1017        return r;
1018    if (v.type != FcTypeString)
1019        return FcResultTypeMismatch;
1020    *s = (FcChar8 *) v.u.s;
1021    return FcResultMatch;
1022}
1023
1024FcResult
1025FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
1026{
1027    FcValue     v;
1028    FcResult    r;
1029
1030    r = FcPatternGet (p, object, id, &v);
1031    if (r != FcResultMatch)
1032        return r;
1033    if (v.type != FcTypeMatrix)
1034        return FcResultTypeMismatch;
1035    *m = (FcMatrix *) v.u.m;
1036    return FcResultMatch;
1037}
1038
1039
1040FcResult
1041FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
1042{
1043    FcValue     v;
1044    FcResult    r;
1045
1046    r = FcPatternGet (p, object, id, &v);
1047    if (r != FcResultMatch)
1048        return r;
1049    if (v.type != FcTypeBool)
1050        return FcResultTypeMismatch;
1051    *b = v.u.b;
1052    return FcResultMatch;
1053}
1054
1055FcResult
1056FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
1057{
1058    FcValue     v;
1059    FcResult    r;
1060
1061    r = FcPatternGet (p, object, id, &v);
1062    if (r != FcResultMatch)
1063        return r;
1064    if (v.type != FcTypeCharSet)
1065        return FcResultTypeMismatch;
1066    *c = (FcCharSet *) v.u.c;
1067    return FcResultMatch;
1068}
1069
1070FcResult
1071FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
1072{
1073    FcValue     v;
1074    FcResult    r;
1075
1076    r = FcPatternGet (p, object, id, &v);
1077    if (r != FcResultMatch)
1078        return r;
1079    if (v.type != FcTypeFTFace)
1080        return FcResultTypeMismatch;
1081    *f = (FT_Face) v.u.f;
1082    return FcResultMatch;
1083}
1084
1085FcResult
1086FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
1087{
1088    FcValue     v;
1089    FcResult    r;
1090
1091    r = FcPatternGet (p, object, id, &v);
1092    if (r != FcResultMatch)
1093        return r;
1094    if (v.type != FcTypeLangSet)
1095        return FcResultTypeMismatch;
1096    *ls = (FcLangSet *) v.u.l;
1097    return FcResultMatch;
1098}
1099
1100FcPattern *
1101FcPatternDuplicate (const FcPattern *orig)
1102{
1103    FcPattern       *new;
1104    int             i;
1105    FcValueList    *l;
1106
1107    new = FcPatternCreate ();
1108    if (!new)
1109        goto bail0;
1110
1111    for (i = 0; i < orig->num; i++)
1112    {
1113        for (l = orig->elts[i].values; l; l = l->next)
1114            if (!FcPatternAdd (new, orig->elts[i].object, l->value, FcTrue))
1115                goto bail1;
1116    }
1117
1118    return new;
1119
1120bail1:
1121    FcPatternDestroy (new);
1122bail0:
1123    return 0;
1124}
1125
1126void
1127FcPatternReference (FcPattern *p)
1128{
1129    if (p->ref != FC_REF_CONSTANT)
1130        p->ref++;
1131}
1132
1133FcPattern *
1134FcPatternVaBuild (FcPattern *orig, va_list va)
1135{
1136    FcPattern   *ret;
1137   
1138    FcPatternVapBuild (ret, orig, va);
1139    return ret;
1140}
1141
1142FcPattern *
1143FcPatternBuild (FcPattern *orig, ...)
1144{
1145    va_list     va;
1146   
1147    va_start (va, orig);
1148    FcPatternVapBuild (orig, orig, va);
1149    va_end (va);
1150    return orig;
1151}
1152
1153/*
1154 * Add all of the elements in 's' to 'p'
1155 */
1156FcBool
1157FcPatternAppend (FcPattern *p, FcPattern *s)
1158{
1159    int             i;
1160    FcPatternElt    *e;
1161    FcValueList     *v;
1162   
1163    for (i = 0; i < s->num; i++)
1164    {
1165        e = &s->elts[i];
1166        for (v = e->values; v; v = v->next)
1167        {
1168            if (!FcPatternAddWithBinding (p, e->object,
1169                                          v->value, v->binding, FcTrue))
1170                return FcFalse;
1171        }
1172    }
1173    return FcTrue;
1174}
1175
1176typedef struct _FcObjectStaticNameList
1177{
1178  void *pPtr;
1179  void *pNext;
1180} FcObjectStaticNameList_t, *FcObjectStaticNameList_p;
1181
1182static FcObjectStaticNameList_p pFcObjectStaticNameListHead = NULL;
1183
1184void
1185FcObjectStaticNameListInit()
1186{
1187  pFcObjectStaticNameListHead = NULL;
1188}
1189
1190void
1191FcObjectStaticNameListFini()
1192{
1193  FcObjectStaticNameList_p pToDelete;
1194
1195  while (pFcObjectStaticNameListHead)
1196  {
1197    pToDelete = pFcObjectStaticNameListHead;
1198    pFcObjectStaticNameListHead = pFcObjectStaticNameListHead->pNext;
1199
1200    free(pToDelete->pPtr);
1201    free(pToDelete);
1202  }
1203}
1204
1205void
1206FcObjectStaticNameListAdd(void *pPtr)
1207{
1208  FcObjectStaticNameList_p pNew;
1209
1210  pNew = (FcObjectStaticNameList_p) malloc(sizeof(FcObjectStaticNameList_t));
1211  if (pNew)
1212  {
1213    pNew->pPtr = pPtr;
1214    pNew->pNext = pFcObjectStaticNameListHead;
1215    pFcObjectStaticNameListHead = pNew;
1216  }
1217}
1218
1219
1220const char *
1221FcObjectStaticName (const char *name)
1222{
1223#define OBJECT_HASH_SIZE    31
1224    static struct objectBucket {
1225        struct objectBucket     *next;
1226        FcChar32                hash;
1227    } *buckets[OBJECT_HASH_SIZE];
1228    FcChar32            hash = FcStringHash ((const FcChar8 *) name);
1229    struct objectBucket **p;
1230    struct objectBucket *b;
1231    int                 size;
1232
1233    for (p = &buckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
1234        if (b->hash == hash && !strcmp (name, (char *) (b + 1)))
1235            return (char *) (b + 1);
1236    size = sizeof (struct objectBucket) + strlen (name) + 1;
1237    b = malloc (size);
1238    FcObjectStaticNameListAdd(b);
1239    FcMemAlloc (FC_MEM_STATICSTR, size);
1240    if (!b)
1241        return NULL;
1242    b->next = 0;
1243    b->hash = hash;
1244    strcpy ((char *) (b + 1), name);
1245    *p = b;
1246    return (char *) (b + 1);
1247}
Note: See TracBrowser for help on using the repository browser.