Coverage Report

Created: 2026-05-16 09:25

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
#include "fcftint.h"
26
27
/* Objects MT-safe for readonly access. */
28
29
FcPattern *
30
FcPatternCreate (void)
31
7.90k
{
32
7.90k
    FcPattern *p;
33
34
7.90k
    p = (FcPattern *)malloc (sizeof (FcPattern));
35
7.90k
    if (!p)
36
0
  return 0;
37
7.90k
    memset (p, 0, sizeof (FcPattern));
38
7.90k
    p->num = 0;
39
7.90k
    p->size = 0;
40
7.90k
    p->elts_offset = FcPtrToOffset (p, NULL);
41
7.90k
    FcRefInit (&p->ref, 1);
42
7.90k
    return p;
43
7.90k
}
44
45
void
46
FcValueDestroy (FcValue v)
47
262k
{
48
262k
    switch ((int)v.type) {
49
99.4k
    case FcTypeString:
50
99.4k
  FcFree (v.u.s);
51
99.4k
  break;
52
0
    case FcTypeMatrix:
53
0
  FcMatrixFree ((FcMatrix *)v.u.m);
54
0
  break;
55
6.90k
    case FcTypeCharSet:
56
6.90k
  FcCharSetDestroy ((FcCharSet *)v.u.c);
57
6.90k
  break;
58
6.90k
    case FcTypeLangSet:
59
6.90k
  FcLangSetDestroy ((FcLangSet *)v.u.l);
60
6.90k
  break;
61
0
    case FcTypeRange:
62
0
  FcRangeDestroy ((FcRange *)v.u.r);
63
0
  break;
64
149k
    default:
65
149k
  break;
66
262k
    }
67
262k
}
68
69
FcValue
70
FcValueCanonicalize (const FcValue *v)
71
395k
{
72
395k
    FcValue newp;
73
74
395k
    switch ((int)v->type) {
75
118k
    case FcTypeString:
76
118k
  newp.u.s = FcValueString (v);
77
118k
  newp.type = FcTypeString;
78
118k
  break;
79
6.91k
    case FcTypeCharSet:
80
6.91k
  newp.u.c = FcValueCharSet (v);
81
6.91k
  newp.type = FcTypeCharSet;
82
6.91k
  break;
83
18.1k
    case FcTypeLangSet:
84
18.1k
  newp.u.l = FcValueLangSet (v);
85
18.1k
  newp.type = FcTypeLangSet;
86
18.1k
  break;
87
0
    case FcTypeRange:
88
0
  newp.u.r = FcValueRange (v);
89
0
  newp.type = FcTypeRange;
90
0
  break;
91
251k
    default:
92
251k
  newp = *v;
93
251k
  break;
94
395k
    }
95
395k
    return newp;
96
395k
}
97
98
FcValue
99
FcValueSave (FcValue v)
100
263k
{
101
263k
    switch ((int)v.type) {
102
99.9k
    case FcTypeString:
103
99.9k
  v.u.s = FcStrdup (v.u.s);
104
99.9k
  if (!v.u.s)
105
0
      v.type = FcTypeVoid;
106
99.9k
  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
6.94k
    case FcTypeCharSet:
113
6.94k
  v.u.c = FcCharSetCopy ((FcCharSet *)v.u.c);
114
6.94k
  if (!v.u.c)
115
0
      v.type = FcTypeVoid;
116
6.94k
  break;
117
6.94k
    case FcTypeLangSet:
118
6.94k
  v.u.l = FcLangSetCopy (v.u.l);
119
6.94k
  if (!v.u.l)
120
0
      v.type = FcTypeVoid;
121
6.94k
  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
149k
    default:
128
149k
  break;
129
263k
    }
130
263k
    return v;
131
263k
}
132
133
FcValueListPtr
134
FcValueListCreate (void)
135
263k
{
136
263k
    return calloc (1, sizeof (FcValueList));
137
263k
}
138
139
void
140
FcValueListDestroy (FcValueListPtr l)
141
259k
{
142
259k
    FcValueListPtr next;
143
521k
    for (; l; l = next) {
144
262k
  FcValueDestroy (l->value);
145
262k
  next = FcValueListNext (l);
146
262k
  free (l);
147
262k
    }
148
259k
}
149
150
FcValueListPtr
151
FcValueListPrepend (FcValueListPtr vallist,
152
                    FcValue        value,
153
                    FcValueBinding binding)
154
5.61k
{
155
5.61k
    FcValueListPtr newp;
156
157
5.61k
    if (value.type == FcTypeVoid)
158
0
  return vallist;
159
5.61k
    newp = FcValueListCreate();
160
5.61k
    if (!newp)
161
0
  return vallist;
162
163
5.61k
    newp->value = FcValueSave (value);
164
5.61k
    newp->binding = binding;
165
5.61k
    newp->next = vallist;
166
167
5.61k
    return newp;
168
5.61k
}
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
29.9k
{
201
29.9k
    FcValueListPtr newp = NULL, l, t = NULL;
202
29.9k
    FcValue        v;
203
204
59.8k
    for (l = orig; l != NULL; l = FcValueListNext (l)) {
205
29.9k
  if (!newp) {
206
29.9k
      t = newp = FcValueListCreate();
207
29.9k
  } else {
208
0
      t->next = FcValueListCreate();
209
0
      t = FcValueListNext (t);
210
0
  }
211
29.9k
  v = FcValueCanonicalize (&l->value);
212
29.9k
  t->value = FcValueSave (v);
213
29.9k
  t->binding = l->binding;
214
29.9k
  t->next = NULL;
215
29.9k
    }
216
217
29.9k
    return newp;
218
29.9k
}
219
220
FcBool
221
FcValueEqual (FcValue va, FcValue vb)
222
5.83k
{
223
5.83k
    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.83k
    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.83k
    case FcTypeString:
245
5.83k
  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.83k
    }
259
0
    return FcFalse;
260
5.83k
}
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.83k
{
320
5.83k
    if (la == lb)
321
0
  return FcTrue;
322
323
9.72k
    while (la && lb) {
324
5.83k
  if (!FcValueEqual (la->value, lb->value))
325
1.94k
      return FcFalse;
326
3.88k
  la = FcValueListNext (la);
327
3.88k
  lb = FcValueListNext (lb);
328
3.88k
    }
329
3.88k
    if (la || lb)
330
0
  return FcFalse;
331
3.88k
    return FcTrue;
332
3.88k
}
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.10k
{
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.10k
    return FcPatternEltValues (&FcPatternElts (p)[0]);
352
4.10k
}
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
9.27k
{
412
9.27k
    int           i;
413
9.27k
    FcPatternElt *elts;
414
415
9.27k
    if (!p)
416
0
  return;
417
418
9.27k
    if (FcRefIsConst (&p->ref)) {
419
1.40k
  FcCacheObjectDereference (FcPatternGetCacheObject (p));
420
1.40k
  return;
421
1.40k
    }
422
423
7.86k
    if (FcRefDec (&p->ref) != 1)
424
0
  return;
425
426
7.86k
    elts = FcPatternElts (p);
427
241k
    for (i = 0; i < FcPatternObjectCount (p); i++)
428
233k
  FcValueListDestroy (FcPatternEltValues (&elts[i]));
429
430
7.86k
    free (elts);
431
7.86k
    free (p);
432
7.86k
}
433
434
int
435
FcPatternObjectCount (const FcPattern *pat)
436
1.83M
{
437
1.83M
    if (pat)
438
1.83M
  return pat->num;
439
440
0
    return 0;
441
1.83M
}
442
443
static int
444
FcPatternObjectPosition (const FcPattern *p, FcObject object)
445
455k
{
446
455k
    int           low, high, mid, c;
447
455k
    FcPatternElt *elts = FcPatternElts (p);
448
449
455k
    low = 0;
450
455k
    high = FcPatternObjectCount (p) - 1;
451
455k
    c = 1;
452
455k
    mid = 0;
453
2.24M
    while (low <= high) {
454
1.92M
  mid = (low + high) >> 1;
455
1.92M
  c = elts[mid].object - object;
456
1.92M
  if (c == 0)
457
133k
      return mid;
458
1.79M
  if (c < 0)
459
1.40M
      low = mid + 1;
460
385k
  else
461
385k
      high = mid - 1;
462
1.79M
    }
463
322k
    if (c < 0)
464
258k
  mid++;
465
322k
    return -(mid + 1);
466
455k
}
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
173k
{
477
173k
    int i = FcPatternObjectPosition (p, object);
478
173k
    if (i < 0)
479
47.3k
  return 0;
480
126k
    return &FcPatternElts (p)[i];
481
173k
}
482
483
FcPatternElt *
484
FcPatternObjectInsertElt (FcPattern *p, FcObject object)
485
263k
{
486
263k
    int           i;
487
263k
    FcPatternElt *e;
488
489
263k
    i = FcPatternObjectPosition (p, object);
490
263k
    if (i < 0) {
491
261k
  i = -i - 1;
492
493
  /* reallocate array */
494
261k
  if (FcPatternObjectCount (p) + 1 >= p->size) {
495
18.5k
      int s = p->size + 16;
496
18.5k
      if (p->size) {
497
10.6k
    FcPatternElt *e0 = FcPatternElts (p);
498
10.6k
    e = (FcPatternElt *)realloc (e0, s * sizeof (FcPatternElt));
499
10.6k
    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
10.6k
      } else
506
7.90k
    e = (FcPatternElt *)malloc (s * sizeof (FcPatternElt));
507
18.5k
      if (!e)
508
0
    return FcFalse;
509
18.5k
      p->elts_offset = FcPtrToOffset (p, e);
510
315k
      while (p->size < s) {
511
296k
    e[p->size].object = 0;
512
296k
    e[p->size].values = NULL;
513
296k
    p->size++;
514
296k
      }
515
18.5k
  }
516
517
261k
  e = FcPatternElts (p);
518
  /* move elts up */
519
261k
  memmove (e + i + 1,
520
261k
           e + i,
521
261k
           sizeof (FcPatternElt) *
522
261k
               (FcPatternObjectCount (p) - i));
523
524
  /* bump count */
525
261k
  p->num++;
526
527
261k
  e[i].object = object;
528
261k
  e[i].values = NULL;
529
261k
    }
530
531
263k
    return FcPatternElts (p) + i;
532
263k
}
533
534
FcBool
535
FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
536
1.94k
{
537
1.94k
    FcPatternIter ia, ib;
538
539
1.94k
    if (pa == pb)
540
0
  return FcTrue;
541
542
1.94k
    if (FcPatternObjectCount (pa) != FcPatternObjectCount (pb))
543
0
  return FcFalse;
544
1.94k
    FcPatternIterStart (pa, &ia);
545
1.94k
    FcPatternIterStart (pb, &ib);
546
5.83k
    do {
547
5.83k
  FcBool ra, rb;
548
549
5.83k
  if (!FcPatternIterEqual (pa, &ia, pb, &ib))
550
1.94k
      return FcFalse;
551
3.88k
  ra = FcPatternIterNext (pa, &ia);
552
3.88k
  rb = FcPatternIterNext (pb, &ib);
553
3.88k
  if (!ra && !rb)
554
0
      break;
555
3.88k
    } while (1);
556
557
0
    return FcTrue;
558
1.94k
}
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
56.1k
{
604
56.1k
    FcPatternElt  *e;
605
56.1k
    FcValueListPtr l, *prev;
606
607
56.1k
    if (FcRefIsConst (&p->ref))
608
0
  goto bail0;
609
610
    /*
611
     * Make sure the stored type is valid for built-in objects
612
     */
613
112k
    for (l = list; l != NULL; l = FcValueListNext (l)) {
614
56.1k
  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
56.1k
    }
622
623
56.1k
    e = FcPatternObjectInsertElt (p, object);
624
56.1k
    if (!e)
625
0
  goto bail0;
626
627
56.1k
    if (append) {
628
38.3k
  for (prev = &e->values; *prev; prev = &(*prev)->next)
629
0
      ;
630
38.3k
  *prev = list;
631
38.3k
    } else {
632
35.5k
  for (prev = &list; *prev; prev = &(*prev)->next)
633
17.7k
      ;
634
17.7k
  *prev = e->values;
635
17.7k
  e->values = list;
636
17.7k
    }
637
638
56.1k
    return FcTrue;
639
640
0
bail0:
641
0
    return FcFalse;
642
56.1k
}
643
644
FcBool
645
FcPatternObjectAddWithBinding (FcPattern     *p,
646
                               FcObject       object,
647
                               FcValue        value,
648
                               FcValueBinding binding,
649
                               FcBool         append)
650
207k
{
651
207k
    FcPatternElt  *e;
652
207k
    FcValueListPtr newp, *prev;
653
654
207k
    if (FcRefIsConst (&p->ref))
655
0
  goto bail0;
656
657
207k
    newp = FcValueListCreate();
658
207k
    if (!newp)
659
0
  goto bail0;
660
661
207k
    newp->value = FcValueSave (value);
662
207k
    newp->binding = binding;
663
207k
    newp->next = NULL;
664
665
207k
    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
207k
    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
207k
    e = FcPatternObjectInsertElt (p, object);
681
207k
    if (!e)
682
0
  goto bail1;
683
684
207k
    if (append) {
685
202k
  for (prev = &e->values; *prev; prev = &(*prev)->next)
686
2.80k
      ;
687
199k
  *prev = newp;
688
199k
    } else {
689
8.41k
  newp->next = e->values;
690
8.41k
  e->values = newp;
691
8.41k
    }
692
693
207k
    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
38.0k
{
704
38.0k
    return FcPatternObjectAddWithBinding (p, object,
705
38.0k
                                          value, FcValueBindingStrong, append);
706
38.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
31.7k
{
725
31.7k
    FcPatternElt *e;
726
727
31.7k
    e = FcPatternObjectFindElt (p, object);
728
31.7k
    if (!e)
729
5.48k
  return FcFalse;
730
731
    /* destroy value */
732
26.2k
    FcValueListDestroy (e->values);
733
734
    /* shuffle existing ones down */
735
26.2k
    memmove (e, e + 1,
736
26.2k
             (FcPatternElts (p) + FcPatternObjectCount (p) - (e + 1)) *
737
26.2k
                 sizeof (FcPatternElt));
738
26.2k
    p->num--;
739
26.2k
    e = FcPatternElts (p) + FcPatternObjectCount (p);
740
26.2k
    e->object = 0;
741
26.2k
    e->values = NULL;
742
26.2k
    return FcTrue;
743
31.7k
}
744
745
FcBool
746
FcPatternDel (FcPattern *p, const char *object)
747
30.8k
{
748
30.8k
    return FcPatternObjectDel (p, FcObjectFromName (object));
749
30.8k
}
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
9.40k
{
777
9.40k
    FcValue v;
778
779
9.40k
    v.type = FcTypeInteger;
780
9.40k
    v.u.i = i;
781
9.40k
    return FcPatternObjectAdd (p, object, v, FcTrue);
782
9.40k
}
783
784
FcBool
785
FcPatternAddInteger (FcPattern *p, const char *object, int i)
786
6.48k
{
787
6.48k
    return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
788
6.48k
}
789
790
FcBool
791
FcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
792
1.92k
{
793
1.92k
    FcValue v;
794
795
1.92k
    v.type = FcTypeDouble;
796
1.92k
    v.u.d = d;
797
1.92k
    return FcPatternObjectAdd (p, object, v, FcTrue);
798
1.92k
}
799
800
FcBool
801
FcPatternAddDouble (FcPattern *p, const char *object, double d)
802
935
{
803
935
    return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
804
935
}
805
806
FcBool
807
FcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
808
4.92k
{
809
4.92k
    FcValue v;
810
811
4.92k
    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
4.92k
    v.type = FcTypeString;
818
4.92k
    v.u.s = s;
819
4.92k
    return FcPatternObjectAdd (p, object, v, FcTrue);
820
4.92k
}
821
822
FcBool
823
FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
824
2.74k
{
825
2.74k
    return FcPatternObjectAddString (p, FcObjectFromName (object), s);
826
2.74k
}
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
10.5k
{
841
10.5k
    FcValue v;
842
843
10.5k
    v.type = FcTypeBool;
844
10.5k
    v.u.b = b;
845
10.5k
    return FcPatternObjectAdd (p, object, v, FcTrue);
846
10.5k
}
847
848
FcBool
849
FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
850
2.74k
{
851
2.74k
    return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
852
2.74k
}
853
854
FcBool
855
FcPatternObjectAddCharSet (FcPattern *p, FcObject object, const FcCharSet *c)
856
27
{
857
27
    FcValue v;
858
859
27
    v.type = FcTypeCharSet;
860
27
    v.u.c = (FcCharSet *)c;
861
27
    return FcPatternObjectAdd (p, object, v, FcTrue);
862
27
}
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
27
{
883
27
    FcValue v;
884
885
27
    v.type = FcTypeLangSet;
886
27
    v.u.l = (FcLangSet *)ls;
887
27
    return FcPatternObjectAdd (p, object, v, FcTrue);
888
27
}
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
87.8k
{
915
87.8k
    FcPatternElt  *e;
916
87.8k
    FcValueListPtr l;
917
918
87.8k
    if (!p)
919
0
  return FcResultNoMatch;
920
87.8k
    e = FcPatternObjectFindElt (p, object);
921
87.8k
    if (!e)
922
16.6k
  return FcResultNoMatch;
923
73.7k
    for (l = FcPatternEltValues (e); l; l = FcValueListNext (l)) {
924
71.1k
  if (!id) {
925
68.5k
      *v = FcValueCanonicalize (&l->value);
926
68.5k
      if (b)
927
0
    *b = l->binding;
928
68.5k
      return FcResultMatch;
929
68.5k
  }
930
2.64k
  id--;
931
2.64k
    }
932
2.64k
    return FcResultNoId;
933
71.1k
}
934
935
FcResult
936
FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
937
82.8k
{
938
82.8k
    return FcPatternObjectGetWithBinding (p, object, id, v, NULL);
939
82.8k
}
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
4.95k
{
950
4.95k
    return FcPatternObjectGetWithBinding (p, FcObjectFromName (object), id, v, NULL);
951
4.95k
}
952
953
FcResult
954
FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
955
20.8k
{
956
20.8k
    FcValue  v;
957
20.8k
    FcResult r;
958
959
20.8k
    r = FcPatternObjectGet (p, object, id, &v);
960
20.8k
    if (r != FcResultMatch)
961
3.95k
  return r;
962
16.8k
    switch ((int)v.type) {
963
2.62k
    case FcTypeDouble:
964
2.62k
  *i = (int)v.u.d;
965
2.62k
  break;
966
14.2k
    case FcTypeInteger:
967
14.2k
  *i = v.u.i;
968
14.2k
  break;
969
0
    default:
970
0
  return FcResultTypeMismatch;
971
16.8k
    }
972
16.8k
    return FcResultMatch;
973
16.8k
}
974
975
FcResult
976
FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
977
20.8k
{
978
20.8k
    return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
979
20.8k
}
980
981
FcResult
982
FcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
983
2.80k
{
984
2.80k
    FcValue  v;
985
2.80k
    FcResult r;
986
987
2.80k
    r = FcPatternObjectGet (p, object, id, &v);
988
2.80k
    if (r != FcResultMatch)
989
2.80k
  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
31.0k
{
1012
31.0k
    FcValue  v;
1013
31.0k
    FcResult r;
1014
1015
31.0k
    r = FcPatternObjectGet (p, object, id, &v);
1016
31.0k
    if (r != FcResultMatch)
1017
5.72k
  return r;
1018
25.2k
    if (v.type != FcTypeString)
1019
0
  return FcResultTypeMismatch;
1020
1021
25.2k
    *s = (FcChar8 *)v.u.s;
1022
25.2k
    return FcResultMatch;
1023
25.2k
}
1024
1025
FcResult
1026
FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 **s)
1027
29.5k
{
1028
29.5k
    return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
1029
29.5k
}
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
23.5k
{
1049
23.5k
    FcValue  v;
1050
23.5k
    FcResult r;
1051
1052
23.5k
    r = FcPatternObjectGet (p, object, id, &v);
1053
23.5k
    if (r != FcResultMatch)
1054
0
  return r;
1055
23.5k
    if (v.type != FcTypeBool)
1056
0
  return FcResultTypeMismatch;
1057
23.5k
    *b = v.u.b;
1058
23.5k
    return FcResultMatch;
1059
23.5k
}
1060
1061
FcResult
1062
FcPatternGetBool (const FcPattern *p, const char *object, int id, FcBool *b)
1063
22.6k
{
1064
22.6k
    return FcPatternObjectGetBool (p, FcObjectFromName (object), id, b);
1065
22.6k
}
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
3.08k
{
1091
3.08k
    FcValue  v;
1092
3.08k
    FcResult r;
1093
1094
3.08k
    r = FcPatternGet (p, object, id, &v);
1095
3.08k
    if (r != FcResultMatch)
1096
3.08k
  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
935
{
1127
935
    FcValue  v;
1128
935
    FcResult res;
1129
1130
935
    res = FcPatternObjectGet (p, object, id, &v);
1131
935
    if (res != FcResultMatch)
1132
935
  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
5.04k
{
1152
5.04k
    FcPattern     *newp;
1153
5.04k
    FcPatternIter  iter;
1154
5.04k
    FcValueListPtr l;
1155
1156
5.04k
    if (!orig)
1157
0
  return NULL;
1158
1159
5.04k
    newp = FcPatternCreate();
1160
5.04k
    if (!newp)
1161
0
  goto bail0;
1162
1163
5.04k
    FcPatternIterStart (orig, &iter);
1164
165k
    do {
1165
331k
  for (l = FcPatternIterGetValues (orig, &iter); l; l = FcValueListNext (l)) {
1166
165k
      if (!FcPatternObjectAddWithBinding (newp, FcPatternIterGetObjectId (orig, &iter),
1167
165k
                                          FcValueCanonicalize (&l->value),
1168
165k
                                          l->binding,
1169
165k
                                          FcTrue))
1170
0
    goto bail1;
1171
165k
  }
1172
165k
    } while (FcPatternIterNext (orig, &iter));
1173
1174
5.04k
    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.79k
{
1185
2.79k
    if (!FcRefIsConst (&p->ref))
1186
91
  FcRefInc (&p->ref);
1187
2.70k
    else
1188
2.70k
  FcCacheObjectReference (FcPatternGetCacheObject (p));
1189
2.79k
}
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
181k
{
1275
181k
    iter->elt = FcPatternObjectCount (pat) > 0 && iter->pos < FcPatternObjectCount (pat) ? &FcPatternElts (pat)[iter->pos] : NULL;
1276
181k
}
1277
1278
void
1279
FcPatternIterStart (const FcPattern *pat, FcPatternIter *iter)
1280
9.01k
{
1281
9.01k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1282
1283
9.01k
    priv->pos = 0;
1284
9.01k
    FcPatternIterSet (pat, priv);
1285
9.01k
}
1286
1287
FcBool
1288
FcPatternIterNext (const FcPattern *pat, FcPatternIter *iter)
1289
173k
{
1290
173k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1291
1292
173k
    priv->pos++;
1293
173k
    if (priv->pos >= FcPatternObjectCount (pat))
1294
5.04k
  return FcFalse;
1295
168k
    FcPatternIterSet (pat, priv);
1296
1297
168k
    return FcTrue;
1298
173k
}
1299
1300
FcBool
1301
FcPatternIterEqual (const FcPattern *p1, FcPatternIter *i1,
1302
                    const FcPattern *p2, FcPatternIter *i2)
1303
5.83k
{
1304
5.83k
    FcBool b1 = FcPatternIterIsValid (p1, i1);
1305
5.83k
    FcBool b2 = FcPatternIterIsValid (p2, i2);
1306
1307
5.83k
    if (!i1 && !i2)
1308
0
  return FcTrue;
1309
5.83k
    if (!b1 || !b2)
1310
0
  return FcFalse;
1311
5.83k
    if (FcPatternIterGetObjectId (p1, i1) != FcPatternIterGetObjectId (p2, i2))
1312
0
  return FcFalse;
1313
1314
5.83k
    return FcValueListEqual (FcPatternIterGetValues (p1, i1),
1315
5.83k
                             FcPatternIterGetValues (p2, i2));
1316
5.83k
}
1317
1318
FcBool
1319
FcPatternFindObjectIter (const FcPattern *pat, FcPatternIter *iter, FcObject object)
1320
17.8k
{
1321
17.8k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1322
17.8k
    int                   i = FcPatternObjectPosition (pat, object);
1323
1324
17.8k
    priv->elt = NULL;
1325
17.8k
    if (i < 0)
1326
14.0k
  return FcFalse;
1327
1328
3.77k
    priv->pos = i;
1329
3.77k
    FcPatternIterSet (pat, priv);
1330
1331
3.77k
    return FcTrue;
1332
17.8k
}
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.6k
{
1343
11.6k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1344
1345
11.6k
    if (priv && priv->elt)
1346
11.6k
  return FcTrue;
1347
1348
0
    return FcFalse;
1349
11.6k
}
1350
1351
FcObject
1352
FcPatternIterGetObjectId (const FcPattern *pat, FcPatternIter *iter)
1353
177k
{
1354
177k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1355
1356
177k
    if (priv && priv->elt)
1357
177k
  return priv->elt->object;
1358
1359
0
    return 0;
1360
177k
}
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
178k
{
1371
178k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1372
1373
178k
    if (priv && priv->elt)
1374
178k
  return FcPatternEltValues (priv->elt);
1375
1376
0
    return NULL;
1377
178k
}
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
935
{
1394
935
    FcValueListPtr l;
1395
1396
935
    for (l = FcPatternIterGetValues (pat, iter); l; l = FcValueListNext (l)) {
1397
935
  if (id == 0) {
1398
935
      *v = FcValueCanonicalize (&l->value);
1399
935
      if (b)
1400
0
    *b = l->binding;
1401
935
      return FcResultMatch;
1402
935
  }
1403
0
  id--;
1404
0
    }
1405
0
    return FcResultNoId;
1406
935
}
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__