Files
@ r20525:bab9e0f1e366
Branch filter:
Location: cpp/openttd-patchpack/source/src/fontdetection.cpp - annotation
r20525:bab9e0f1e366
26.8 KiB
text/x-c
(svn r25549) -Update from WebTranslator v3.0:
finnish - 41 changes by jpx_
korean - 39 changes by telk5093
polish - 6 changes by p0358
slovak - 37 changes by Milsa
finnish - 41 changes by jpx_
korean - 39 changes by telk5093
polish - 6 changes by p0358
slovak - 37 changes by Milsa
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 | r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20435:719caf72f69b r20435:719caf72f69b r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20425:36b710759198 r20425:36b710759198 r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20432:c9229f47a633 r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20421:689b79ec796e r20435:719caf72f69b r20435:719caf72f69b | /* $Id$ */
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file fontdetection.cpp Detection of the right font. */
#ifdef WITH_FREETYPE
#include "stdafx.h"
#include "debug.h"
#include "fontdetection.h"
#include "string_func.h"
#include "strings_func.h"
extern FT_Library _library;
/**
* Get the font loaded into a Freetype face by using a font-name.
* If no appropriate font is found, the function returns an error
*/
/* ========================================================================================
* Windows support
* ======================================================================================== */
#ifdef WIN32
#include "core/alloc_func.hpp"
#include "core/math_func.hpp"
#include <windows.h>
#include <shlobj.h> /* SHGetFolderPath */
#include "os/windows/win32.h"
/**
* Get the short DOS 8.3 format for paths.
* FreeType doesn't support Unicode filenames and Windows' fopen (as used
* by FreeType) doesn't support UTF-8 filenames. So we have to convert the
* filename into something that isn't UTF-8 but represents the Unicode file
* name. This is the short DOS 8.3 format. This does not contain any
* characters that fopen doesn't support.
* @param long_path the path in UTF-8.
* @return the short path in ANSI (ASCII).
*/
char *GetShortPath(const char *long_path)
{
static char short_path[MAX_PATH];
#ifdef UNICODE
/* The non-unicode GetShortPath doesn't support UTF-8...,
* so convert the path to wide chars, then get the short
* path and convert it back again. */
wchar_t long_path_w[MAX_PATH];
MultiByteToWideChar(CP_UTF8, 0, long_path, -1, long_path_w, MAX_PATH);
wchar_t short_path_w[MAX_PATH];
GetShortPathNameW(long_path_w, short_path_w, MAX_PATH);
WideCharToMultiByte(CP_ACP, 0, short_path_w, -1, short_path, MAX_PATH, NULL, NULL);
#else
/* Technically not needed, but do it for consistency. */
GetShortPathNameA(long_path, short_path, MAX_PATH);
#endif
return short_path;
}
/* Get the font file to be loaded into Freetype by looping the registry
* location where windows lists all installed fonts. Not very nice, will
* surely break if the registry path changes, but it works. Much better
* solution would be to use CreateFont, and extract the font data from it
* by GetFontData. The problem with this is that the font file needs to be
* kept in memory then until the font is no longer needed. This could mean
* an additional memory usage of 30MB (just for fonts!) when using an eastern
* font for all font sizes */
#define FONT_DIR_NT "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
#define FONT_DIR_9X "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts"
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
{
FT_Error err = FT_Err_Cannot_Open_Resource;
HKEY hKey;
LONG ret;
TCHAR vbuffer[MAX_PATH], dbuffer[256];
TCHAR *font_namep;
char *font_path;
uint index;
/* On windows NT (2000, NT3.5, XP, etc.) the fonts are stored in the
* "Windows NT" key, on Windows 9x in the Windows key. To save us having
* to retrieve the windows version, we'll just query both */
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_NT), 0, KEY_READ, &hKey);
if (ret != ERROR_SUCCESS) ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_9X), 0, KEY_READ, &hKey);
if (ret != ERROR_SUCCESS) {
DEBUG(freetype, 0, "Cannot open registry key HKLM\\SOFTWARE\\Microsoft\\Windows (NT)\\CurrentVersion\\Fonts");
return err;
}
/* For Unicode we need some conversion between widechar and
* normal char to match the data returned by RegEnumValue,
* otherwise just use parameter */
#if defined(UNICODE)
font_namep = MallocT<TCHAR>(MAX_PATH);
MB_TO_WIDE_BUFFER(font_name, font_namep, MAX_PATH * sizeof(TCHAR));
#else
font_namep = const_cast<char *>(font_name); // only cast because in unicode pointer is not const
#endif
for (index = 0;; index++) {
TCHAR *s;
DWORD vbuflen = lengthof(vbuffer);
DWORD dbuflen = lengthof(dbuffer);
ret = RegEnumValue(hKey, index, vbuffer, &vbuflen, NULL, NULL, (byte*)dbuffer, &dbuflen);
if (ret != ERROR_SUCCESS) goto registry_no_font_found;
/* The font names in the registry are of the following 3 forms:
* - ADMUI3.fon
* - Book Antiqua Bold (TrueType)
* - Batang & BatangChe & Gungsuh & GungsuhChe (TrueType)
* We will strip the font-type '()' if any and work with the font name
* itself, which must match exactly; if...
* TTC files, font files which contain more than one font are separated
* by '&'. Our best bet will be to do substr match for the fontname
* and then let FreeType figure out which index to load */
s = _tcschr(vbuffer, _T('('));
if (s != NULL) s[-1] = '\0';
if (_tcschr(vbuffer, _T('&')) == NULL) {
if (_tcsicmp(vbuffer, font_namep) == 0) break;
} else {
if (_tcsstr(vbuffer, font_namep) != NULL) break;
}
}
if (!SUCCEEDED(OTTDSHGetFolderPath(NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, vbuffer))) {
DEBUG(freetype, 0, "SHGetFolderPath cannot return fonts directory");
goto folder_error;
}
/* Some fonts are contained in .ttc files, TrueType Collection fonts. These
* contain multiple fonts inside this single file. GetFontData however
* returns the whole file, so we need to check each font inside to get the
* proper font.
* Also note that FreeType does not support UNICODE filenames! */
#if defined(UNICODE)
/* We need a cast here back from wide because FreeType doesn't support
* widechar filenames. Just use the buffer we allocated before for the
* font_name search */
font_path = (char*)font_namep;
WIDE_TO_MB_BUFFER(vbuffer, font_path, MAX_PATH * sizeof(TCHAR));
#else
font_path = vbuffer;
#endif
ttd_strlcat(font_path, "\\", MAX_PATH * sizeof(TCHAR));
ttd_strlcat(font_path, WIDE_TO_MB(dbuffer), MAX_PATH * sizeof(TCHAR));
/* Convert the path into something that FreeType understands */
font_path = GetShortPath(font_path);
index = 0;
do {
err = FT_New_Face(_library, font_path, index, face);
if (err != FT_Err_Ok) break;
if (strncasecmp(font_name, (*face)->family_name, strlen((*face)->family_name)) == 0) break;
/* Try english name if font name failed */
if (strncasecmp(font_name + strlen(font_name) + 1, (*face)->family_name, strlen((*face)->family_name)) == 0) break;
err = FT_Err_Cannot_Open_Resource;
} while ((FT_Long)++index != (*face)->num_faces);
folder_error:
registry_no_font_found:
#if defined(UNICODE)
free(font_namep);
#endif
RegCloseKey(hKey);
return err;
}
/**
* Fonts can have localised names and when the system locale is the same as
* one of those localised names Windows will always return that localised name
* instead of allowing to get the non-localised (English US) name of the font.
* This will later on give problems as freetype uses the non-localised name of
* the font and we need to compare based on that name.
* Windows furthermore DOES NOT have an API to get the non-localised name nor
* can we override the system locale. This means that we have to actually read
* the font itself to gather the font name we want.
* Based on: http://blogs.msdn.com/michkap/archive/2006/02/13/530814.aspx
* @param logfont the font information to get the english name of.
* @return the English name (if it could be found).
*/
static const char *GetEnglishFontName(const ENUMLOGFONTEX *logfont)
{
static char font_name[MAX_PATH];
const char *ret_font_name = NULL;
uint pos = 0;
HDC dc;
HGDIOBJ oldfont;
byte *buf;
DWORD dw;
uint16 format, count, stringOffset, platformId, encodingId, languageId, nameId, length, offset;
HFONT font = CreateFontIndirect(&logfont->elfLogFont);
if (font == NULL) goto err1;
dc = GetDC(NULL);
oldfont = SelectObject(dc, font);
dw = GetFontData(dc, 'eman', 0, NULL, 0);
if (dw == GDI_ERROR) goto err2;
buf = MallocT<byte>(dw);
dw = GetFontData(dc, 'eman', 0, buf, dw);
if (dw == GDI_ERROR) goto err3;
format = buf[pos++] << 8;
format += buf[pos++];
assert(format == 0);
count = buf[pos++] << 8;
count += buf[pos++];
stringOffset = buf[pos++] << 8;
stringOffset += buf[pos++];
for (uint i = 0; i < count; i++) {
platformId = buf[pos++] << 8;
platformId += buf[pos++];
encodingId = buf[pos++] << 8;
encodingId += buf[pos++];
languageId = buf[pos++] << 8;
languageId += buf[pos++];
nameId = buf[pos++] << 8;
nameId += buf[pos++];
if (nameId != 1) {
pos += 4; // skip length and offset
continue;
}
length = buf[pos++] << 8;
length += buf[pos++];
offset = buf[pos++] << 8;
offset += buf[pos++];
/* Don't buffer overflow */
length = min(length, MAX_PATH - 1);
for (uint j = 0; j < length; j++) font_name[j] = buf[stringOffset + offset + j];
font_name[length] = '\0';
if ((platformId == 1 && languageId == 0) || // Macintosh English
(platformId == 3 && languageId == 0x0409)) { // Microsoft English (US)
ret_font_name = font_name;
break;
}
}
err3:
free(buf);
err2:
SelectObject(dc, oldfont);
ReleaseDC(NULL, dc);
DeleteObject(font);
err1:
return ret_font_name == NULL ? WIDE_TO_MB((const TCHAR*)logfont->elfFullName) : ret_font_name;
}
class FontList {
protected:
TCHAR **fonts;
uint items;
uint capacity;
public:
FontList() : fonts(NULL), items(0), capacity(0) { };
~FontList() {
if (this->fonts == NULL) return;
for (uint i = 0; i < this->items; i++) {
free(this->fonts[i]);
}
free(this->fonts);
}
bool Add(const TCHAR *font) {
for (uint i = 0; i < this->items; i++) {
if (_tcscmp(this->fonts[i], font) == 0) return false;
}
if (this->items == this->capacity) {
this->capacity += 10;
this->fonts = ReallocT(this->fonts, this->capacity);
}
this->fonts[this->items++] = _tcsdup(font);
return true;
}
};
struct EFCParam {
FreeTypeSettings *settings;
LOCALESIGNATURE locale;
MissingGlyphSearcher *callback;
FontList fonts;
};
static int CALLBACK EnumFontCallback(const ENUMLOGFONTEX *logfont, const NEWTEXTMETRICEX *metric, DWORD type, LPARAM lParam)
{
EFCParam *info = (EFCParam *)lParam;
/* Skip duplicates */
if (!info->fonts.Add((const TCHAR*)logfont->elfFullName)) return 1;
/* Only use TrueType fonts */
if (!(type & TRUETYPE_FONTTYPE)) return 1;
/* Don't use SYMBOL fonts */
if (logfont->elfLogFont.lfCharSet == SYMBOL_CHARSET) return 1;
/* Use monospaced fonts when asked for it. */
if (info->callback->Monospace() && (logfont->elfLogFont.lfPitchAndFamily & (FF_MODERN | FIXED_PITCH)) != (FF_MODERN | FIXED_PITCH)) return 1;
/* The font has to have at least one of the supported locales to be usable. */
if ((metric->ntmFontSig.fsCsb[0] & info->locale.lsCsbSupported[0]) == 0 && (metric->ntmFontSig.fsCsb[1] & info->locale.lsCsbSupported[1]) == 0) {
/* On win9x metric->ntmFontSig seems to contain garbage. */
FONTSIGNATURE fs;
memset(&fs, 0, sizeof(fs));
HFONT font = CreateFontIndirect(&logfont->elfLogFont);
if (font != NULL) {
HDC dc = GetDC(NULL);
HGDIOBJ oldfont = SelectObject(dc, font);
GetTextCharsetInfo(dc, &fs, 0);
SelectObject(dc, oldfont);
ReleaseDC(NULL, dc);
DeleteObject(font);
}
if ((fs.fsCsb[0] & info->locale.lsCsbSupported[0]) == 0 && (fs.fsCsb[1] & info->locale.lsCsbSupported[1]) == 0) return 1;
}
char font_name[MAX_PATH];
#if defined(UNICODE)
WIDE_TO_MB_BUFFER((const TCHAR*)logfont->elfFullName, font_name, lengthof(font_name));
#else
strecpy(font_name, (const TCHAR*)logfont->elfFullName, lastof(font_name));
#endif
/* Add english name after font name */
const char *english_name = GetEnglishFontName(logfont);
strecpy(font_name + strlen(font_name) + 1, english_name, lastof(font_name));
/* Check whether we can actually load the font. */
bool ft_init = _library != NULL;
bool found = false;
FT_Face face;
/* Init FreeType if needed. */
if ((ft_init || FT_Init_FreeType(&_library) == FT_Err_Ok) && GetFontByFaceName(font_name, &face) == FT_Err_Ok) {
FT_Done_Face(face);
found = true;
}
if (!ft_init) {
/* Uninit FreeType if we did the init. */
FT_Done_FreeType(_library);
_library = NULL;
}
if (!found) return 1;
info->callback->SetFontNames(info->settings, font_name);
if (info->callback->FindMissingGlyphs(NULL)) return 1;
DEBUG(freetype, 1, "Fallback font: %s (%s)", font_name, english_name);
return 0; // stop enumerating
}
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
{
DEBUG(freetype, 1, "Trying fallback fonts");
EFCParam langInfo;
if (GetLocaleInfo(MAKELCID(winlangid, SORT_DEFAULT), LOCALE_FONTSIGNATURE, (LPTSTR)&langInfo.locale, sizeof(langInfo.locale) / sizeof(TCHAR)) == 0) {
/* Invalid langid or some other mysterious error, can't determine fallback font. */
DEBUG(freetype, 1, "Can't get locale info for fallback font (langid=0x%x)", winlangid);
return false;
}
langInfo.settings = settings;
langInfo.callback = callback;
LOGFONT font;
/* Enumerate all fonts. */
font.lfCharSet = DEFAULT_CHARSET;
font.lfFaceName[0] = '\0';
font.lfPitchAndFamily = 0;
HDC dc = GetDC(NULL);
int ret = EnumFontFamiliesEx(dc, &font, (FONTENUMPROC)&EnumFontCallback, (LPARAM)&langInfo, 0);
ReleaseDC(NULL, dc);
return ret == 0;
}
#elif defined(__APPLE__) /* end ifdef Win32 */
/* ========================================================================================
* OSX support
* ======================================================================================== */
#include "os/macosx/macos.h"
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
{
FT_Error err = FT_Err_Cannot_Open_Resource;
/* Get font reference from name. */
CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name, kCFStringEncodingUTF8);
ATSFontRef font = ATSFontFindFromName(name, kATSOptionFlagsDefault);
CFRelease(name);
if (font == kInvalidFont) return err;
/* Get a file system reference for the font. */
FSRef ref;
OSStatus os_err = -1;
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
if (MacOSVersionIsAtLeast(10, 5, 0)) {
os_err = ATSFontGetFileReference(font, &ref);
} else
#endif
{
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) && !__LP64__
/* This type was introduced with the 10.5 SDK. */
#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
#define ATSFSSpec FSSpec
#endif
FSSpec spec;
os_err = ATSFontGetFileSpecification(font, (ATSFSSpec *)&spec);
if (os_err == noErr) os_err = FSpMakeFSRef(&spec, &ref);
#endif
}
if (os_err == noErr) {
/* Get unix path for file. */
UInt8 file_path[PATH_MAX];
if (FSRefMakePath(&ref, file_path, sizeof(file_path)) == noErr) {
DEBUG(freetype, 3, "Font path for %s: %s", font_name, file_path);
err = FT_New_Face(_library, (const char *)file_path, 0, face);
}
}
return err;
}
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
{
const char *str;
bool result = false;
callback->FindMissingGlyphs(&str);
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
if (MacOSVersionIsAtLeast(10, 5, 0)) {
/* Determine fallback font using CoreText. This uses the language isocode
* to find a suitable font. CoreText is available from 10.5 onwards. */
char lang[16];
if (strcmp(language_isocode, "zh_TW") == 0) {
/* Traditional Chinese */
strecpy(lang, "zh-Hant", lastof(lang));
} else if (strcmp(language_isocode, "zh_CN") == 0) {
/* Simplified Chinese */
strecpy(lang, "zh-Hans", lastof(lang));
} else if (strncmp(language_isocode, "ur", 2) == 0) {
/* The urdu alphabet is variant of persian. As OS X has no default
* font that advertises an urdu language code, search for persian
* support instead. */
strecpy(lang, "fa", lastof(lang));
} else {
/* Just copy the first part of the isocode. */
strecpy(lang, language_isocode, lastof(lang));
char *sep = strchr(lang, '_');
if (sep != NULL) *sep = '\0';
}
CFStringRef lang_code;
lang_code = CFStringCreateWithCString(kCFAllocatorDefault, lang, kCFStringEncodingUTF8);
/* Create a font iterator and iterate over all fonts that
* are available to the application. */
ATSFontIterator itr;
ATSFontRef font;
ATSFontIteratorCreate(kATSFontContextLocal, NULL, NULL, kATSOptionFlagsUnRestrictedScope, &itr);
while (!result && ATSFontIteratorNext(itr, &font) == noErr) {
/* Get CoreText font handle. */
CTFontRef font_ref = CTFontCreateWithPlatformFont(font, 0.0, NULL, NULL);
CFArrayRef langs = CTFontCopySupportedLanguages(font_ref);
if (langs != NULL) {
/* Font has a list of supported languages. */
for (CFIndex i = 0; i < CFArrayGetCount(langs); i++) {
CFStringRef lang = (CFStringRef)CFArrayGetValueAtIndex(langs, i);
if (CFStringCompare(lang, lang_code, kCFCompareAnchored) == kCFCompareEqualTo) {
/* Lang code is supported by font, get full font name. */
CFStringRef font_name = CTFontCopyFullName(font_ref);
char name[128];
CFStringGetCString(font_name, name, lengthof(name), kCFStringEncodingUTF8);
CFRelease(font_name);
/* Skip some inappropriate or ugly looking fonts that have better alternatives. */
if (strncmp(name, "Courier", 7) == 0 || strncmp(name, "Apple Symbols", 13) == 0 ||
strncmp(name, ".Aqua", 5) == 0 || strncmp(name, "LastResort", 10) == 0 ||
strncmp(name, "GB18030 Bitmap", 14) == 0) continue;
/* Save result. */
callback->SetFontNames(settings, name);
DEBUG(freetype, 2, "CT-Font for %s: %s", language_isocode, name);
result = true;
break;
}
}
CFRelease(langs);
}
CFRelease(font_ref);
}
ATSFontIteratorRelease(&itr);
CFRelease(lang_code);
} else
#endif
{
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) && !__LP64__
/* Determine fallback font using ATSUI. This uses a string sample with
* missing characters. This is not failure-proof, but a better way like
* using the isocode as in the CoreText code path is not available.
* ATSUI was deprecated with 10.6 and is only partially available in
* 64-bit mode. */
/* Remove all control characters in the range from SCC_CONTROL_START to
* SCC_CONTROL_END as well as all ASCII < 0x20 from the string as it will
* mess with the automatic font detection */
char buff[256]; // This length is enough to find a suitable replacement font
strecpy(buff, str, lastof(buff));
str_validate(buff, lastof(buff), SVS_ALLOW_NEWLINE);
/* Extract a UniChar representation of the sample string. */
CFStringRef cf_str = CFStringCreateWithCString(kCFAllocatorDefault, buff, kCFStringEncodingUTF8);
if (cf_str == NULL) {
/* Something went wrong. Corrupt/invalid sample string? */
return false;
}
CFIndex str_len = CFStringGetLength(cf_str);
UniChar string[str_len];
CFStringGetCharacters(cf_str, CFRangeMake(0, str_len), string);
/* Create a default text style with the default font. */
ATSUStyle style;
ATSUCreateStyle(&style);
/* Create a text layout object from the sample string using the text style. */
UniCharCount run_len = kATSUToTextEnd;
ATSUTextLayout text_layout;
ATSUCreateTextLayoutWithTextPtr(string, kATSUFromTextBeginning, kATSUToTextEnd, str_len, 1, &run_len, &style, &text_layout);
/* Try to match a font for the sample text. ATSUMatchFontsToText stops after
* it finds the first continuous character run not renderable with the currently
* selected font starting at offset. The matching needs to be repeated until
* the end of the string is reached to make sure the fallback font matches for
* all characters in the string and not only the first run. */
UniCharArrayOffset offset = kATSUFromTextBeginning;
OSStatus os_err;
do {
ATSUFontID font;
UniCharCount run_len;
os_err = ATSUMatchFontsToText(text_layout, offset, kATSUToTextEnd, &font, &offset, &run_len);
if (os_err == kATSUFontsMatched) {
/* Found a better fallback font. Update the text layout
* object with the new font. */
ATSUAttributeTag tag = kATSUFontTag;
ByteCount size = sizeof(font);
ATSUAttributeValuePtr val = &font;
ATSUSetAttributes(style, 1, &tag, &size, &val);
offset += run_len;
}
/* Exit if the end of the string is reached or some other error occurred. */
} while (os_err == kATSUFontsMatched && offset < (UniCharArrayOffset)str_len);
if (os_err == noErr || os_err == kATSUFontsMatched) {
/* ATSUMatchFontsToText exited normally. Extract font
* out of the text layout object. */
ATSUFontID font;
ByteCount act_len;
ATSUGetAttribute(style, kATSUFontTag, sizeof(font), &font, &act_len);
/* Get unique font name. The result is not a c-string, we have
* to leave space for a \0 and terminate it ourselves. */
char name[128];
ATSUFindFontName(font, kFontUniqueName, kFontNoPlatformCode, kFontNoScriptCode, kFontNoLanguageCode, 127, name, &act_len, NULL);
name[act_len > 127 ? 127 : act_len] = '\0';
/* Save Result. */
callback->SetFontNames(settings, name);
DEBUG(freetype, 2, "ATSUI-Font for %s: %s", language_isocode, name);
result = true;
}
ATSUDisposeTextLayout(text_layout);
ATSUDisposeStyle(style);
CFRelease(cf_str);
#endif
}
if (result && strncmp(settings->medium.font, "Geeza Pro", 9) == 0) {
/* The font 'Geeza Pro' is often found for arabic characters, but
* it has the 'tiny' problem of not having any latin characters.
* 'Arial Unicode MS' on the other hand has arabic and latin glyphs,
* but seems to 'forget' to inform the OS about this fact. Manually
* substitute the latter for the former if it is loadable. */
bool ft_init = _library != NULL;
FT_Face face;
/* Init FreeType if needed. */
if ((ft_init || FT_Init_FreeType(&_library) == FT_Err_Ok) && GetFontByFaceName("Arial Unicode MS", &face) == FT_Err_Ok) {
FT_Done_Face(face);
callback->SetFontNames(settings, "Arial Unicode MS");
DEBUG(freetype, 1, "Replacing font 'Geeza Pro' with 'Arial Unicode MS'");
}
if (!ft_init) {
/* Uninit FreeType if we did the init. */
FT_Done_FreeType(_library);
_library = NULL;
}
}
callback->FindMissingGlyphs(NULL);
return result;
}
#elif defined(WITH_FONTCONFIG) /* end ifdef __APPLE__ */
#include <fontconfig/fontconfig.h>
/* ========================================================================================
* FontConfig (unix) support
* ======================================================================================== */
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
{
FT_Error err = FT_Err_Cannot_Open_Resource;
if (!FcInit()) {
ShowInfoF("Unable to load font configuration");
} else {
FcPattern *match;
FcPattern *pat;
FcFontSet *fs;
FcResult result;
char *font_style;
char *font_family;
/* Split & strip the font's style */
font_family = strdup(font_name);
font_style = strchr(font_family, ',');
if (font_style != NULL) {
font_style[0] = '\0';
font_style++;
while (*font_style == ' ' || *font_style == '\t') font_style++;
}
/* Resolve the name and populate the information structure */
pat = FcNameParse((FcChar8*)font_family);
if (font_style != NULL) FcPatternAddString(pat, FC_STYLE, (FcChar8*)font_style);
FcConfigSubstitute(0, pat, FcMatchPattern);
FcDefaultSubstitute(pat);
fs = FcFontSetCreate();
match = FcFontMatch(0, pat, &result);
if (fs != NULL && match != NULL) {
int i;
FcChar8 *family;
FcChar8 *style;
FcChar8 *file;
FcFontSetAdd(fs, match);
for (i = 0; err != FT_Err_Ok && i < fs->nfont; i++) {
/* Try the new filename */
if (FcPatternGetString(fs->fonts[i], FC_FILE, 0, &file) == FcResultMatch &&
FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == FcResultMatch &&
FcPatternGetString(fs->fonts[i], FC_STYLE, 0, &style) == FcResultMatch) {
/* The correct style? */
if (font_style != NULL && strcasecmp(font_style, (char*)style) != 0) continue;
/* Font config takes the best shot, which, if the family name is spelled
* wrongly a 'random' font, so check whether the family name is the
* same as the supplied name */
if (strcasecmp(font_family, (char*)family) == 0) {
err = FT_New_Face(_library, (char *)file, 0, face);
}
}
}
}
free(font_family);
FcPatternDestroy(pat);
FcFontSetDestroy(fs);
FcFini();
}
return err;
}
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
{
if (!FcInit()) return false;
bool ret = false;
/* Fontconfig doesn't handle full language isocodes, only the part
* before the _ of e.g. en_GB is used, so "remove" everything after
* the _. */
char lang[16];
seprintf(lang, lastof(lang), ":lang=%s", language_isocode);
char *split = strchr(lang, '_');
if (split != NULL) *split = '\0';
/* First create a pattern to match the wanted language. */
FcPattern *pat = FcNameParse((FcChar8*)lang);
/* We only want to know the filename. */
FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_SPACING, FC_SLANT, FC_WEIGHT, NULL);
/* Get the list of filenames matching the wanted language. */
FcFontSet *fs = FcFontList(NULL, pat, os);
/* We don't need these anymore. */
FcObjectSetDestroy(os);
FcPatternDestroy(pat);
if (fs != NULL) {
int best_weight = -1;
const char *best_font = NULL;
for (int i = 0; i < fs->nfont; i++) {
FcPattern *font = fs->fonts[i];
FcChar8 *file = NULL;
FcResult res = FcPatternGetString(font, FC_FILE, 0, &file);
if (res != FcResultMatch || file == NULL) {
continue;
}
/* Get a font with the right spacing .*/
int value = 0;
FcPatternGetInteger(font, FC_SPACING, 0, &value);
if (callback->Monospace() != (value == FC_MONO) && value != FC_DUAL) continue;
/* Do not use those that explicitly say they're slanted. */
FcPatternGetInteger(font, FC_SLANT, 0, &value);
if (value != 0) continue;
/* We want the fatter font as they look better at small sizes. */
FcPatternGetInteger(font, FC_WEIGHT, 0, &value);
if (value <= best_weight) continue;
callback->SetFontNames(settings, (const char*)file);
bool missing = callback->FindMissingGlyphs(NULL);
DEBUG(freetype, 1, "Font \"%s\" misses%s glyphs", file, missing ? "" : " no");
if (!missing) {
best_weight = value;
best_font = (const char *)file;
}
}
if (best_font != NULL) {
ret = true;
callback->SetFontNames(settings, best_font);
InitFreeType(callback->Monospace());
}
/* Clean up the list of filenames. */
FcFontSetDestroy(fs);
}
FcFini();
return ret;
}
#else /* without WITH_FONTCONFIG */
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) {return FT_Err_Cannot_Open_Resource;}
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) { return false; }
#endif /* WITH_FONTCONFIG */
#endif /* WITH_FREETYPE */
|