Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: third_party/ots/src/woff2.cc

Issue 966703002: Updating OTS with new fixes for Color table from github (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixing file permissions Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/ots/src/woff2.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 // This is the implementation of decompression of the proposed WOFF Ultra 5 // This is the implementation of decompression of the proposed WOFF Ultra
6 // Condensed file format. 6 // Condensed file format.
7 7
8 #include <cassert> 8 #include <cassert>
9 #include <cstdlib> 9 #include <cstdlib>
10 #include <vector> 10 #include <vector>
(...skipping 27 matching lines...) Expand all
38 38
39 const size_t kSfntHeaderSize = 12; 39 const size_t kSfntHeaderSize = 12;
40 const size_t kSfntEntrySize = 16; 40 const size_t kSfntEntrySize = 16;
41 const size_t kCheckSumAdjustmentOffset = 8; 41 const size_t kCheckSumAdjustmentOffset = 8;
42 42
43 const size_t kEndPtsOfContoursOffset = 10; 43 const size_t kEndPtsOfContoursOffset = 10;
44 const size_t kCompositeGlyphBegin = 10; 44 const size_t kCompositeGlyphBegin = 10;
45 45
46 // Note that the byte order is big-endian, not the same as ots.cc 46 // Note that the byte order is big-endian, not the same as ots.cc
47 #define TAG(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d) 47 #define TAG(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d)
48 #define CHR(t) (t >> 24), (t >> 16), (t >> 8), (t >> 0)
48 49
49 const unsigned int kWoff2FlagsTransform = 1 << 5; 50 const unsigned int kWoff2FlagsTransform = 1 << 5;
50 51
51 const uint32_t kKnownTags[] = { 52 const uint32_t kKnownTags[] = {
52 TAG('c', 'm', 'a', 'p'), // 0 53 TAG('c', 'm', 'a', 'p'), // 0
53 TAG('h', 'e', 'a', 'd'), // 1 54 TAG('h', 'e', 'a', 'd'), // 1
54 TAG('h', 'h', 'e', 'a'), // 2 55 TAG('h', 'h', 'e', 'a'), // 2
55 TAG('h', 'm', 't', 'x'), // 3 56 TAG('h', 'm', 't', 'x'), // 3
56 TAG('m', 'a', 'x', 'p'), // 4 57 TAG('m', 'a', 'x', 'p'), // 4
57 TAG('n', 'a', 'm', 'e'), // 5 58 TAG('n', 'a', 'm', 'e'), // 5
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 129
129 uint32_t dst_offset; 130 uint32_t dst_offset;
130 uint32_t dst_length; 131 uint32_t dst_length;
131 132
132 Table() 133 Table()
133 : tag(0), 134 : tag(0),
134 flags(0), 135 flags(0),
135 transform_length(0), 136 transform_length(0),
136 dst_offset(0), 137 dst_offset(0),
137 dst_length(0) {} 138 dst_length(0) {}
139
140 bool operator<(const Table& other) const {
141 return tag < other.tag;
142 }
138 }; 143 };
139 144
140 // Based on section 6.1.1 of MicroType Express draft spec 145 // Based on section 6.1.1 of MicroType Express draft spec
141 bool Read255UShort(ots::Buffer* buf, uint16_t* value) { 146 bool Read255UShort(ots::Buffer* buf, uint16_t* value) {
142 static const uint8_t kWordCode = 253; 147 static const uint8_t kWordCode = 253;
143 static const uint8_t kOneMoreByteCode2 = 254; 148 static const uint8_t kOneMoreByteCode2 = 254;
144 static const uint8_t kOneMoreByteCode1 = 255; 149 static const uint8_t kOneMoreByteCode1 = 255;
145 static const uint8_t kLowestUCode = 253; 150 static const uint8_t kLowestUCode = 253;
146 uint8_t code = 0; 151 uint8_t code = 0;
147 if (!buf->ReadU8(&code)) { 152 if (!buf->ReadU8(&code)) {
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 if (index_format) { 507 if (index_format) {
503 offset = StoreU32(dst, offset, value); 508 offset = StoreU32(dst, offset, value);
504 } else { 509 } else {
505 offset = StoreU16(dst, offset, static_cast<uint16_t>(value >> 1)); 510 offset = StoreU16(dst, offset, static_cast<uint16_t>(value >> 1));
506 } 511 }
507 } 512 }
508 return true; 513 return true;
509 } 514 }
510 515
511 // Reconstruct entire glyf table based on transformed original 516 // Reconstruct entire glyf table based on transformed original
512 bool ReconstructGlyf(const uint8_t* data, size_t data_size, 517 bool ReconstructGlyf(ots::OpenTypeFile* file,
518 const uint8_t* data, size_t data_size,
513 uint8_t* dst, size_t dst_size, 519 uint8_t* dst, size_t dst_size,
514 uint8_t* loca_buf, size_t loca_size) { 520 uint8_t* loca_buf, size_t loca_size) {
515 static const int kNumSubStreams = 7; 521 static const int kNumSubStreams = 7;
516 ots::Buffer file(data, data_size); 522 ots::Buffer buffer(data, data_size);
517 uint32_t version; 523 uint32_t version;
518 std::vector<std::pair<const uint8_t*, size_t> > substreams(kNumSubStreams); 524 std::vector<std::pair<const uint8_t*, size_t> > substreams(kNumSubStreams);
519 525
520 if (!file.ReadU32(&version)) { 526 if (!buffer.ReadU32(&version)) {
521 return OTS_FAILURE(); 527 return OTS_FAILURE_MSG("Failed to read 'version' of transformed 'glyf' table ");
522 } 528 }
523 uint16_t num_glyphs; 529 uint16_t num_glyphs;
530 if (!buffer.ReadU16(&num_glyphs)) {
531 return OTS_FAILURE_MSG("Failed to read 'numGlyphs' from transformed 'glyf' t able");
532 }
524 uint16_t index_format; 533 uint16_t index_format;
525 if (!file.ReadU16(&num_glyphs) || 534 if (!buffer.ReadU16(&index_format)) {
526 !file.ReadU16(&index_format)) { 535 return OTS_FAILURE_MSG("Failed to read 'indexFormat' from transformed 'glyf' table");
527 return OTS_FAILURE();
528 } 536 }
529 unsigned int offset = (2 + kNumSubStreams) * 4; 537 unsigned int offset = (2 + kNumSubStreams) * 4;
530 if (offset > data_size) { 538 if (offset > data_size) {
531 return OTS_FAILURE(); 539 return OTS_FAILURE_MSG("Size of transformed 'glyf' table is too small to fit its data");
532 } 540 }
533 // Invariant from here on: data_size >= offset 541 // Invariant from here on: data_size >= offset
534 for (int i = 0; i < kNumSubStreams; ++i) { 542 for (int i = 0; i < kNumSubStreams; ++i) {
535 uint32_t substream_size; 543 uint32_t substream_size;
536 if (!file.ReadU32(&substream_size)) { 544 if (!buffer.ReadU32(&substream_size)) {
537 return OTS_FAILURE(); 545 return OTS_FAILURE_MSG("Failed to read substream size %d of transformed 'g lyf' table", i);
538 } 546 }
539 if (substream_size > data_size - offset) { 547 if (substream_size > data_size - offset) {
540 return OTS_FAILURE(); 548 return OTS_FAILURE_MSG("Size of substream %d of transformed 'glyf' table d oes not fit in table size");
541 } 549 }
542 substreams.at(i) = std::make_pair(data + offset, substream_size); 550 substreams.at(i) = std::make_pair(data + offset, substream_size);
543 offset += substream_size; 551 offset += substream_size;
544 } 552 }
545 ots::Buffer n_contour_stream(substreams.at(0).first, substreams.at(0).second); 553 ots::Buffer n_contour_stream(substreams.at(0).first, substreams.at(0).second);
546 ots::Buffer n_points_stream(substreams.at(1).first, substreams.at(1).second); 554 ots::Buffer n_points_stream(substreams.at(1).first, substreams.at(1).second);
547 ots::Buffer flag_stream(substreams.at(2).first, substreams.at(2).second); 555 ots::Buffer flag_stream(substreams.at(2).first, substreams.at(2).second);
548 ots::Buffer glyph_stream(substreams.at(3).first, substreams.at(3).second); 556 ots::Buffer glyph_stream(substreams.at(3).first, substreams.at(3).second);
549 ots::Buffer composite_stream(substreams.at(4).first, substreams.at(4).second); 557 ots::Buffer composite_stream(substreams.at(4).first, substreams.at(4).second);
550 ots::Buffer bbox_stream(substreams.at(5).first, substreams.at(5).second); 558 ots::Buffer bbox_stream(substreams.at(5).first, substreams.at(5).second);
551 ots::Buffer instruction_stream(substreams.at(6).first, 559 ots::Buffer instruction_stream(substreams.at(6).first,
552 substreams.at(6).second); 560 substreams.at(6).second);
553 561
554 std::vector<uint32_t> loca_values; 562 std::vector<uint32_t> loca_values;
555 loca_values.reserve(num_glyphs + 1); 563 loca_values.reserve(num_glyphs + 1);
556 std::vector<uint16_t> n_points_vec; 564 std::vector<uint16_t> n_points_vec;
557 std::vector<Point> points; 565 std::vector<Point> points;
558 uint32_t loca_offset = 0; 566 uint32_t loca_offset = 0;
559 for (unsigned int i = 0; i < num_glyphs; ++i) { 567 for (unsigned int i = 0; i < num_glyphs; ++i) {
560 size_t glyph_size = 0; 568 size_t glyph_size = 0;
561 uint16_t n_contours = 0; 569 uint16_t n_contours = 0;
562 if (!n_contour_stream.ReadU16(&n_contours)) { 570 if (!n_contour_stream.ReadU16(&n_contours)) {
563 return OTS_FAILURE(); 571 return OTS_FAILURE_MSG("Filed to read 'numberOfContours' of glyph %d from transformed 'glyf' table", i);
564 } 572 }
565 uint8_t* glyf_dst = dst + loca_offset; 573 uint8_t* glyf_dst = dst + loca_offset;
566 size_t glyf_dst_size = dst_size - loca_offset; 574 size_t glyf_dst_size = dst_size - loca_offset;
567 if (n_contours == 0xffff) { 575 if (n_contours == 0xffff) {
568 // composite glyph 576 // composite glyph
569 bool have_instructions = false; 577 bool have_instructions = false;
570 uint16_t instruction_size = 0; 578 uint16_t instruction_size = 0;
571 if (!ProcessComposite(&composite_stream, glyf_dst, glyf_dst_size, 579 if (!ProcessComposite(&composite_stream, glyf_dst, glyf_dst_size,
572 &glyph_size, &have_instructions)) { 580 &glyph_size, &have_instructions)) {
573 return OTS_FAILURE(); 581 return OTS_FAILURE_MSG("Filed to process composite glyph %d from transfo rmed 'glyf' table", i);
574 } 582 }
575 if (have_instructions) { 583 if (have_instructions) {
576 if (!Read255UShort(&glyph_stream, &instruction_size)) { 584 if (!Read255UShort(&glyph_stream, &instruction_size)) {
577 return OTS_FAILURE(); 585 return OTS_FAILURE_MSG("Failed to read 'instructionLength' of glyph %d from transformed 'glyf' table", i);
578 } 586 }
579 // No integer overflow here (instruction_size < 2^16). 587 // No integer overflow here (instruction_size < 2^16).
580 if (instruction_size + 2U > glyf_dst_size - glyph_size) { 588 if (instruction_size + 2U > glyf_dst_size - glyph_size) {
581 return OTS_FAILURE(); 589 return OTS_FAILURE_MSG("'instructionLength' of glyph %d from transform ed 'glyf' table does not fit in the destination glyph size", i);
582 } 590 }
583 StoreU16(glyf_dst, glyph_size, instruction_size); 591 StoreU16(glyf_dst, glyph_size, instruction_size);
584 if (!instruction_stream.Read(glyf_dst + glyph_size + 2, 592 if (!instruction_stream.Read(glyf_dst + glyph_size + 2,
585 instruction_size)) { 593 instruction_size)) {
586 return OTS_FAILURE(); 594 return OTS_FAILURE_MSG("Filed to read instructions of glyph %d from tr ansformed 'glyf' table", i);
587 } 595 }
588 glyph_size += instruction_size + 2; 596 glyph_size += instruction_size + 2;
589 } 597 }
590 } else if (n_contours > 0) { 598 } else if (n_contours > 0) {
591 // simple glyph 599 // simple glyph
592 n_points_vec.clear(); 600 n_points_vec.clear();
593 points.clear(); 601 points.clear();
594 uint32_t total_n_points = 0; 602 uint32_t total_n_points = 0;
595 uint16_t n_points_contour; 603 uint16_t n_points_contour;
596 for (uint32_t j = 0; j < n_contours; ++j) { 604 for (uint32_t j = 0; j < n_contours; ++j) {
597 if (!Read255UShort(&n_points_stream, &n_points_contour)) { 605 if (!Read255UShort(&n_points_stream, &n_points_contour)) {
598 return OTS_FAILURE(); 606 return OTS_FAILURE_MSG("Filed to read number of points of contour %d o f glyph %d from transformed 'glyf' table", j, i);
599 } 607 }
600 n_points_vec.push_back(n_points_contour); 608 n_points_vec.push_back(n_points_contour);
601 if (total_n_points + n_points_contour < total_n_points) { 609 if (total_n_points + n_points_contour < total_n_points) {
602 return OTS_FAILURE(); 610 return OTS_FAILURE_MSG("Negative number of points of contour %d of gly ph %d from transformed 'glyf' table", j, i);
603 } 611 }
604 total_n_points += n_points_contour; 612 total_n_points += n_points_contour;
605 } 613 }
606 uint32_t flag_size = total_n_points; 614 uint32_t flag_size = total_n_points;
607 if (flag_size > flag_stream.length() - flag_stream.offset()) { 615 if (flag_size > flag_stream.length() - flag_stream.offset()) {
608 return OTS_FAILURE(); 616 return OTS_FAILURE();
609 } 617 }
610 const uint8_t* flags_buf = flag_stream.buffer() + flag_stream.offset(); 618 const uint8_t* flags_buf = flag_stream.buffer() + flag_stream.offset();
611 const uint8_t* triplet_buf = glyph_stream.buffer() + 619 const uint8_t* triplet_buf = glyph_stream.buffer() +
612 glyph_stream.offset(); 620 glyph_stream.offset();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
647 instruction_size + 2U) { 655 instruction_size + 2U) {
648 return OTS_FAILURE(); 656 return OTS_FAILURE();
649 } 657 }
650 uint8_t* instruction_dst = glyf_dst + header_and_endpts_contours_size; 658 uint8_t* instruction_dst = glyf_dst + header_and_endpts_contours_size;
651 StoreU16(instruction_dst, 0, instruction_size); 659 StoreU16(instruction_dst, 0, instruction_size);
652 if (!instruction_stream.Read(instruction_dst + 2, instruction_size)) { 660 if (!instruction_stream.Read(instruction_dst + 2, instruction_size)) {
653 return OTS_FAILURE(); 661 return OTS_FAILURE();
654 } 662 }
655 if (!StorePoints(points, n_contours, instruction_size, 663 if (!StorePoints(points, n_contours, instruction_size,
656 glyf_dst, glyf_dst_size, &glyph_size)) { 664 glyf_dst, glyf_dst_size, &glyph_size)) {
657 return OTS_FAILURE(); 665 return OTS_FAILURE_MSG("Failed to store points of glyph %d from the tran sformed 'glyf' table", i);
658 } 666 }
659 } else { 667 } else {
660 glyph_size = 0; 668 glyph_size = 0;
661 } 669 }
662 loca_values.push_back(loca_offset); 670 loca_values.push_back(loca_offset);
663 if (glyph_size + 3 < glyph_size) { 671 if (glyph_size + 3 < glyph_size) {
664 return OTS_FAILURE(); 672 return OTS_FAILURE();
665 } 673 }
666 glyph_size = ots::Round2(glyph_size); 674 glyph_size = ots::Round2(glyph_size);
667 if (glyph_size > dst_size - loca_offset) { 675 if (glyph_size > dst_size - loca_offset) {
668 // This shouldn't happen, but this test defensively maintains the 676 // This shouldn't happen, but this test defensively maintains the
669 // invariant that loca_offset <= dst_size. 677 // invariant that loca_offset <= dst_size.
670 return OTS_FAILURE(); 678 return OTS_FAILURE();
671 } 679 }
672 loca_offset += glyph_size; 680 loca_offset += glyph_size;
673 } 681 }
674 loca_values.push_back(loca_offset); 682 loca_values.push_back(loca_offset);
675 assert(loca_values.size() == static_cast<size_t>(num_glyphs + 1)); 683 assert(loca_values.size() == static_cast<size_t>(num_glyphs + 1));
676 if (!ProcessBboxStream(&bbox_stream, num_glyphs, loca_values, 684 if (!ProcessBboxStream(&bbox_stream, num_glyphs, loca_values,
677 dst, dst_size)) { 685 dst, dst_size)) {
678 return OTS_FAILURE(); 686 return OTS_FAILURE_MSG("Filed to process 'bboxStream' from the transformed ' glyf' table");
679 } 687 }
680 return StoreLoca(loca_values, index_format, loca_buf, loca_size); 688 return StoreLoca(loca_values, index_format, loca_buf, loca_size);
681 } 689 }
682 690
683 // This is linear search, but could be changed to binary because we 691 // This is linear search, but could be changed to binary because we
684 // do have a guarantee that the tables are sorted by tag. But the total 692 // do have a guarantee that the tables are sorted by tag. But the total
685 // cpu time is expected to be very small in any case. 693 // cpu time is expected to be very small in any case.
686 const Table* FindTable(const std::vector<Table>& tables, uint32_t tag) { 694 const Table* FindTable(const std::vector<Table>& tables, uint32_t tag) {
687 size_t n_tables = tables.size(); 695 size_t n_tables = tables.size();
688 for (size_t i = 0; i < n_tables; ++i) { 696 for (size_t i = 0; i < n_tables; ++i) {
689 if (tables.at(i).tag == tag) { 697 if (tables.at(i).tag == tag) {
690 return &tables.at(i); 698 return &tables.at(i);
691 } 699 }
692 } 700 }
693 return NULL; 701 return NULL;
694 } 702 }
695 703
696 bool ReconstructTransformed(const std::vector<Table>& tables, uint32_t tag, 704 bool ReconstructTransformed(ots::OpenTypeFile* file,
705 const std::vector<Table>& tables, uint32_t tag,
697 const uint8_t* transformed_buf, size_t transformed_size, 706 const uint8_t* transformed_buf, size_t transformed_size,
698 uint8_t* dst, size_t dst_length) { 707 uint8_t* dst, size_t dst_length) {
699 if (tag == TAG('g', 'l', 'y', 'f')) { 708 if (tag == TAG('g', 'l', 'y', 'f')) {
700 const Table* glyf_table = FindTable(tables, tag); 709 const Table* glyf_table = FindTable(tables, tag);
701 const Table* loca_table = FindTable(tables, TAG('l', 'o', 'c', 'a')); 710 const Table* loca_table = FindTable(tables, TAG('l', 'o', 'c', 'a'));
702 if (glyf_table == NULL || loca_table == NULL) { 711 if (glyf_table == NULL || loca_table == NULL) {
703 return OTS_FAILURE(); 712 return OTS_FAILURE();
704 } 713 }
705 if (static_cast<uint64_t>(glyf_table->dst_offset) + glyf_table->dst_length > 714 if (static_cast<uint64_t>(glyf_table->dst_offset) + glyf_table->dst_length >
706 dst_length) { 715 dst_length) {
707 return OTS_FAILURE(); 716 return OTS_FAILURE();
708 } 717 }
709 if (static_cast<uint64_t>(loca_table->dst_offset) + loca_table->dst_length > 718 if (static_cast<uint64_t>(loca_table->dst_offset) + loca_table->dst_length >
710 dst_length) { 719 dst_length) {
711 return OTS_FAILURE(); 720 return OTS_FAILURE();
712 } 721 }
713 return ReconstructGlyf(transformed_buf, transformed_size, 722 return ReconstructGlyf(file, transformed_buf, transformed_size,
714 dst + glyf_table->dst_offset, glyf_table->dst_length, 723 dst + glyf_table->dst_offset, glyf_table->dst_length,
715 dst + loca_table->dst_offset, loca_table->dst_length); 724 dst + loca_table->dst_offset, loca_table->dst_length);
716 } else if (tag == TAG('l', 'o', 'c', 'a')) { 725 } else if (tag == TAG('l', 'o', 'c', 'a')) {
717 // processing was already done by glyf table, but validate 726 // processing was already done by glyf table, but validate
718 if (!FindTable(tables, TAG('g', 'l', 'y', 'f'))) { 727 if (!FindTable(tables, TAG('g', 'l', 'y', 'f'))) {
719 return OTS_FAILURE(); 728 return OTS_FAILURE();
720 } 729 }
721 } else { 730 } else {
722 // transform for the tag is not known 731 // transform for the tag is not known
723 return OTS_FAILURE(); 732 return OTS_FAILURE();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 return OTS_FAILURE_MSG("Bits 6 and 7 are not 0 for table directory entry % d", i); 805 return OTS_FAILURE_MSG("Bits 6 and 7 are not 0 for table directory entry % d", i);
797 } 806 }
798 uint32_t flags = 0; 807 uint32_t flags = 0;
799 // Always transform the glyf and loca tables 808 // Always transform the glyf and loca tables
800 if (tag == TAG('g', 'l', 'y', 'f') || 809 if (tag == TAG('g', 'l', 'y', 'f') ||
801 tag == TAG('l', 'o', 'c', 'a')) { 810 tag == TAG('l', 'o', 'c', 'a')) {
802 flags |= kWoff2FlagsTransform; 811 flags |= kWoff2FlagsTransform;
803 } 812 }
804 uint32_t dst_length; 813 uint32_t dst_length;
805 if (!ReadBase128(buffer, &dst_length)) { 814 if (!ReadBase128(buffer, &dst_length)) {
806 return OTS_FAILURE_MSG("Failed to read \"origLength\" for table %4.4s", (c har*)&tag); 815 return OTS_FAILURE_MSG("Failed to read 'origLength' for table '%c%c%c%c'", CHR(tag));
807 } 816 }
808 uint32_t transform_length = dst_length; 817 uint32_t transform_length = dst_length;
809 if ((flags & kWoff2FlagsTransform) != 0) { 818 if ((flags & kWoff2FlagsTransform) != 0) {
810 if (!ReadBase128(buffer, &transform_length)) { 819 if (!ReadBase128(buffer, &transform_length)) {
811 return OTS_FAILURE_MSG("Failed to read \"transformLength\" for table %4. 4s", (char*)&tag); 820 return OTS_FAILURE_MSG("Failed to read 'transformLength' for table '%c%c %c%c'", CHR(tag));
812 } 821 }
813 } 822 }
814 // Disallow huge numbers (> 1GB) for sanity. 823 // Disallow huge numbers (> 1GB) for sanity.
815 if (transform_length > 1024 * 1024 * 1024 || 824 if (transform_length > 1024 * 1024 * 1024 ||
816 dst_length > 1024 * 1024 * 1024) { 825 dst_length > 1024 * 1024 * 1024) {
817 return OTS_FAILURE_MSG("\"origLength\" or \"transformLength\" > 1GB"); 826 return OTS_FAILURE_MSG("'origLength' or 'transformLength' > 1GB");
818 } 827 }
819 table->tag = tag; 828 table->tag = tag;
820 table->flags = flags; 829 table->flags = flags;
821 table->transform_length = transform_length; 830 table->transform_length = transform_length;
822 table->dst_length = dst_length; 831 table->dst_length = dst_length;
823 } 832 }
824 return true; 833 return true;
825 } 834 }
826 835
827 } // namespace 836 } // namespace
828 837
829 namespace ots { 838 namespace ots {
830 839
831 size_t ComputeWOFF2FinalSize(const uint8_t* data, size_t length) { 840 size_t ComputeWOFF2FinalSize(const uint8_t* data, size_t length) {
832 ots::Buffer file(data, length); 841 ots::Buffer file(data, length);
833 uint32_t total_length; 842 uint32_t total_length;
834 843
835 if (!file.Skip(16) || 844 if (!file.Skip(16) ||
836 !file.ReadU32(&total_length)) { 845 !file.ReadU32(&total_length)) {
837 return 0; 846 return 0;
838 } 847 }
839 return total_length; 848 return total_length;
840 } 849 }
841 850
842 bool ConvertWOFF2ToTTF(ots::OpenTypeFile* file, 851 bool ConvertWOFF2ToSFNT(ots::OpenTypeFile* file,
843 uint8_t* result, size_t result_length, 852 uint8_t* result, size_t result_length,
844 const uint8_t* data, size_t length) { 853 const uint8_t* data, size_t length) {
845 static const uint32_t kWoff2Signature = 0x774f4632; // "wOF2" 854 static const uint32_t kWoff2Signature = 0x774f4632; // "wOF2"
846 ots::Buffer buffer(data, length); 855 ots::Buffer buffer(data, length);
847 856
848 uint32_t signature; 857 uint32_t signature;
849 uint32_t flavor = 0; 858 uint32_t flavor = 0;
850 if (!buffer.ReadU32(&signature) || signature != kWoff2Signature || 859 if (!buffer.ReadU32(&signature) || signature != kWoff2Signature ||
851 !buffer.ReadU32(&flavor)) { 860 !buffer.ReadU32(&flavor)) {
852 return OTS_FAILURE_MSG("Failed to read \"signature\" or \"flavor\", or not W OFF2 signature"); 861 return OTS_FAILURE_MSG("Failed to read 'signature' or 'flavor', or not WOFF2 signature");
853 } 862 }
854 863
855 if (!IsValidVersionTag(ntohl(flavor))) { 864 if (!IsValidVersionTag(ntohl(flavor))) {
856 return OTS_FAILURE_MSG("Invalid \"flavor\""); 865 return OTS_FAILURE_MSG("Invalid 'flavor'");
857 } 866 }
858 867
859 uint32_t reported_length; 868 uint32_t reported_length;
860 if (!buffer.ReadU32(&reported_length) || length != reported_length) { 869 if (!buffer.ReadU32(&reported_length) || length != reported_length) {
861 return OTS_FAILURE_MSG("Failed to read \"length\" or it does not match the a ctual file size"); 870 return OTS_FAILURE_MSG("Failed to read 'length' or it does not match the act ual file size");
862 } 871 }
863 uint16_t num_tables; 872 uint16_t num_tables;
864 if (!buffer.ReadU16(&num_tables) || !num_tables) { 873 if (!buffer.ReadU16(&num_tables) || !num_tables) {
865 return OTS_FAILURE_MSG("Failed to read \"numTables\""); 874 return OTS_FAILURE_MSG("Failed to read 'numTables'");
866 } 875 }
876
877 uint16_t reserved_value;
878 if (!buffer.ReadU16(&reserved_value)) {
879 return OTS_FAILURE_MSG("Failed to read 'reserved' field");
880 }
881
867 // We don't care about these fields of the header: 882 // We don't care about these fields of the header:
868 // uint16_t reserved 883 // uint32_t total_sfnt_size, the caller already passes it as result_length
869 // uint32_t total_sfnt_size 884 if (!buffer.Skip(4)) {
870 if (!buffer.Skip(6)) { 885 return OTS_FAILURE_MSG("Failed to read 'totalSfntSize'");
871 return OTS_FAILURE_MSG("Failed to read \"reserve\" or \"totalSfntSize\"");
872 } 886 }
873 uint32_t compressed_length; 887 uint32_t compressed_length;
874 if (!buffer.ReadU32(&compressed_length)) { 888 if (!buffer.ReadU32(&compressed_length)) {
875 return OTS_FAILURE_MSG("Failed to read \"totalCompressedSize\""); 889 return OTS_FAILURE_MSG("Failed to read 'totalCompressedSize'");
876 } 890 }
877 if (compressed_length > std::numeric_limits<uint32_t>::max()) { 891 if (compressed_length > std::numeric_limits<uint32_t>::max()) {
878 return OTS_FAILURE(); 892 return OTS_FAILURE();
879 } 893 }
880 894
881 // We don't care about these fields of the header: 895 // We don't care about these fields of the header:
882 // uint16_t major_version, minor_version 896 // uint16_t major_version, minor_version
883 // uint32_t meta_offset, meta_length, meta_orig_length 897 if (!buffer.Skip(2 * 2)) {
884 // uint32_t priv_offset, priv_length 898 return OTS_FAILURE_MSG("Failed to read 'majorVersion' or 'minorVersion'");
885 if (!buffer.Skip(24)) {
886 return OTS_FAILURE();
887 } 899 }
900
901 // Checks metadata block size.
902 uint32_t meta_offset;
903 uint32_t meta_length;
904 uint32_t meta_length_orig;
905 if (!buffer.ReadU32(&meta_offset) ||
906 !buffer.ReadU32(&meta_length) ||
907 !buffer.ReadU32(&meta_length_orig)) {
908 return OTS_FAILURE_MSG("Failed to read header metadata block fields");
909 }
910 if (meta_offset) {
911 if (meta_offset >= length || length - meta_offset < meta_length) {
912 return OTS_FAILURE_MSG("Invalid metadata block offset or length");
913 }
914 }
915
916 // Checks private data block size.
917 uint32_t priv_offset;
918 uint32_t priv_length;
919 if (!buffer.ReadU32(&priv_offset) ||
920 !buffer.ReadU32(&priv_length)) {
921 return OTS_FAILURE_MSG("Failed to read header private block fields");
922 }
923 if (priv_offset) {
924 if (priv_offset >= length || length - priv_offset < priv_length) {
925 return OTS_FAILURE_MSG("Invalid private block offset or length");
926 }
927 }
928
888 std::vector<Table> tables(num_tables); 929 std::vector<Table> tables(num_tables);
889 if (!ReadTableDirectory(file, &buffer, &tables, num_tables)) { 930 if (!ReadTableDirectory(file, &buffer, &tables, num_tables)) {
890 return OTS_FAILURE_MSG("Failed to read table directory"); 931 return OTS_FAILURE_MSG("Failed to read table directory");
891 } 932 }
892 uint64_t compressed_offset = buffer.offset(); 933 uint64_t compressed_offset = buffer.offset();
893 if (compressed_offset > std::numeric_limits<uint32_t>::max()) { 934 if (compressed_offset > std::numeric_limits<uint32_t>::max()) {
894 return OTS_FAILURE(); 935 return OTS_FAILURE();
895 } 936 }
896 uint64_t dst_offset = kSfntHeaderSize + 937 uint64_t dst_offset = kSfntHeaderSize +
897 kSfntEntrySize * static_cast<uint64_t>(num_tables); 938 kSfntEntrySize * static_cast<uint64_t>(num_tables);
898 for (uint16_t i = 0; i < num_tables; ++i) { 939 for (uint16_t i = 0; i < num_tables; ++i) {
899 Table* table = &tables.at(i); 940 Table* table = &tables.at(i);
900 table->dst_offset = static_cast<uint32_t>(dst_offset); 941 table->dst_offset = static_cast<uint32_t>(dst_offset);
901 dst_offset += table->dst_length; 942 dst_offset += table->dst_length;
902 if (dst_offset > std::numeric_limits<uint32_t>::max()) { 943 if (dst_offset > std::numeric_limits<uint32_t>::max()) {
903 return OTS_FAILURE(); 944 return OTS_FAILURE();
904 } 945 }
905 dst_offset = ots::Round4(dst_offset); 946 dst_offset = ots::Round4(dst_offset);
906 } 947 }
907 if (ots::Round4(compressed_offset + compressed_length) > length || dst_offset > result_length) { 948
908 return OTS_FAILURE(); 949 uint64_t block_end = ots::Round4(compressed_offset + compressed_length);
950 if (block_end > length || dst_offset != result_length) {
951 return OTS_FAILURE_MSG("Uncompressed sfnt size mismatch");
909 } 952 }
910 953
911 const uint32_t sfnt_header_and_table_directory_size = 12 + 16 * num_tables; 954 const uint32_t sfnt_header_and_table_directory_size = 12 + 16 * num_tables;
912 if (sfnt_header_and_table_directory_size > result_length) { 955 if (sfnt_header_and_table_directory_size > result_length) {
913 return OTS_FAILURE(); 956 return OTS_FAILURE();
914 } 957 }
915 958
959 if (meta_offset) {
960 if (block_end != meta_offset) {
961 return OTS_FAILURE_MSG("Invalid metadata block offset");
962 }
963 block_end = ots::Round4(static_cast<uint64_t>(meta_offset) +
964 static_cast<uint64_t>(meta_length));
965 if (block_end > std::numeric_limits<uint32_t>::max()) {
966 return OTS_FAILURE_MSG("Invalid metadata block length");
967 }
968 }
969
970 if (priv_offset) {
971 if (block_end != priv_offset) {
972 return OTS_FAILURE_MSG("Invalid private block offset");
973 }
974 block_end = ots::Round4(static_cast<uint64_t>(priv_offset) +
975 static_cast<uint64_t>(priv_length));
976 if (block_end > std::numeric_limits<uint32_t>::max()) {
977 return OTS_FAILURE_MSG("Invalid private block length");
978 }
979 }
980
981 if (block_end != ots::Round4(length)) {
982 return OTS_FAILURE_MSG("File length mismatch (trailing junk?)");
983 }
984
916 // Start building the font 985 // Start building the font
917 size_t offset = 0; 986 size_t offset = 0;
918 offset = StoreU32(result, offset, flavor); 987 offset = StoreU32(result, offset, flavor);
919 offset = StoreU16(result, offset, num_tables); 988 offset = StoreU16(result, offset, num_tables);
920 uint8_t max_pow2 = 0; 989 uint8_t max_pow2 = 0;
921 while (1u << (max_pow2 + 1) <= num_tables) { 990 while (1u << (max_pow2 + 1) <= num_tables) {
922 max_pow2++; 991 max_pow2++;
923 } 992 }
924 const uint16_t output_search_range = (1u << max_pow2) << 4; 993 const uint16_t output_search_range = (1u << max_pow2) << 4;
925 offset = StoreU16(result, offset, output_search_range); 994 offset = StoreU16(result, offset, output_search_range);
926 offset = StoreU16(result, offset, max_pow2); 995 offset = StoreU16(result, offset, max_pow2);
927 offset = StoreU16(result, offset, (num_tables << 4) - output_search_range); 996 offset = StoreU16(result, offset, (num_tables << 4) - output_search_range);
997
998 // sort tags in the table directory in ascending alphabetical order
999 std::vector<Table> sorted_tables(tables);
1000 std::sort(sorted_tables.begin(), sorted_tables.end());
1001
928 for (uint16_t i = 0; i < num_tables; ++i) { 1002 for (uint16_t i = 0; i < num_tables; ++i) {
929 const Table* table = &tables.at(i); 1003 const Table* table = &sorted_tables.at(i);
930 offset = StoreU32(result, offset, table->tag); 1004 offset = StoreU32(result, offset, table->tag);
931 offset = StoreU32(result, offset, 0); // checksum, to fill in later 1005 offset = StoreU32(result, offset, 0); // checksum, to fill in later
932 offset = StoreU32(result, offset, table->dst_offset); 1006 offset = StoreU32(result, offset, table->dst_offset);
933 offset = StoreU32(result, offset, table->dst_length); 1007 offset = StoreU32(result, offset, table->dst_length);
934 } 1008 }
935 std::vector<uint8_t> uncompressed_buf; 1009 std::vector<uint8_t> uncompressed_buf;
936 const uint8_t* transform_buf = NULL; 1010 const uint8_t* transform_buf = NULL;
937 uint64_t total_size = 0; 1011 uint64_t total_size = 0;
938 1012
939 for (uint16_t i = 0; i < num_tables; ++i) { 1013 for (uint16_t i = 0; i < num_tables; ++i) {
940 total_size += tables.at(i).transform_length; 1014 total_size += tables.at(i).transform_length;
941 if (total_size > std::numeric_limits<uint32_t>::max()) { 1015 if (total_size > std::numeric_limits<uint32_t>::max()) {
942 return OTS_FAILURE(); 1016 return OTS_FAILURE();
943 } 1017 }
944 } 1018 }
945 // Enforce same 30M limit on uncompressed tables as OTS 1019 // Enforce same 30M limit on uncompressed tables as OTS
946 if (total_size > 30 * 1024 * 1024) { 1020 if (total_size > 30 * 1024 * 1024) {
947 return OTS_FAILURE(); 1021 return OTS_FAILURE();
948 } 1022 }
949 const size_t total_size_size_t = static_cast<size_t>(total_size); 1023 const size_t total_size_size_t = static_cast<size_t>(total_size);
950 uncompressed_buf.resize(total_size_size_t); 1024 uncompressed_buf.resize(total_size_size_t);
951 const uint8_t* src_buf = data + compressed_offset; 1025 const uint8_t* src_buf = data + compressed_offset;
952 if (!Woff2Uncompress(&uncompressed_buf[0], total_size_size_t, 1026 if (!Woff2Uncompress(&uncompressed_buf[0], total_size_size_t,
953 src_buf, compressed_length)) { 1027 src_buf, compressed_length)) {
954 return OTS_FAILURE(); 1028 return OTS_FAILURE_MSG("Failed to uncompress font data");
955 } 1029 }
956 transform_buf = &uncompressed_buf[0]; 1030 transform_buf = &uncompressed_buf[0];
957 1031
958 for (uint16_t i = 0; i < num_tables; ++i) { 1032 for (uint16_t i = 0; i < num_tables; ++i) {
959 const Table* table = &tables.at(i); 1033 const Table* table = &tables.at(i);
960 uint32_t flags = table->flags; 1034 uint32_t flags = table->flags;
961 size_t transform_length = table->transform_length; 1035 size_t transform_length = table->transform_length;
962 1036
963 if ((flags & kWoff2FlagsTransform) == 0) { 1037 if ((flags & kWoff2FlagsTransform) == 0) {
964 if (transform_length != table->dst_length) { 1038 if (transform_length != table->dst_length) {
965 return OTS_FAILURE(); 1039 return OTS_FAILURE();
966 } 1040 }
967 if (static_cast<uint64_t>(table->dst_offset) + transform_length > 1041 if (static_cast<uint64_t>(table->dst_offset) + transform_length >
968 result_length) { 1042 result_length) {
969 return OTS_FAILURE(); 1043 return OTS_FAILURE();
970 } 1044 }
971 std::memcpy(result + table->dst_offset, transform_buf, 1045 std::memcpy(result + table->dst_offset, transform_buf,
972 transform_length); 1046 transform_length);
973 } else { 1047 } else {
974 if (!ReconstructTransformed(tables, table->tag, 1048 if (!ReconstructTransformed(file, tables, table->tag,
975 transform_buf, transform_length, result, result_length)) { 1049 transform_buf, transform_length, result, result_length)) {
976 return OTS_FAILURE(); 1050 return OTS_FAILURE_MSG("Failed to reconstruct '%c%c%c%c' table", CHR(tab le->tag));
977 } 1051 }
978 } 1052 }
979 1053
980 transform_buf += transform_length; 1054 transform_buf += transform_length;
981 if (transform_buf > &uncompressed_buf[0] + uncompressed_buf.size()) { 1055 if (transform_buf > &uncompressed_buf[0] + uncompressed_buf.size()) {
982 return OTS_FAILURE(); 1056 return OTS_FAILURE();
983 } 1057 }
984 } 1058 }
985 1059
986 return FixChecksums(tables, result); 1060 return FixChecksums(sorted_tables, result);
987 } 1061 }
988 1062
989 } // namespace ots 1063 } // namespace ots
990 1064
991 #undef TABLE_NAME 1065 #undef TABLE_NAME
OLDNEW
« no previous file with comments | « third_party/ots/src/woff2.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698