| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cff.h" | 5 #include "cff.h" |
| 6 | 6 |
| 7 #include <cstring> | 7 #include <cstring> |
| 8 #include <utility> // std::pair | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "maxp.h" |
| 11 #include "cff_type2_charstring.h" | 12 #include "cff_type2_charstring.h" |
| 12 | 13 |
| 13 // CFF - PostScript font program (Compact Font Format) table | 14 // CFF - PostScript font program (Compact Font Format) table |
| 14 // http://www.microsoft.com/typography/otspec/cff.htm | 15 // http://www.microsoft.com/typography/otspec/cff.htm |
| 15 // http://www.microsoft.com/typography/otspec/cffspec.htm | 16 // http://www.microsoft.com/typography/otspec/cffspec.htm |
| 16 | 17 |
| 18 #define TABLE_NAME "CFF" |
| 19 |
| 17 namespace { | 20 namespace { |
| 18 | 21 |
| 19 enum DICT_OPERAND_TYPE { | 22 enum DICT_OPERAND_TYPE { |
| 20 DICT_OPERAND_INTEGER, | 23 DICT_OPERAND_INTEGER, |
| 21 DICT_OPERAND_REAL, | 24 DICT_OPERAND_REAL, |
| 22 DICT_OPERATOR, | 25 DICT_OPERATOR, |
| 23 }; | 26 }; |
| 24 | 27 |
| 25 enum DICT_DATA_TYPE { | 28 enum DICT_DATA_TYPE { |
| 26 DICT_DATA_TOPLEVEL, | 29 DICT_DATA_TOPLEVEL, |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 if (operands.back().second != DICT_OPERAND_INTEGER) { | 411 if (operands.back().second != DICT_OPERAND_INTEGER) { |
| 409 return OTS_FAILURE(); | 412 return OTS_FAILURE(); |
| 410 } | 413 } |
| 411 if (operands.back().first >= 1024 * 1024 * 1024) { | 414 if (operands.back().first >= 1024 * 1024 * 1024) { |
| 412 return OTS_FAILURE(); | 415 return OTS_FAILURE(); |
| 413 } | 416 } |
| 414 if (operands.back().first + offset >= table_length) { | 417 if (operands.back().first + offset >= table_length) { |
| 415 return OTS_FAILURE(); | 418 return OTS_FAILURE(); |
| 416 } | 419 } |
| 417 // parse "16. Local Subrs INDEX" | 420 // parse "16. Local Subrs INDEX" |
| 418 ots::Buffer table(data, table_length); | 421 ots::Buffer cff_table(data, table_length); |
| 419 table.set_offset(operands.back().first + offset); | 422 cff_table.set_offset(operands.back().first + offset); |
| 420 ots::CFFIndex *local_subrs_index = NULL; | 423 ots::CFFIndex *local_subrs_index = NULL; |
| 421 if (type == DICT_DATA_FDARRAY) { | 424 if (type == DICT_DATA_FDARRAY) { |
| 422 if (out_cff->local_subrs_per_font.empty()) { | 425 if (out_cff->local_subrs_per_font.empty()) { |
| 423 return OTS_FAILURE(); // not reached. | 426 return OTS_FAILURE(); // not reached. |
| 424 } | 427 } |
| 425 local_subrs_index = out_cff->local_subrs_per_font.back(); | 428 local_subrs_index = out_cff->local_subrs_per_font.back(); |
| 426 } else { // type == DICT_DATA_TOPLEVEL | 429 } else { // type == DICT_DATA_TOPLEVEL |
| 427 if (out_cff->local_subrs) { | 430 if (out_cff->local_subrs) { |
| 428 return OTS_FAILURE(); // two or more local_subrs? | 431 return OTS_FAILURE(); // two or more local_subrs? |
| 429 } | 432 } |
| 430 local_subrs_index = new ots::CFFIndex; | 433 local_subrs_index = new ots::CFFIndex; |
| 431 out_cff->local_subrs = local_subrs_index; | 434 out_cff->local_subrs = local_subrs_index; |
| 432 } | 435 } |
| 433 if (!ParseIndex(&table, local_subrs_index)) { | 436 if (!ParseIndex(&cff_table, local_subrs_index)) { |
| 434 return OTS_FAILURE(); | 437 return OTS_FAILURE(); |
| 435 } | 438 } |
| 436 break; | 439 break; |
| 437 } | 440 } |
| 438 | 441 |
| 439 // boolean | 442 // boolean |
| 440 case (12U << 8) + 14: // ForceBold | 443 case (12U << 8) + 14: // ForceBold |
| 441 if (operands.size() != 1) { | 444 if (operands.size() != 1) { |
| 442 return OTS_FAILURE(); | 445 return OTS_FAILURE(); |
| 443 } | 446 } |
| 444 if (operands.back().second != DICT_OPERAND_INTEGER) { | 447 if (operands.back().second != DICT_OPERAND_INTEGER) { |
| 445 return OTS_FAILURE(); | 448 return OTS_FAILURE(); |
| 446 } | 449 } |
| 447 if (operands.back().first >= 2) { | 450 if (operands.back().first >= 2) { |
| 448 return OTS_FAILURE(); | 451 return OTS_FAILURE(); |
| 449 } | 452 } |
| 450 break; | 453 break; |
| 451 | 454 |
| 452 default: | 455 default: |
| 453 return OTS_FAILURE(); | 456 return OTS_FAILURE(); |
| 454 } | 457 } |
| 455 operands.clear(); | 458 operands.clear(); |
| 456 } | 459 } |
| 457 | 460 |
| 458 return true; | 461 return true; |
| 459 } | 462 } |
| 460 | 463 |
| 461 bool ParseDictData(const uint8_t *data, size_t table_length, | 464 bool ParseDictData(const uint8_t *data, size_t table_length, |
| 462 const ots::CFFIndex &index, size_t sid_max, | 465 const ots::CFFIndex &index, uint16_t glyphs, |
| 463 DICT_DATA_TYPE type, ots::OpenTypeCFF *out_cff) { | 466 size_t sid_max, DICT_DATA_TYPE type, |
| 467 ots::OpenTypeCFF *out_cff) { |
| 464 for (unsigned i = 1; i < index.offsets.size(); ++i) { | 468 for (unsigned i = 1; i < index.offsets.size(); ++i) { |
| 465 if (type == DICT_DATA_TOPLEVEL) { | 469 if (type == DICT_DATA_TOPLEVEL) { |
| 466 out_cff->char_strings_array.push_back(new ots::CFFIndex); | 470 out_cff->char_strings_array.push_back(new ots::CFFIndex); |
| 467 } | 471 } |
| 468 size_t dict_length = index.offsets[i] - index.offsets[i - 1]; | 472 size_t dict_length = index.offsets[i] - index.offsets[i - 1]; |
| 469 ots::Buffer table(data + index.offsets[i - 1], dict_length); | 473 ots::Buffer table(data + index.offsets[i - 1], dict_length); |
| 470 | 474 |
| 471 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands; | 475 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands; |
| 472 | 476 |
| 473 FONT_FORMAT font_format = FORMAT_UNKNOWN; | 477 FONT_FORMAT font_format = FORMAT_UNKNOWN; |
| 474 bool have_ros = false; | 478 bool have_ros = false; |
| 475 uint16_t glyphs = 0; | 479 uint16_t charstring_glyphs = 0; |
| 476 size_t charset_offset = 0; | 480 size_t charset_offset = 0; |
| 477 | 481 |
| 478 while (table.offset() < dict_length) { | 482 while (table.offset() < dict_length) { |
| 479 if (!ParseDictDataReadNext(&table, &operands)) { | 483 if (!ParseDictDataReadNext(&table, &operands)) { |
| 480 return OTS_FAILURE(); | 484 return OTS_FAILURE(); |
| 481 } | 485 } |
| 482 if (operands.empty()) { | 486 if (operands.empty()) { |
| 483 return OTS_FAILURE(); | 487 return OTS_FAILURE(); |
| 484 } | 488 } |
| 485 if (operands.size() > 48) { | 489 if (operands.size() > 48) { |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 595 return OTS_FAILURE(); | 599 return OTS_FAILURE(); |
| 596 } | 600 } |
| 597 if (operands.back().first <= 1) { | 601 if (operands.back().first <= 1) { |
| 598 break; // predefined encoding, "Standard" or "Expert", is used. | 602 break; // predefined encoding, "Standard" or "Expert", is used. |
| 599 } | 603 } |
| 600 if (!CheckOffset(operands.back(), table_length)) { | 604 if (!CheckOffset(operands.back(), table_length)) { |
| 601 return OTS_FAILURE(); | 605 return OTS_FAILURE(); |
| 602 } | 606 } |
| 603 | 607 |
| 604 // parse sub dictionary INDEX. | 608 // parse sub dictionary INDEX. |
| 605 ots::Buffer table(data, table_length); | 609 ots::Buffer cff_table(data, table_length); |
| 606 table.set_offset(operands.back().first); | 610 cff_table.set_offset(operands.back().first); |
| 607 uint8_t format = 0; | 611 uint8_t format = 0; |
| 608 if (!table.ReadU8(&format)) { | 612 if (!cff_table.ReadU8(&format)) { |
| 609 return OTS_FAILURE(); | 613 return OTS_FAILURE(); |
| 610 } | 614 } |
| 611 if (format & 0x80) { | 615 if (format & 0x80) { |
| 612 // supplemental encoding is not supported at the moment. | 616 // supplemental encoding is not supported at the moment. |
| 613 return OTS_FAILURE(); | 617 return OTS_FAILURE(); |
| 614 } | 618 } |
| 615 // TODO(yusukes): support & parse supplemental encoding tables. | 619 // TODO(yusukes): support & parse supplemental encoding tables. |
| 616 break; | 620 break; |
| 617 } | 621 } |
| 618 | 622 |
| 619 case 17: { // CharStrings | 623 case 17: { // CharStrings |
| 620 if (type != DICT_DATA_TOPLEVEL) { | 624 if (type != DICT_DATA_TOPLEVEL) { |
| 621 return OTS_FAILURE(); | 625 return OTS_FAILURE(); |
| 622 } | 626 } |
| 623 if (operands.size() != 1) { | 627 if (operands.size() != 1) { |
| 624 return OTS_FAILURE(); | 628 return OTS_FAILURE(); |
| 625 } | 629 } |
| 626 if (!CheckOffset(operands.back(), table_length)) { | 630 if (!CheckOffset(operands.back(), table_length)) { |
| 627 return OTS_FAILURE(); | 631 return OTS_FAILURE(); |
| 628 } | 632 } |
| 629 // parse "14. CharStrings INDEX" | 633 // parse "14. CharStrings INDEX" |
| 630 ots::Buffer table(data, table_length); | 634 ots::Buffer cff_table(data, table_length); |
| 631 table.set_offset(operands.back().first); | 635 cff_table.set_offset(operands.back().first); |
| 632 ots::CFFIndex *charstring_index = out_cff->char_strings_array.back(); | 636 ots::CFFIndex *charstring_index = out_cff->char_strings_array.back(); |
| 633 if (!ParseIndex(&table, charstring_index)) { | 637 if (!ParseIndex(&cff_table, charstring_index)) { |
| 634 return OTS_FAILURE(); | 638 return OTS_FAILURE(); |
| 635 } | 639 } |
| 636 if (charstring_index->count < 2) { | 640 if (charstring_index->count < 2) { |
| 637 return OTS_FAILURE(); | 641 return OTS_FAILURE(); |
| 638 } | 642 } |
| 639 if (glyphs) { | 643 if (charstring_glyphs) { |
| 640 return OTS_FAILURE(); // multiple charstring tables? | 644 return OTS_FAILURE(); // multiple charstring tables? |
| 641 } | 645 } |
| 642 glyphs = charstring_index->count; | 646 charstring_glyphs = charstring_index->count; |
| 647 if (charstring_glyphs != glyphs) { |
| 648 return OTS_FAILURE(); // CFF and maxp have different number of glyp
hs? |
| 649 } |
| 643 break; | 650 break; |
| 644 } | 651 } |
| 645 | 652 |
| 646 case (12U << 8) + 36: { // FDArray | 653 case (12U << 8) + 36: { // FDArray |
| 647 if (type != DICT_DATA_TOPLEVEL) { | 654 if (type != DICT_DATA_TOPLEVEL) { |
| 648 return OTS_FAILURE(); | 655 return OTS_FAILURE(); |
| 649 } | 656 } |
| 650 if (operands.size() != 1) { | 657 if (operands.size() != 1) { |
| 651 return OTS_FAILURE(); | 658 return OTS_FAILURE(); |
| 652 } | 659 } |
| 653 if (!CheckOffset(operands.back(), table_length)) { | 660 if (!CheckOffset(operands.back(), table_length)) { |
| 654 return OTS_FAILURE(); | 661 return OTS_FAILURE(); |
| 655 } | 662 } |
| 656 | 663 |
| 657 // parse sub dictionary INDEX. | 664 // parse sub dictionary INDEX. |
| 658 ots::Buffer table(data, table_length); | 665 ots::Buffer cff_table(data, table_length); |
| 659 table.set_offset(operands.back().first); | 666 cff_table.set_offset(operands.back().first); |
| 660 ots::CFFIndex sub_dict_index; | 667 ots::CFFIndex sub_dict_index; |
| 661 if (!ParseIndex(&table, &sub_dict_index)) { | 668 if (!ParseIndex(&cff_table, &sub_dict_index)) { |
| 662 return OTS_FAILURE(); | 669 return OTS_FAILURE(); |
| 663 } | 670 } |
| 664 if (!ParseDictData(data, table_length, | 671 if (!ParseDictData(data, table_length, |
| 665 sub_dict_index, sid_max, DICT_DATA_FDARRAY, | 672 sub_dict_index, |
| 673 glyphs, sid_max, DICT_DATA_FDARRAY, |
| 666 out_cff)) { | 674 out_cff)) { |
| 667 return OTS_FAILURE(); | 675 return OTS_FAILURE(); |
| 668 } | 676 } |
| 669 if (out_cff->font_dict_length != 0) { | 677 if (out_cff->font_dict_length != 0) { |
| 670 return OTS_FAILURE(); // two or more FDArray found. | 678 return OTS_FAILURE(); // two or more FDArray found. |
| 671 } | 679 } |
| 672 out_cff->font_dict_length = sub_dict_index.count; | 680 out_cff->font_dict_length = sub_dict_index.count; |
| 673 break; | 681 break; |
| 674 } | 682 } |
| 675 | 683 |
| 676 case (12U << 8) + 37: { // FDSelect | 684 case (12U << 8) + 37: { // FDSelect |
| 677 if (type != DICT_DATA_TOPLEVEL) { | 685 if (type != DICT_DATA_TOPLEVEL) { |
| 678 return OTS_FAILURE(); | 686 return OTS_FAILURE(); |
| 679 } | 687 } |
| 680 if (operands.size() != 1) { | 688 if (operands.size() != 1) { |
| 681 return OTS_FAILURE(); | 689 return OTS_FAILURE(); |
| 682 } | 690 } |
| 683 if (!CheckOffset(operands.back(), table_length)) { | 691 if (!CheckOffset(operands.back(), table_length)) { |
| 684 return OTS_FAILURE(); | 692 return OTS_FAILURE(); |
| 685 } | 693 } |
| 686 | 694 |
| 687 // parse FDSelect data structure | 695 // parse FDSelect data structure |
| 688 ots::Buffer table(data, table_length); | 696 ots::Buffer cff_table(data, table_length); |
| 689 table.set_offset(operands.back().first); | 697 cff_table.set_offset(operands.back().first); |
| 690 uint8_t format = 0; | 698 uint8_t format = 0; |
| 691 if (!table.ReadU8(&format)) { | 699 if (!cff_table.ReadU8(&format)) { |
| 692 return OTS_FAILURE(); | 700 return OTS_FAILURE(); |
| 693 } | 701 } |
| 694 if (format == 0) { | 702 if (format == 0) { |
| 695 for (uint16_t j = 0; j < glyphs; ++j) { | 703 for (uint16_t j = 0; j < glyphs; ++j) { |
| 696 uint8_t fd_index = 0; | 704 uint8_t fd_index = 0; |
| 697 if (!table.ReadU8(&fd_index)) { | 705 if (!cff_table.ReadU8(&fd_index)) { |
| 698 return OTS_FAILURE(); | 706 return OTS_FAILURE(); |
| 699 } | 707 } |
| 700 (out_cff->fd_select)[j] = fd_index; | 708 (out_cff->fd_select)[j] = fd_index; |
| 701 } | 709 } |
| 702 } else if (format == 3) { | 710 } else if (format == 3) { |
| 703 uint16_t n_ranges = 0; | 711 uint16_t n_ranges = 0; |
| 704 if (!table.ReadU16(&n_ranges)) { | 712 if (!cff_table.ReadU16(&n_ranges)) { |
| 705 return OTS_FAILURE(); | 713 return OTS_FAILURE(); |
| 706 } | 714 } |
| 707 if (n_ranges == 0) { | 715 if (n_ranges == 0) { |
| 708 return OTS_FAILURE(); | 716 return OTS_FAILURE(); |
| 709 } | 717 } |
| 710 | 718 |
| 711 uint16_t last_gid = 0; | 719 uint16_t last_gid = 0; |
| 712 uint8_t fd_index = 0; | 720 uint8_t fd_index = 0; |
| 713 for (unsigned j = 0; j < n_ranges; ++j) { | 721 for (unsigned j = 0; j < n_ranges; ++j) { |
| 714 uint16_t first = 0; // GID | 722 uint16_t first = 0; // GID |
| 715 if (!table.ReadU16(&first)) { | 723 if (!cff_table.ReadU16(&first)) { |
| 716 return OTS_FAILURE(); | 724 return OTS_FAILURE(); |
| 717 } | 725 } |
| 718 | 726 |
| 719 // Sanity checks. | 727 // Sanity checks. |
| 720 if ((j == 0) && (first != 0)) { | 728 if ((j == 0) && (first != 0)) { |
| 721 return OTS_FAILURE(); | 729 return OTS_FAILURE(); |
| 722 } | 730 } |
| 723 if ((j != 0) && (last_gid >= first)) { | 731 if ((j != 0) && (last_gid >= first)) { |
| 724 return OTS_FAILURE(); // not increasing order. | 732 return OTS_FAILURE(); // not increasing order. |
| 725 } | 733 } |
| 726 | 734 |
| 727 // Copy the mapping to |out_cff->fd_select|. | 735 // Copy the mapping to |out_cff->fd_select|. |
| 728 if (j != 0) { | 736 if (j != 0) { |
| 729 for (uint16_t k = last_gid; k < first; ++k) { | 737 for (uint16_t k = last_gid; k < first; ++k) { |
| 730 if (!out_cff->fd_select.insert( | 738 if (!out_cff->fd_select.insert( |
| 731 std::make_pair(k, fd_index)).second) { | 739 std::make_pair(k, fd_index)).second) { |
| 732 return OTS_FAILURE(); | 740 return OTS_FAILURE(); |
| 733 } | 741 } |
| 734 } | 742 } |
| 735 } | 743 } |
| 736 | 744 |
| 737 if (!table.ReadU8(&fd_index)) { | 745 if (!cff_table.ReadU8(&fd_index)) { |
| 738 return OTS_FAILURE(); | 746 return OTS_FAILURE(); |
| 739 } | 747 } |
| 740 last_gid = first; | 748 last_gid = first; |
| 741 // TODO(yusukes): check GID? | 749 // TODO(yusukes): check GID? |
| 742 } | 750 } |
| 743 uint16_t sentinel = 0; | 751 uint16_t sentinel = 0; |
| 744 if (!table.ReadU16(&sentinel)) { | 752 if (!cff_table.ReadU16(&sentinel)) { |
| 745 return OTS_FAILURE(); | 753 return OTS_FAILURE(); |
| 746 } | 754 } |
| 747 if (last_gid >= sentinel) { | 755 if (last_gid >= sentinel) { |
| 748 return OTS_FAILURE(); | 756 return OTS_FAILURE(); |
| 749 } | 757 } |
| 750 for (uint16_t k = last_gid; k < sentinel; ++k) { | 758 for (uint16_t k = last_gid; k < sentinel; ++k) { |
| 751 if (!out_cff->fd_select.insert( | 759 if (!out_cff->fd_select.insert( |
| 752 std::make_pair(k, fd_index)).second) { | 760 std::make_pair(k, fd_index)).second) { |
| 753 return OTS_FAILURE(); | 761 return OTS_FAILURE(); |
| 754 } | 762 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 821 } | 829 } |
| 822 operands.clear(); | 830 operands.clear(); |
| 823 | 831 |
| 824 if (font_format == FORMAT_UNKNOWN) { | 832 if (font_format == FORMAT_UNKNOWN) { |
| 825 font_format = FORMAT_OTHER; | 833 font_format = FORMAT_OTHER; |
| 826 } | 834 } |
| 827 } | 835 } |
| 828 | 836 |
| 829 // parse "13. Charsets" | 837 // parse "13. Charsets" |
| 830 if (charset_offset) { | 838 if (charset_offset) { |
| 831 ots::Buffer table(data, table_length); | 839 ots::Buffer cff_table(data, table_length); |
| 832 table.set_offset(charset_offset); | 840 cff_table.set_offset(charset_offset); |
| 833 uint8_t format = 0; | 841 uint8_t format = 0; |
| 834 if (!table.ReadU8(&format)) { | 842 if (!cff_table.ReadU8(&format)) { |
| 835 return OTS_FAILURE(); | 843 return OTS_FAILURE(); |
| 836 } | 844 } |
| 837 switch (format) { | 845 switch (format) { |
| 838 case 0: | 846 case 0: |
| 839 for (uint16_t j = 1 /* .notdef is omitted */; j < glyphs; ++j) { | 847 for (uint16_t j = 1 /* .notdef is omitted */; j < glyphs; ++j) { |
| 840 uint16_t sid = 0; | 848 uint16_t sid = 0; |
| 841 if (!table.ReadU16(&sid)) { | 849 if (!cff_table.ReadU16(&sid)) { |
| 842 return OTS_FAILURE(); | 850 return OTS_FAILURE(); |
| 843 } | 851 } |
| 844 if (!have_ros && (sid > sid_max)) { | 852 if (!have_ros && (sid > sid_max)) { |
| 845 return OTS_FAILURE(); | 853 return OTS_FAILURE(); |
| 846 } | 854 } |
| 847 // TODO(yusukes): check CIDs when have_ros is true. | 855 // TODO(yusukes): check CIDs when have_ros is true. |
| 848 } | 856 } |
| 849 break; | 857 break; |
| 850 | 858 |
| 851 case 1: | 859 case 1: |
| 852 case 2: { | 860 case 2: { |
| 853 uint32_t total = 1; // .notdef is omitted. | 861 uint32_t total = 1; // .notdef is omitted. |
| 854 while (total < glyphs) { | 862 while (total < glyphs) { |
| 855 uint16_t sid = 0; | 863 uint16_t sid = 0; |
| 856 if (!table.ReadU16(&sid)) { | 864 if (!cff_table.ReadU16(&sid)) { |
| 857 return OTS_FAILURE(); | 865 return OTS_FAILURE(); |
| 858 } | 866 } |
| 859 if (!have_ros && (sid > sid_max)) { | 867 if (!have_ros && (sid > sid_max)) { |
| 860 return OTS_FAILURE(); | 868 return OTS_FAILURE(); |
| 861 } | 869 } |
| 862 // TODO(yusukes): check CIDs when have_ros is true. | 870 // TODO(yusukes): check CIDs when have_ros is true. |
| 863 | 871 |
| 864 if (format == 1) { | 872 if (format == 1) { |
| 865 uint8_t left = 0; | 873 uint8_t left = 0; |
| 866 if (!table.ReadU8(&left)) { | 874 if (!cff_table.ReadU8(&left)) { |
| 867 return OTS_FAILURE(); | 875 return OTS_FAILURE(); |
| 868 } | 876 } |
| 869 total += (left + 1); | 877 total += (left + 1); |
| 870 } else { | 878 } else { |
| 871 uint16_t left = 0; | 879 uint16_t left = 0; |
| 872 if (!table.ReadU16(&left)) { | 880 if (!cff_table.ReadU16(&left)) { |
| 873 return OTS_FAILURE(); | 881 return OTS_FAILURE(); |
| 874 } | 882 } |
| 875 total += (left + 1); | 883 total += (left + 1); |
| 876 } | 884 } |
| 877 } | 885 } |
| 878 break; | 886 break; |
| 879 } | 887 } |
| 880 | 888 |
| 881 default: | 889 default: |
| 882 return OTS_FAILURE(); | 890 return OTS_FAILURE(); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 // parse "10. String INDEX" | 960 // parse "10. String INDEX" |
| 953 table.set_offset(top_dict_index.offset_to_next); | 961 table.set_offset(top_dict_index.offset_to_next); |
| 954 CFFIndex string_index; | 962 CFFIndex string_index; |
| 955 if (!ParseIndex(&table, &string_index)) { | 963 if (!ParseIndex(&table, &string_index)) { |
| 956 return OTS_FAILURE(); | 964 return OTS_FAILURE(); |
| 957 } | 965 } |
| 958 if (string_index.count >= 65000 - kNStdString) { | 966 if (string_index.count >= 65000 - kNStdString) { |
| 959 return OTS_FAILURE(); | 967 return OTS_FAILURE(); |
| 960 } | 968 } |
| 961 | 969 |
| 970 const uint16_t num_glyphs = file->maxp->num_glyphs; |
| 962 const size_t sid_max = string_index.count + kNStdString; | 971 const size_t sid_max = string_index.count + kNStdString; |
| 963 // string_index.count == 0 is allowed. | 972 // string_index.count == 0 is allowed. |
| 964 | 973 |
| 965 // parse "9. Top DICT Data" | 974 // parse "9. Top DICT Data" |
| 966 if (!ParseDictData(data, length, top_dict_index, | 975 if (!ParseDictData(data, length, top_dict_index, |
| 967 sid_max, DICT_DATA_TOPLEVEL, file->cff)) { | 976 num_glyphs, sid_max, |
| 977 DICT_DATA_TOPLEVEL, file->cff)) { |
| 968 return OTS_FAILURE(); | 978 return OTS_FAILURE(); |
| 969 } | 979 } |
| 970 | 980 |
| 971 // parse "16. Global Subrs INDEX" | 981 // parse "16. Global Subrs INDEX" |
| 972 table.set_offset(string_index.offset_to_next); | 982 table.set_offset(string_index.offset_to_next); |
| 973 CFFIndex global_subrs_index; | 983 CFFIndex global_subrs_index; |
| 974 if (!ParseIndex(&table, &global_subrs_index)) { | 984 if (!ParseIndex(&table, &global_subrs_index)) { |
| 975 return OTS_FAILURE(); | 985 return OTS_FAILURE(); |
| 976 } | 986 } |
| 977 | 987 |
| 978 // Check if all fd_index in FDSelect are valid. | 988 // Check if all fd_index in FDSelect are valid. |
| 979 std::map<uint16_t, uint8_t>::const_iterator iter; | 989 std::map<uint16_t, uint8_t>::const_iterator iter; |
| 980 std::map<uint16_t, uint8_t>::const_iterator end = file->cff->fd_select.end(); | 990 std::map<uint16_t, uint8_t>::const_iterator end = file->cff->fd_select.end(); |
| 981 for (iter = file->cff->fd_select.begin(); iter != end; ++iter) { | 991 for (iter = file->cff->fd_select.begin(); iter != end; ++iter) { |
| 982 if (iter->second >= file->cff->font_dict_length) { | 992 if (iter->second >= file->cff->font_dict_length) { |
| 983 return OTS_FAILURE(); | 993 return OTS_FAILURE(); |
| 984 } | 994 } |
| 985 } | 995 } |
| 986 | 996 |
| 987 // Check if all charstrings (font hinting code for each glyph) are valid. | 997 // Check if all charstrings (font hinting code for each glyph) are valid. |
| 988 for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) { | 998 for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) { |
| 989 if (!ValidateType2CharStringIndex(*(file->cff->char_strings_array.at(i)), | 999 if (!ValidateType2CharStringIndex(file, |
| 1000 *(file->cff->char_strings_array.at(i)), |
| 990 global_subrs_index, | 1001 global_subrs_index, |
| 991 file->cff->fd_select, | 1002 file->cff->fd_select, |
| 992 file->cff->local_subrs_per_font, | 1003 file->cff->local_subrs_per_font, |
| 993 file->cff->local_subrs, | 1004 file->cff->local_subrs, |
| 994 &table)) { | 1005 &table)) { |
| 995 return OTS_FAILURE(); | 1006 return OTS_FAILURE_MSG("Failed validating charstring set %d", (int) i); |
| 996 } | 1007 } |
| 997 } | 1008 } |
| 998 | 1009 |
| 999 return true; | 1010 return true; |
| 1000 } | 1011 } |
| 1001 | 1012 |
| 1002 bool ots_cff_should_serialise(OpenTypeFile *file) { | 1013 bool ots_cff_should_serialise(OpenTypeFile *file) { |
| 1003 return file->cff != NULL; | 1014 return file->cff != NULL; |
| 1004 } | 1015 } |
| 1005 | 1016 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1019 } | 1030 } |
| 1020 for (size_t i = 0; i < file->cff->local_subrs_per_font.size(); ++i) { | 1031 for (size_t i = 0; i < file->cff->local_subrs_per_font.size(); ++i) { |
| 1021 delete (file->cff->local_subrs_per_font)[i]; | 1032 delete (file->cff->local_subrs_per_font)[i]; |
| 1022 } | 1033 } |
| 1023 delete file->cff->local_subrs; | 1034 delete file->cff->local_subrs; |
| 1024 delete file->cff; | 1035 delete file->cff; |
| 1025 } | 1036 } |
| 1026 } | 1037 } |
| 1027 | 1038 |
| 1028 } // namespace ots | 1039 } // namespace ots |
| 1040 |
| 1041 #undef TABLE_NAME |
| OLD | NEW |