Coverage Report

Created: 2025-07-07 10:01

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