| 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__ |