File: | src/fcmatch.c |
Location: | line 598, column 6 |
Description: | Passed-by-value struct argument contains uninitialized data (e.g., field: 'type') |
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 | ||||
27 | static double | |||
28 | FcCompareNumber (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 | ||||
58 | static double | |||
59 | FcCompareString (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 | ||||
64 | static double | |||
65 | FcCompareFamily (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 | ||||
79 | static double | |||
80 | FcComparePostScript (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 | ||||
97 | static double | |||
98 | FcCompareLang (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 | ||||
144 | static double | |||
145 | FcCompareBool (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 | ||||
152 | static double | |||
153 | FcCompareCharSet (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 | ||||
158 | static double | |||
159 | FcCompareSize (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 | ||||
191 | static double | |||
192 | FcCompareSizeRange (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 | ||||
225 | bail: | |||
226 | if (r1) | |||
227 | FcRangeDestroy (r1); | |||
228 | if (r2) | |||
229 | FcRangeDestroy (r2); | |||
230 | ||||
231 | return ret; | |||
232 | } | |||
233 | ||||
234 | static double | |||
235 | FcCompareFilename (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 | ||||
268 | typedef 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 | ||||
283 | typedef 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 | ||||
313 | typedef 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 }, | |||
325 | static const FcMatcher _FcMatchers [] = { | |||
326 | { FC_INVALID_OBJECT, NULL((void*)0), -1, -1 }, | |||
327 | #include "fcobjs.h" | |||
328 | }; | |||
329 | #undef FC_OBJECT | |||
330 | ||||
331 | static const FcMatcher* | |||
332 | FcObjectToMatcher (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 | ||||
354 | static FcBool | |||
355 | FcCompareValueList (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 | ||||
443 | static FcBool | |||
444 | FcCompare (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 | ||||
481 | FcPattern * | |||
482 | FcFontRenderPrepare (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) | |||
| ||||
497 | return NULL((void*)0); | |||
498 | for (i = 0; i < font->num; i++) | |||
499 | { | |||
500 | fe = &FcPatternElts(font)((FcPatternElt *) ((intptr_t) (font) + ((font)->elts_offset )))[i]; | |||
501 | if (fe->object == FC_FAMILYLANG_OBJECT || | |||
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 || | |||
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) | |||
589 | { | |||
590 | const FcMatcher *match = FcObjectToMatcher (pe->object, FcFalse0); | |||
591 | if (!FcCompareValueList (pe->object, match, | |||
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); | |||
| ||||
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 | ||||
626 | static FcPattern * | |||
627 | FcFontSetMatchInternal (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 | ||||
741 | FcPattern * | |||
742 | FcFontSetMatch (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 | ||||
769 | FcPattern * | |||
770 | FcFontMatch (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 | ||||
802 | typedef struct _FcSortNode { | |||
803 | FcPattern *pattern; | |||
804 | double score[PRI_END]; | |||
805 | } FcSortNode; | |||
806 | ||||
807 | static int | |||
808 | FcSortCompare (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 | ||||
823 | static FcBool | |||
824 | FcSortWalk (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 | ||||
885 | bail: | |||
886 | if (cs) | |||
887 | FcCharSetDestroy (cs); | |||
888 | ||||
889 | return ret; | |||
890 | } | |||
891 | ||||
892 | void | |||
893 | FcFontSetSortDestroy (FcFontSet *fs) | |||
894 | { | |||
895 | FcFontSetDestroy (fs); | |||
896 | } | |||
897 | ||||
898 | FcFontSet * | |||
899 | FcFontSetSort (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 | ||||
1070 | bail2: | |||
1071 | FcFontSetDestroy (ret); | |||
1072 | bail1: | |||
1073 | free (nodes); | |||
1074 | bail0: | |||
1075 | return 0; | |||
1076 | } | |||
1077 | ||||
1078 | FcFontSet * | |||
1079 | FcFontSort (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__ |