~ubuntu-branches/ubuntu/lucid/fontconfig/lucid

« back to all changes in this revision

Viewing changes to src/fcpat.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio M. Di Nitto
  • Date: 2004-10-07 06:04:17 UTC
  • Revision ID: james.westby@ubuntu.com-20041007060417-dliqa1ebkoh7isns
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
30
FcPattern *
 
31
FcPatternCreate (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
 
 
46
void
 
47
FcValueDestroy (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
 
 
67
FcValue
 
68
FcValueSave (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
 
 
97
void
 
98
FcValueListDestroy (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
 
 
125
FcBool
 
126
FcValueEqual (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
 
 
166
static FcChar32
 
167
FcDoubleHash (double d)
 
168
{
 
169
    if (d < 0)
 
170
        d = -d;
 
171
    if (d > 0xffffffff)
 
172
        d = 0xffffffff;
 
173
    return (FcChar32) d;
 
174
}
 
175
 
 
176
static FcChar32
 
177
FcStringHash (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
 
 
188
static FcChar32
 
189
FcValueHash (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
 
 
218
static FcBool
 
219
FcValueListEqual (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
 
 
236
static FcChar32
 
237
FcValueListHash (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
 
 
249
void
 
250
FcPatternDestroy (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
 
 
275
typedef struct _FcValueListEnt FcValueListEnt;
 
276
 
 
277
struct _FcValueListEnt {
 
278
    FcValueListEnt  *next;
 
279
    FcValueList     *list;
 
280
    FcChar32        hash, pad;
 
281
};
 
282
 
 
283
typedef union _FcValueListAlign {
 
284
    FcValueListEnt  ent;
 
285
    FcValueList     list;
 
286
} FcValueListAlign;
 
287
 
 
288
static int          FcValueListFrozenCount[FcTypeLangSet + 1];
 
289
static int          FcValueListFrozenBytes[FcTypeLangSet + 1];
 
290
static char         *FcValueListFrozenName[] = {
 
291
    "Void", 
 
292
    "Integer", 
 
293
    "Double", 
 
294
    "String", 
 
295
    "Bool",
 
296
    "Matrix",
 
297
    "CharSet",
 
298
    "FTFace",
 
299
    "LangSet"
 
300
};
 
301
 
 
302
void
 
303
FcValueListReport (void);
 
304
    
 
305
void
 
306
FcValueListReport (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
 
 
317
static FcValueListEnt *
 
318
FcValueListEntCreate (FcValueList *h)
 
319
{
 
320
    FcValueListAlign    *ea;
 
321
    FcValueListEnt  *e;
 
322
    FcValueList     *l, *new;
 
323
    int             n;
 
324
    int             string_size = 0;
 
325
    FcChar8         *strs;
 
326
    int             size;
 
327
 
 
328
    n = 0;
 
329
    for (l = h; l; l = l->next)
 
330
    {
 
331
        if (l->value.type == FcTypeString)
 
332
            string_size += strlen ((char *) l->value.u.s) + 1;
 
333
        n++;
 
334
    }
 
335
    size = sizeof (FcValueListAlign) + n * sizeof (FcValueList) + string_size;
 
336
    FcValueListFrozenCount[h->value.type]++;
 
337
    FcValueListFrozenBytes[h->value.type] += size;
 
338
    ea = malloc (size);
 
339
    if (!ea)
 
340
        return 0;
 
341
    FcMemAlloc (FC_MEM_VALLIST, size);
 
342
    e = &ea->ent;
 
343
    e->list = (FcValueList *) (ea + 1);
 
344
    strs = (FcChar8 *) (e->list + n);
 
345
    new = e->list;
 
346
    for (l = h; l; l = l->next, new++)
 
347
    {
 
348
        if (l->value.type == FcTypeString)
 
349
        {
 
350
            new->value.type = FcTypeString;
 
351
            new->value.u.s = strs;
 
352
            strcpy ((char *) strs, (char *) l->value.u.s);
 
353
            strs += strlen ((char *) strs) + 1;
 
354
        }
 
355
        else
 
356
        {
 
357
            new->value = l->value;
 
358
            new->value = FcValueSave (new->value);
 
359
        }
 
360
        new->binding = l->binding;
 
361
        if (l->next)
 
362
            new->next = new + 1;
 
363
        else
 
364
            new->next = 0;
 
365
    }
 
366
    return e;
 
367
}
 
368
 
 
369
static int      FcValueListTotal;
 
370
static int      FcValueListUsed;
 
371
 
 
372
static FcValueList *
 
373
FcValueListFreeze (FcValueList *l)
 
374
{
 
375
    static FcValueListEnt   *hashTable[FC_VALUE_LIST_HASH_SIZE];
 
376
    FcChar32                hash = FcValueListHash (l);
 
377
    FcValueListEnt          **bucket = &hashTable[hash % FC_VALUE_LIST_HASH_SIZE];
 
378
    FcValueListEnt          *ent;
 
379
 
 
380
    FcValueListTotal++;
 
381
    for (ent = *bucket; ent; ent = ent->next)
 
382
    {
 
383
        if (ent->hash == hash && FcValueListEqual (ent->list, l))
 
384
            return ent->list;
 
385
    }
 
386
 
 
387
    ent = FcValueListEntCreate (l);
 
388
    if (!ent)
 
389
        return 0;
 
390
 
 
391
    FcValueListUsed++;
 
392
    ent->hash = hash;
 
393
    ent->next = *bucket;
 
394
    *bucket = ent;
 
395
    return ent->list;
 
396
}
 
397
 
 
398
static FcChar32
 
399
FcPatternBaseHash (FcPattern *b)
 
400
{
 
401
    FcChar32    hash = b->num;
 
402
    int         i;
 
403
 
 
404
    for (i = 0; i < b->num; i++)
 
405
        hash = ((hash << 1) | (hash >> 31)) ^ ((long) b->elts[i].values);
 
406
    return hash;
 
407
}
 
408
 
 
409
typedef struct _FcPatternEnt FcPatternEnt;
 
410
 
 
411
struct _FcPatternEnt {
 
412
    FcPatternEnt    *next;
 
413
    FcChar32        hash;
 
414
    FcPattern       pattern;
 
415
};
 
416
 
 
417
static int      FcPatternTotal;
 
418
static int      FcPatternUsed;
 
419
 
 
420
static FcPattern *
 
421
FcPatternBaseFreeze (FcPattern *b)
 
422
{
 
423
    static FcPatternEnt *hashTable[FC_VALUE_LIST_HASH_SIZE];
 
424
    FcChar32            hash = FcPatternBaseHash (b);
 
425
    FcPatternEnt        **bucket = &hashTable[hash % FC_VALUE_LIST_HASH_SIZE];
 
426
    FcPatternEnt        *ent;
 
427
    int                 i;
 
428
    char                *objects;
 
429
    int                 size_objects;
 
430
    int                 size;
 
431
 
 
432
    FcPatternTotal++;
 
433
    for (ent = *bucket; ent; ent = ent->next)
 
434
    {
 
435
        if (ent->hash == hash && b->num == ent->pattern.num)
 
436
        {
 
437
            for (i = 0; i < b->num; i++)
 
438
            {
 
439
                if (strcmp (b->elts[i].object, ent->pattern.elts[i].object))
 
440
                    break;
 
441
                if (b->elts[i].values != ent->pattern.elts[i].values)
 
442
                    break;
 
443
            }
 
444
            if (i == b->num)
 
445
                return &ent->pattern;
 
446
        }
 
447
    }
 
448
 
 
449
    /*
 
450
     * Compute size of pattern + elts + object names
 
451
     */
 
452
    size_objects = 0;
 
453
    for (i = 0; i < b->num; i++)
 
454
        size_objects += strlen (b->elts[i].object) + 1;
 
455
 
 
456
    size = sizeof (FcPatternEnt) + b->num*sizeof (FcPatternElt) + size_objects;
 
457
    ent = malloc (size);
 
458
    if (!ent)
 
459
        return 0;
 
460
 
 
461
    FcMemAlloc (FC_MEM_PATTERN, size);
 
462
    FcPatternUsed++;
 
463
 
 
464
    ent->pattern.elts = (FcPatternElt *) (ent + 1);
 
465
    ent->pattern.num = b->num;
 
466
    ent->pattern.size = b->num;
 
467
    ent->pattern.ref = FC_REF_CONSTANT;
 
468
 
 
469
    objects = (char *) (ent->pattern.elts + b->num);
 
470
    for (i = 0; i < b->num; i++)
 
471
    {
 
472
        ent->pattern.elts[i].values = b->elts[i].values;
 
473
        strcpy (objects, b->elts[i].object);
 
474
        ent->pattern.elts[i].object = objects;
 
475
        objects += strlen (objects) + 1;
 
476
    }
 
477
 
 
478
    ent->hash = hash;
 
479
    ent->next = *bucket;
 
480
    *bucket = ent;
 
481
    return &ent->pattern;
 
482
}
 
483
 
 
484
FcPattern *
 
485
FcPatternFreeze (FcPattern *p)
 
486
{
 
487
    FcPattern   *b, *n = 0;
 
488
    int         size;
 
489
    int         i;
 
490
    
 
491
    size = sizeof (FcPattern) + p->num * sizeof (FcPatternElt);
 
492
    b = (FcPattern *) malloc (size);
 
493
    if (!b)
 
494
        return 0;
 
495
    FcMemAlloc (FC_MEM_PATTERN, size);
 
496
    b->num = p->num;
 
497
    b->size = b->num;
 
498
    b->ref = 1;
 
499
    b->elts = (FcPatternElt *) (b + 1);
 
500
    /*
 
501
     * Freeze object lists
 
502
     */
 
503
    for (i = 0; i < p->num; i++)
 
504
    {
 
505
        b->elts[i].object = p->elts[i].object;
 
506
        b->elts[i].values = FcValueListFreeze (p->elts[i].values);
 
507
        if (!b->elts[i].values)
 
508
            goto bail;
 
509
    }
 
510
    /*
 
511
     * Freeze base
 
512
     */
 
513
    n = FcPatternBaseFreeze (b);
 
514
#ifdef CHATTY
 
515
    if (FcDebug() & FC_DBG_MEMORY)
 
516
    {
 
517
        printf ("ValueLists: total %9d used %9d\n", FcValueListTotal, FcValueListUsed);
 
518
        printf ("Patterns:   total %9d used %9d\n", FcPatternTotal, FcPatternUsed);
 
519
    }
 
520
#endif
 
521
bail:
 
522
    free (b);
 
523
#ifdef DEBUG
 
524
    assert (FcPatternEqual (n, p));
 
525
#endif
 
526
    return n;
 
527
}
 
528
 
 
529
static int
 
530
FcPatternPosition (const FcPattern *p, const char *object)
 
531
{
 
532
    int     low, high, mid, c;
 
533
 
 
534
    low = 0;
 
535
    high = p->num - 1;
 
536
    c = 1;
 
537
    mid = 0;
 
538
    while (low <= high)
 
539
    {
 
540
        mid = (low + high) >> 1;
 
541
        c = strcmp (p->elts[mid].object, object);
 
542
        if (c == 0)
 
543
            return mid;
 
544
        if (c < 0)
 
545
            low = mid + 1;
 
546
        else
 
547
            high = mid - 1;
 
548
    }
 
549
    if (c < 0)
 
550
        mid++;
 
551
    return -(mid + 1);
 
552
}
 
553
 
 
554
FcPatternElt *
 
555
FcPatternFindElt (const FcPattern *p, const char *object)
 
556
{
 
557
    int     i = FcPatternPosition (p, object);
 
558
    if (i < 0)
 
559
        return 0;
 
560
    return &p->elts[i];
 
561
}
 
562
 
 
563
FcPatternElt *
 
564
FcPatternInsertElt (FcPattern *p, const char *object)
 
565
{
 
566
    int             i;
 
567
    FcPatternElt   *e;
 
568
    
 
569
    i = FcPatternPosition (p, object);
 
570
    if (i < 0)
 
571
    {
 
572
        i = -i - 1;
 
573
    
 
574
        /* grow array */
 
575
        if (p->num + 1 >= p->size)
 
576
        {
 
577
            int s = p->size + 16;
 
578
            if (p->elts)
 
579
                e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt));
 
580
            else
 
581
                e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
 
582
            if (!e)
 
583
                return FcFalse;
 
584
            p->elts = e;
 
585
            if (p->size)
 
586
                FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
 
587
            FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
 
588
            while (p->size < s)
 
589
            {
 
590
                p->elts[p->size].object = 0;
 
591
                p->elts[p->size].values = 0;
 
592
                p->size++;
 
593
            }
 
594
        }
 
595
        
 
596
        /* move elts up */
 
597
        memmove (p->elts + i + 1,
 
598
                 p->elts + i,
 
599
                 sizeof (FcPatternElt) *
 
600
                 (p->num - i));
 
601
                 
 
602
        /* bump count */
 
603
        p->num++;
 
604
        
 
605
        p->elts[i].object = object;
 
606
        p->elts[i].values = 0;
 
607
    }
 
608
    
 
609
    return &p->elts[i];
 
610
}
 
611
 
 
612
FcBool
 
613
FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
 
614
{
 
615
    int i;
 
616
 
 
617
    if (pa == pb)
 
618
        return FcTrue;
 
619
 
 
620
    if (pa->num != pb->num)
 
621
        return FcFalse;
 
622
    for (i = 0; i < pa->num; i++)
 
623
    {
 
624
        if (strcmp (pa->elts[i].object, pb->elts[i].object) != 0)
 
625
            return FcFalse;
 
626
        if (!FcValueListEqual (pa->elts[i].values, pb->elts[i].values))
 
627
            return FcFalse;
 
628
    }
 
629
    return FcTrue;
 
630
}
 
631
 
 
632
FcChar32
 
633
FcPatternHash (const FcPattern *p)
 
634
{
 
635
    int         i;
 
636
    FcChar32    h = 0;
 
637
 
 
638
    for (i = 0; i < p->num; i++)
 
639
    {
 
640
        h = (((h << 1) | (h >> 31)) ^ 
 
641
             FcStringHash ((const FcChar8 *) p->elts[i].object) ^
 
642
             FcValueListHash (p->elts[i].values));
 
643
    }
 
644
    return h;
 
645
}
 
646
 
 
647
FcBool
 
648
FcPatternEqualSubset (const FcPattern *pa, const FcPattern *pb, const FcObjectSet *os)
 
649
{
 
650
    FcPatternElt    *ea, *eb;
 
651
    int             i;
 
652
    
 
653
    for (i = 0; i < os->nobject; i++)
 
654
    {
 
655
        ea = FcPatternFindElt (pa, os->objects[i]);
 
656
        eb = FcPatternFindElt (pb, os->objects[i]);
 
657
        if (ea)
 
658
        {
 
659
            if (!eb)
 
660
                return FcFalse;
 
661
            if (!FcValueListEqual (ea->values, eb->values))
 
662
                return FcFalse;
 
663
        }
 
664
        else
 
665
        {
 
666
            if (eb)
 
667
                return FcFalse;
 
668
        }
 
669
    }
 
670
    return FcTrue;
 
671
}
 
672
 
 
673
FcBool
 
674
FcPatternAddWithBinding  (FcPattern         *p,
 
675
                          const char        *object,
 
676
                          FcValue           value,
 
677
                          FcValueBinding    binding,
 
678
                          FcBool            append)
 
679
{
 
680
    FcPatternElt   *e;
 
681
    FcValueList    *new, **prev;
 
682
 
 
683
    if (p->ref == FC_REF_CONSTANT)
 
684
        goto bail0;
 
685
 
 
686
    new = (FcValueList *) malloc (sizeof (FcValueList));
 
687
    if (!new)
 
688
        goto bail0;
 
689
 
 
690
    FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
 
691
    /* dup string */
 
692
    value = FcValueSave (value);
 
693
    if (value.type == FcTypeVoid)
 
694
        goto bail1;
 
695
 
 
696
    new->value = value;
 
697
    new->binding = binding;
 
698
    new->next = 0;
 
699
    
 
700
    e = FcPatternInsertElt (p, object);
 
701
    if (!e)
 
702
        goto bail2;
 
703
    
 
704
    if (append)
 
705
    {
 
706
        for (prev = &e->values; *prev; prev = &(*prev)->next);
 
707
        *prev = new;
 
708
    }
 
709
    else
 
710
    {
 
711
        new->next = e->values;
 
712
        e->values = new;
 
713
    }
 
714
    
 
715
    return FcTrue;
 
716
 
 
717
bail2:    
 
718
    switch (value.type) {
 
719
    case FcTypeString:
 
720
        FcStrFree ((FcChar8 *) value.u.s);
 
721
        break;
 
722
    case FcTypeMatrix:
 
723
        FcMatrixFree ((FcMatrix *) value.u.m);
 
724
        break;
 
725
    case FcTypeCharSet:
 
726
        FcCharSetDestroy ((FcCharSet *) value.u.c);
 
727
        break;
 
728
    case FcTypeLangSet:
 
729
        FcLangSetDestroy ((FcLangSet *) value.u.l);
 
730
        break;
 
731
    default:
 
732
        break;
 
733
    }
 
734
bail1:
 
735
    FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
 
736
    free (new);
 
737
bail0:
 
738
    return FcFalse;
 
739
}
 
740
 
 
741
FcBool
 
742
FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
 
743
{
 
744
    return FcPatternAddWithBinding (p, object, value, FcValueBindingStrong, append);
 
745
}
 
746
 
 
747
FcBool
 
748
FcPatternAddWeak  (FcPattern *p, const char *object, FcValue value, FcBool append)
 
749
{
 
750
    return FcPatternAddWithBinding (p, object, value, FcValueBindingWeak, append);
 
751
}
 
752
 
 
753
FcBool
 
754
FcPatternDel (FcPattern *p, const char *object)
 
755
{
 
756
    FcPatternElt   *e;
 
757
    int             i;
 
758
 
 
759
    e = FcPatternFindElt (p, object);
 
760
    if (!e)
 
761
        return FcFalse;
 
762
 
 
763
    i = e - p->elts;
 
764
    
 
765
    /* destroy value */
 
766
    FcValueListDestroy (e->values);
 
767
    
 
768
    /* shuffle existing ones down */
 
769
    memmove (e, e+1, (p->elts + p->num - (e + 1)) * sizeof (FcPatternElt));
 
770
    p->num--;
 
771
    p->elts[p->num].object = 0;
 
772
    p->elts[p->num].values = 0;
 
773
    return FcTrue;
 
774
}
 
775
 
 
776
FcBool
 
777
FcPatternAddInteger (FcPattern *p, const char *object, int i)
 
778
{
 
779
    FcValue     v;
 
780
 
 
781
    v.type = FcTypeInteger;
 
782
    v.u.i = i;
 
783
    return FcPatternAdd (p, object, v, FcTrue);
 
784
}
 
785
 
 
786
FcBool
 
787
FcPatternAddDouble (FcPattern *p, const char *object, double d)
 
788
{
 
789
    FcValue     v;
 
790
 
 
791
    v.type = FcTypeDouble;
 
792
    v.u.d = d;
 
793
    return FcPatternAdd (p, object, v, FcTrue);
 
794
}
 
795
 
 
796
 
 
797
FcBool
 
798
FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
 
799
{
 
800
    FcValue     v;
 
801
 
 
802
    v.type = FcTypeString;
 
803
    v.u.s = s;
 
804
    return FcPatternAdd (p, object, v, FcTrue);
 
805
}
 
806
 
 
807
FcBool
 
808
FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
 
809
{
 
810
    FcValue     v;
 
811
 
 
812
    v.type = FcTypeMatrix;
 
813
    v.u.m = (FcMatrix *) s;
 
814
    return FcPatternAdd (p, object, v, FcTrue);
 
815
}
 
816
 
 
817
 
 
818
FcBool
 
819
FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
 
820
{
 
821
    FcValue     v;
 
822
 
 
823
    v.type = FcTypeBool;
 
824
    v.u.b = b;
 
825
    return FcPatternAdd (p, object, v, FcTrue);
 
826
}
 
827
 
 
828
FcBool
 
829
FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
 
830
{
 
831
    FcValue     v;
 
832
 
 
833
    v.type = FcTypeCharSet;
 
834
    v.u.c = (FcCharSet *) c;
 
835
    return FcPatternAdd (p, object, v, FcTrue);
 
836
}
 
837
 
 
838
FcBool
 
839
FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
 
840
{
 
841
    FcValue     v;
 
842
 
 
843
    v.type = FcTypeFTFace;
 
844
    v.u.f = (void *) f;
 
845
    return FcPatternAdd (p, object, v, FcTrue);
 
846
}
 
847
 
 
848
FcBool
 
849
FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
 
850
{
 
851
    FcValue     v;
 
852
 
 
853
    v.type = FcTypeLangSet;
 
854
    v.u.l = (FcLangSet *) ls;
 
855
    return FcPatternAdd (p, object, v, FcTrue);
 
856
}
 
857
 
 
858
FcResult
 
859
FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
 
860
{
 
861
    FcPatternElt   *e;
 
862
    FcValueList    *l;
 
863
 
 
864
    e = FcPatternFindElt (p, object);
 
865
    if (!e)
 
866
        return FcResultNoMatch;
 
867
    for (l = e->values; l; l = l->next)
 
868
    {
 
869
        if (!id)
 
870
        {
 
871
            *v = l->value;
 
872
            return FcResultMatch;
 
873
        }
 
874
        id--;
 
875
    }
 
876
    return FcResultNoId;
 
877
}
 
878
 
 
879
FcResult
 
880
FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
 
881
{
 
882
    FcValue     v;
 
883
    FcResult    r;
 
884
 
 
885
    r = FcPatternGet (p, object, id, &v);
 
886
    if (r != FcResultMatch)
 
887
        return r;
 
888
    switch (v.type) {
 
889
    case FcTypeDouble:
 
890
        *i = (int) v.u.d;
 
891
        break;
 
892
    case FcTypeInteger:
 
893
        *i = v.u.i;
 
894
        break;
 
895
    default:
 
896
        return FcResultTypeMismatch;
 
897
    }
 
898
    return FcResultMatch;
 
899
}
 
900
 
 
901
FcResult
 
902
FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
 
903
{
 
904
    FcValue     v;
 
905
    FcResult    r;
 
906
 
 
907
    r = FcPatternGet (p, object, id, &v);
 
908
    if (r != FcResultMatch)
 
909
        return r;
 
910
    switch (v.type) {
 
911
    case FcTypeDouble:
 
912
        *d = v.u.d;
 
913
        break;
 
914
    case FcTypeInteger:
 
915
        *d = (double) v.u.i;
 
916
        break;
 
917
    default:
 
918
        return FcResultTypeMismatch;
 
919
    }
 
920
    return FcResultMatch;
 
921
}
 
922
 
 
923
FcResult
 
924
FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
 
925
{
 
926
    FcValue     v;
 
927
    FcResult    r;
 
928
 
 
929
    r = FcPatternGet (p, object, id, &v);
 
930
    if (r != FcResultMatch)
 
931
        return r;
 
932
    if (v.type != FcTypeString)
 
933
        return FcResultTypeMismatch;
 
934
    *s = (FcChar8 *) v.u.s;
 
935
    return FcResultMatch;
 
936
}
 
937
 
 
938
FcResult
 
939
FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
 
940
{
 
941
    FcValue     v;
 
942
    FcResult    r;
 
943
 
 
944
    r = FcPatternGet (p, object, id, &v);
 
945
    if (r != FcResultMatch)
 
946
        return r;
 
947
    if (v.type != FcTypeMatrix)
 
948
        return FcResultTypeMismatch;
 
949
    *m = (FcMatrix *) v.u.m;
 
950
    return FcResultMatch;
 
951
}
 
952
 
 
953
 
 
954
FcResult
 
955
FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
 
956
{
 
957
    FcValue     v;
 
958
    FcResult    r;
 
959
 
 
960
    r = FcPatternGet (p, object, id, &v);
 
961
    if (r != FcResultMatch)
 
962
        return r;
 
963
    if (v.type != FcTypeBool)
 
964
        return FcResultTypeMismatch;
 
965
    *b = v.u.b;
 
966
    return FcResultMatch;
 
967
}
 
968
 
 
969
FcResult
 
970
FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
 
971
{
 
972
    FcValue     v;
 
973
    FcResult    r;
 
974
 
 
975
    r = FcPatternGet (p, object, id, &v);
 
976
    if (r != FcResultMatch)
 
977
        return r;
 
978
    if (v.type != FcTypeCharSet)
 
979
        return FcResultTypeMismatch;
 
980
    *c = (FcCharSet *) v.u.c;
 
981
    return FcResultMatch;
 
982
}
 
983
 
 
984
FcResult
 
985
FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
 
986
{
 
987
    FcValue     v;
 
988
    FcResult    r;
 
989
 
 
990
    r = FcPatternGet (p, object, id, &v);
 
991
    if (r != FcResultMatch)
 
992
        return r;
 
993
    if (v.type != FcTypeFTFace)
 
994
        return FcResultTypeMismatch;
 
995
    *f = (FT_Face) v.u.f;
 
996
    return FcResultMatch;
 
997
}
 
998
 
 
999
FcResult
 
1000
FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
 
1001
{
 
1002
    FcValue     v;
 
1003
    FcResult    r;
 
1004
 
 
1005
    r = FcPatternGet (p, object, id, &v);
 
1006
    if (r != FcResultMatch)
 
1007
        return r;
 
1008
    if (v.type != FcTypeLangSet)
 
1009
        return FcResultTypeMismatch;
 
1010
    *ls = (FcLangSet *) v.u.l;
 
1011
    return FcResultMatch;
 
1012
}
 
1013
 
 
1014
FcPattern *
 
1015
FcPatternDuplicate (const FcPattern *orig)
 
1016
{
 
1017
    FcPattern       *new;
 
1018
    int             i;
 
1019
    FcValueList    *l;
 
1020
 
 
1021
    new = FcPatternCreate ();
 
1022
    if (!new)
 
1023
        goto bail0;
 
1024
 
 
1025
    for (i = 0; i < orig->num; i++)
 
1026
    {
 
1027
        for (l = orig->elts[i].values; l; l = l->next)
 
1028
            if (!FcPatternAdd (new, orig->elts[i].object, l->value, FcTrue))
 
1029
                goto bail1;
 
1030
    }
 
1031
 
 
1032
    return new;
 
1033
 
 
1034
bail1:
 
1035
    FcPatternDestroy (new);
 
1036
bail0:
 
1037
    return 0;
 
1038
}
 
1039
 
 
1040
void
 
1041
FcPatternReference (FcPattern *p)
 
1042
{
 
1043
    if (p->ref != FC_REF_CONSTANT)
 
1044
        p->ref++;
 
1045
}
 
1046
 
 
1047
FcPattern *
 
1048
FcPatternVaBuild (FcPattern *orig, va_list va)
 
1049
{
 
1050
    FcPattern   *ret;
 
1051
    
 
1052
    FcPatternVapBuild (ret, orig, va);
 
1053
    return ret;
 
1054
}
 
1055
 
 
1056
FcPattern *
 
1057
FcPatternBuild (FcPattern *orig, ...)
 
1058
{
 
1059
    va_list     va;
 
1060
    
 
1061
    va_start (va, orig);
 
1062
    FcPatternVapBuild (orig, orig, va);
 
1063
    va_end (va);
 
1064
    return orig;
 
1065
}