Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/workdir/UnpackedTarball/fontconfig/src/fcpat.c
Line
Count
Source
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
25
#if ENABLE_FREETYPE
26
#include "fcftint.h"
27
#else
28
typedef struct FT_FaceRec_* FT_Face;
29
#endif
30
31
/* Objects MT-safe for readonly access. */
32
33
FcPattern *
34
FcPatternCreate (void)
35
3.52k
{
36
3.52k
    FcPattern *p;
37
38
3.52k
    p = (FcPattern *)malloc (sizeof (FcPattern));
39
3.52k
    if (!p)
40
0
  return 0;
41
3.52k
    memset (p, 0, sizeof (FcPattern));
42
3.52k
    p->num = 0;
43
3.52k
    p->size = 0;
44
3.52k
    p->elts_offset = FcPtrToOffset (p, NULL);
45
3.52k
    FcRefInit (&p->ref, 1);
46
3.52k
    return p;
47
3.52k
}
48
49
void
50
FcValueDestroy (FcValue v)
51
104k
{
52
104k
    switch ((int)v.type) {
53
42.0k
    case FcTypeString:
54
42.0k
  FcFree (v.u.s);
55
42.0k
  break;
56
0
    case FcTypeMatrix:
57
0
  FcMatrixFree ((FcMatrix *)v.u.m);
58
0
  break;
59
3.41k
    case FcTypeCharSet:
60
3.41k
  FcCharSetDestroy ((FcCharSet *)v.u.c);
61
3.41k
  break;
62
3.41k
    case FcTypeLangSet:
63
3.41k
  FcLangSetDestroy ((FcLangSet *)v.u.l);
64
3.41k
  break;
65
0
    case FcTypeRange:
66
0
  FcRangeDestroy ((FcRange *)v.u.r);
67
0
  break;
68
55.4k
    default:
69
55.4k
  break;
70
104k
    }
71
104k
}
72
73
FcValue
74
FcValueCanonicalize (const FcValue *v)
75
144k
{
76
144k
    FcValue newp;
77
78
144k
    switch ((int)v->type) {
79
63.3k
    case FcTypeString:
80
63.3k
  newp.u.s = FcValueString (v);
81
63.3k
  newp.type = FcTypeString;
82
63.3k
  break;
83
3.42k
    case FcTypeCharSet:
84
3.42k
  newp.u.c = FcValueCharSet (v);
85
3.42k
  newp.type = FcTypeCharSet;
86
3.42k
  break;
87
4.22k
    case FcTypeLangSet:
88
4.22k
  newp.u.l = FcValueLangSet (v);
89
4.22k
  newp.type = FcTypeLangSet;
90
4.22k
  break;
91
0
    case FcTypeRange:
92
0
  newp.u.r = FcValueRange (v);
93
0
  newp.type = FcTypeRange;
94
0
  break;
95
73.6k
    default:
96
73.6k
  newp = *v;
97
73.6k
  break;
98
144k
    }
99
144k
    return newp;
100
144k
}
101
102
FcValue
103
FcValueSave (FcValue v)
104
105k
{
105
105k
    switch ((int)v.type) {
106
42.4k
    case FcTypeString:
107
42.4k
  v.u.s = FcStrCopy (v.u.s);
108
42.4k
  if (!v.u.s)
109
0
      v.type = FcTypeVoid;
110
42.4k
  break;
111
0
    case FcTypeMatrix:
112
0
  v.u.m = FcMatrixCopy (v.u.m);
113
0
  if (!v.u.m)
114
0
      v.type = FcTypeVoid;
115
0
  break;
116
3.44k
    case FcTypeCharSet:
117
3.44k
  v.u.c = FcCharSetCopy ((FcCharSet *)v.u.c);
118
3.44k
  if (!v.u.c)
119
0
      v.type = FcTypeVoid;
120
3.44k
  break;
121
3.44k
    case FcTypeLangSet:
122
3.44k
  v.u.l = FcLangSetCopy (v.u.l);
123
3.44k
  if (!v.u.l)
124
0
      v.type = FcTypeVoid;
125
3.44k
  break;
126
0
    case FcTypeRange:
127
0
  v.u.r = FcRangeCopy (v.u.r);
128
0
  if (!v.u.r)
129
0
      v.type = FcTypeVoid;
130
0
  break;
131
56.2k
    default:
132
56.2k
  break;
133
105k
    }
134
105k
    return v;
135
105k
}
136
137
FcValueListPtr
138
FcValueListCreate (void)
139
105k
{
140
105k
    return calloc (1, sizeof (FcValueList));
141
105k
}
142
143
void
144
FcValueListDestroy (FcValueListPtr l)
145
104k
{
146
104k
    FcValueListPtr next;
147
208k
    for (; l; l = next) {
148
104k
  FcValueDestroy (l->value);
149
104k
  next = FcValueListNext (l);
150
104k
  free (l);
151
104k
    }
152
104k
}
153
154
FcValueListPtr
155
FcValueListPrepend (FcValueListPtr vallist,
156
                    FcValue        value,
157
                    FcValueBinding binding)
158
396
{
159
396
    FcValueListPtr newp;
160
161
396
    if (value.type == FcTypeVoid)
162
0
  return vallist;
163
396
    newp = FcValueListCreate();
164
396
    if (!newp)
165
0
  return vallist;
166
167
396
    newp->value = FcValueSave (value);
168
396
    newp->binding = binding;
169
396
    newp->next = vallist;
170
171
396
    return newp;
172
396
}
173
174
FcValueListPtr
175
FcValueListAppend (FcValueListPtr vallist,
176
                   FcValue        value,
177
                   FcValueBinding binding)
178
0
{
179
0
    FcValueListPtr newp, last;
180
181
0
    if (value.type == FcTypeVoid)
182
0
  return vallist;
183
0
    newp = FcValueListCreate();
184
0
    if (!newp)
185
0
  return vallist;
186
187
0
    newp->value = FcValueSave (value);
188
0
    newp->binding = binding;
189
0
    newp->next = NULL;
190
191
0
    if (vallist) {
192
0
  for (last = vallist; FcValueListNext (last); last = FcValueListNext (last))
193
0
      ;
194
195
0
  last->next = newp;
196
0
    } else
197
0
  vallist = newp;
198
199
0
    return vallist;
200
0
}
201
202
FcValueListPtr
203
FcValueListDuplicate (FcValueListPtr orig)
204
2.17k
{
205
2.17k
    FcValueListPtr newp = NULL, l, t = NULL;
206
2.17k
    FcValue        v;
207
208
4.35k
    for (l = orig; l != NULL; l = FcValueListNext (l)) {
209
2.17k
  if (!newp) {
210
2.17k
      t = newp = FcValueListCreate();
211
2.17k
  } else {
212
0
      t->next = FcValueListCreate();
213
0
      t = FcValueListNext (t);
214
0
  }
215
2.17k
  v = FcValueCanonicalize (&l->value);
216
2.17k
  t->value = FcValueSave (v);
217
2.17k
  t->binding = l->binding;
218
2.17k
  t->next = NULL;
219
2.17k
    }
220
221
2.17k
    return newp;
222
2.17k
}
223
224
FcBool
225
FcValueEqual (FcValue va, FcValue vb)
226
5.72k
{
227
5.72k
    if (va.type != vb.type) {
228
0
  if (va.type == FcTypeInteger) {
229
0
      va.type = FcTypeDouble;
230
0
      va.u.d = va.u.i;
231
0
  }
232
0
  if (vb.type == FcTypeInteger) {
233
0
      vb.type = FcTypeDouble;
234
0
      vb.u.d = vb.u.i;
235
0
  }
236
0
  if (va.type != vb.type)
237
0
      return FcFalse;
238
0
    }
239
5.72k
    switch (va.type) {
240
0
    case FcTypeUnknown:
241
0
  return FcFalse; /* don't know how to compare this object */
242
0
    case FcTypeVoid:
243
0
  return FcTrue;
244
0
    case FcTypeInteger:
245
0
  return va.u.i == vb.u.i;
246
0
    case FcTypeDouble:
247
0
  return va.u.d == vb.u.d;
248
5.72k
    case FcTypeString:
249
5.72k
  return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
250
0
    case FcTypeBool:
251
0
  return va.u.b == vb.u.b;
252
0
    case FcTypeMatrix:
253
0
  return FcMatrixEqual (va.u.m, vb.u.m);
254
0
    case FcTypeCharSet:
255
0
  return FcCharSetEqual (va.u.c, vb.u.c);
256
0
    case FcTypeFTFace:
257
0
  return va.u.f == vb.u.f;
258
0
    case FcTypeLangSet:
259
0
  return FcLangSetEqual (va.u.l, vb.u.l);
260
0
    case FcTypeRange:
261
0
  return FcRangeIsInRange (va.u.r, vb.u.r);
262
5.72k
    }
263
0
    return FcFalse;
264
5.72k
}
265
266
static FcChar32
267
FcDoubleHash (double d)
268
0
{
269
0
    if (d < 0)
270
0
  d = -d;
271
0
    if (d > 0xffffffff)
272
0
  d = 0xffffffff;
273
0
    return (FcChar32)d;
274
0
}
275
276
FcChar32
277
FcStringHash (const FcChar8 *s)
278
0
{
279
0
    FcChar8  c;
280
0
    FcChar32 h = 0;
281
282
0
    if (s)
283
0
  while ((c = *s++))
284
0
      h = ((h << 1) | (h >> 31)) ^ c;
285
0
    return h;
286
0
}
287
288
static FcChar32
289
FcValueHash (const FcValue *v)
290
0
{
291
0
    switch (v->type) {
292
0
    case FcTypeUnknown:
293
0
    case FcTypeVoid:
294
0
  return 0;
295
0
    case FcTypeInteger:
296
0
  return (FcChar32)v->u.i;
297
0
    case FcTypeDouble:
298
0
  return FcDoubleHash (v->u.d);
299
0
    case FcTypeString:
300
0
  return FcStringHash (FcValueString (v));
301
0
    case FcTypeBool:
302
0
  return (FcChar32)v->u.b;
303
0
    case FcTypeMatrix:
304
0
  return (FcDoubleHash (v->u.m->xx) ^
305
0
          FcDoubleHash (v->u.m->xy) ^
306
0
          FcDoubleHash (v->u.m->yx) ^
307
0
          FcDoubleHash (v->u.m->yy));
308
0
    case FcTypeCharSet:
309
0
  return (FcChar32)FcValueCharSet (v)->num;
310
0
    case FcTypeFTFace:
311
0
#if ENABLE_FREETYPE
312
0
  return FcStringHash ((const FcChar8 *)((FT_Face)v->u.f)->family_name) ^
313
0
         FcStringHash ((const FcChar8 *)((FT_Face)v->u.f)->style_name);
314
#else
315
    return 0;
316
#endif
317
0
    case FcTypeLangSet:
318
0
  return FcLangSetHash (FcValueLangSet (v));
319
0
    case FcTypeRange:
320
0
  return FcRangeHash (FcValueRange (v));
321
0
    }
322
0
    return 0;
323
0
}
324
325
static FcBool
326
FcValueListEqual (FcValueListPtr la, FcValueListPtr lb)
327
5.72k
{
328
5.72k
    if (la == lb)
329
0
  return FcTrue;
330
331
9.54k
    while (la && lb) {
332
5.72k
  if (!FcValueEqual (la->value, lb->value))
333
1.90k
      return FcFalse;
334
3.81k
  la = FcValueListNext (la);
335
3.81k
  lb = FcValueListNext (lb);
336
3.81k
    }
337
3.81k
    if (la || lb)
338
0
  return FcFalse;
339
3.81k
    return FcTrue;
340
3.81k
}
341
342
static FcChar32
343
FcValueListHash (FcValueListPtr l)
344
0
{
345
0
    FcChar32 hash = 0;
346
347
0
    for (; l; l = FcValueListNext (l)) {
348
0
  hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (&l->value);
349
0
    }
350
0
    return hash;
351
0
}
352
353
static void *
354
FcPatternGetCacheObject (FcPattern *p)
355
4.02k
{
356
    /* We use a value to find the cache, instead of the FcPattern object
357
     * because the pattern itself may be a cache allocation if we rewrote the path,
358
     * so the p may not be in the cached region. */
359
4.02k
    return FcPatternEltValues (&FcPatternElts (p)[0]);
360
4.02k
}
361
362
FcPattern *
363
FcPatternCacheRewriteFile (const FcPattern *p,
364
                           FcCache         *cache,
365
                           const FcChar8   *relocated_font_file)
366
0
{
367
0
    FcPatternElt *elts = FcPatternElts (p);
368
0
    size_t        i, j;
369
0
    FcChar8      *data;
370
0
    FcPattern    *new_p;
371
0
    FcPatternElt *new_elts;
372
0
    FcValueList  *new_value_list;
373
0
    size_t        new_path_len = strlen ((char *)relocated_font_file);
374
0
    FcChar8      *new_path;
375
376
    /* Allocate space for the patter, the PatternElt headers and
377
     * the FC_FILE FcValueList and path that will be freed with the
378
     * cache */
379
0
    data = FcCacheAllocate (cache,
380
0
                            sizeof (FcPattern) +
381
0
                                p->num * sizeof (FcPatternElt) +
382
0
                                sizeof (FcValueList) +
383
0
                                new_path_len + 1);
384
385
0
    new_p = (FcPattern *)data;
386
0
    data += sizeof (FcPattern);
387
0
    new_elts = (FcPatternElt *)(data);
388
0
    data += p->num * sizeof (FcPatternElt);
389
0
    new_value_list = (FcValueList *)data;
390
0
    data += sizeof (FcValueList);
391
0
    new_path = data;
392
393
0
    *new_p = *p;
394
0
    new_p->elts_offset = FcPtrToOffset (new_p, new_elts);
395
396
    /* Copy all but the FILE values from the cache */
397
0
    for (i = 0, j = 0; i < p->num; i++) {
398
0
  FcPatternElt *elt = &elts[i];
399
0
  new_elts[j].object = elt->object;
400
0
  if (elt->object != FC_FILE_OBJECT)
401
0
      new_elts[j++].values = FcPatternEltValues (elt);
402
0
  else
403
0
      new_elts[j++].values = new_value_list;
404
0
    }
405
406
0
    new_value_list->next = NULL;
407
0
    new_value_list->value.type = FcTypeString;
408
0
    new_value_list->value.u.s = new_path;
409
0
    new_value_list->binding = FcValueBindingWeak;
410
411
    /* Add rewritten path at the end */
412
0
    strcpy ((char *)new_path, (char *)relocated_font_file);
413
414
0
    return new_p;
415
0
}
416
417
void
418
FcPatternDestroy (FcPattern *p)
419
4.87k
{
420
4.87k
    int           i;
421
4.87k
    FcPatternElt *elts;
422
423
4.87k
    if (!p)
424
0
  return;
425
426
4.87k
    if (FcRefIsConst (&p->ref)) {
427
1.37k
  FcCacheObjectDereference (FcPatternGetCacheObject (p));
428
1.37k
  return;
429
1.37k
    }
430
431
3.49k
    if (FcRefDec (&p->ref) != 1)
432
0
  return;
433
434
3.49k
    elts = FcPatternElts (p);
435
85.0k
    for (i = 0; i < FcPatternObjectCount (p); i++)
436
81.5k
  FcValueListDestroy (FcPatternEltValues (&elts[i]));
437
438
3.49k
    free (elts);
439
3.49k
    free (p);
440
3.49k
}
441
442
int
443
FcPatternObjectCount (const FcPattern *pat)
444
846k
{
445
846k
    if (pat)
446
846k
  return pat->num;
447
448
0
    return 0;
449
846k
}
450
451
static int
452
FcPatternObjectPosition (const FcPattern *p, FcObject object)
453
173k
{
454
173k
    int           low, high, mid, c;
455
173k
    FcPatternElt *elts = FcPatternElts (p);
456
457
173k
    low = 0;
458
173k
    high = FcPatternObjectCount (p) - 1;
459
173k
    c = 1;
460
173k
    mid = 0;
461
807k
    while (low <= high) {
462
697k
  mid = (low + high) >> 1;
463
697k
  c = elts[mid].object - object;
464
697k
  if (c == 0)
465
62.5k
      return mid;
466
634k
  if (c < 0)
467
506k
      low = mid + 1;
468
128k
  else
469
128k
      high = mid - 1;
470
634k
    }
471
110k
    if (c < 0)
472
103k
  mid++;
473
110k
    return -(mid + 1);
474
173k
}
475
476
int
477
FcPatternPosition (const FcPattern *p, const char *object)
478
0
{
479
0
    return FcPatternObjectPosition (p, FcObjectFromName (object));
480
0
}
481
482
FcPatternElt *
483
FcPatternObjectFindElt (const FcPattern *p, FcObject object)
484
66.2k
{
485
66.2k
    int i = FcPatternObjectPosition (p, object);
486
66.2k
    if (i < 0)
487
4.14k
  return 0;
488
62.0k
    return &FcPatternElts (p)[i];
489
66.2k
}
490
491
FcPatternElt *
492
FcPatternObjectInsertElt (FcPattern *p, FcObject object)
493
105k
{
494
105k
    int           i;
495
105k
    FcPatternElt *e;
496
497
105k
    i = FcPatternObjectPosition (p, object);
498
105k
    if (i < 0) {
499
105k
  i = -i - 1;
500
501
  /* reallocate array */
502
105k
  if (FcPatternObjectCount (p) + 1 >= p->size) {
503
7.21k
      int s = p->size + 16;
504
7.21k
      if (p->size) {
505
3.69k
    FcPatternElt *e0 = FcPatternElts (p);
506
3.69k
    e = (FcPatternElt *)realloc (e0, s * sizeof (FcPatternElt));
507
3.69k
    if (!e) /* maybe it was mmapped */
508
0
    {
509
0
        e = malloc (s * sizeof (FcPatternElt));
510
0
        if (e)
511
0
      memcpy (e, e0, FcPatternObjectCount (p) * sizeof (FcPatternElt));
512
0
    }
513
3.69k
      } else
514
3.52k
    e = (FcPatternElt *)malloc (s * sizeof (FcPatternElt));
515
7.21k
      if (!e)
516
0
    return FcFalse;
517
7.21k
      p->elts_offset = FcPtrToOffset (p, e);
518
122k
      while (p->size < s) {
519
115k
    e[p->size].object = 0;
520
115k
    e[p->size].values = NULL;
521
115k
    p->size++;
522
115k
      }
523
7.21k
  }
524
525
105k
  e = FcPatternElts (p);
526
  /* move elts up */
527
105k
  memmove (e + i + 1,
528
105k
           e + i,
529
105k
           sizeof (FcPatternElt) *
530
105k
               (FcPatternObjectCount (p) - i));
531
532
  /* bump count */
533
105k
  p->num++;
534
535
105k
  e[i].object = object;
536
105k
  e[i].values = NULL;
537
105k
    }
538
539
105k
    return FcPatternElts (p) + i;
540
105k
}
541
542
FcBool
543
FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
544
1.90k
{
545
1.90k
    FcPatternIter ia, ib;
546
547
1.90k
    if (pa == pb)
548
0
  return FcTrue;
549
550
1.90k
    if (FcPatternObjectCount (pa) != FcPatternObjectCount (pb))
551
0
  return FcFalse;
552
1.90k
    FcPatternIterStart (pa, &ia);
553
1.90k
    FcPatternIterStart (pb, &ib);
554
5.72k
    do {
555
5.72k
  FcBool ra, rb;
556
557
5.72k
  if (!FcPatternIterEqual (pa, &ia, pb, &ib))
558
1.90k
      return FcFalse;
559
3.81k
  ra = FcPatternIterNext (pa, &ia);
560
3.81k
  rb = FcPatternIterNext (pb, &ib);
561
3.81k
  if (!ra && !rb)
562
0
      break;
563
3.81k
    } while (1);
564
565
0
    return FcTrue;
566
1.90k
}
567
568
FcChar32
569
FcPatternHash (const FcPattern *p)
570
0
{
571
0
    int           i;
572
0
    FcChar32      h = 0;
573
0
    FcPatternElt *pe = FcPatternElts (p);
574
575
0
    for (i = 0; i < FcPatternObjectCount (p); i++) {
576
0
  h = (((h << 1) | (h >> 31)) ^
577
0
       pe[i].object ^
578
0
       FcValueListHash (FcPatternEltValues (&pe[i])));
579
0
    }
580
0
    return h;
581
0
}
582
583
FcBool
584
FcPatternEqualSubset (const FcPattern *pai, const FcPattern *pbi, const FcObjectSet *os)
585
0
{
586
0
    FcPatternElt *ea, *eb;
587
0
    int           i;
588
589
0
    for (i = 0; i < os->nobjIds; i++) {
590
0
  ea = FcPatternObjectFindElt (pai, os->objIds[i]);
591
0
  eb = FcPatternObjectFindElt (pbi, os->objIds[i]);
592
0
  if (ea) {
593
0
      if (!eb)
594
0
    return FcFalse;
595
0
      if (!FcValueListEqual (FcPatternEltValues (ea), FcPatternEltValues (eb)))
596
0
    return FcFalse;
597
0
  } else {
598
0
      if (eb)
599
0
    return FcFalse;
600
0
  }
601
0
    }
602
0
    return FcTrue;
603
0
}
604
605
FcBool
606
FcPatternObjectListAdd (FcPattern     *p,
607
                        FcObject       object,
608
                        FcValueListPtr list,
609
                        FcBool         append)
610
4.09k
{
611
4.09k
    FcPatternElt  *e;
612
4.09k
    FcValueListPtr l, *prev;
613
614
4.09k
    if (FcRefIsConst (&p->ref))
615
0
  goto bail0;
616
617
    /*
618
     * Make sure the stored type is valid for built-in objects
619
     */
620
8.18k
    for (l = list; l != NULL; l = FcValueListNext (l)) {
621
4.09k
  if (!FcObjectValidType (object, l->value.type)) {
622
0
      fprintf (stderr,
623
0
               "Fontconfig warning: FcPattern object %s does not accept value", FcObjectName (object));
624
0
      FcValuePrintFile (stderr, l->value);
625
0
      fprintf (stderr, "\n");
626
0
      goto bail0;
627
0
  }
628
4.09k
    }
629
630
4.09k
    e = FcPatternObjectInsertElt (p, object);
631
4.09k
    if (!e)
632
0
  goto bail0;
633
634
4.09k
    if (append) {
635
2.83k
  for (prev = &e->values; *prev; prev = &(*prev)->next)
636
0
      ;
637
2.83k
  *prev = list;
638
2.83k
    } else {
639
2.50k
  for (prev = &list; *prev; prev = &(*prev)->next)
640
1.25k
      ;
641
1.25k
  *prev = e->values;
642
1.25k
  e->values = list;
643
1.25k
    }
644
645
4.09k
    return FcTrue;
646
647
0
bail0:
648
0
    return FcFalse;
649
4.09k
}
650
651
FcBool
652
FcPatternObjectAddWithBinding (FcPattern     *p,
653
                               FcObject       object,
654
                               FcValue        value,
655
                               FcValueBinding binding,
656
                               FcBool         append)
657
101k
{
658
101k
    FcPatternElt  *e;
659
101k
    FcValueListPtr newp, *prev;
660
661
101k
    if (FcRefIsConst (&p->ref))
662
0
  goto bail0;
663
664
101k
    newp = FcValueListCreate();
665
101k
    if (!newp)
666
0
  goto bail0;
667
668
101k
    newp->value = FcValueSave (value);
669
101k
    newp->binding = binding;
670
101k
    newp->next = NULL;
671
672
101k
    if (newp->value.type == FcTypeVoid)
673
0
  goto bail1;
674
675
    /*
676
     * Make sure the stored type is valid for built-in objects
677
     */
678
101k
    if (!FcObjectValidType (object, newp->value.type)) {
679
0
  fprintf (stderr,
680
0
           "Fontconfig warning: FcPattern object %s does not accept value",
681
0
           FcObjectName (object));
682
0
  FcValuePrintFile (stderr, newp->value);
683
0
  fprintf (stderr, "\n");
684
0
  goto bail1;
685
0
    }
686
687
101k
    e = FcPatternObjectInsertElt (p, object);
688
101k
    if (!e)
689
0
  goto bail1;
690
691
101k
    if (append) {
692
101k
  for (prev = &e->values; *prev; prev = &(*prev)->next)
693
198
      ;
694
100k
  *prev = newp;
695
100k
    } else {
696
594
  newp->next = e->values;
697
594
  e->values = newp;
698
594
    }
699
700
101k
    return FcTrue;
701
702
0
bail1:
703
0
    FcValueListDestroy (newp);
704
0
bail0:
705
0
    return FcFalse;
706
0
}
707
708
FcBool
709
FcPatternObjectAdd (FcPattern *p, FcObject object, FcValue value, FcBool append)
710
3.07k
{
711
3.07k
    return FcPatternObjectAddWithBinding (p, object,
712
3.07k
                                          value, FcValueBindingStrong, append);
713
3.07k
}
714
715
FcBool
716
FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
717
0
{
718
0
    return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
719
0
                                          value, FcValueBindingStrong, append);
720
0
}
721
722
FcBool
723
FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append)
724
0
{
725
0
    return FcPatternObjectAddWithBinding (p, FcObjectFromName (object),
726
0
                                          value, FcValueBindingWeak, append);
727
0
}
728
729
FcBool
730
FcPatternObjectDel (FcPattern *p, FcObject object)
731
22.8k
{
732
22.8k
    FcPatternElt *e;
733
734
22.8k
    e = FcPatternObjectFindElt (p, object);
735
22.8k
    if (!e)
736
366
  return FcFalse;
737
738
    /* destroy value */
739
22.4k
    FcValueListDestroy (e->values);
740
741
    /* shuffle existing ones down */
742
22.4k
    memmove (e, e + 1,
743
22.4k
             (FcPatternElts (p) + FcPatternObjectCount (p) - (e + 1)) *
744
22.4k
                 sizeof (FcPatternElt));
745
22.4k
    p->num--;
746
22.4k
    e = FcPatternElts (p) + FcPatternObjectCount (p);
747
22.4k
    e->object = 0;
748
22.4k
    e->values = NULL;
749
22.4k
    return FcTrue;
750
22.8k
}
751
752
FcBool
753
FcPatternDel (FcPattern *p, const char *object)
754
22.7k
{
755
22.7k
    return FcPatternObjectDel (p, FcObjectFromName (object));
756
22.7k
}
757
758
FcBool
759
FcPatternRemove (FcPattern *p, const char *object, int id)
760
0
{
761
0
    FcPatternElt   *e;
762
0
    FcValueListPtr *prev, l;
763
764
0
    e = FcPatternObjectFindElt (p, FcObjectFromName (object));
765
0
    if (!e)
766
0
  return FcFalse;
767
0
    for (prev = &e->values; (l = *prev); prev = &l->next) {
768
0
  if (!id) {
769
0
      *prev = l->next;
770
0
      l->next = NULL;
771
0
      FcValueListDestroy (l);
772
0
      if (!e->values)
773
0
    FcPatternDel (p, object);
774
0
      return FcTrue;
775
0
  }
776
0
  id--;
777
0
    }
778
0
    return FcFalse;
779
0
}
780
781
FcBool
782
FcPatternObjectAddInteger (FcPattern *p, FcObject object, int i)
783
725
{
784
725
    FcValue v;
785
786
725
    v.type = FcTypeInteger;
787
725
    v.u.i = i;
788
725
    return FcPatternObjectAdd (p, object, v, FcTrue);
789
725
}
790
791
FcBool
792
FcPatternAddInteger (FcPattern *p, const char *object, int i)
793
447
{
794
447
    return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
795
447
}
796
797
FcBool
798
FcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
799
162
{
800
162
    FcValue v;
801
802
162
    v.type = FcTypeDouble;
803
162
    v.u.d = d;
804
162
    return FcPatternObjectAdd (p, object, v, FcTrue);
805
162
}
806
807
FcBool
808
FcPatternAddDouble (FcPattern *p, const char *object, double d)
809
66
{
810
66
    return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
811
66
}
812
813
FcBool
814
FcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
815
494
{
816
494
    FcValue v;
817
818
494
    if (!s) {
819
0
  v.type = FcTypeVoid;
820
0
  v.u.s = 0;
821
0
  return FcPatternObjectAdd (p, object, v, FcTrue);
822
0
    }
823
824
494
    v.type = FcTypeString;
825
494
    v.u.s = s;
826
494
    return FcPatternObjectAdd (p, object, v, FcTrue);
827
494
}
828
829
FcBool
830
FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
831
185
{
832
185
    return FcPatternObjectAddString (p, FcObjectFromName (object), s);
833
185
}
834
835
FcBool
836
FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
837
0
{
838
0
    FcValue v;
839
840
0
    v.type = FcTypeMatrix;
841
0
    v.u.m = s;
842
0
    return FcPatternAdd (p, object, v, FcTrue);
843
0
}
844
845
FcBool
846
FcPatternObjectAddBool (FcPattern *p, FcObject object, FcBool b)
847
876
{
848
876
    FcValue v;
849
850
876
    v.type = FcTypeBool;
851
876
    v.u.b = b;
852
876
    return FcPatternObjectAdd (p, object, v, FcTrue);
853
876
}
854
855
FcBool
856
FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
857
183
{
858
183
    return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
859
183
}
860
861
FcBool
862
FcPatternObjectAddCharSet (FcPattern *p, FcObject object, const FcCharSet *c)
863
15
{
864
15
    FcValue v;
865
866
15
    v.type = FcTypeCharSet;
867
15
    v.u.c = (FcCharSet *)c;
868
15
    return FcPatternObjectAdd (p, object, v, FcTrue);
869
15
}
870
871
FcBool
872
FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
873
0
{
874
0
    return FcPatternObjectAddCharSet (p, FcObjectFromName (object), c);
875
0
}
876
877
FcBool
878
FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
879
0
{
880
0
#if ENABLE_FREETYPE
881
0
    FcValue v;
882
883
0
    v.type = FcTypeFTFace;
884
0
    v.u.f = (void *)f;
885
0
    return FcPatternAdd (p, object, v, FcTrue);
886
#else
887
    return FcFalse;
888
#endif
889
0
}
890
891
FcBool
892
FcPatternObjectAddLangSet (FcPattern *p, FcObject object, const FcLangSet *ls)
893
15
{
894
15
    FcValue v;
895
896
15
    v.type = FcTypeLangSet;
897
15
    v.u.l = (FcLangSet *)ls;
898
15
    return FcPatternObjectAdd (p, object, v, FcTrue);
899
15
}
900
901
FcBool
902
FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
903
0
{
904
0
    return FcPatternObjectAddLangSet (p, FcObjectFromName (object), ls);
905
0
}
906
907
FcBool
908
FcPatternObjectAddRange (FcPattern *p, FcObject object, const FcRange *r)
909
0
{
910
0
    FcValue v;
911
912
0
    v.type = FcTypeRange;
913
0
    v.u.r = (FcRange *)r;
914
0
    return FcPatternObjectAdd (p, object, v, FcTrue);
915
0
}
916
917
FcBool
918
FcPatternAddRange (FcPattern *p, const char *object, const FcRange *r)
919
0
{
920
0
    return FcPatternObjectAddRange (p, FcObjectFromName (object), r);
921
0
}
922
923
FcResult
924
FcPatternObjectGetWithBinding (const FcPattern *p, FcObject object, int id, FcValue *v, FcValueBinding *b)
925
39.4k
{
926
39.4k
    FcPatternElt  *e;
927
39.4k
    FcValueListPtr l;
928
929
39.4k
    if (!p)
930
0
  return FcResultNoMatch;
931
39.4k
    e = FcPatternObjectFindElt (p, object);
932
39.4k
    if (!e)
933
1.92k
  return FcResultNoMatch;
934
40.0k
    for (l = FcPatternEltValues (e); l; l = FcValueListNext (l)) {
935
37.5k
  if (!id) {
936
34.9k
      *v = FcValueCanonicalize (&l->value);
937
34.9k
      if (b)
938
0
    *b = l->binding;
939
34.9k
      return FcResultMatch;
940
34.9k
  }
941
2.56k
  id--;
942
2.56k
    }
943
2.56k
    return FcResultNoId;
944
37.5k
}
945
946
FcResult
947
FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
948
39.0k
{
949
39.0k
    return FcPatternObjectGetWithBinding (p, object, id, v, NULL);
950
39.0k
}
951
952
FcResult
953
FcPatternGetWithBinding (const FcPattern *p, const char *object, int id, FcValue *v, FcValueBinding *b)
954
0
{
955
0
    return FcPatternObjectGetWithBinding (p, FcObjectFromName (object), id, v, b);
956
0
}
957
958
FcResult
959
FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
960
338
{
961
338
    return FcPatternObjectGetWithBinding (p, FcObjectFromName (object), id, v, NULL);
962
338
}
963
964
FcResult
965
FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
966
9.10k
{
967
9.10k
    FcValue  v;
968
9.10k
    FcResult r;
969
970
9.10k
    r = FcPatternObjectGet (p, object, id, &v);
971
9.10k
    if (r != FcResultMatch)
972
1.05k
  return r;
973
8.04k
    switch ((int)v.type) {
974
2.54k
    case FcTypeDouble:
975
2.54k
  *i = (int)v.u.d;
976
2.54k
  break;
977
5.49k
    case FcTypeInteger:
978
5.49k
  *i = v.u.i;
979
5.49k
  break;
980
0
    default:
981
0
  return FcResultTypeMismatch;
982
8.04k
    }
983
8.04k
    return FcResultMatch;
984
8.04k
}
985
986
FcResult
987
FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
988
9.10k
{
989
9.10k
    return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
990
9.10k
}
991
992
FcResult
993
FcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
994
198
{
995
198
    FcValue  v;
996
198
    FcResult r;
997
998
198
    r = FcPatternObjectGet (p, object, id, &v);
999
198
    if (r != FcResultMatch)
1000
198
  return r;
1001
0
    switch ((int)v.type) {
1002
0
    case FcTypeDouble:
1003
0
  *d = v.u.d;
1004
0
  break;
1005
0
    case FcTypeInteger:
1006
0
  *d = (double)v.u.i;
1007
0
  break;
1008
0
    default:
1009
0
  return FcResultTypeMismatch;
1010
0
    }
1011
0
    return FcResultMatch;
1012
0
}
1013
1014
FcResult
1015
FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
1016
0
{
1017
0
    return FcPatternObjectGetDouble (p, FcObjectFromName (object), id, d);
1018
0
}
1019
1020
FcResult
1021
FcPatternObjectGetString (const FcPattern *p, FcObject object, int id, FcChar8 **s)
1022
24.2k
{
1023
24.2k
    FcValue  v;
1024
24.2k
    FcResult r;
1025
1026
24.2k
    r = FcPatternObjectGet (p, object, id, &v);
1027
24.2k
    if (r != FcResultMatch)
1028
2.76k
  return r;
1029
21.4k
    if (v.type != FcTypeString)
1030
0
  return FcResultTypeMismatch;
1031
1032
21.4k
    *s = (FcChar8 *)v.u.s;
1033
21.4k
    return FcResultMatch;
1034
21.4k
}
1035
1036
FcResult
1037
FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 **s)
1038
22.8k
{
1039
22.8k
    return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
1040
22.8k
}
1041
1042
FcResult
1043
FcPatternGetMatrix (const FcPattern *p, const char *object, int id, FcMatrix **m)
1044
0
{
1045
0
    FcValue  v;
1046
0
    FcResult r;
1047
1048
0
    r = FcPatternGet (p, object, id, &v);
1049
0
    if (r != FcResultMatch)
1050
0
  return r;
1051
0
    if (v.type != FcTypeMatrix)
1052
0
  return FcResultTypeMismatch;
1053
0
    *m = (FcMatrix *)v.u.m;
1054
0
    return FcResultMatch;
1055
0
}
1056
1057
FcResult
1058
FcPatternObjectGetBool (const FcPattern *p, FcObject object, int id, FcBool *b)
1059
5.23k
{
1060
5.23k
    FcValue  v;
1061
5.23k
    FcResult r;
1062
1063
5.23k
    r = FcPatternObjectGet (p, object, id, &v);
1064
5.23k
    if (r != FcResultMatch)
1065
0
  return r;
1066
5.23k
    if (v.type != FcTypeBool)
1067
0
  return FcResultTypeMismatch;
1068
5.23k
    *b = v.u.b;
1069
5.23k
    return FcResultMatch;
1070
5.23k
}
1071
1072
FcResult
1073
FcPatternGetBool (const FcPattern *p, const char *object, int id, FcBool *b)
1074
5.16k
{
1075
5.16k
    return FcPatternObjectGetBool (p, FcObjectFromName (object), id, b);
1076
5.16k
}
1077
1078
FcResult
1079
FcPatternGetCharSet (const FcPattern *p, const char *object, int id, FcCharSet **c)
1080
0
{
1081
0
    return FcPatternObjectGetCharSet (p, FcObjectFromName (object), id, c);
1082
0
}
1083
1084
FcResult
1085
FcPatternObjectGetCharSet (const FcPattern *p, FcObject object, int id, FcCharSet **c)
1086
0
{
1087
0
    FcValue  v;
1088
0
    FcResult r;
1089
1090
0
    r = FcPatternObjectGet (p, object, id, &v);
1091
0
    if (r != FcResultMatch)
1092
0
  return r;
1093
0
    if (v.type != FcTypeCharSet)
1094
0
  return FcResultTypeMismatch;
1095
0
    *c = (FcCharSet *)v.u.c;
1096
0
    return FcResultMatch;
1097
0
}
1098
1099
FcResult
1100
FcPatternGetFTFace (const FcPattern *p, const char *object, int id, FT_Face *f)
1101
206
{
1102
206
#if ENABLE_FREETYPE
1103
206
    FcValue  v;
1104
206
    FcResult r;
1105
1106
206
    r = FcPatternGet (p, object, id, &v);
1107
206
    if (r != FcResultMatch)
1108
206
  return r;
1109
0
    if (v.type != FcTypeFTFace)
1110
0
  return FcResultTypeMismatch;
1111
0
    *f = (FT_Face)v.u.f;
1112
0
    return FcResultMatch;
1113
#else
1114
    return FcResultNoMatch;
1115
#endif
1116
0
}
1117
1118
FcResult
1119
FcPatternGetLangSet (const FcPattern *p, const char *object, int id, FcLangSet **ls)
1120
0
{
1121
0
    return FcPatternObjectGetLangSet (p, FcObjectFromName (object), id, ls);
1122
0
}
1123
1124
FcResult
1125
FcPatternObjectGetLangSet (const FcPattern *p, FcObject object, int id, FcLangSet **ls)
1126
0
{
1127
0
    FcValue  v;
1128
0
    FcResult r;
1129
1130
0
    r = FcPatternObjectGet (p, object, id, &v);
1131
0
    if (r != FcResultMatch)
1132
0
  return r;
1133
0
    if (v.type != FcTypeLangSet)
1134
0
  return FcResultTypeMismatch;
1135
0
    *ls = (FcLangSet *)v.u.l;
1136
0
    return FcResultMatch;
1137
0
}
1138
1139
FcResult
1140
FcPatternObjectGetRange (const FcPattern *p, FcObject object, int id, FcRange **r)
1141
66
{
1142
66
    FcValue  v;
1143
66
    FcResult res;
1144
1145
66
    res = FcPatternObjectGet (p, object, id, &v);
1146
66
    if (res != FcResultMatch)
1147
66
  return res;
1148
0
    switch ((int)v.type) {
1149
0
    case FcTypeRange:
1150
0
  *r = (FcRange *)v.u.r;
1151
0
  break;
1152
0
    default:
1153
0
  return FcResultTypeMismatch;
1154
0
    }
1155
0
    return FcResultMatch;
1156
0
}
1157
1158
FcResult
1159
FcPatternGetRange (const FcPattern *p, const char *object, int id, FcRange **r)
1160
0
{
1161
0
    return FcPatternObjectGetRange (p, FcObjectFromName (object), id, r);
1162
0
}
1163
1164
FcPattern *
1165
FcPatternDuplicate (const FcPattern *orig)
1166
3.29k
{
1167
3.29k
    FcPattern     *newp;
1168
3.29k
    FcPatternIter  iter;
1169
3.29k
    FcValueListPtr l;
1170
1171
3.29k
    if (!orig)
1172
0
  return NULL;
1173
1174
3.29k
    newp = FcPatternCreate();
1175
3.29k
    if (!newp)
1176
0
  goto bail0;
1177
1178
3.29k
    FcPatternIterStart (orig, &iter);
1179
98.1k
    do {
1180
196k
  for (l = FcPatternIterGetValues (orig, &iter); l; l = FcValueListNext (l)) {
1181
98.1k
      if (!FcPatternObjectAddWithBinding (newp, FcPatternIterGetObjectId (orig, &iter),
1182
98.1k
                                          FcValueCanonicalize (&l->value),
1183
98.1k
                                          l->binding,
1184
98.1k
                                          FcTrue))
1185
0
    goto bail1;
1186
98.1k
  }
1187
98.1k
    } while (FcPatternIterNext (orig, &iter));
1188
1189
3.29k
    return newp;
1190
1191
0
bail1:
1192
0
    FcPatternDestroy (newp);
1193
0
bail0:
1194
0
    return 0;
1195
0
}
1196
1197
void
1198
FcPatternReference (FcPattern *p)
1199
2.65k
{
1200
2.65k
    if (!FcRefIsConst (&p->ref))
1201
3
  FcRefInc (&p->ref);
1202
2.65k
    else
1203
2.65k
  FcCacheObjectReference (FcPatternGetCacheObject (p));
1204
2.65k
}
1205
1206
FcPattern *
1207
FcPatternVaBuild (FcPattern *p, va_list va)
1208
0
{
1209
0
    FcPattern *ret;
1210
1211
0
    FcPatternVapBuild (ret, p, va);
1212
0
    return ret;
1213
0
}
1214
1215
FcPattern *
1216
FcPatternBuild (FcPattern *p, ...)
1217
0
{
1218
0
    va_list va;
1219
1220
0
    va_start (va, p);
1221
0
    FcPatternVapBuild (p, p, va);
1222
0
    va_end (va);
1223
0
    return p;
1224
0
}
1225
1226
/*
1227
 * Add all of the elements in 's' to 'p'
1228
 */
1229
FcBool
1230
FcPatternAppend (FcPattern *p, FcPattern *s)
1231
0
{
1232
0
    FcPatternIter  iter;
1233
0
    FcValueListPtr v;
1234
1235
0
    FcPatternIterStart (s, &iter);
1236
0
    do {
1237
0
  for (v = FcPatternIterGetValues (s, &iter); v; v = FcValueListNext (v)) {
1238
0
      if (!FcPatternObjectAddWithBinding (p, FcPatternIterGetObjectId (s, &iter),
1239
0
                                          FcValueCanonicalize (&v->value),
1240
0
                                          v->binding, FcTrue))
1241
0
    return FcFalse;
1242
0
  }
1243
0
    } while (FcPatternIterNext (s, &iter));
1244
1245
0
    return FcTrue;
1246
0
}
1247
1248
FcPattern *
1249
FcPatternFilter (FcPattern *p, const FcObjectSet *os)
1250
0
{
1251
0
    int            i;
1252
0
    FcPattern     *ret;
1253
0
    FcPatternElt  *e;
1254
0
    FcValueListPtr v;
1255
1256
0
    if (!os)
1257
0
  return FcPatternDuplicate (p);
1258
1259
0
    ret = FcPatternCreate();
1260
0
    if (!ret)
1261
0
  return NULL;
1262
1263
0
    for (i = 0; i < os->nobjIds; i++) {
1264
0
  e = FcPatternObjectFindElt (p, os->objIds[i]);
1265
0
  if (e) {
1266
0
      for (v = FcPatternEltValues (e); v; v = FcValueListNext (v)) {
1267
0
    if (!FcPatternObjectAddWithBinding (ret, e->object,
1268
0
                                        FcValueCanonicalize (&v->value),
1269
0
                                        v->binding, FcTrue))
1270
0
        goto bail0;
1271
0
      }
1272
0
  }
1273
0
    }
1274
0
    return ret;
1275
1276
0
bail0:
1277
0
    FcPatternDestroy (ret);
1278
0
    return NULL;
1279
0
}
1280
1281
typedef struct _FcPatternPrivateIter {
1282
    FcPatternElt *elt;
1283
    int           pos;
1284
} FcPatternPrivateIter;
1285
1286
static void
1287
FcPatternIterSet (const FcPattern *pat, FcPatternPrivateIter *iter)
1288
110k
{
1289
110k
    iter->elt = FcPatternObjectCount (pat) > 0 && iter->pos < FcPatternObjectCount (pat) ? &FcPatternElts (pat)[iter->pos] : NULL;
1290
110k
}
1291
1292
void
1293
FcPatternIterStart (const FcPattern *pat, FcPatternIter *iter)
1294
7.19k
{
1295
7.19k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1296
1297
7.19k
    priv->pos = 0;
1298
7.19k
    FcPatternIterSet (pat, priv);
1299
7.19k
}
1300
1301
FcBool
1302
FcPatternIterNext (const FcPattern *pat, FcPatternIter *iter)
1303
105k
{
1304
105k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1305
1306
105k
    priv->pos++;
1307
105k
    if (priv->pos >= FcPatternObjectCount (pat))
1308
3.29k
  return FcFalse;
1309
102k
    FcPatternIterSet (pat, priv);
1310
1311
102k
    return FcTrue;
1312
105k
}
1313
1314
FcBool
1315
FcPatternIterEqual (const FcPattern *p1, FcPatternIter *i1,
1316
                    const FcPattern *p2, FcPatternIter *i2)
1317
5.72k
{
1318
5.72k
    FcBool b1 = FcPatternIterIsValid (p1, i1);
1319
5.72k
    FcBool b2 = FcPatternIterIsValid (p2, i2);
1320
1321
5.72k
    if (!i1 && !i2)
1322
0
  return FcTrue;
1323
5.72k
    if (!b1 || !b2)
1324
0
  return FcFalse;
1325
5.72k
    if (FcPatternIterGetObjectId (p1, i1) != FcPatternIterGetObjectId (p2, i2))
1326
0
  return FcFalse;
1327
1328
5.72k
    return FcValueListEqual (FcPatternIterGetValues (p1, i1),
1329
5.72k
                             FcPatternIterGetValues (p2, i2));
1330
5.72k
}
1331
1332
FcBool
1333
FcPatternFindObjectIter (const FcPattern *pat, FcPatternIter *iter, FcObject object)
1334
1.33k
{
1335
1.33k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1336
1.33k
    int                   i = FcPatternObjectPosition (pat, object);
1337
1338
1.33k
    priv->elt = NULL;
1339
1.33k
    if (i < 0)
1340
1.02k
  return FcFalse;
1341
1342
303
    priv->pos = i;
1343
303
    FcPatternIterSet (pat, priv);
1344
1345
303
    return FcTrue;
1346
1.33k
}
1347
1348
FcBool
1349
FcPatternFindIter (const FcPattern *pat, FcPatternIter *iter, const char *object)
1350
0
{
1351
0
    return FcPatternFindObjectIter (pat, iter, FcObjectFromName (object));
1352
0
}
1353
1354
FcBool
1355
FcPatternIterIsValid (const FcPattern *pat, FcPatternIter *iter)
1356
11.4k
{
1357
11.4k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1358
1359
11.4k
    if (priv && priv->elt)
1360
11.4k
  return FcTrue;
1361
1362
0
    return FcFalse;
1363
11.4k
}
1364
1365
FcObject
1366
FcPatternIterGetObjectId (const FcPattern *pat, FcPatternIter *iter)
1367
109k
{
1368
109k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1369
1370
109k
    if (priv && priv->elt)
1371
109k
  return priv->elt->object;
1372
1373
0
    return 0;
1374
109k
}
1375
1376
const char *
1377
FcPatternIterGetObject (const FcPattern *pat, FcPatternIter *iter)
1378
0
{
1379
0
    return FcObjectName (FcPatternIterGetObjectId (pat, iter));
1380
0
}
1381
1382
FcValueListPtr
1383
FcPatternIterGetValues (const FcPattern *pat, FcPatternIter *iter)
1384
109k
{
1385
109k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1386
1387
109k
    if (priv && priv->elt)
1388
109k
  return FcPatternEltValues (priv->elt);
1389
1390
0
    return NULL;
1391
109k
}
1392
1393
int
1394
FcPatternIterValueCount (const FcPattern *pat, FcPatternIter *iter)
1395
0
{
1396
0
    int            count = 0;
1397
0
    FcValueListPtr l;
1398
1399
0
    for (l = FcPatternIterGetValues (pat, iter); l; l = FcValueListNext (l))
1400
0
  count++;
1401
1402
0
    return count;
1403
0
}
1404
1405
FcResult
1406
FcPatternIterGetValue (const FcPattern *pat, FcPatternIter *iter, int id, FcValue *v, FcValueBinding *b)
1407
66
{
1408
66
    FcValueListPtr l;
1409
1410
66
    for (l = FcPatternIterGetValues (pat, iter); l; l = FcValueListNext (l)) {
1411
66
  if (id == 0) {
1412
66
      *v = FcValueCanonicalize (&l->value);
1413
66
      if (b)
1414
0
    *b = l->binding;
1415
66
      return FcResultMatch;
1416
66
  }
1417
0
  id--;
1418
0
    }
1419
0
    return FcResultNoId;
1420
66
}
1421
1422
FcBool
1423
FcPatternSerializeAlloc (FcSerialize *serialize, const FcPattern *pat)
1424
13
{
1425
13
    int           i;
1426
13
    FcPatternElt *elts = FcPatternElts (pat);
1427
1428
13
    if (!FcSerializeAlloc (serialize, pat, sizeof (FcPattern)))
1429
0
  return FcFalse;
1430
13
    if (!FcSerializeAlloc (serialize, elts, FcPatternObjectCount (pat) * sizeof (FcPatternElt)))
1431
0
  return FcFalse;
1432
393
    for (i = 0; i < FcPatternObjectCount (pat); i++)
1433
380
  if (!FcValueListSerializeAlloc (serialize, FcPatternEltValues (elts + i)))
1434
0
      return FcFalse;
1435
13
    return FcTrue;
1436
13
}
1437
1438
FcPattern *
1439
FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
1440
13
{
1441
13
    FcPattern    *pat_serialized;
1442
13
    FcPatternElt *elts = FcPatternElts (pat);
1443
13
    FcPatternElt *elts_serialized;
1444
13
    FcValueList  *values_serialized;
1445
13
    int           i;
1446
1447
13
    pat_serialized = FcSerializePtr (serialize, pat);
1448
13
    if (!pat_serialized)
1449
0
  return NULL;
1450
13
    *pat_serialized = *pat;
1451
13
    pat_serialized->size = FcPatternObjectCount (pat);
1452
13
    FcRefSetConst (&pat_serialized->ref);
1453
1454
13
    elts_serialized = FcSerializePtr (serialize, elts);
1455
13
    if (!elts_serialized)
1456
0
  return NULL;
1457
1458
13
    pat_serialized->elts_offset = FcPtrToOffset (pat_serialized,
1459
13
                                                 elts_serialized);
1460
1461
393
    for (i = 0; i < FcPatternObjectCount (pat); i++) {
1462
380
  values_serialized = FcValueListSerialize (serialize, FcPatternEltValues (elts + i));
1463
380
  if (!values_serialized)
1464
0
      return NULL;
1465
380
  elts_serialized[i].object = elts[i].object;
1466
380
  elts_serialized[i].values = FcPtrToEncodedOffset (&elts_serialized[i],
1467
380
                                                    values_serialized,
1468
380
                                                    FcValueList);
1469
380
    }
1470
13
    if (FcDebug() & FC_DBG_CACHEV) {
1471
0
  printf ("Raw pattern:\n");
1472
0
  FcPatternPrint (pat);
1473
0
  printf ("Serialized pattern:\n");
1474
0
  FcPatternPrint (pat_serialized);
1475
0
  printf ("\n");
1476
0
    }
1477
13
    return pat_serialized;
1478
13
}
1479
1480
FcBool
1481
FcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *vl)
1482
380
{
1483
760
    while (vl) {
1484
380
  if (!FcSerializeAlloc (serialize, vl, sizeof (FcValueList)))
1485
0
      return FcFalse;
1486
380
  switch ((int)vl->value.type) {
1487
155
  case FcTypeString:
1488
155
      if (!FcStrSerializeAlloc (serialize, vl->value.u.s))
1489
0
    return FcFalse;
1490
155
      break;
1491
155
  case FcTypeCharSet:
1492
13
      if (!FcCharSetSerializeAlloc (serialize, vl->value.u.c))
1493
0
    return FcFalse;
1494
13
      break;
1495
13
  case FcTypeLangSet:
1496
13
      if (!FcLangSetSerializeAlloc (serialize, vl->value.u.l))
1497
0
    return FcFalse;
1498
13
      break;
1499
13
  case FcTypeRange:
1500
0
      if (!FcRangeSerializeAlloc (serialize, vl->value.u.r))
1501
0
    return FcFalse;
1502
0
      break;
1503
199
  default:
1504
199
      break;
1505
380
  }
1506
380
  vl = vl->next;
1507
380
    }
1508
380
    return FcTrue;
1509
380
}
1510
1511
FcValueList *
1512
FcValueListSerialize (FcSerialize *serialize, const FcValueList *vl)
1513
380
{
1514
380
    FcValueList *vl_serialized;
1515
380
    FcChar8     *s_serialized;
1516
380
    FcCharSet   *c_serialized;
1517
380
    FcLangSet   *l_serialized;
1518
380
    FcRange     *r_serialized;
1519
380
    FcValueList *head_serialized = NULL;
1520
380
    FcValueList *prev_serialized = NULL;
1521
1522
760
    while (vl) {
1523
380
  vl_serialized = FcSerializePtr (serialize, vl);
1524
380
  if (!vl_serialized)
1525
0
      return NULL;
1526
1527
380
  if (prev_serialized)
1528
0
      prev_serialized->next = FcPtrToEncodedOffset (prev_serialized,
1529
380
                                                    vl_serialized,
1530
380
                                                    FcValueList);
1531
380
  else
1532
380
      head_serialized = vl_serialized;
1533
1534
380
  vl_serialized->next = NULL;
1535
380
  vl_serialized->value.type = vl->value.type;
1536
380
  switch ((int)vl->value.type) {
1537
69
  case FcTypeInteger:
1538
69
      vl_serialized->value.u.i = vl->value.u.i;
1539
69
      break;
1540
26
  case FcTypeDouble:
1541
26
      vl_serialized->value.u.d = vl->value.u.d;
1542
26
      break;
1543
155
  case FcTypeString:
1544
155
      s_serialized = FcStrSerialize (serialize, vl->value.u.s);
1545
155
      if (!s_serialized)
1546
0
    return NULL;
1547
155
      vl_serialized->value.u.s = FcPtrToEncodedOffset (&vl_serialized->value,
1548
155
                                                       s_serialized,
1549
155
                                                       FcChar8);
1550
155
      break;
1551
104
  case FcTypeBool:
1552
104
      vl_serialized->value.u.b = vl->value.u.b;
1553
104
      break;
1554
0
  case FcTypeMatrix:
1555
      /* can't happen */
1556
0
      break;
1557
13
  case FcTypeCharSet:
1558
13
      c_serialized = FcCharSetSerialize (serialize, vl->value.u.c);
1559
13
      if (!c_serialized)
1560
0
    return NULL;
1561
13
      vl_serialized->value.u.c = FcPtrToEncodedOffset (&vl_serialized->value,
1562
13
                                                       c_serialized,
1563
13
                                                       FcCharSet);
1564
13
      break;
1565
0
  case FcTypeFTFace:
1566
      /* can't happen */
1567
0
      break;
1568
13
  case FcTypeLangSet:
1569
13
      l_serialized = FcLangSetSerialize (serialize, vl->value.u.l);
1570
13
      if (!l_serialized)
1571
0
    return NULL;
1572
13
      vl_serialized->value.u.l = FcPtrToEncodedOffset (&vl_serialized->value,
1573
13
                                                       l_serialized,
1574
13
                                                       FcLangSet);
1575
13
      break;
1576
0
  case FcTypeRange:
1577
0
      r_serialized = FcRangeSerialize (serialize, vl->value.u.r);
1578
0
      if (!r_serialized)
1579
0
    return NULL;
1580
0
      vl_serialized->value.u.r = FcPtrToEncodedOffset (&vl_serialized->value,
1581
0
                                                       r_serialized,
1582
0
                                                       FcRange);
1583
0
      break;
1584
0
  default:
1585
0
      break;
1586
380
  }
1587
380
  prev_serialized = vl_serialized;
1588
380
  vl = vl->next;
1589
380
    }
1590
380
    return head_serialized;
1591
380
}
1592
1593
#define __fcpat__
1594
#include "fcaliastail.h"
1595
#if ENABLE_FREETYPE
1596
#include "fcftaliastail.h"
1597
#endif
1598
#undef __fcpat__