Bug Summary

File:src/fcmatch.c
Location:line 598, column 6
Description:Passed-by-value struct argument contains uninitialized data (e.g., field: 'type')

Annotated Source Code

1/*
2 * fontconfig/src/fcmatch.c
3 *
4 * Copyright © 2000 Keith Packard
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of the author(s) not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. The authors make no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
15 *
16 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
23 */
24
25#include "fcint.h"
26
27static double
28FcCompareNumber (FcValue *value1, FcValue *value2)
29{
30 double v1, v2, v;
31
32 switch ((int) value1->type) {
33 case FcTypeInteger:
34 v1 = (double) value1->u.i;
35 break;
36 case FcTypeDouble:
37 v1 = value1->u.d;
38 break;
39 default:
40 return -1.0;
41 }
42 switch ((int) value2->type) {
43 case FcTypeInteger:
44 v2 = (double) value2->u.i;
45 break;
46 case FcTypeDouble:
47 v2 = value2->u.d;
48 break;
49 default:
50 return -1.0;
51 }
52 v = v2 - v1;
53 if (v < 0)
54 v = -v;
55 return v;
56}
57
58static double
59FcCompareString (FcValue *v1, FcValue *v2)
60{
61 return (double) FcStrCmpIgnoreCase (FcValueString(v1)(((((intptr_t) ((v1)->u.s)) & 1) != 0) ? ((FcChar8 *) (
(intptr_t) (v1) + ((((intptr_t) ((v1)->u.s)) & ~1)))) :
(v1)->u.s)
, FcValueString(v2)(((((intptr_t) ((v2)->u.s)) & 1) != 0) ? ((FcChar8 *) (
(intptr_t) (v2) + ((((intptr_t) ((v2)->u.s)) & ~1)))) :
(v2)->u.s)
) != 0;
62}
63
64static double
65FcCompareFamily (FcValue *v1, FcValue *v2)
66{
67 /* rely on the guarantee in FcPatternObjectAddWithBinding that
68 * families are always FcTypeString. */
69 const FcChar8* v1_string = FcValueString(v1)(((((intptr_t) ((v1)->u.s)) & 1) != 0) ? ((FcChar8 *) (
(intptr_t) (v1) + ((((intptr_t) ((v1)->u.s)) & ~1)))) :
(v1)->u.s)
;
70 const FcChar8* v2_string = FcValueString(v2)(((((intptr_t) ((v2)->u.s)) & 1) != 0) ? ((FcChar8 *) (
(intptr_t) (v2) + ((((intptr_t) ((v2)->u.s)) & ~1)))) :
(v2)->u.s)
;
71
72 if (FcToLower(*v1_string)(((0101 <= (*v1_string) && (*v1_string) <= 0132
)) ? (*v1_string) - 0101 + 0141 : (*v1_string))
!= FcToLower(*v2_string)(((0101 <= (*v2_string) && (*v2_string) <= 0132
)) ? (*v2_string) - 0101 + 0141 : (*v2_string))
&&
73 *v1_string != ' ' && *v2_string != ' ')
74 return 1.0;
75
76 return (double) FcStrCmpIgnoreBlanksAndCase (v1_string, v2_string) != 0;
77}
78
79static double
80FcComparePostScript (FcValue *v1, FcValue *v2)
81{
82 const FcChar8 *v1_string = FcValueString (v1)(((((intptr_t) ((v1)->u.s)) & 1) != 0) ? ((FcChar8 *) (
(intptr_t) (v1) + ((((intptr_t) ((v1)->u.s)) & ~1)))) :
(v1)->u.s)
;
83 const FcChar8 *v2_string = FcValueString (v2)(((((intptr_t) ((v2)->u.s)) & 1) != 0) ? ((FcChar8 *) (
(intptr_t) (v2) + ((((intptr_t) ((v2)->u.s)) & ~1)))) :
(v2)->u.s)
;
84 int n;
85 size_t len;
86
87 if (FcToLower (*v1_string)(((0101 <= (*v1_string) && (*v1_string) <= 0132
)) ? (*v1_string) - 0101 + 0141 : (*v1_string))
!= FcToLower (*v2_string)(((0101 <= (*v2_string) && (*v2_string) <= 0132
)) ? (*v2_string) - 0101 + 0141 : (*v2_string))
&&
88 *v1_string != ' ' && *v2_string != ' ')
89 return 1.0;
90
91 n = FcStrMatchIgnoreCaseAndDelims (v1_string, v2_string, (const FcChar8 *)" -");
92 len = strlen ((const char *)v1_string);
93
94 return (double)(len - n) / (double)len;
95}
96
97static double
98FcCompareLang (FcValue *v1, FcValue *v2)
99{
100 FcLangResult result;
101 FcValue value1 = FcValueCanonicalize(v1), value2 = FcValueCanonicalize(v2);
102
103 switch ((int) value1.type) {
104 case FcTypeLangSet:
105 switch ((int) value2.type) {
106 case FcTypeLangSet:
107 result = FcLangSetCompare (value1.u.l, value2.u.l);
108 break;
109 case FcTypeString:
110 result = FcLangSetHasLang (value1.u.l,
111 value2.u.s);
112 break;
113 default:
114 return -1.0;
115 }
116 break;
117 case FcTypeString:
118 switch ((int) value2.type) {
119 case FcTypeLangSet:
120 result = FcLangSetHasLang (value2.u.l, value1.u.s);
121 break;
122 case FcTypeString:
123 result = FcLangCompare (value1.u.s,
124 value2.u.s);
125 break;
126 default:
127 return -1.0;
128 }
129 break;
130 default:
131 return -1.0;
132 }
133 switch (result) {
134 case FcLangEqual:
135 return 0;
136 case FcLangDifferentCountry:
137 return 1;
138 case FcLangDifferentLang:
139 default:
140 return 2;
141 }
142}
143
144static double
145FcCompareBool (FcValue *v1, FcValue *v2)
146{
147 if (v2->type != FcTypeBool || v1->type != FcTypeBool)
148 return -1.0;
149 return (double) v2->u.b != v1->u.b;
150}
151
152static double
153FcCompareCharSet (FcValue *v1, FcValue *v2)
154{
155 return (double) FcCharSetSubtractCount (FcValueCharSet(v1)(((((intptr_t) ((v1)->u.c)) & 1) != 0) ? ((const FcCharSet
*) ((intptr_t) (v1) + ((((intptr_t) ((v1)->u.c)) & ~1
)))) : (v1)->u.c)
, FcValueCharSet(v2)(((((intptr_t) ((v2)->u.c)) & 1) != 0) ? ((const FcCharSet
*) ((intptr_t) (v2) + ((((intptr_t) ((v2)->u.c)) & ~1
)))) : (v2)->u.c)
);
156}
157
158static double
159FcCompareSize (FcValue *value1, FcValue *value2)
160{
161 double v1, v2, v;
162
163 switch ((int) value1->type) {
164 case FcTypeInteger:
165 v1 = value1->u.i;
166 break;
167 case FcTypeDouble:
168 v1 = value1->u.d;
169 break;
170 default:
171 return -1;
172 }
173 switch ((int) value2->type) {
174 case FcTypeInteger:
175 v2 = value2->u.i;
176 break;
177 case FcTypeDouble:
178 v2 = value2->u.d;
179 break;
180 default:
181 return -1;
182 }
183 if (v2 == 0)
184 return 0;
185 v = v2 - v1;
186 if (v < 0)
187 v = -v;
188 return v;
189}
190
191static double
192FcCompareSizeRange (FcValue *v1, FcValue *v2)
193{
194 FcValue value1 = FcValueCanonicalize (v1);
195 FcValue value2 = FcValueCanonicalize (v2);
196 FcRange *r1 = NULL((void*)0), *r2 = NULL((void*)0);
197 double ret = -1.0;
198
199 switch ((int) value1.type) {
200 case FcTypeDouble:
201 r1 = FcRangeCreateDouble (value1.u.d, value1.u.d);
202 break;
203 case FcTypeRange:
204 r1 = FcRangeCopy (value1.u.r);
205 break;
206 default:
207 goto bail;
208 }
209 switch ((int) value2.type) {
210 case FcTypeDouble:
211 r2 = FcRangeCreateDouble (value2.u.d, value2.u.d);
212 break;
213 case FcTypeRange:
214 r2 = FcRangeCopy (value2.u.r);
215 break;
216 default:
217 goto bail;
218 }
219
220 if (FcRangeIsInRange (r1, r2))
221 ret = 0.0;
222 else
223 ret = FC_MIN (fabs (r1->end - r2->begin), fabs (r1->begin - r2->end))((fabs (r1->end - r2->begin)) < (fabs (r1->begin -
r2->end)) ? (fabs (r1->end - r2->begin)) : (fabs (r1
->begin - r2->end)))
;
224
225bail:
226 if (r1)
227 FcRangeDestroy (r1);
228 if (r2)
229 FcRangeDestroy (r2);
230
231 return ret;
232}
233
234static double
235FcCompareFilename (FcValue *v1, FcValue *v2)
236{
237 const FcChar8 *s1 = FcValueString (v1)(((((intptr_t) ((v1)->u.s)) & 1) != 0) ? ((FcChar8 *) (
(intptr_t) (v1) + ((((intptr_t) ((v1)->u.s)) & ~1)))) :
(v1)->u.s)
, *s2 = FcValueString (v2)(((((intptr_t) ((v2)->u.s)) & 1) != 0) ? ((FcChar8 *) (
(intptr_t) (v2) + ((((intptr_t) ((v2)->u.s)) & ~1)))) :
(v2)->u.s)
;
238 if (FcStrCmp (s1, s2) == 0)
239 return 0.0;
240 else if (FcStrCmpIgnoreCase (s1, s2) == 0)
241 return 1.0;
242 else if (FcStrGlobMatch (s1, s2))
243 return 2.0;
244 else
245 return 3.0;
246}
247
248
249/* Define priorities to -1 for objects that don't have a compare function. */
250
251#define PRI_NULL(n)PRI_n_STRONG = -1, PRI_n_WEAK = -1, \
252 PRI_ ## n ## _STRONG = -1, \
253 PRI_ ## n ## _WEAK = -1,
254#define PRI1(n)
255#define PRI_FcCompareFamily(n)PRI1(n) PRI1(n)
256#define PRI_FcCompareString(n)PRI1(n) PRI1(n)
257#define PRI_FcCompareNumber(n)PRI1(n) PRI1(n)
258#define PRI_FcCompareSize(n)PRI1(n) PRI1(n)
259#define PRI_FcCompareBool(n)PRI1(n) PRI1(n)
260#define PRI_FcCompareFilename(n)PRI1(n) PRI1(n)
261#define PRI_FcCompareCharSet(n)PRI1(n) PRI1(n)
262#define PRI_FcCompareLang(n)PRI1(n) PRI1(n)
263#define PRI_FcComparePostScript(n)PRI1(n) PRI1(n)
264#define PRI_FcCompareSizeRange(n)PRI1(n) PRI1(n)
265
266#define FC_OBJECT(NAME, Type, Cmp) PRI_##Cmp(NAME)
267
268typedef enum _FcMatcherPriorityDummy {
269#include "fcobjs.h"
270} FcMatcherPriorityDummy;
271
272#undef FC_OBJECT
273
274
275/* Canonical match priority order. */
276
277#undef PRI1
278#define PRI1(n) \
279 PRI_ ## n, \
280 PRI_ ## n ## _STRONG = PRI_ ## n, \
281 PRI_ ## n ## _WEAK = PRI_ ## n
282
283typedef enum _FcMatcherPriority {
284 PRI1(FILE),
285 PRI1(FONTFORMAT),
286 PRI1(SCALABLE),
287 PRI1(COLOR),
288 PRI1(FOUNDRY),
289 PRI1(CHARSET),
290 PRI_FAMILY_STRONG,
291 PRI_POSTSCRIPT_NAME_STRONG,
292 PRI1(LANG),
293 PRI_FAMILY_WEAK,
294 PRI_POSTSCRIPT_NAME_WEAK,
295 PRI1(SYMBOL),
296 PRI1(SPACING),
297 PRI1(SIZE),
298 PRI1(PIXEL_SIZE),
299 PRI1(STYLE),
300 PRI1(SLANT),
301 PRI1(WEIGHT),
302 PRI1(WIDTH),
303 PRI1(DECORATIVE),
304 PRI1(ANTIALIAS),
305 PRI1(RASTERIZER),
306 PRI1(OUTLINE),
307 PRI1(FONTVERSION),
308 PRI_END
309} FcMatcherPriority;
310
311#undef PRI1
312
313typedef struct _FcMatcher {
314 FcObject object;
315 double (*compare) (FcValue *value1, FcValue *value2);
316 int strong, weak;
317} FcMatcher;
318
319/*
320 * Order is significant, it defines the precedence of
321 * each value, earlier values are more significant than
322 * later values
323 */
324#define FC_OBJECT(NAME, Type, Cmp) { FC_##NAME##_OBJECT, Cmp, PRI_##NAME##_STRONG, PRI_##NAME##_WEAK },
325static const FcMatcher _FcMatchers [] = {
326 { FC_INVALID_OBJECT, NULL((void*)0), -1, -1 },
327#include "fcobjs.h"
328};
329#undef FC_OBJECT
330
331static const FcMatcher*
332FcObjectToMatcher (FcObject object,
333 FcBool include_lang)
334{
335 if (include_lang)
336 {
337 switch (object) {
338 case FC_FAMILYLANG_OBJECT:
339 case FC_STYLELANG_OBJECT:
340 case FC_FULLNAMELANG_OBJECT:
341 object = FC_LANG_OBJECT;
342 break;
343 }
344 }
345 if (object > FC_MAX_BASE_OBJECT(FC_ONE_AFTER_MAX_BASE_OBJECT - 1) ||
346 !_FcMatchers[object].compare ||
347 _FcMatchers[object].strong == -1 ||
348 _FcMatchers[object].weak == -1)
349 return NULL((void*)0);
350
351 return _FcMatchers + object;
352}
353
354static FcBool
355FcCompareValueList (FcObject object,
356 const FcMatcher *match,
357 FcValueListPtr v1orig, /* pattern */
358 FcValueListPtr v2orig, /* target */
359 FcValue *bestValue,
360 double *value,
361 int *n,
362 FcResult *result)
363{
364 FcValueListPtr v1, v2;
365 double v, best, bestStrong, bestWeak;
366 int j, k, pos = 0;
367
368 if (!match)
369 {
370 if (bestValue)
371 *bestValue = FcValueCanonicalize(&v2orig->value);
372 if (n)
373 *n = 0;
374 return FcTrue1;
375 }
376
377 best = 1e99;
378 bestStrong = 1e99;
379 bestWeak = 1e99;
380 j = 0;
381 for (v1 = v1orig; v1; v1 = FcValueListNext(v1)(((((intptr_t) ((v1)->next)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (v1) + ((((intptr_t) ((v1)->next)) & ~
1)))) : (v1)->next)
)
382 {
383 for (v2 = v2orig, k = 0; v2; v2 = FcValueListNext(v2)(((((intptr_t) ((v2)->next)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (v2) + ((((intptr_t) ((v2)->next)) & ~
1)))) : (v2)->next)
, k++)
384 {
385 v = (match->compare) (&v1->value, &v2->value);
386 if (v < 0)
387 {
388 *result = FcResultTypeMismatch;
389 return FcFalse0;
390 }
391 v = v * 1000 + j;
392 if (v < best)
393 {
394 if (bestValue)
395 *bestValue = FcValueCanonicalize(&v2->value);
396 best = v;
397 pos = k;
398 }
399 if (v1->binding == FcValueBindingStrong)
400 {
401 if (v < bestStrong)
402 bestStrong = v;
403 }
404 else
405 {
406 if (v < bestWeak)
407 bestWeak = v;
408 }
409 }
410 j++;
411 }
412 if (FcDebug ()(FcDebugVal) & FC_DBG_MATCHV2)
413 {
414 printf (" %s: %g ", FcObjectName (object), best);
415 FcValueListPrint (v1orig);
416 printf (", ");
417 FcValueListPrint (v2orig);
418 printf ("\n");
419 }
420 if (value)
421 {
422 int weak = match->weak;
423 int strong = match->strong;
424 if (weak == strong)
425 value[strong] += best;
426 else
427 {
428 value[weak] += bestWeak;
429 value[strong] += bestStrong;
430 }
431 }
432 if (n)
433 *n = pos;
434
435 return FcTrue1;
436}
437
438/*
439 * Return a value indicating the distance between the two lists of
440 * values
441 */
442
443static FcBool
444FcCompare (FcPattern *pat,
445 FcPattern *fnt,
446 double *value,
447 FcResult *result)
448{
449 int i, i1, i2;
450
451 for (i = 0; i < PRI_END; i++)
452 value[i] = 0.0;
453
454 i1 = 0;
455 i2 = 0;
456 while (i1 < pat->num && i2 < fnt->num)
457 {
458 FcPatternElt *elt_i1 = &FcPatternElts(pat)((FcPatternElt *) ((intptr_t) (pat) + ((pat)->elts_offset)
))
[i1];
459 FcPatternElt *elt_i2 = &FcPatternElts(fnt)((FcPatternElt *) ((intptr_t) (fnt) + ((fnt)->elts_offset)
))
[i2];
460
461 i = FcObjectCompare(elt_i1->object, elt_i2->object)((int) elt_i1->object - (int) elt_i2->object);
462 if (i > 0)
463 i2++;
464 else if (i < 0)
465 i1++;
466 else
467 {
468 const FcMatcher *match = FcObjectToMatcher (elt_i1->object, FcFalse0);
469 if (!FcCompareValueList (elt_i1->object, match,
470 FcPatternEltValues(elt_i1)(((((intptr_t) ((elt_i1)->values)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (elt_i1) + ((((intptr_t) ((elt_i1)->values
)) & ~1)))) : (elt_i1)->values)
,
471 FcPatternEltValues(elt_i2)(((((intptr_t) ((elt_i2)->values)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (elt_i2) + ((((intptr_t) ((elt_i2)->values
)) & ~1)))) : (elt_i2)->values)
,
472 NULL((void*)0), value, NULL((void*)0), result))
473 return FcFalse0;
474 i1++;
475 i2++;
476 }
477 }
478 return FcTrue1;
479}
480
481FcPattern *
482FcFontRenderPrepare (FcConfig *config,
483 FcPattern *pat,
484 FcPattern *font)
485{
486 FcPattern *new;
487 int i;
488 FcPatternElt *fe, *pe;
489 FcValue v;
490 FcResult result;
491
492 assert (pat != NULL)(__builtin_expect(!(pat != ((void*)0)), 0) ? __assert_rtn(__func__
, "fcmatch.c", 492, "pat != NULL") : (void)0)
;
493 assert (font != NULL)(__builtin_expect(!(font != ((void*)0)), 0) ? __assert_rtn(__func__
, "fcmatch.c", 493, "font != NULL") : (void)0)
;
494
495 new = FcPatternCreate ();
496 if (!new)
1
Assuming 'new' is non-null
2
Taking false branch
497 return NULL((void*)0);
498 for (i = 0; i < font->num; i++)
3
Loop condition is true. Entering loop body
8
Loop condition is true. Entering loop body
13
Loop condition is true. Entering loop body
18
Loop condition is true. Entering loop body
499 {
500 fe = &FcPatternElts(font)((FcPatternElt *) ((intptr_t) (font) + ((font)->elts_offset
)))
[i];
501 if (fe->object == FC_FAMILYLANG_OBJECT ||
4
Taking false branch
9
Taking false branch
14
Taking false branch
19
Taking false branch
502 fe->object == FC_STYLELANG_OBJECT ||
503 fe->object == FC_FULLNAMELANG_OBJECT)
504 {
505 /* ignore those objects. we need to deal with them
506 * another way */
507 continue;
508 }
509 if (fe->object == FC_FAMILY_OBJECT ||
5
Taking false branch
10
Taking false branch
15
Taking false branch
20
Taking false branch
510 fe->object == FC_STYLE_OBJECT ||
511 fe->object == FC_FULLNAME_OBJECT)
512 {
513 FcPatternElt *fel, *pel;
514
515 FC_ASSERT_STATIC ((FC_FAMILY_OBJECT + 1) == FC_FAMILYLANG_OBJECT)typedef int _static_assert_on_line_515_failed[((((FC_FAMILY_OBJECT
+ 1) == FC_FAMILYLANG_OBJECT)))?1:-1] __attribute__((unused)
)
;
516 FC_ASSERT_STATIC ((FC_STYLE_OBJECT + 1) == FC_STYLELANG_OBJECT)typedef int _static_assert_on_line_516_failed[((((FC_STYLE_OBJECT
+ 1) == FC_STYLELANG_OBJECT)))?1:-1] __attribute__((unused))
;
517 FC_ASSERT_STATIC ((FC_FULLNAME_OBJECT + 1) == FC_FULLNAMELANG_OBJECT)typedef int _static_assert_on_line_517_failed[((((FC_FULLNAME_OBJECT
+ 1) == FC_FULLNAMELANG_OBJECT)))?1:-1] __attribute__((unused
))
;
518
519 fel = FcPatternObjectFindElt (font, fe->object + 1);
520 pel = FcPatternObjectFindElt (pat, fe->object + 1);
521
522 if (fel && pel)
523 {
524 /* The font has name languages, and pattern asks for specific language(s).
525 * Match on language and and prefer that result.
526 * Note: Currently the code only give priority to first matching language.
527 */
528 int n = 1, j;
529 FcValueListPtr l1, l2, ln = NULL((void*)0), ll = NULL((void*)0);
530 const FcMatcher *match = FcObjectToMatcher (pel->object, FcTrue1);
531
532 if (!FcCompareValueList (pel->object, match,
533 FcPatternEltValues (pel)(((((intptr_t) ((pel)->values)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (pel) + ((((intptr_t) ((pel)->values)) &
~1)))) : (pel)->values)
,
534 FcPatternEltValues (fel)(((((intptr_t) ((fel)->values)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (fel) + ((((intptr_t) ((fel)->values)) &
~1)))) : (fel)->values)
, NULL((void*)0), NULL((void*)0), &n, &result))
535 {
536 FcPatternDestroy (new);
537 return NULL((void*)0);
538 }
539
540 for (j = 0, l1 = FcPatternEltValues (fe)(((((intptr_t) ((fe)->values)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (fe) + ((((intptr_t) ((fe)->values)) &
~1)))) : (fe)->values)
, l2 = FcPatternEltValues (fel)(((((intptr_t) ((fel)->values)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (fel) + ((((intptr_t) ((fel)->values)) &
~1)))) : (fel)->values)
;
541 l1 != NULL((void*)0) || l2 != NULL((void*)0);
542 j++, l1 = l1 ? FcValueListNext (l1)(((((intptr_t) ((l1)->next)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (l1) + ((((intptr_t) ((l1)->next)) & ~
1)))) : (l1)->next)
: NULL((void*)0), l2 = l2 ? FcValueListNext (l2)(((((intptr_t) ((l2)->next)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (l2) + ((((intptr_t) ((l2)->next)) & ~
1)))) : (l2)->next)
: NULL((void*)0))
543 {
544 if (j == n)
545 {
546 if (l1)
547 ln = FcValueListPrepend (ln,
548 FcValueCanonicalize (&l1->value),
549 FcValueBindingStrong);
550 if (l2)
551 ll = FcValueListPrepend (ll,
552 FcValueCanonicalize (&l2->value),
553 FcValueBindingStrong);
554 }
555 else
556 {
557 if (l1)
558 ln = FcValueListAppend (ln,
559 FcValueCanonicalize (&l1->value),
560 FcValueBindingStrong);
561 if (l2)
562 ll = FcValueListAppend (ll,
563 FcValueCanonicalize (&l2->value),
564 FcValueBindingStrong);
565 }
566 }
567 FcPatternObjectListAdd (new, fe->object, ln, FcFalse0);
568 FcPatternObjectListAdd (new, fel->object, ll, FcFalse0);
569
570 continue;
571 }
572 else if (fel)
573 {
574 /* Pattern doesn't ask for specific language. Copy all for name and
575 * lang. */
576 FcValueListPtr l1, l2;
577
578 l1 = FcValueListDuplicate (FcPatternEltValues (fe)(((((intptr_t) ((fe)->values)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (fe) + ((((intptr_t) ((fe)->values)) &
~1)))) : (fe)->values)
);
579 l2 = FcValueListDuplicate (FcPatternEltValues (fel)(((((intptr_t) ((fel)->values)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (fel) + ((((intptr_t) ((fel)->values)) &
~1)))) : (fel)->values)
);
580 FcPatternObjectListAdd (new, fe->object, l1, FcFalse0);
581 FcPatternObjectListAdd (new, fel->object, l2, FcFalse0);
582
583 continue;
584 }
585 }
586
587 pe = FcPatternObjectFindElt (pat, fe->object);
588 if (pe)
6
Assuming 'pe' is null
7
Taking false branch
11
Assuming 'pe' is null
12
Taking false branch
16
Assuming 'pe' is null
17
Taking false branch
21
Assuming 'pe' is non-null
22
Taking true branch
589 {
590 const FcMatcher *match = FcObjectToMatcher (pe->object, FcFalse0);
591 if (!FcCompareValueList (pe->object, match,
23
Taking false branch
592 FcPatternEltValues(pe)(((((intptr_t) ((pe)->values)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (pe) + ((((intptr_t) ((pe)->values)) &
~1)))) : (pe)->values)
,
593 FcPatternEltValues(fe)(((((intptr_t) ((fe)->values)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (fe) + ((((intptr_t) ((fe)->values)) &
~1)))) : (fe)->values)
, &v, NULL((void*)0), NULL((void*)0), &result))
594 {
595 FcPatternDestroy (new);
596 return NULL((void*)0);
597 }
598 FcPatternObjectAdd (new, fe->object, v, FcFalse0);
24
Passed-by-value struct argument contains uninitialized data (e.g., field: 'type')
599 }
600 else
601 {
602 FcPatternObjectListAdd (new, fe->object,
603 FcValueListDuplicate (FcPatternEltValues (fe)(((((intptr_t) ((fe)->values)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (fe) + ((((intptr_t) ((fe)->values)) &
~1)))) : (fe)->values)
),
604 FcTrue1);
605 }
606 }
607 for (i = 0; i < pat->num; i++)
608 {
609 pe = &FcPatternElts(pat)((FcPatternElt *) ((intptr_t) (pat) + ((pat)->elts_offset)
))
[i];
610 fe = FcPatternObjectFindElt (font, pe->object);
611 if (!fe &&
612 pe->object != FC_FAMILYLANG_OBJECT &&
613 pe->object != FC_STYLELANG_OBJECT &&
614 pe->object != FC_FULLNAMELANG_OBJECT)
615 {
616 FcPatternObjectListAdd (new, pe->object,
617 FcValueListDuplicate (FcPatternEltValues(pe)(((((intptr_t) ((pe)->values)) & 1) != 0) ? ((FcValueList
*) ((intptr_t) (pe) + ((((intptr_t) ((pe)->values)) &
~1)))) : (pe)->values)
),
618 FcFalse0);
619 }
620 }
621
622 FcConfigSubstituteWithPat (config, new, pat, FcMatchFont);
623 return new;
624}
625
626static FcPattern *
627FcFontSetMatchInternal (FcFontSet **sets,
628 int nsets,
629 FcPattern *p,
630 FcResult *result)
631{
632 double score[PRI_END], bestscore[PRI_END];
633 int f;
634 FcFontSet *s;
635 FcPattern *best;
636 int i;
637 int set;
638
639 for (i = 0; i < PRI_END; i++)
640 bestscore[i] = 0;
641 best = 0;
642 if (FcDebug ()(FcDebugVal) & FC_DBG_MATCH1)
643 {
644 printf ("Match ");
645 FcPatternPrint (p);
646 }
647 for (set = 0; set < nsets; set++)
648 {
649 s = sets[set];
650 if (!s)
651 continue;
652 for (f = 0; f < s->nfont; f++)
653 {
654 if (FcDebug ()(FcDebugVal) & FC_DBG_MATCHV2)
655 {
656 printf ("Font %d ", f);
657 FcPatternPrint (s->fonts[f]);
658 }
659 if (!FcCompare (p, s->fonts[f], score, result))
660 return 0;
661 if (FcDebug ()(FcDebugVal) & FC_DBG_MATCHV2)
662 {
663 printf ("Score");
664 for (i = 0; i < PRI_END; i++)
665 {
666 printf (" %g", score[i]);
667 }
668 printf ("\n");
669 }
670 for (i = 0; i < PRI_END; i++)
671 {
672 if (best && bestscore[i] < score[i])
673 break;
674 if (!best || score[i] < bestscore[i])
675 {
676 for (i = 0; i < PRI_END; i++)
677 bestscore[i] = score[i];
678 best = s->fonts[f];
679 break;
680 }
681 }
682 }
683 }
684 if (FcDebug ()(FcDebugVal) & FC_DBG_MATCH1)
685 {
686 printf ("Best score");
687 for (i = 0; i < PRI_END; i++)
688 printf (" %g", bestscore[i]);
689 printf ("\n");
690 FcPatternPrint (best);
691 }
692 if (FcDebug ()(FcDebugVal) & FC_DBG_MATCH24096)
693 {
694 char *env = getenv ("FC_DBG_MATCH_FILTER");
695 FcObjectSet *os = NULL((void*)0);
696
697 if (env)
698 {
699 char *ss, *s;
700 char *p;
701 FcBool f = FcTrue1;
702
703 ss = s = strdup (env);
704 os = FcObjectSetCreate ();
705 while (f)
706 {
707 size_t len;
708 char *x;
709
710 if (!(p = strchr (s, ',')))
711 {
712 f = FcFalse0;
713 len = strlen (s) + 1;
714 }
715 else
716 {
717 len = (p - s) + 1;
718 }
719 x = malloc (sizeof (char) * len);
720 strncpy (x, s, len - 1)__builtin___strncpy_chk (x, s, len - 1, __builtin_object_size
(x, 2 > 1 ? 1 : 0))
;
721 x[len - 1] = 0;
722 if (FcObjectFromName (x) > 0)
723 FcObjectSetAdd (os, x);
724 s = p + 1;
725 free (x);
726 }
727 free (ss);
728 }
729 FcPatternPrint2 (p, best, os);
730 if (os)
731 FcObjectSetDestroy (os);
732 }
733 /* assuming that 'result' is initialized with FcResultNoMatch
734 * outside this function */
735 if (best)
736 *result = FcResultMatch;
737
738 return best;
739}
740
741FcPattern *
742FcFontSetMatch (FcConfig *config,
743 FcFontSet **sets,
744 int nsets,
745 FcPattern *p,
746 FcResult *result)
747{
748 FcPattern *best;
749
750 assert (sets != NULL)(__builtin_expect(!(sets != ((void*)0)), 0) ? __assert_rtn(__func__
, "fcmatch.c", 750, "sets != NULL") : (void)0)
;
751 assert (p != NULL)(__builtin_expect(!(p != ((void*)0)), 0) ? __assert_rtn(__func__
, "fcmatch.c", 751, "p != NULL") : (void)0)
;
752 assert (result != NULL)(__builtin_expect(!(result != ((void*)0)), 0) ? __assert_rtn(
__func__, "fcmatch.c", 752, "result != NULL") : (void)0)
;
753
754 *result = FcResultNoMatch;
755
756 if (!config)
757 {
758 config = FcConfigGetCurrent ();
759 if (!config)
760 return 0;
761 }
762 best = FcFontSetMatchInternal (sets, nsets, p, result);
763 if (best)
764 return FcFontRenderPrepare (config, p, best);
765 else
766 return NULL((void*)0);
767}
768
769FcPattern *
770FcFontMatch (FcConfig *config,
771 FcPattern *p,
772 FcResult *result)
773{
774 FcFontSet *sets[2];
775 int nsets;
776 FcPattern *best;
777
778 assert (p != NULL)(__builtin_expect(!(p != ((void*)0)), 0) ? __assert_rtn(__func__
, "fcmatch.c", 778, "p != NULL") : (void)0)
;
779 assert (result != NULL)(__builtin_expect(!(result != ((void*)0)), 0) ? __assert_rtn(
__func__, "fcmatch.c", 779, "result != NULL") : (void)0)
;
780
781 *result = FcResultNoMatch;
782
783 if (!config)
784 {
785 config = FcConfigGetCurrent ();
786 if (!config)
787 return 0;
788 }
789 nsets = 0;
790 if (config->fonts[FcSetSystem])
791 sets[nsets++] = config->fonts[FcSetSystem];
792 if (config->fonts[FcSetApplication])
793 sets[nsets++] = config->fonts[FcSetApplication];
794
795 best = FcFontSetMatchInternal (sets, nsets, p, result);
796 if (best)
797 return FcFontRenderPrepare (config, p, best);
798 else
799 return NULL((void*)0);
800}
801
802typedef struct _FcSortNode {
803 FcPattern *pattern;
804 double score[PRI_END];
805} FcSortNode;
806
807static int
808FcSortCompare (const void *aa, const void *ab)
809{
810 FcSortNode *a = *(FcSortNode **) aa;
811 FcSortNode *b = *(FcSortNode **) ab;
812 double *as = &a->score[0];
813 double *bs = &b->score[0];
814 double ad = 0, bd = 0;
815 int i;
816
817 i = PRI_END;
818 while (i-- && (ad = *as++) == (bd = *bs++))
819 ;
820 return ad < bd ? -1 : ad > bd ? 1 : 0;
821}
822
823static FcBool
824FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **csp, FcBool trim)
825{
826 FcBool ret = FcFalse0;
827 FcCharSet *cs;
828 int i;
829
830 cs = 0;
831 if (trim || csp)
832 {
833 cs = FcCharSetCreate ();
834 if (cs == NULL((void*)0))
835 goto bail;
836 }
837
838 for (i = 0; i < nnode; i++)
839 {
840 FcSortNode *node = *n++;
841 FcBool adds_chars = FcFalse0;
842
843 /*
844 * Only fetch node charset if we'd need it
845 */
846 if (cs)
847 {
848 FcCharSet *ncs;
849
850 if (FcPatternGetCharSet (node->pattern, FC_CHARSET"charset", 0, &ncs) !=
851 FcResultMatch)
852 continue;
853
854 if (!FcCharSetMerge (cs, ncs, &adds_chars))
855 goto bail;
856 }
857
858 /*
859 * If this font isn't a subset of the previous fonts,
860 * add it to the list
861 */
862 if (!i || !trim || adds_chars)
863 {
864 FcPatternReference (node->pattern);
865 if (FcDebug ()(FcDebugVal) & FC_DBG_MATCHV2)
866 {
867 printf ("Add ");
868 FcPatternPrint (node->pattern);
869 }
870 if (!FcFontSetAdd (fs, node->pattern))
871 {
872 FcPatternDestroy (node->pattern);
873 goto bail;
874 }
875 }
876 }
877 if (csp)
878 {
879 *csp = cs;
880 cs = 0;
881 }
882
883 ret = FcTrue1;
884
885bail:
886 if (cs)
887 FcCharSetDestroy (cs);
888
889 return ret;
890}
891
892void
893FcFontSetSortDestroy (FcFontSet *fs)
894{
895 FcFontSetDestroy (fs);
896}
897
898FcFontSet *
899FcFontSetSort (FcConfig *config FC_UNUSED__attribute__((unused)),
900 FcFontSet **sets,
901 int nsets,
902 FcPattern *p,
903 FcBool trim,
904 FcCharSet **csp,
905 FcResult *result)
906{
907 FcFontSet *ret;
908 FcFontSet *s;
909 FcSortNode *nodes;
910 FcSortNode **nodeps, **nodep;
911 int nnodes;
912 FcSortNode *new;
913 int set;
914 int f;
915 int i;
916 int nPatternLang;
917 FcBool *patternLangSat;
918 FcValue patternLang;
919
920 assert (sets != NULL)(__builtin_expect(!(sets != ((void*)0)), 0) ? __assert_rtn(__func__
, "fcmatch.c", 920, "sets != NULL") : (void)0)
;
921 assert (p != NULL)(__builtin_expect(!(p != ((void*)0)), 0) ? __assert_rtn(__func__
, "fcmatch.c", 921, "p != NULL") : (void)0)
;
922 assert (result != NULL)(__builtin_expect(!(result != ((void*)0)), 0) ? __assert_rtn(
__func__, "fcmatch.c", 922, "result != NULL") : (void)0)
;
923
924 /* There are some implementation that relying on the result of
925 * "result" to check if the return value of FcFontSetSort
926 * is valid or not.
927 * So we should initialize it to the conservative way since
928 * this function doesn't return NULL anymore.
929 */
930 if (result)
931 *result = FcResultNoMatch;
932
933 if (FcDebug ()(FcDebugVal) & FC_DBG_MATCH1)
934 {
935 printf ("Sort ");
936 FcPatternPrint (p);
937 }
938 nnodes = 0;
939 for (set = 0; set < nsets; set++)
940 {
941 s = sets[set];
942 if (!s)
943 continue;
944 nnodes += s->nfont;
945 }
946 if (!nnodes)
947 return FcFontSetCreate ();
948
949 for (nPatternLang = 0;
950 FcPatternGet (p, FC_LANG"lang", nPatternLang, &patternLang) == FcResultMatch;
951 nPatternLang++)
952 ;
953
954 /* freed below */
955 nodes = malloc (nnodes * sizeof (FcSortNode) +
956 nnodes * sizeof (FcSortNode *) +
957 nPatternLang * sizeof (FcBool));
958 if (!nodes)
959 goto bail0;
960 nodeps = (FcSortNode **) (nodes + nnodes);
961 patternLangSat = (FcBool *) (nodeps + nnodes);
962
963 new = nodes;
964 nodep = nodeps;
965 for (set = 0; set < nsets; set++)
966 {
967 s = sets[set];
968 if (!s)
969 continue;
970 for (f = 0; f < s->nfont; f++)
971 {
972 if (FcDebug ()(FcDebugVal) & FC_DBG_MATCHV2)
973 {
974 printf ("Font %d ", f);
975 FcPatternPrint (s->fonts[f]);
976 }
977 new->pattern = s->fonts[f];
978 if (!FcCompare (p, new->pattern, new->score, result))
979 goto bail1;
980 if (FcDebug ()(FcDebugVal) & FC_DBG_MATCHV2)
981 {
982 printf ("Score");
983 for (i = 0; i < PRI_END; i++)
984 {
985 printf (" %g", new->score[i]);
986 }
987 printf ("\n");
988 }
989 *nodep = new;
990 new++;
991 nodep++;
992 }
993 }
994
995 nnodes = new - nodes;
996
997 qsort (nodeps, nnodes, sizeof (FcSortNode *),
998 FcSortCompare);
999
1000 for (i = 0; i < nPatternLang; i++)
1001 patternLangSat[i] = FcFalse0;
1002
1003 for (f = 0; f < nnodes; f++)
1004 {
1005 FcBool satisfies = FcFalse0;
1006 /*
1007 * If this node matches any language, go check
1008 * which ones and satisfy those entries
1009 */
1010 if (nodeps[f]->score[PRI_LANG] < 2000)
1011 {
1012 for (i = 0; i < nPatternLang; i++)
1013 {
1014 FcValue nodeLang;
1015
1016 if (!patternLangSat[i] &&
1017 FcPatternGet (p, FC_LANG"lang", i, &patternLang) == FcResultMatch &&
1018 FcPatternGet (nodeps[f]->pattern, FC_LANG"lang", 0, &nodeLang) == FcResultMatch)
1019 {
1020 double compare = FcCompareLang (&patternLang, &nodeLang);
1021 if (compare >= 0 && compare < 2)
1022 {
1023 if (FcDebug ()(FcDebugVal) & FC_DBG_MATCHV2)
1024 {
1025 FcChar8 *family;
1026 FcChar8 *style;
1027
1028 if (FcPatternGetString (nodeps[f]->pattern, FC_FAMILY"family", 0, &family) == FcResultMatch &&
1029 FcPatternGetString (nodeps[f]->pattern, FC_STYLE"style", 0, &style) == FcResultMatch)
1030 printf ("Font %s:%s matches language %d\n", family, style, i);
1031 }
1032 patternLangSat[i] = FcTrue1;
1033 satisfies = FcTrue1;
1034 break;
1035 }
1036 }
1037 }
1038 }
1039 if (!satisfies)
1040 {
1041 nodeps[f]->score[PRI_LANG] = 10000.0;
1042 }
1043 }
1044
1045 /*
1046 * Re-sort once the language issues have been settled
1047 */
1048 qsort (nodeps, nnodes, sizeof (FcSortNode *),
1049 FcSortCompare);
1050
1051 ret = FcFontSetCreate ();
1052 if (!ret)
1053 goto bail1;
1054
1055 if (!FcSortWalk (nodeps, nnodes, ret, csp, trim))
1056 goto bail2;
1057
1058 free (nodes);
1059
1060 if (FcDebug()(FcDebugVal) & FC_DBG_MATCH1)
1061 {
1062 printf ("First font ");
1063 FcPatternPrint (ret->fonts[0]);
1064 }
1065 if (ret->nfont > 0)
1066 *result = FcResultMatch;
1067
1068 return ret;
1069
1070bail2:
1071 FcFontSetDestroy (ret);
1072bail1:
1073 free (nodes);
1074bail0:
1075 return 0;
1076}
1077
1078FcFontSet *
1079FcFontSort (FcConfig *config,
1080 FcPattern *p,
1081 FcBool trim,
1082 FcCharSet **csp,
1083 FcResult *result)
1084{
1085 FcFontSet *sets[2];
1086 int nsets;
1087
1088 assert (p != NULL)(__builtin_expect(!(p != ((void*)0)), 0) ? __assert_rtn(__func__
, "fcmatch.c", 1088, "p != NULL") : (void)0)
;
1089 assert (result != NULL)(__builtin_expect(!(result != ((void*)0)), 0) ? __assert_rtn(
__func__, "fcmatch.c", 1089, "result != NULL") : (void)0)
;
1090
1091 *result = FcResultNoMatch;
1092
1093 if (!config)
1094 {
1095 config = FcConfigGetCurrent ();
1096 if (!config)
1097 return 0;
1098 }
1099 nsets = 0;
1100 if (config->fonts[FcSetSystem])
1101 sets[nsets++] = config->fonts[FcSetSystem];
1102 if (config->fonts[FcSetApplication])
1103 sets[nsets++] = config->fonts[FcSetApplication];
1104 return FcFontSetSort (config, sets, nsets, p, trim, csp, result);
1105}
1106#define __fcmatch__
1107#include "fcaliastail.h"
1108#undef __fcmatch__