Coverage Report

Created: 2025-11-16 09:57

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
6.47k
{
32
6.47k
    FcPattern *p;
33
34
6.47k
    p = (FcPattern *)malloc (sizeof (FcPattern));
35
6.47k
    if (!p)
36
0
  return 0;
37
6.47k
    memset (p, 0, sizeof (FcPattern));
38
6.47k
    p->num = 0;
39
6.47k
    p->size = 0;
40
6.47k
    p->elts_offset = FcPtrToOffset (p, NULL);
41
6.47k
    FcRefInit (&p->ref, 1);
42
6.47k
    return p;
43
6.47k
}
44
45
void
46
FcValueDestroy (FcValue v)
47
210k
{
48
210k
    switch ((int)v.type) {
49
80.9k
    case FcTypeString:
50
80.9k
  FcFree (v.u.s);
51
80.9k
  break;
52
0
    case FcTypeMatrix:
53
0
  FcMatrixFree ((FcMatrix *)v.u.m);
54
0
  break;
55
5.78k
    case FcTypeCharSet:
56
5.78k
  FcCharSetDestroy ((FcCharSet *)v.u.c);
57
5.78k
  break;
58
5.78k
    case FcTypeLangSet:
59
5.78k
  FcLangSetDestroy ((FcLangSet *)v.u.l);
60
5.78k
  break;
61
0
    case FcTypeRange:
62
0
  FcRangeDestroy ((FcRange *)v.u.r);
63
0
  break;
64
117k
    default:
65
117k
  break;
66
210k
    }
67
210k
}
68
69
FcValue
70
FcValueCanonicalize (const FcValue *v)
71
311k
{
72
311k
    FcValue newp;
73
74
311k
    switch ((int)v->type) {
75
99.2k
    case FcTypeString:
76
99.2k
  newp.u.s = FcValueString (v);
77
99.2k
  newp.type = FcTypeString;
78
99.2k
  break;
79
5.79k
    case FcTypeCharSet:
80
5.79k
  newp.u.c = FcValueCharSet (v);
81
5.79k
  newp.type = FcTypeCharSet;
82
5.79k
  break;
83
13.6k
    case FcTypeLangSet:
84
13.6k
  newp.u.l = FcValueLangSet (v);
85
13.6k
  newp.type = FcTypeLangSet;
86
13.6k
  break;
87
0
    case FcTypeRange:
88
0
  newp.u.r = FcValueRange (v);
89
0
  newp.type = FcTypeRange;
90
0
  break;
91
192k
    default:
92
192k
  newp = *v;
93
192k
  break;
94
311k
    }
95
311k
    return newp;
96
311k
}
97
98
FcValue
99
FcValueSave (FcValue v)
100
210k
{
101
210k
    switch ((int)v.type) {
102
81.2k
    case FcTypeString:
103
81.2k
  v.u.s = FcStrdup (v.u.s);
104
81.2k
  if (!v.u.s)
105
0
      v.type = FcTypeVoid;
106
81.2k
  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
5.80k
    case FcTypeCharSet:
113
5.80k
  v.u.c = FcCharSetCopy ((FcCharSet *)v.u.c);
114
5.80k
  if (!v.u.c)
115
0
      v.type = FcTypeVoid;
116
5.80k
  break;
117
5.80k
    case FcTypeLangSet:
118
5.80k
  v.u.l = FcLangSetCopy (v.u.l);
119
5.80k
  if (!v.u.l)
120
0
      v.type = FcTypeVoid;
121
5.80k
  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
118k
    default:
128
118k
  break;
129
210k
    }
130
210k
    return v;
131
210k
}
132
133
FcValueListPtr
134
FcValueListCreate (void)
135
210k
{
136
210k
    return calloc (1, sizeof (FcValueList));
137
210k
}
138
139
void
140
FcValueListDestroy (FcValueListPtr l)
141
208k
{
142
208k
    FcValueListPtr next;
143
418k
    for (; l; l = next) {
144
210k
  FcValueDestroy (l->value);
145
210k
  next = FcValueListNext (l);
146
210k
  free (l);
147
210k
    }
148
208k
}
149
150
FcValueListPtr
151
FcValueListPrepend (FcValueListPtr vallist,
152
                    FcValue        value,
153
                    FcValueBinding binding)
154
3.92k
{
155
3.92k
    FcValueListPtr newp;
156
157
3.92k
    if (value.type == FcTypeVoid)
158
0
  return vallist;
159
3.92k
    newp = FcValueListCreate();
160
3.92k
    if (!newp)
161
0
  return vallist;
162
163
3.92k
    newp->value = FcValueSave (value);
164
3.92k
    newp->binding = binding;
165
3.92k
    newp->next = vallist;
166
167
3.92k
    return newp;
168
3.92k
}
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
20.9k
{
201
20.9k
    FcValueListPtr newp = NULL, l, t = NULL;
202
20.9k
    FcValue        v;
203
204
41.8k
    for (l = orig; l != NULL; l = FcValueListNext (l)) {
205
20.9k
  if (!newp) {
206
20.9k
      t = newp = FcValueListCreate();
207
20.9k
  } else {
208
0
      t->next = FcValueListCreate();
209
0
      t = FcValueListNext (t);
210
0
  }
211
20.9k
  v = FcValueCanonicalize (&l->value);
212
20.9k
  t->value = FcValueSave (v);
213
20.9k
  t->binding = l->binding;
214
20.9k
  t->next = NULL;
215
20.9k
    }
216
217
20.9k
    return newp;
218
20.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
7.85k
{
412
7.85k
    int           i;
413
7.85k
    FcPatternElt *elts;
414
415
7.85k
    if (!p)
416
0
  return;
417
418
7.85k
    if (FcRefIsConst (&p->ref)) {
419
1.40k
  FcCacheObjectDereference (FcPatternGetCacheObject (p));
420
1.40k
  return;
421
1.40k
    }
422
423
6.45k
    if (FcRefDec (&p->ref) != 1)
424
0
  return;
425
426
6.45k
    elts = FcPatternElts (p);
427
189k
    for (i = 0; i < FcPatternObjectCount (p); i++)
428
183k
  FcValueListDestroy (FcPatternEltValues (&elts[i]));
429
430
6.45k
    free (elts);
431
6.45k
    free (p);
432
6.45k
}
433
434
int
435
FcPatternObjectCount (const FcPattern *pat)
436
1.50M
{
437
1.50M
    if (pat)
438
1.50M
  return pat->num;
439
440
0
    return 0;
441
1.50M
}
442
443
static int
444
FcPatternObjectPosition (const FcPattern *p, FcObject object)
445
359k
{
446
359k
    int           low, high, mid, c;
447
359k
    FcPatternElt *elts = FcPatternElts (p);
448
449
359k
    low = 0;
450
359k
    high = FcPatternObjectCount (p) - 1;
451
359k
    c = 1;
452
359k
    mid = 0;
453
1.75M
    while (low <= high) {
454
1.50M
  mid = (low + high) >> 1;
455
1.50M
  c = elts[mid].object - object;
456
1.50M
  if (c == 0)
457
108k
      return mid;
458
1.39M
  if (c < 0)
459
1.10M
      low = mid + 1;
460
293k
  else
461
293k
      high = mid - 1;
462
1.39M
    }
463
250k
    if (c < 0)
464
206k
  mid++;
465
250k
    return -(mid + 1);
466
359k
}
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
136k
{
477
136k
    int i = FcPatternObjectPosition (p, object);
478
136k
    if (i < 0)
479
31.9k
  return 0;
480
104k
    return &FcPatternElts (p)[i];
481
136k
}
482
483
FcPatternElt *
484
FcPatternObjectInsertElt (FcPattern *p, FcObject object)
485
210k
{
486
210k
    int           i;
487
210k
    FcPatternElt *e;
488
489
210k
    i = FcPatternObjectPosition (p, object);
490
210k
    if (i < 0) {
491
208k
  i = -i - 1;
492
493
  /* reallocate array */
494
208k
  if (FcPatternObjectCount (p) + 1 >= p->size) {
495
14.8k
      int s = p->size + 16;
496
14.8k
      if (p->size) {
497
8.35k
    FcPatternElt *e0 = FcPatternElts (p);
498
8.35k
    e = (FcPatternElt *)realloc (e0, s * sizeof (FcPatternElt));
499
8.35k
    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
8.35k
      } else
506
6.47k
    e = (FcPatternElt *)malloc (s * sizeof (FcPatternElt));
507
14.8k
      if (!e)
508
0
    return FcFalse;
509
14.8k
      p->elts_offset = FcPtrToOffset (p, e);
510
251k
      while (p->size < s) {
511
237k
    e[p->size].object = 0;
512
237k
    e[p->size].values = NULL;
513
237k
    p->size++;
514
237k
      }
515
14.8k
  }
516
517
208k
  e = FcPatternElts (p);
518
  /* move elts up */
519
208k
  memmove (e + i + 1,
520
208k
           e + i,
521
208k
           sizeof (FcPatternElt) *
522
208k
               (FcPatternObjectCount (p) - i));
523
524
  /* bump count */
525
208k
  p->num++;
526
527
208k
  e[i].object = object;
528
208k
  e[i].values = NULL;
529
208k
    }
530
531
210k
    return FcPatternElts (p) + i;
532
210k
}
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
39.2k
{
604
39.2k
    FcPatternElt  *e;
605
39.2k
    FcValueListPtr l, *prev;
606
607
39.2k
    if (FcRefIsConst (&p->ref))
608
0
  goto bail0;
609
610
    /*
611
     * Make sure the stored type is valid for built-in objects
612
     */
613
78.4k
    for (l = list; l != NULL; l = FcValueListNext (l)) {
614
39.2k
  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
39.2k
    }
622
623
39.2k
    e = FcPatternObjectInsertElt (p, object);
624
39.2k
    if (!e)
625
0
  goto bail0;
626
627
39.2k
    if (append) {
628
26.8k
  for (prev = &e->values; *prev; prev = &(*prev)->next)
629
0
      ;
630
26.8k
  *prev = list;
631
26.8k
    } else {
632
24.8k
  for (prev = &list; *prev; prev = &(*prev)->next)
633
12.4k
      ;
634
12.4k
  *prev = e->values;
635
12.4k
  e->values = list;
636
12.4k
    }
637
638
39.2k
    return FcTrue;
639
640
0
bail0:
641
0
    return FcFalse;
642
39.2k
}
643
644
FcBool
645
FcPatternObjectAddWithBinding (FcPattern     *p,
646
                               FcObject       object,
647
                               FcValue        value,
648
                               FcValueBinding binding,
649
                               FcBool         append)
650
171k
{
651
171k
    FcPatternElt  *e;
652
171k
    FcValueListPtr newp, *prev;
653
654
171k
    if (FcRefIsConst (&p->ref))
655
0
  goto bail0;
656
657
171k
    newp = FcValueListCreate();
658
171k
    if (!newp)
659
0
  goto bail0;
660
661
171k
    newp->value = FcValueSave (value);
662
171k
    newp->binding = binding;
663
171k
    newp->next = NULL;
664
665
171k
    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
171k
    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
171k
    e = FcPatternObjectInsertElt (p, object);
681
171k
    if (!e)
682
0
  goto bail1;
683
684
171k
    if (append) {
685
167k
  for (prev = &e->values; *prev; prev = &(*prev)->next)
686
1.96k
      ;
687
165k
  *prev = newp;
688
165k
    } else {
689
5.88k
  newp->next = e->values;
690
5.88k
  e->values = newp;
691
5.88k
    }
692
693
171k
    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
26.3k
{
704
26.3k
    return FcPatternObjectAddWithBinding (p, object,
705
26.3k
                                          value, FcValueBindingStrong, append);
706
26.3k
}
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
27.7k
{
725
27.7k
    FcPatternElt *e;
726
727
27.7k
    e = FcPatternObjectFindElt (p, object);
728
27.7k
    if (!e)
729
2.55k
  return FcFalse;
730
731
    /* destroy value */
732
25.1k
    FcValueListDestroy (e->values);
733
734
    /* shuffle existing ones down */
735
25.1k
    memmove (e, e + 1,
736
25.1k
             (FcPatternElts (p) + FcPatternObjectCount (p) - (e + 1)) *
737
25.1k
                 sizeof (FcPatternElt));
738
25.1k
    p->num--;
739
25.1k
    e = FcPatternElts (p) + FcPatternObjectCount (p);
740
25.1k
    e->object = 0;
741
25.1k
    e->values = NULL;
742
25.1k
    return FcTrue;
743
27.7k
}
744
745
FcBool
746
FcPatternDel (FcPattern *p, const char *object)
747
27.0k
{
748
27.0k
    return FcPatternObjectDel (p, FcObjectFromName (object));
749
27.0k
}
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
6.53k
{
777
6.53k
    FcValue v;
778
779
6.53k
    v.type = FcTypeInteger;
780
6.53k
    v.u.i = i;
781
6.53k
    return FcPatternObjectAdd (p, object, v, FcTrue);
782
6.53k
}
783
784
FcBool
785
FcPatternAddInteger (FcPattern *p, const char *object, int i)
786
4.51k
{
787
4.51k
    return FcPatternObjectAddInteger (p, FcObjectFromName (object), i);
788
4.51k
}
789
790
FcBool
791
FcPatternObjectAddDouble (FcPattern *p, FcObject object, double d)
792
1.33k
{
793
1.33k
    FcValue v;
794
795
1.33k
    v.type = FcTypeDouble;
796
1.33k
    v.u.d = d;
797
1.33k
    return FcPatternObjectAdd (p, object, v, FcTrue);
798
1.33k
}
799
800
FcBool
801
FcPatternAddDouble (FcPattern *p, const char *object, double d)
802
654
{
803
654
    return FcPatternObjectAddDouble (p, FcObjectFromName (object), d);
804
654
}
805
806
FcBool
807
FcPatternObjectAddString (FcPattern *p, FcObject object, const FcChar8 *s)
808
3.35k
{
809
3.35k
    FcValue v;
810
811
3.35k
    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
3.35k
    v.type = FcTypeString;
818
3.35k
    v.u.s = s;
819
3.35k
    return FcPatternObjectAdd (p, object, v, FcTrue);
820
3.35k
}
821
822
FcBool
823
FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
824
1.89k
{
825
1.89k
    return FcPatternObjectAddString (p, FcObjectFromName (object), s);
826
1.89k
}
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
7.27k
{
841
7.27k
    FcValue v;
842
843
7.27k
    v.type = FcTypeBool;
844
7.27k
    v.u.b = b;
845
7.27k
    return FcPatternObjectAdd (p, object, v, FcTrue);
846
7.27k
}
847
848
FcBool
849
FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
850
1.89k
{
851
1.89k
    return FcPatternObjectAddBool (p, FcObjectFromName (object), b);
852
1.89k
}
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
70.3k
{
915
70.3k
    FcPatternElt  *e;
916
70.3k
    FcValueListPtr l;
917
918
70.3k
    if (!p)
919
0
  return FcResultNoMatch;
920
70.3k
    e = FcPatternObjectFindElt (p, object);
921
70.3k
    if (!e)
922
11.7k
  return FcResultNoMatch;
923
61.2k
    for (l = FcPatternEltValues (e); l; l = FcValueListNext (l)) {
924
58.5k
  if (!id) {
925
55.8k
      *v = FcValueCanonicalize (&l->value);
926
55.8k
      if (b)
927
0
    *b = l->binding;
928
55.8k
      return FcResultMatch;
929
55.8k
  }
930
2.71k
  id--;
931
2.71k
    }
932
2.71k
    return FcResultNoId;
933
58.5k
}
934
935
FcResult
936
FcPatternObjectGet (const FcPattern *p, FcObject object, int id, FcValue *v)
937
66.9k
{
938
66.9k
    return FcPatternObjectGetWithBinding (p, object, id, v, NULL);
939
66.9k
}
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
3.42k
{
950
3.42k
    return FcPatternObjectGetWithBinding (p, FcObjectFromName (object), id, v, NULL);
951
3.42k
}
952
953
FcResult
954
FcPatternObjectGetInteger (const FcPattern *p, FcObject object, int id, int *i)
955
16.8k
{
956
16.8k
    FcValue  v;
957
16.8k
    FcResult r;
958
959
16.8k
    r = FcPatternObjectGet (p, object, id, &v);
960
16.8k
    if (r != FcResultMatch)
961
2.97k
  return r;
962
13.9k
    switch ((int)v.type) {
963
2.59k
    case FcTypeDouble:
964
2.59k
  *i = (int)v.u.d;
965
2.59k
  break;
966
11.3k
    case FcTypeInteger:
967
11.3k
  *i = v.u.i;
968
11.3k
  break;
969
0
    default:
970
0
  return FcResultTypeMismatch;
971
13.9k
    }
972
13.9k
    return FcResultMatch;
973
13.9k
}
974
975
FcResult
976
FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
977
16.8k
{
978
16.8k
    return FcPatternObjectGetInteger (p, FcObjectFromName (object), id, i);
979
16.8k
}
980
981
FcResult
982
FcPatternObjectGetDouble (const FcPattern *p, FcObject object, int id, double *d)
983
1.96k
{
984
1.96k
    FcValue  v;
985
1.96k
    FcResult r;
986
987
1.96k
    r = FcPatternObjectGet (p, object, id, &v);
988
1.96k
    if (r != FcResultMatch)
989
1.96k
  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
27.4k
{
1012
27.4k
    FcValue  v;
1013
27.4k
    FcResult r;
1014
1015
27.4k
    r = FcPatternObjectGet (p, object, id, &v);
1016
27.4k
    if (r != FcResultMatch)
1017
4.82k
  return r;
1018
22.6k
    if (v.type != FcTypeString)
1019
0
  return FcResultTypeMismatch;
1020
1021
22.6k
    *s = (FcChar8 *)v.u.s;
1022
22.6k
    return FcResultMatch;
1023
22.6k
}
1024
1025
FcResult
1026
FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 **s)
1027
26.0k
{
1028
26.0k
    return FcPatternObjectGetString (p, FcObjectFromName (object), id, s);
1029
26.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
17.3k
{
1049
17.3k
    FcValue  v;
1050
17.3k
    FcResult r;
1051
1052
17.3k
    r = FcPatternObjectGet (p, object, id, &v);
1053
17.3k
    if (r != FcResultMatch)
1054
0
  return r;
1055
17.3k
    if (v.type != FcTypeBool)
1056
0
  return FcResultTypeMismatch;
1057
17.3k
    *b = v.u.b;
1058
17.3k
    return FcResultMatch;
1059
17.3k
}
1060
1061
FcResult
1062
FcPatternGetBool (const FcPattern *p, const char *object, int id, FcBool *b)
1063
16.6k
{
1064
16.6k
    return FcPatternObjectGetBool (p, FcObjectFromName (object), id, b);
1065
16.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
2.11k
{
1091
2.11k
    FcValue  v;
1092
2.11k
    FcResult r;
1093
1094
2.11k
    r = FcPatternGet (p, object, id, &v);
1095
2.11k
    if (r != FcResultMatch)
1096
2.11k
  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
654
{
1127
654
    FcValue  v;
1128
654
    FcResult res;
1129
1130
654
    res = FcPatternObjectGet (p, object, id, &v);
1131
654
    if (res != FcResultMatch)
1132
654
  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
4.48k
{
1152
4.48k
    FcPattern     *newp;
1153
4.48k
    FcPatternIter  iter;
1154
4.48k
    FcValueListPtr l;
1155
1156
4.48k
    if (!orig)
1157
0
  return NULL;
1158
1159
4.48k
    newp = FcPatternCreate();
1160
4.48k
    if (!newp)
1161
0
  goto bail0;
1162
1163
4.48k
    FcPatternIterStart (orig, &iter);
1164
142k
    do {
1165
285k
  for (l = FcPatternIterGetValues (orig, &iter); l; l = FcValueListNext (l)) {
1166
142k
      if (!FcPatternObjectAddWithBinding (newp, FcPatternIterGetObjectId (orig, &iter),
1167
142k
                                          FcValueCanonicalize (&l->value),
1168
142k
                                          l->binding,
1169
142k
                                          FcTrue))
1170
0
    goto bail1;
1171
142k
  }
1172
142k
    } while (FcPatternIterNext (orig, &iter));
1173
1174
4.48k
    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.70k
{
1185
2.70k
    if (!FcRefIsConst (&p->ref))
1186
0
  FcRefInc (&p->ref);
1187
2.70k
    else
1188
2.70k
  FcCacheObjectReference (FcPatternGetCacheObject (p));
1189
2.70k
}
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
157k
{
1275
157k
    iter->elt = FcPatternObjectCount (pat) > 0 && iter->pos < FcPatternObjectCount (pat) ? &FcPatternElts (pat)[iter->pos] : NULL;
1276
157k
}
1277
1278
void
1279
FcPatternIterStart (const FcPattern *pat, FcPatternIter *iter)
1280
8.44k
{
1281
8.44k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1282
1283
8.44k
    priv->pos = 0;
1284
8.44k
    FcPatternIterSet (pat, priv);
1285
8.44k
}
1286
1287
FcBool
1288
FcPatternIterNext (const FcPattern *pat, FcPatternIter *iter)
1289
150k
{
1290
150k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1291
1292
150k
    priv->pos++;
1293
150k
    if (priv->pos >= FcPatternObjectCount (pat))
1294
4.48k
  return FcFalse;
1295
146k
    FcPatternIterSet (pat, priv);
1296
1297
146k
    return FcTrue;
1298
150k
}
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
12.5k
{
1321
12.5k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1322
12.5k
    int                   i = FcPatternObjectPosition (pat, object);
1323
1324
12.5k
    priv->elt = NULL;
1325
12.5k
    if (i < 0)
1326
9.84k
  return FcFalse;
1327
1328
2.65k
    priv->pos = i;
1329
2.65k
    FcPatternIterSet (pat, priv);
1330
1331
2.65k
    return FcTrue;
1332
12.5k
}
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
154k
{
1354
154k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1355
1356
154k
    if (priv && priv->elt)
1357
154k
  return priv->elt->object;
1358
1359
0
    return 0;
1360
154k
}
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
155k
{
1371
155k
    FcPatternPrivateIter *priv = (FcPatternPrivateIter *)iter;
1372
1373
155k
    if (priv && priv->elt)
1374
155k
  return FcPatternEltValues (priv->elt);
1375
1376
0
    return NULL;
1377
155k
}
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
654
{
1394
654
    FcValueListPtr l;
1395
1396
654
    for (l = FcPatternIterGetValues (pat, iter); l; l = FcValueListNext (l)) {
1397
654
  if (id == 0) {
1398
654
      *v = FcValueCanonicalize (&l->value);
1399
654
      if (b)
1400
0
    *b = l->binding;
1401
654
      return FcResultMatch;
1402
654
  }
1403
0
  id--;
1404
0
    }
1405
0
    return FcResultNoId;
1406
654
}
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__