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