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

Side by Side Diff: src/cff_type2_charstring.cc

Issue 658573004: Updating to new OTS repo from https://github.com/khaledhosny/ots.git (Closed) Base URL: https://chromium.googlesource.com/external/ots@master
Patch Set: Adding Colored Emoji changes from external/git repo Created 6 years, 2 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
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 // A parser for the Type 2 Charstring Format. 5 // A parser for the Type 2 Charstring Format.
6 // http://www.adobe.com/devnet/font/pdfs/5177.Type2.pdf 6 // http://www.adobe.com/devnet/font/pdfs/5177.Type2.pdf
7 7
8 #include "cff_type2_charstring.h" 8 #include "cff_type2_charstring.h"
9 9
10 #include <climits> 10 #include <climits>
11 #include <cstdio> 11 #include <cstdio>
12 #include <cstring> 12 #include <cstring>
13 #include <stack> 13 #include <stack>
14 #include <string> 14 #include <string>
15 #include <utility> 15 #include <utility>
16 16
17 #define TABLE_NAME "CFF"
18
17 namespace { 19 namespace {
18 20
19 // Type 2 Charstring Implementation Limits. See Appendix. B in Adobe Technical 21 // Type 2 Charstring Implementation Limits. See Appendix. B in Adobe Technical
20 // Note #5177. 22 // Note #5177.
21 const int32_t kMaxSubrsCount = 65536; 23 const int32_t kMaxSubrsCount = 65536;
22 const size_t kMaxCharStringLength = 65535; 24 const size_t kMaxCharStringLength = 65535;
23 const size_t kMaxArgumentStack = 48; 25 const size_t kMaxArgumentStack = 48;
24 const size_t kMaxNumberOfStemHints = 96; 26 const size_t kMaxNumberOfStemHints = 96;
25 const size_t kMaxSubrNesting = 10; 27 const size_t kMaxSubrNesting = 10;
26 28
27 // |dummy_result| should be a huge positive integer so callsubr and callgsubr 29 // |dummy_result| should be a huge positive integer so callsubr and callgsubr
28 // will fail with the dummy value. 30 // will fail with the dummy value.
29 const int32_t dummy_result = INT_MAX; 31 const int32_t dummy_result = INT_MAX;
30 32
31 bool ExecuteType2CharString(size_t call_depth, 33 bool ExecuteType2CharString(ots::OpenTypeFile *file,
34 size_t call_depth,
32 const ots::CFFIndex& global_subrs_index, 35 const ots::CFFIndex& global_subrs_index,
33 const ots::CFFIndex& local_subrs_index, 36 const ots::CFFIndex& local_subrs_index,
34 ots::Buffer *cff_table, 37 ots::Buffer *cff_table,
35 ots::Buffer *char_string, 38 ots::Buffer *char_string,
36 std::stack<int32_t> *argument_stack, 39 std::stack<int32_t> *argument_stack,
37 bool *out_found_endchar, 40 bool *out_found_endchar,
38 bool *out_found_width, 41 bool *out_found_width,
39 size_t *in_out_num_stems); 42 size_t *in_out_num_stems);
40 43
44 #ifdef DUMP_T2CHARSTRING
45 // Converts |op| to a string and returns it.
46 const char *Type2CharStringOperatorToString(ots::Type2CharStringOperator op) {
47 switch (op) {
48 case ots::kHStem:
49 return "HStem";
50 case ots::kVStem:
51 return "VStem";
52 case ots::kVMoveTo:
53 return "VMoveTo";
54 case ots::kRLineTo:
55 return "RLineTo";
56 case ots::kHLineTo:
57 return "HLineTo";
58 case ots::kVLineTo:
59 return "VLineTo";
60 case ots::kRRCurveTo:
61 return "RRCurveTo";
62 case ots::kCallSubr:
63 return "CallSubr";
64 case ots::kReturn:
65 return "Return";
66 case ots::kEndChar:
67 return "EndChar";
68 case ots::kHStemHm:
69 return "HStemHm";
70 case ots::kHintMask:
71 return "HintMask";
72 case ots::kCntrMask:
73 return "CntrMask";
74 case ots::kRMoveTo:
75 return "RMoveTo";
76 case ots::kHMoveTo:
77 return "HMoveTo";
78 case ots::kVStemHm:
79 return "VStemHm";
80 case ots::kRCurveLine:
81 return "RCurveLine";
82 case ots::kRLineCurve:
83 return "RLineCurve";
84 case ots::kVVCurveTo:
85 return "VVCurveTo";
86 case ots::kHHCurveTo:
87 return "HHCurveTo";
88 case ots::kCallGSubr:
89 return "CallGSubr";
90 case ots::kVHCurveTo:
91 return "VHCurveTo";
92 case ots::kHVCurveTo:
93 return "HVCurveTo";
94 case ots::kDotSection:
95 return "DotSection";
96 case ots::kAnd:
97 return "And";
98 case ots::kOr:
99 return "Or";
100 case ots::kNot:
101 return "Not";
102 case ots::kAbs:
103 return "Abs";
104 case ots::kAdd:
105 return "Add";
106 case ots::kSub:
107 return "Sub";
108 case ots::kDiv:
109 return "Div";
110 case ots::kNeg:
111 return "Neg";
112 case ots::kEq:
113 return "Eq";
114 case ots::kDrop:
115 return "Drop";
116 case ots::kPut:
117 return "Put";
118 case ots::kGet:
119 return "Get";
120 case ots::kIfElse:
121 return "IfElse";
122 case ots::kRandom:
123 return "Random";
124 case ots::kMul:
125 return "Mul";
126 case ots::kSqrt:
127 return "Sqrt";
128 case ots::kDup:
129 return "Dup";
130 case ots::kExch:
131 return "Exch";
132 case ots::kIndex:
133 return "Index";
134 case ots::kRoll:
135 return "Roll";
136 case ots::kHFlex:
137 return "HFlex";
138 case ots::kFlex:
139 return "Flex";
140 case ots::kHFlex1:
141 return "HFlex1";
142 case ots::kFlex1:
143 return "Flex1";
144 }
145
146 return "UNKNOWN";
147 }
148 #endif
149
41 // Read one or more bytes from the |char_string| buffer and stores the number 150 // Read one or more bytes from the |char_string| buffer and stores the number
42 // read on |out_number|. If the number read is an operator (ex 'vstem'), sets 151 // read on |out_number|. If the number read is an operator (ex 'vstem'), sets
43 // true on |out_is_operator|. Returns true if the function read a number. 152 // true on |out_is_operator|. Returns true if the function read a number.
44 bool ReadNextNumberFromType2CharString(ots::Buffer *char_string, 153 bool ReadNextNumberFromType2CharString(ots::Buffer *char_string,
45 int32_t *out_number, 154 int32_t *out_number,
46 bool *out_is_operator) { 155 bool *out_is_operator) {
47 uint8_t v = 0; 156 uint8_t v = 0;
48 if (!char_string->ReadU8(&v)) { 157 if (!char_string->ReadU8(&v)) {
49 return OTS_FAILURE(); 158 return OTS_FAILURE();
50 } 159 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 return OTS_FAILURE(); 218 return OTS_FAILURE();
110 } 219 }
111 220
112 return true; 221 return true;
113 } 222 }
114 223
115 // Executes |op| and updates |argument_stack|. Returns true if the execution 224 // Executes |op| and updates |argument_stack|. Returns true if the execution
116 // succeeds. If the |op| is kCallSubr or kCallGSubr, the function recursively 225 // succeeds. If the |op| is kCallSubr or kCallGSubr, the function recursively
117 // calls ExecuteType2CharString() function. The arguments other than |op| and 226 // calls ExecuteType2CharString() function. The arguments other than |op| and
118 // |argument_stack| are passed for that reason. 227 // |argument_stack| are passed for that reason.
119 bool ExecuteType2CharStringOperator(int32_t op, 228 bool ExecuteType2CharStringOperator(ots::OpenTypeFile *file,
229 int32_t op,
120 size_t call_depth, 230 size_t call_depth,
121 const ots::CFFIndex& global_subrs_index, 231 const ots::CFFIndex& global_subrs_index,
122 const ots::CFFIndex& local_subrs_index, 232 const ots::CFFIndex& local_subrs_index,
123 ots::Buffer *cff_table, 233 ots::Buffer *cff_table,
124 ots::Buffer *char_string, 234 ots::Buffer *char_string,
125 std::stack<int32_t> *argument_stack, 235 std::stack<int32_t> *argument_stack,
126 bool *out_found_endchar, 236 bool *out_found_endchar,
127 bool *in_out_found_width, 237 bool *in_out_found_width,
128 size_t *in_out_num_stems) { 238 size_t *in_out_num_stems) {
129 const size_t stack_size = argument_stack->size(); 239 const size_t stack_size = argument_stack->size();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 if (length > kMaxCharStringLength) { 283 if (length > kMaxCharStringLength) {
174 return OTS_FAILURE(); 284 return OTS_FAILURE();
175 } 285 }
176 const size_t offset = subrs_index.offsets[subr_number]; 286 const size_t offset = subrs_index.offsets[subr_number];
177 cff_table->set_offset(offset); 287 cff_table->set_offset(offset);
178 if (!cff_table->Skip(length)) { 288 if (!cff_table->Skip(length)) {
179 return OTS_FAILURE(); 289 return OTS_FAILURE();
180 } 290 }
181 ots::Buffer char_string_to_jump(cff_table->buffer() + offset, length); 291 ots::Buffer char_string_to_jump(cff_table->buffer() + offset, length);
182 292
183 return ExecuteType2CharString(call_depth + 1, 293 return ExecuteType2CharString(file,
294 call_depth + 1,
184 global_subrs_index, 295 global_subrs_index,
185 local_subrs_index, 296 local_subrs_index,
186 cff_table, 297 cff_table,
187 &char_string_to_jump, 298 &char_string_to_jump,
188 argument_stack, 299 argument_stack,
189 out_found_endchar, 300 out_found_endchar,
190 in_out_found_width, 301 in_out_found_width,
191 in_out_num_stems); 302 in_out_num_stems);
192 } 303 }
193 304
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 } else if ((stack_size >= 9) && 526 } else if ((stack_size >= 9) &&
416 ((stack_size - 9) % 8) == 0) { 527 ((stack_size - 9) % 8) == 0) {
417 // {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf? 528 // {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf?
418 successful = true; 529 successful = true;
419 } 530 }
420 while (!argument_stack->empty()) 531 while (!argument_stack->empty())
421 argument_stack->pop(); 532 argument_stack->pop();
422 return successful ? true : OTS_FAILURE(); 533 return successful ? true : OTS_FAILURE();
423 } 534 }
424 535
536 case ots::kDotSection:
537 // Deprecated operator but harmless, we probably should drop it some how.
538 if (stack_size != 0) {
539 return OTS_FAILURE();
540 }
541 return true;
542
425 case ots::kAnd: 543 case ots::kAnd:
426 case ots::kOr: 544 case ots::kOr:
427 case ots::kEq: 545 case ots::kEq:
428 case ots::kAdd: 546 case ots::kAdd:
429 case ots::kSub: 547 case ots::kSub:
430 if (stack_size < 2) { 548 if (stack_size < 2) {
431 return OTS_FAILURE(); 549 return OTS_FAILURE();
432 } 550 }
433 argument_stack->pop(); 551 argument_stack->pop();
434 argument_stack->pop(); 552 argument_stack->pop();
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 return OTS_FAILURE(); 706 return OTS_FAILURE();
589 } 707 }
590 if (stack_size != 11) { 708 if (stack_size != 11) {
591 return OTS_FAILURE(); 709 return OTS_FAILURE();
592 } 710 }
593 while (!argument_stack->empty()) 711 while (!argument_stack->empty())
594 argument_stack->pop(); 712 argument_stack->pop();
595 return true; 713 return true;
596 } 714 }
597 715
598 OTS_WARNING("Undefined operator: %d (0x%x)", op, op); 716 return OTS_FAILURE_MSG("Undefined operator: %d (0x%x)", op, op);
599 return OTS_FAILURE();
600 } 717 }
601 718
602 // Executes |char_string| and updates |argument_stack|. 719 // Executes |char_string| and updates |argument_stack|.
603 // 720 //
604 // call_depth: The current call depth. Initial value is zero. 721 // call_depth: The current call depth. Initial value is zero.
605 // global_subrs_index: Global subroutines. 722 // global_subrs_index: Global subroutines.
606 // local_subrs_index: Local subroutines for the current glyph. 723 // local_subrs_index: Local subroutines for the current glyph.
607 // cff_table: A whole CFF table which contains all global and local subroutines. 724 // cff_table: A whole CFF table which contains all global and local subroutines.
608 // char_string: A charstring we'll execute. |char_string| can be a main routine 725 // char_string: A charstring we'll execute. |char_string| can be a main routine
609 // in CharString INDEX, or a subroutine in GlobalSubr/LocalSubr. 726 // in CharString INDEX, or a subroutine in GlobalSubr/LocalSubr.
610 // argument_stack: The stack which an operator in |char_string| operates. 727 // argument_stack: The stack which an operator in |char_string| operates.
611 // out_found_endchar: true is set if |char_string| contains 'endchar'. 728 // out_found_endchar: true is set if |char_string| contains 'endchar'.
612 // in_out_found_width: true is set if |char_string| contains 'width' byte (which 729 // in_out_found_width: true is set if |char_string| contains 'width' byte (which
613 // is 0 or 1 byte.) 730 // is 0 or 1 byte.)
614 // in_out_num_stems: total number of hstems and vstems processed so far. 731 // in_out_num_stems: total number of hstems and vstems processed so far.
615 bool ExecuteType2CharString(size_t call_depth, 732 bool ExecuteType2CharString(ots::OpenTypeFile *file,
733 size_t call_depth,
616 const ots::CFFIndex& global_subrs_index, 734 const ots::CFFIndex& global_subrs_index,
617 const ots::CFFIndex& local_subrs_index, 735 const ots::CFFIndex& local_subrs_index,
618 ots::Buffer *cff_table, 736 ots::Buffer *cff_table,
619 ots::Buffer *char_string, 737 ots::Buffer *char_string,
620 std::stack<int32_t> *argument_stack, 738 std::stack<int32_t> *argument_stack,
621 bool *out_found_endchar, 739 bool *out_found_endchar,
622 bool *in_out_found_width, 740 bool *in_out_found_width,
623 size_t *in_out_num_stems) { 741 size_t *in_out_num_stems) {
624 if (call_depth > kMaxSubrNesting) { 742 if (call_depth > kMaxSubrNesting) {
625 return OTS_FAILURE(); 743 return OTS_FAILURE();
626 } 744 }
627 *out_found_endchar = false; 745 *out_found_endchar = false;
628 746
629 const size_t length = char_string->length(); 747 const size_t length = char_string->length();
630 while (char_string->offset() < length) { 748 while (char_string->offset() < length) {
631 int32_t operator_or_operand = 0; 749 int32_t operator_or_operand = 0;
632 bool is_operator = false; 750 bool is_operator = false;
633 if (!ReadNextNumberFromType2CharString(char_string, 751 if (!ReadNextNumberFromType2CharString(char_string,
634 &operator_or_operand, 752 &operator_or_operand,
635 &is_operator)) { 753 &is_operator)) {
636 return OTS_FAILURE(); 754 return OTS_FAILURE();
637 } 755 }
638 756
757 #ifdef DUMP_T2CHARSTRING
639 /* 758 /*
640 You can dump all operators and operands (except mask bytes for hintmask 759 You can dump all operators and operands (except mask bytes for hintmask
641 and cntrmask) by the following code: 760 and cntrmask) by the following code:
761 */
642 762
643 if (!is_operator) { 763 if (!is_operator) {
644 std::fprintf(stderr, "#%d# ", operator_or_operand); 764 std::fprintf(stderr, "#%d# ", operator_or_operand);
645 } else { 765 } else {
646 std::fprintf(stderr, "#%s#\n", 766 std::fprintf(stderr, "#%s#\n",
647 Type2CharStringOperatorToString( 767 Type2CharStringOperatorToString(
648 Type2CharStringOperator(operator_or_operand)), 768 ots::Type2CharStringOperator(operator_or_operand))
649 operator_or_operand); 769 );
650 } 770 }
651 */ 771 #endif
652 772
653 if (!is_operator) { 773 if (!is_operator) {
654 argument_stack->push(operator_or_operand); 774 argument_stack->push(operator_or_operand);
655 if (argument_stack->size() > kMaxArgumentStack) { 775 if (argument_stack->size() > kMaxArgumentStack) {
656 return OTS_FAILURE(); 776 return OTS_FAILURE();
657 } 777 }
658 continue; 778 continue;
659 } 779 }
660 780
661 // An operator is found. Execute it. 781 // An operator is found. Execute it.
662 if (!ExecuteType2CharStringOperator(operator_or_operand, 782 if (!ExecuteType2CharStringOperator(file,
783 operator_or_operand,
663 call_depth, 784 call_depth,
664 global_subrs_index, 785 global_subrs_index,
665 local_subrs_index, 786 local_subrs_index,
666 cff_table, 787 cff_table,
667 char_string, 788 char_string,
668 argument_stack, 789 argument_stack,
669 out_found_endchar, 790 out_found_endchar,
670 in_out_found_width, 791 in_out_found_width,
671 in_out_num_stems)) { 792 in_out_num_stems)) {
672 return OTS_FAILURE(); 793 return OTS_FAILURE();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 } 838 }
718 839
719 return true; 840 return true;
720 } 841 }
721 842
722 } // namespace 843 } // namespace
723 844
724 namespace ots { 845 namespace ots {
725 846
726 bool ValidateType2CharStringIndex( 847 bool ValidateType2CharStringIndex(
848 ots::OpenTypeFile *file,
727 const CFFIndex& char_strings_index, 849 const CFFIndex& char_strings_index,
728 const CFFIndex& global_subrs_index, 850 const CFFIndex& global_subrs_index,
729 const std::map<uint16_t, uint8_t> &fd_select, 851 const std::map<uint16_t, uint8_t> &fd_select,
730 const std::vector<CFFIndex *> &local_subrs_per_font, 852 const std::vector<CFFIndex *> &local_subrs_per_font,
731 const CFFIndex *local_subrs, 853 const CFFIndex *local_subrs,
732 Buffer* cff_table) { 854 Buffer* cff_table) {
733 const uint16_t num_offsets = 855 const uint16_t num_offsets =
734 static_cast<uint16_t>(char_strings_index.offsets.size()); 856 static_cast<uint16_t>(char_strings_index.offsets.size());
735 if (num_offsets != char_strings_index.offsets.size() || num_offsets == 0) { 857 if (num_offsets != char_strings_index.offsets.size() || num_offsets == 0) {
736 return OTS_FAILURE(); // no charstring. 858 return OTS_FAILURE(); // no charstring.
(...skipping 29 matching lines...) Expand all
766 CFFIndex default_empty_subrs; 888 CFFIndex default_empty_subrs;
767 if (!local_subrs_to_use){ 889 if (!local_subrs_to_use){
768 local_subrs_to_use = &default_empty_subrs; 890 local_subrs_to_use = &default_empty_subrs;
769 } 891 }
770 892
771 // Check a charstring for the |i|-th glyph. 893 // Check a charstring for the |i|-th glyph.
772 std::stack<int32_t> argument_stack; 894 std::stack<int32_t> argument_stack;
773 bool found_endchar = false; 895 bool found_endchar = false;
774 bool found_width = false; 896 bool found_width = false;
775 size_t num_stems = 0; 897 size_t num_stems = 0;
776 if (!ExecuteType2CharString(0 /* initial call_depth is zero */, 898 if (!ExecuteType2CharString(file,
899 0 /* initial call_depth is zero */,
777 global_subrs_index, *local_subrs_to_use, 900 global_subrs_index, *local_subrs_to_use,
778 cff_table, &char_string, &argument_stack, 901 cff_table, &char_string, &argument_stack,
779 &found_endchar, &found_width, &num_stems)) { 902 &found_endchar, &found_width, &num_stems)) {
780 return OTS_FAILURE(); 903 return OTS_FAILURE();
781 } 904 }
782 if (!found_endchar) { 905 if (!found_endchar) {
783 return OTS_FAILURE(); 906 return OTS_FAILURE();
784 } 907 }
785 } 908 }
786 return true; 909 return true;
787 } 910 }
788 911
789 } // namespace ots 912 } // namespace ots
913
914 #undef TABLE_NAME
OLDNEW
« .gitmodules ('K') | « src/cff_type2_charstring.h ('k') | src/cmap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698