Line  | Count  | Source  | 
1  |  | // Copyright (c) 2012-2017 The OTS Authors. All rights reserved.  | 
2  |  | // Use of this source code is governed by a BSD-style license that can be  | 
3  |  | // found in the LICENSE file.  | 
4  |  |  | 
5  |  | #include "cff.h"  | 
6  |  |  | 
7  |  | #include <cstring>  | 
8  |  | #include <utility>  | 
9  |  | #include <vector>  | 
10  |  |  | 
11  |  | #include "maxp.h"  | 
12  |  | #include "cff_charstring.h"  | 
13  |  | #include "variations.h"  | 
14  |  |  | 
15  |  | // CFF - PostScript font program (Compact Font Format) table  | 
16  |  | // http://www.microsoft.com/typography/otspec/cff.htm  | 
17  |  | // http://www.microsoft.com/typography/otspec/cffspec.htm  | 
18  |  |  | 
19  |  | #define TABLE_NAME "CFF"  | 
20  |  |  | 
21  |  | namespace { | 
22  |  |  | 
23  |  | enum DICT_OPERAND_TYPE { | 
24  |  |   DICT_OPERAND_INTEGER,  | 
25  |  |   DICT_OPERAND_REAL,  | 
26  |  |   DICT_OPERATOR,  | 
27  |  | };  | 
28  |  |  | 
29  |  | enum DICT_DATA_TYPE { | 
30  |  |   DICT_DATA_TOPLEVEL,  | 
31  |  |   DICT_DATA_FDARRAY,  | 
32  |  |   DICT_DATA_PRIVATE,  | 
33  |  | };  | 
34  |  |  | 
35  |  | enum FONT_FORMAT { | 
36  |  |   FORMAT_UNKNOWN,  | 
37  |  |   FORMAT_CID_KEYED,  | 
38  |  |   FORMAT_OTHER,  // Including synthetic fonts  | 
39  |  | };  | 
40  |  |  | 
41  |  | // see Appendix. A  | 
42  |  | const size_t kNStdString = 390;  | 
43  |  |  | 
44  |  | typedef std::pair<int32_t, DICT_OPERAND_TYPE> Operand;  | 
45  |  |  | 
46  | 455k  | bool ReadOffset(ots::Buffer &table, uint8_t off_size, uint32_t *offset) { | 
47  | 455k  |   if (off_size > 4) { | 
48  | 0  |     return OTS_FAILURE();  | 
49  | 0  |   }  | 
50  |  |  | 
51  | 455k  |   uint32_t tmp32 = 0;  | 
52  | 1.64M  |   for (unsigned i = 0; i < off_size; ++i) { | 
53  | 1.19M  |     uint8_t tmp8 = 0;  | 
54  | 1.19M  |     if (!table.ReadU8(&tmp8)) { | 
55  | 0  |       return OTS_FAILURE();  | 
56  | 0  |     }  | 
57  | 1.19M  |     tmp32 <<= 8;  | 
58  | 1.19M  |     tmp32 += tmp8;  | 
59  | 1.19M  |   }  | 
60  | 455k  |   *offset = tmp32;  | 
61  | 455k  |   return true;  | 
62  | 455k  | }  | 
63  |  |  | 
64  | 4.43k  | bool ParseIndex(ots::Buffer &table, ots::CFFIndex &index, bool cff2 = false) { | 
65  | 4.43k  |   index.off_size = 0;  | 
66  | 4.43k  |   index.offsets.clear();  | 
67  |  |  | 
68  | 4.43k  |   if (cff2) { | 
69  | 1.26k  |     if (!table.ReadU32(&(index.count))) { | 
70  | 1  |       return OTS_FAILURE();  | 
71  | 1  |     }  | 
72  | 3.17k  |   } else { | 
73  | 3.17k  |     uint16_t count;  | 
74  | 3.17k  |     if (!table.ReadU16(&count)) { | 
75  | 1  |       return OTS_FAILURE();  | 
76  | 1  |     }  | 
77  | 3.17k  |     index.count = count;  | 
78  | 3.17k  |   }  | 
79  |  |  | 
80  | 4.43k  |   if (index.count == 0) { | 
81  |  |     // An empty INDEX.  | 
82  | 693  |     index.offset_to_next = table.offset();  | 
83  | 693  |     return true;  | 
84  | 693  |   }  | 
85  |  |  | 
86  | 3.73k  |   if (!table.ReadU8(&(index.off_size))) { | 
87  | 1  |     return OTS_FAILURE();  | 
88  | 1  |   }  | 
89  | 3.73k  |   if (index.off_size < 1 || index.off_size > 4) { | 
90  | 36  |     return OTS_FAILURE();  | 
91  | 36  |   }  | 
92  |  |  | 
93  | 3.70k  |   const size_t array_size = (index.count + 1) * index.off_size;  | 
94  |  |   // less than ((64k + 1) * 4), thus does not overflow.  | 
95  | 3.70k  |   const size_t object_data_offset = table.offset() + array_size;  | 
96  |  |   // does not overflow too, since offset() <= 1GB.  | 
97  |  |  | 
98  | 3.70k  |   if (object_data_offset >= table.length()) { | 
99  | 32  |     return OTS_FAILURE();  | 
100  | 32  |   }  | 
101  |  |  | 
102  | 458k  |   for (unsigned i = 0; i <= index.count; ++i) {  // '<=' is not a typo. | 
103  | 455k  |     uint32_t rel_offset = 0;  | 
104  | 455k  |     if (!ReadOffset(table, index.off_size, &rel_offset)) { | 
105  | 0  |       return OTS_FAILURE();  | 
106  | 0  |     }  | 
107  | 455k  |     if (rel_offset < 1) { | 
108  | 8  |       return OTS_FAILURE();  | 
109  | 8  |     }  | 
110  | 455k  |     if (i == 0 && rel_offset != 1) { | 
111  | 5  |       return OTS_FAILURE();  | 
112  | 5  |     }  | 
113  |  |  | 
114  | 455k  |     if (rel_offset > table.length()) { | 
115  | 4  |       return OTS_FAILURE();  | 
116  | 4  |     }  | 
117  |  |  | 
118  |  |     // does not underflow.  | 
119  | 455k  |     if (object_data_offset > table.length() - (rel_offset - 1)) { | 
120  | 3  |       return OTS_FAILURE();  | 
121  | 3  |     }  | 
122  |  |  | 
123  | 455k  |     index.offsets.push_back(  | 
124  | 455k  |         object_data_offset + (rel_offset - 1));  // less than length(), 1GB.  | 
125  | 455k  |   }  | 
126  |  |  | 
127  | 451k  |   for (unsigned i = 1; i < index.offsets.size(); ++i) { | 
128  |  |     // We allow consecutive identical offsets here for zero-length strings.  | 
129  |  |     // See http://crbug.com/69341 for more details.  | 
130  | 448k  |     if (index.offsets[i] < index.offsets[i - 1]) { | 
131  | 3  |       return OTS_FAILURE();  | 
132  | 3  |     }  | 
133  | 448k  |   }  | 
134  |  |  | 
135  | 3.64k  |   index.offset_to_next = index.offsets.back();  | 
136  | 3.64k  |   return true;  | 
137  | 3.64k  | }  | 
138  |  |  | 
139  |  | bool ParseNameData(  | 
140  | 616  |     ots::Buffer *table, const ots::CFFIndex &index, std::string* out_name) { | 
141  | 616  |   uint8_t name[256] = {0}; | 
142  |  |  | 
143  | 616  |   const size_t length = index.offsets[1] - index.offsets[0];  | 
144  |  |   // font names should be no longer than 127 characters.  | 
145  | 616  |   if (length > 127) { | 
146  | 2  |     return OTS_FAILURE();  | 
147  | 2  |   }  | 
148  |  |  | 
149  | 614  |   table->set_offset(index.offsets[0]);  | 
150  | 614  |   if (!table->Read(name, length)) { | 
151  | 0  |     return OTS_FAILURE();  | 
152  | 0  |   }  | 
153  |  |  | 
154  | 11.3k  |   for (size_t i = 0; i < length; ++i) { | 
155  |  |     // setting the first byte to NUL is allowed.  | 
156  | 10.7k  |     if (i == 0 && name[i] == 0) continue;  | 
157  |  |     // non-ASCII characters are not recommended (except the first character).  | 
158  | 10.7k  |     if (name[i] < 33 || name[i] > 126) { | 
159  | 10  |       return OTS_FAILURE();  | 
160  | 10  |     }  | 
161  |  |     // [, ], ... are not allowed.  | 
162  | 10.7k  |     if (std::strchr("[](){}<>/% ", name[i])) { | 
163  | 1  |       return OTS_FAILURE();  | 
164  | 1  |     }  | 
165  | 10.7k  |   }  | 
166  |  |  | 
167  | 603  |   *out_name = reinterpret_cast<char *>(name);  | 
168  | 603  |   return true;  | 
169  | 614  | }  | 
170  |  |  | 
171  | 2.51k  | bool CheckOffset(const Operand& operand, size_t table_length) { | 
172  | 2.51k  |   if (operand.second != DICT_OPERAND_INTEGER) { | 
173  | 5  |     return OTS_FAILURE();  | 
174  | 5  |   }  | 
175  | 2.50k  |   if (operand.first >= static_cast<int32_t>(table_length) || operand.first < 0) { | 
176  | 37  |     return OTS_FAILURE();  | 
177  | 37  |   }  | 
178  | 2.47k  |   return true;  | 
179  | 2.50k  | }  | 
180  |  |  | 
181  | 3.19k  | bool CheckSid(const Operand& operand, size_t sid_max) { | 
182  | 3.19k  |   if (operand.second != DICT_OPERAND_INTEGER) { | 
183  | 1  |     return OTS_FAILURE();  | 
184  | 1  |   }  | 
185  | 3.19k  |   if (operand.first > static_cast<int32_t>(sid_max) || operand.first < 0) { | 
186  | 22  |     return OTS_FAILURE();  | 
187  | 22  |   }  | 
188  | 3.17k  |   return true;  | 
189  | 3.19k  | }  | 
190  |  |  | 
191  | 1.65k  | bool ParseDictDataBcd(ots::Buffer &table, std::vector<Operand> &operands) { | 
192  | 1.65k  |   bool read_decimal_point = false;  | 
193  | 1.65k  |   bool read_e = false;  | 
194  |  |  | 
195  | 1.65k  |   uint8_t nibble = 0;  | 
196  | 1.65k  |   size_t count = 0;  | 
197  | 7.87k  |   while (true) { | 
198  | 7.87k  |     if (!table.ReadU8(&nibble)) { | 
199  | 2  |       return OTS_FAILURE();  | 
200  | 2  |     }  | 
201  | 7.87k  |     if ((nibble & 0xf0) == 0xf0) { | 
202  | 276  |       if ((nibble & 0xf) == 0xf) { | 
203  |  |         // TODO(yusukes): would be better to store actual double value,  | 
204  |  |         // rather than the dummy integer.  | 
205  | 275  |         operands.push_back(std::make_pair(0, DICT_OPERAND_REAL));  | 
206  | 275  |         return true;  | 
207  | 275  |       }  | 
208  | 1  |       return OTS_FAILURE();  | 
209  | 276  |     }  | 
210  | 7.59k  |     if ((nibble & 0x0f) == 0x0f) { | 
211  | 1.37k  |       operands.push_back(std::make_pair(0, DICT_OPERAND_REAL));  | 
212  | 1.37k  |       return true;  | 
213  | 1.37k  |     }  | 
214  |  |  | 
215  |  |     // check number format  | 
216  | 6.22k  |     uint8_t nibbles[2];  | 
217  | 6.22k  |     nibbles[0] = (nibble & 0xf0) >> 8;  | 
218  | 6.22k  |     nibbles[1] = (nibble & 0x0f);  | 
219  | 18.6k  |     for (unsigned i = 0; i < 2; ++i) { | 
220  | 12.4k  |       if (nibbles[i] == 0xd) {  // reserved number | 
221  | 2  |         return OTS_FAILURE();  | 
222  | 2  |       }  | 
223  | 12.4k  |       if ((nibbles[i] == 0xe) &&  // minus  | 
224  | 2  |           ((count > 0) || (i > 0))) { | 
225  | 2  |         return OTS_FAILURE();  // minus sign should be the first character.  | 
226  | 2  |       }  | 
227  | 12.4k  |       if (nibbles[i] == 0xa) {  // decimal point | 
228  | 315  |         if (!read_decimal_point) { | 
229  | 314  |           read_decimal_point = true;  | 
230  | 314  |         } else { | 
231  | 1  |           return OTS_FAILURE();  // two or more points.  | 
232  | 1  |         }  | 
233  | 315  |       }  | 
234  | 12.4k  |       if ((nibbles[i] == 0xb) ||  // E+  | 
235  | 12.4k  |           (nibbles[i] == 0xc)) {  // E- | 
236  | 39  |         if (!read_e) { | 
237  | 35  |           read_e = true;  | 
238  | 35  |         } else { | 
239  | 4  |           return OTS_FAILURE();  // two or more E's.  | 
240  | 4  |         }  | 
241  | 39  |       }  | 
242  | 12.4k  |     }  | 
243  | 6.21k  |     ++count;  | 
244  | 6.21k  |   }  | 
245  | 1.65k  | }  | 
246  |  |  | 
247  |  | bool ParseDictDataEscapedOperator(ots::Buffer &table,  | 
248  | 6.01k  |                                   std::vector<Operand> &operands) { | 
249  | 6.01k  |   uint8_t op = 0;  | 
250  | 6.01k  |   if (!table.ReadU8(&op)) { | 
251  | 4  |     return OTS_FAILURE();  | 
252  | 4  |   }  | 
253  |  |  | 
254  | 6.00k  |   if ((op <= 14) ||  | 
255  | 3.12k  |       (op >= 17 && op <= 23) ||  | 
256  | 5.99k  |       (op >= 30 && op <= 38)) { | 
257  | 5.99k  |     operands.push_back(std::make_pair((12 << 8) + op, DICT_OPERATOR));  | 
258  | 5.99k  |     return true;  | 
259  | 5.99k  |   }  | 
260  |  |  | 
261  |  |   // reserved area.  | 
262  | 10  |   return OTS_FAILURE();  | 
263  | 6.00k  | }  | 
264  |  |  | 
265  |  | bool ParseDictDataNumber(ots::Buffer &table, uint8_t b0,  | 
266  | 37.8k  |                          std::vector<Operand> &operands) { | 
267  | 37.8k  |   uint8_t b1 = 0;  | 
268  | 37.8k  |   uint8_t b2 = 0;  | 
269  | 37.8k  |   uint8_t b3 = 0;  | 
270  | 37.8k  |   uint8_t b4 = 0;  | 
271  |  |  | 
272  | 37.8k  |   switch (b0) { | 
273  | 469  |     case 28:  // shortint  | 
274  | 469  |       if (!table.ReadU8(&b1) ||  | 
275  | 467  |           !table.ReadU8(&b2)) { | 
276  | 4  |         return OTS_FAILURE();  | 
277  | 4  |       }  | 
278  |  |       //the two-byte value needs to be casted to int16_t in order to get the right sign  | 
279  | 465  |       operands.push_back(std::make_pair(  | 
280  | 465  |           static_cast<int16_t>((b1 << 8) + b2), DICT_OPERAND_INTEGER));  | 
281  | 465  |       return true;  | 
282  |  |  | 
283  | 2.14k  |     case 29:  // longint  | 
284  | 2.14k  |       if (!table.ReadU8(&b1) ||  | 
285  | 2.14k  |           !table.ReadU8(&b2) ||  | 
286  | 2.14k  |           !table.ReadU8(&b3) ||  | 
287  | 2.14k  |           !table.ReadU8(&b4)) { | 
288  | 5  |         return OTS_FAILURE();  | 
289  | 5  |       }  | 
290  | 2.13k  |       operands.push_back(std::make_pair(  | 
291  | 2.13k  |           (b1 << 24) + (b2 << 16) + (b3 << 8) + b4,  | 
292  | 2.13k  |           DICT_OPERAND_INTEGER));  | 
293  | 2.13k  |       return true;  | 
294  |  |  | 
295  | 1.65k  |     case 30:  // binary coded decimal  | 
296  | 1.65k  |       return ParseDictDataBcd(table, operands);  | 
297  |  |  | 
298  | 33.5k  |     default:  | 
299  | 33.5k  |       break;  | 
300  | 37.8k  |   }  | 
301  |  |  | 
302  | 33.5k  |   int32_t result;  | 
303  | 33.5k  |   if (b0 >=32 && b0 <=246) { | 
304  | 23.7k  |     result = b0 - 139;  | 
305  | 23.7k  |   } else if (b0 >=247 && b0 <= 250) { | 
306  | 8.21k  |     if (!table.ReadU8(&b1)) { | 
307  | 3  |       return OTS_FAILURE();  | 
308  | 3  |     }  | 
309  | 8.20k  |     result = (b0 - 247) * 256 + b1 + 108;  | 
310  | 8.20k  |   } else if (b0 >= 251 && b0 <= 254) { | 
311  | 1.66k  |     if (!table.ReadU8(&b1)) { | 
312  | 2  |       return OTS_FAILURE();  | 
313  | 2  |     }  | 
314  | 1.66k  |     result = -(b0 - 251) * 256 + b1 - 108;  | 
315  | 1.66k  |   } else { | 
316  | 0  |     return OTS_FAILURE();  | 
317  | 0  |   }  | 
318  |  |  | 
319  | 33.5k  |   operands.push_back(std::make_pair(result, DICT_OPERAND_INTEGER));  | 
320  | 33.5k  |   return true;  | 
321  | 33.5k  | }  | 
322  |  |  | 
323  |  | bool ParseDictDataReadNext(ots::Buffer &table,  | 
324  | 57.7k  |                            std::vector<Operand> &operands) { | 
325  | 57.7k  |   uint8_t op = 0;  | 
326  | 57.7k  |   if (!table.ReadU8(&op)) { | 
327  | 0  |     return OTS_FAILURE();  | 
328  | 0  |   }  | 
329  | 57.7k  |   if (op <= 24) { | 
330  | 19.8k  |     if (op == 12) { | 
331  | 6.01k  |       return ParseDictDataEscapedOperator(table, operands);  | 
332  | 6.01k  |     }  | 
333  | 13.8k  |     operands.push_back(std::make_pair(  | 
334  | 13.8k  |         static_cast<int32_t>(op), DICT_OPERATOR));  | 
335  | 13.8k  |     return true;  | 
336  | 37.8k  |   } else if (op <= 27 || op == 31 || op == 255) { | 
337  |  |     // reserved area.  | 
338  | 15  |     return OTS_FAILURE();  | 
339  | 15  |   }  | 
340  |  |  | 
341  | 37.8k  |   return ParseDictDataNumber(table, op, operands);  | 
342  | 57.7k  | }  | 
343  |  |  | 
344  | 57.7k  | bool OperandsOverflow(std::vector<Operand>& operands, bool cff2) { | 
345  |  |   // An operator may be preceded by up to a maximum of 48 operands in CFF1 and  | 
346  |  |   // 513 operands in CFF2.  | 
347  | 57.7k  |   if ((cff2 && operands.size() > ots::kMaxCFF2ArgumentStack) ||  | 
348  | 57.7k  |       (!cff2 && operands.size() > ots::kMaxCFF1ArgumentStack)) { | 
349  | 5  |     return true;  | 
350  | 5  |   }  | 
351  | 57.7k  |   return false;  | 
352  | 57.7k  | }  | 
353  |  |  | 
354  |  | bool ParseDictDataReadOperands(ots::Buffer& dict,  | 
355  |  |                                std::vector<Operand>& operands,  | 
356  | 57.7k  |                                bool cff2) { | 
357  | 57.7k  |   if (!ParseDictDataReadNext(dict, operands)) { | 
358  | 55  |     return OTS_FAILURE();  | 
359  | 55  |   }  | 
360  | 57.7k  |   if (operands.empty()) { | 
361  | 0  |     return OTS_FAILURE();  | 
362  | 0  |   }  | 
363  | 57.7k  |   if (OperandsOverflow(operands, cff2)) { | 
364  | 5  |     return OTS_FAILURE();  | 
365  | 5  |   }  | 
366  | 57.7k  |   return true;  | 
367  | 57.7k  | }  | 
368  |  |  | 
369  | 3.41k  | bool ValidCFF2DictOp(int32_t op, DICT_DATA_TYPE type) { | 
370  | 3.41k  |   if (type == DICT_DATA_TOPLEVEL) { | 
371  | 1.35k  |     switch (op) { | 
372  | 223  |       case (12 << 8) + 7:  // FontMatrix  | 
373  | 594  |       case 17:              // CharStrings  | 
374  | 1.05k  |       case (12 << 8) + 36: // FDArray  | 
375  | 1.26k  |       case (12 << 8) + 37: // FDSelect  | 
376  | 1.34k  |       case 24:              // vstore  | 
377  | 1.34k  |         return true;  | 
378  | 7  |       default:  | 
379  | 7  |         return false;  | 
380  | 1.35k  |     }  | 
381  | 2.05k  |   } else if (type == DICT_DATA_FDARRAY) { | 
382  | 497  |     if (op == 18) // Private DICT  | 
383  | 496  |       return true;  | 
384  | 1.56k  |   } else if (type == DICT_DATA_PRIVATE) { | 
385  | 1.56k  |     switch (op) { | 
386  | 2  |       case (12 << 8) + 14: // ForceBold  | 
387  | 4  |       case (12 << 8) + 19: // initialRandomSeed  | 
388  | 5  |       case 20:              // defaultWidthX  | 
389  | 6  |       case 21:              // nominalWidthX  | 
390  | 6  |         return false;  | 
391  | 1.55k  |       default:  | 
392  | 1.55k  |         return true;  | 
393  | 1.56k  |     }  | 
394  | 1.56k  |   }  | 
395  |  |  | 
396  | 1  |   return false;  | 
397  | 3.41k  | }  | 
398  |  |  | 
399  |  | bool ParsePrivateDictData(  | 
400  |  |     ots::Buffer &table, size_t offset, size_t dict_length,  | 
401  | 1.14k  |     DICT_DATA_TYPE type, ots::OpenTypeCFF *out_cff) { | 
402  | 1.14k  |   ots::Buffer dict(table.buffer() + offset, dict_length);  | 
403  | 1.14k  |   std::vector<Operand> operands;  | 
404  | 1.14k  |   bool cff2 = (out_cff->major == 2);  | 
405  | 1.14k  |   bool blend_seen = false;  | 
406  | 1.14k  |   int32_t vsindex = 0;  | 
407  |  |  | 
408  |  |   // Since a Private DICT for FDArray might not have a Local Subr (e.g. Hiragino  | 
409  |  |   // Kaku Gothic Std W8), we create an empty Local Subr here to match the size  | 
410  |  |   // of FDArray the size of |local_subrs_per_font|.  | 
411  |  |   // For CFF2, |vsindex_per_font| gets a similar treatment.  | 
412  | 1.14k  |   if (type == DICT_DATA_FDARRAY) { | 
413  | 836  |     out_cff->local_subrs_per_font.push_back(new ots::CFFIndex);  | 
414  | 836  |     if (cff2) { | 
415  | 488  |       out_cff->vsindex_per_font.push_back(vsindex);  | 
416  | 488  |     }  | 
417  | 836  |   }  | 
418  |  |  | 
419  | 22.1k  |   while (dict.offset() < dict.length()) { | 
420  | 21.1k  |     if (!ParseDictDataReadOperands(dict, operands, cff2)) { | 
421  | 16  |       return OTS_FAILURE();  | 
422  | 16  |     }  | 
423  | 21.1k  |     if (operands.back().second != DICT_OPERATOR) { | 
424  | 14.7k  |       continue;  | 
425  | 14.7k  |     }  | 
426  |  |  | 
427  |  |     // got operator  | 
428  | 6.36k  |     const int32_t op = operands.back().first;  | 
429  | 6.36k  |     operands.pop_back();  | 
430  |  |  | 
431  | 6.36k  |     if (cff2 && !ValidCFF2DictOp(op, DICT_DATA_PRIVATE)) { | 
432  | 6  |       return OTS_FAILURE();  | 
433  | 6  |     }  | 
434  |  |  | 
435  | 6.35k  |     bool clear_operands = true;  | 
436  | 6.35k  |     switch (op) { | 
437  |  |       // hints  | 
438  | 656  |       case 6:  // BlueValues  | 
439  | 837  |       case 7:  // OtherBlues  | 
440  | 1.70k  |       case 8:  // FamilyBlues  | 
441  | 1.83k  |       case 9:  // FamilyOtherBlues  | 
442  | 1.83k  |         if ((operands.size() % 2) != 0) { | 
443  | 5  |           return OTS_FAILURE();  | 
444  | 5  |         }  | 
445  | 1.83k  |         break;  | 
446  |  |  | 
447  |  |       // array  | 
448  | 1.83k  |       case (12 << 8) + 12:  // StemSnapH (delta)  | 
449  | 932  |       case (12 << 8) + 13:  // StemSnapV (delta)  | 
450  | 932  |         if (operands.empty()) { | 
451  | 1  |           return OTS_FAILURE();  | 
452  | 1  |         }  | 
453  | 931  |         break;  | 
454  |  |  | 
455  |  |       // number  | 
456  | 931  |       case 10:  // StdHW  | 
457  | 1.12k  |       case 11:  // StdVW  | 
458  | 1.57k  |       case 20:  // defaultWidthX  | 
459  | 1.92k  |       case 21:  // nominalWidthX  | 
460  | 2.06k  |       case (12 << 8) + 9:   // BlueScale  | 
461  | 2.13k  |       case (12 << 8) + 10:  // BlueShift  | 
462  | 2.39k  |       case (12 << 8) + 11:  // BlueFuzz  | 
463  | 2.57k  |       case (12 << 8) + 17:  // LanguageGroup  | 
464  | 2.58k  |       case (12 << 8) + 18:  // ExpansionFactor  | 
465  | 2.60k  |       case (12 << 8) + 19:  // initialRandomSeed  | 
466  | 2.60k  |         if (operands.size() != 1) { | 
467  | 16  |           return OTS_FAILURE();  | 
468  | 16  |         }  | 
469  | 2.58k  |         break;  | 
470  |  |  | 
471  |  |       // Local Subrs INDEX, offset(self)  | 
472  | 2.58k  |       case 19: { | 
473  | 545  |         if (operands.size() != 1) { | 
474  | 3  |           return OTS_FAILURE();  | 
475  | 3  |         }  | 
476  | 542  |         if (operands.back().second != DICT_OPERAND_INTEGER) { | 
477  | 1  |           return OTS_FAILURE();  | 
478  | 1  |         }  | 
479  |  |         // In theory a negative operand could occur here, if the Local Subrs  | 
480  |  |         // were stored before the Private dict, but this does not seem to be  | 
481  |  |         // well supported by implementations, and mishandling of a negative  | 
482  |  |         // offset (e.g. by using unsigned offset arithmetic) might become a  | 
483  |  |         // vector for exploitation.  AFAIK no major font creation tool will  | 
484  |  |         // generate such an offset, so to be on the safe side, we don't allow  | 
485  |  |         // it here.  | 
486  | 541  |         if (operands.back().first >= 1024 * 1024 * 1024 || operands.back().first < 0) { | 
487  | 3  |           return OTS_FAILURE();  | 
488  | 3  |         }  | 
489  | 538  |         if (operands.back().first + offset >= table.length()) { | 
490  | 4  |           return OTS_FAILURE();  | 
491  | 4  |         }  | 
492  |  |         // parse "16. Local Subrs INDEX"  | 
493  | 534  |         table.set_offset(operands.back().first + offset);  | 
494  | 534  |         ots::CFFIndex *local_subrs_index = NULL;  | 
495  | 534  |         if (type == DICT_DATA_FDARRAY) { | 
496  | 304  |           if (out_cff->local_subrs_per_font.empty()) { | 
497  | 0  |             return OTS_FAILURE();  // not reached.  | 
498  | 0  |           }  | 
499  | 304  |           local_subrs_index = out_cff->local_subrs_per_font.back();  | 
500  | 304  |         } else { // type == DICT_DATA_TOPLEVEL | 
501  | 230  |           if (out_cff->local_subrs) { | 
502  | 0  |             return OTS_FAILURE();  // two or more local_subrs?  | 
503  | 0  |           }  | 
504  | 230  |           local_subrs_index = new ots::CFFIndex;  | 
505  | 230  |           out_cff->local_subrs = local_subrs_index;  | 
506  | 230  |         }  | 
507  | 534  |         if (!ParseIndex(table, *local_subrs_index, cff2)) { | 
508  | 4  |           return OTS_FAILURE();  | 
509  | 4  |         }  | 
510  | 530  |         break;  | 
511  | 534  |       }  | 
512  |  |  | 
513  |  |       // boolean  | 
514  | 530  |       case (12 << 8) + 14:  // ForceBold  | 
515  | 11  |         if (operands.size() != 1) { | 
516  | 1  |           return OTS_FAILURE();  | 
517  | 1  |         }  | 
518  | 10  |         if (operands.back().second != DICT_OPERAND_INTEGER) { | 
519  | 1  |           return OTS_FAILURE();  | 
520  | 1  |         }  | 
521  | 9  |         if (operands.back().first >= 2 || operands.back().first < 0) { | 
522  | 4  |           return OTS_FAILURE();  | 
523  | 4  |         }  | 
524  | 5  |         break;  | 
525  |  |  | 
526  | 9  |       case 22: { // vsindex | 
527  | 9  |         if (!cff2) { | 
528  | 2  |           return OTS_FAILURE();  | 
529  | 2  |         }  | 
530  | 7  |         if (operands.size() != 1) { | 
531  | 1  |           return OTS_FAILURE();  | 
532  | 1  |         }  | 
533  | 6  |         if (operands.back().second != DICT_OPERAND_INTEGER) { | 
534  | 1  |           return OTS_FAILURE();  | 
535  | 1  |         }  | 
536  | 5  |         if (blend_seen) { | 
537  | 1  |           return OTS_FAILURE();  | 
538  | 1  |         }  | 
539  | 4  |         vsindex = operands.back().first;  | 
540  | 4  |         if (vsindex < 0 ||  | 
541  | 3  |             vsindex >= static_cast<int32_t>(out_cff->region_index_count.size())) { | 
542  | 3  |           return OTS_FAILURE();  | 
543  | 3  |         }  | 
544  | 1  |         out_cff->vsindex_per_font.back() = vsindex;  | 
545  | 1  |         break;  | 
546  | 4  |       }  | 
547  |  |  | 
548  | 402  |       case 23: { // blend | 
549  | 402  |         if (!cff2) { | 
550  | 1  |           return OTS_FAILURE();  | 
551  | 1  |         }  | 
552  | 401  |         if (operands.size() < 1) { | 
553  | 1  |           return OTS_FAILURE();  | 
554  | 1  |         }  | 
555  | 400  |         if (vsindex >= static_cast<int32_t>(out_cff->region_index_count.size())) { | 
556  | 1  |           return OTS_FAILURE();  | 
557  | 1  |         }  | 
558  | 399  |         uint16_t k = out_cff->region_index_count.at(vsindex);  | 
559  |  |             | 
560  | 399  |         if (operands.back().first > static_cast<uint16_t>(0xffff) || operands.back().first < 0){ | 
561  | 3  |           return OTS_FAILURE();  | 
562  | 3  |         }  | 
563  | 396  |         uint16_t n = static_cast<uint16_t>(operands.back().first);  | 
564  | 396  |         if (operands.size() < n * (k + 1) + 1) { | 
565  | 2  |           return OTS_FAILURE();  | 
566  | 2  |         }  | 
567  | 394  |         size_t operands_size = operands.size();  | 
568  |  |         // Keep the 1st n operands on the stack for the next operator to use  | 
569  |  |         // and pop the rest. There can be multiple consecutive blend operator,  | 
570  |  |         // so this makes sure the operands of all of them are kept on the  | 
571  |  |         // stack.  | 
572  | 3.82k  |         while (operands.size() > operands_size - ((n * k) + 1))  | 
573  | 3.42k  |           operands.pop_back();  | 
574  | 394  |         clear_operands = false;  | 
575  | 394  |         blend_seen = true;  | 
576  | 394  |         break;  | 
577  | 396  |       }  | 
578  |  |  | 
579  | 16  |       default:  | 
580  | 16  |         return OTS_FAILURE();  | 
581  | 6.35k  |     }  | 
582  | 6.28k  |     if (clear_operands) { | 
583  | 5.88k  |       operands.clear();  | 
584  | 5.88k  |     }  | 
585  | 6.28k  |   }  | 
586  |  |  | 
587  | 1.04k  |   return true;  | 
588  | 1.14k  | }  | 
589  |  |  | 
590  | 197  | bool ParseVariationStore(ots::OpenTypeCFF& out_cff, ots::Buffer& table) { | 
591  | 197  |   uint16_t length;  | 
592  |  |  | 
593  | 197  |   if (!table.ReadU16(&length)) { | 
594  | 1  |     return OTS_FAILURE();  | 
595  | 1  |   }  | 
596  |  |  | 
597  |  |   // Empty VariationStore is allowed.  | 
598  | 196  |   if (!length) { | 
599  | 4  |     return true;  | 
600  | 4  |   }  | 
601  |  |  | 
602  | 192  |   if (length > table.remaining()) { | 
603  | 2  |     return OTS_FAILURE();  | 
604  | 2  |   }  | 
605  |  |  | 
606  | 190  |   if (!ParseItemVariationStore(out_cff.GetFont(),  | 
607  | 190  |                                table.buffer() + table.offset(), length,  | 
608  | 190  |                                &(out_cff.region_index_count))) { | 
609  | 78  |     return OTS_FAILURE();  | 
610  | 78  |   }  | 
611  |  |  | 
612  | 112  |   return true;  | 
613  | 190  | }  | 
614  |  |  | 
615  |  | bool ParseDictData(ots::Buffer& table, ots::Buffer& dict,  | 
616  |  |                    uint16_t glyphs, size_t sid_max, DICT_DATA_TYPE type,  | 
617  |  |                    ots::OpenTypeCFF *out_cff);  | 
618  |  |  | 
619  |  | bool ParseDictData(ots::Buffer& table, const ots::CFFIndex &index,  | 
620  |  |                    uint16_t glyphs, size_t sid_max, DICT_DATA_TYPE type,  | 
621  | 1.16k  |                    ots::OpenTypeCFF *out_cff) { | 
622  | 2.51k  |   for (unsigned i = 1; i < index.offsets.size(); ++i) { | 
623  | 1.68k  |     size_t dict_length = index.offsets[i] - index.offsets[i - 1];  | 
624  | 1.68k  |     ots::Buffer dict(table.buffer() + index.offsets[i - 1], dict_length);  | 
625  |  |  | 
626  | 1.68k  |     if (!ParseDictData(table, dict, glyphs, sid_max, type, out_cff)) { | 
627  | 328  |       return OTS_FAILURE();  | 
628  | 328  |     }  | 
629  | 1.68k  |   }  | 
630  | 833  |   return true;  | 
631  | 1.16k  | }  | 
632  |  |  | 
633  |  | bool ParseDictData(ots::Buffer& table, ots::Buffer& dict,  | 
634  |  |                    uint16_t glyphs, size_t sid_max, DICT_DATA_TYPE type,  | 
635  | 2.37k  |                    ots::OpenTypeCFF *out_cff) { | 
636  | 2.37k  |   bool cff2 = (out_cff->major == 2);  | 
637  | 2.37k  |   std::vector<Operand> operands;  | 
638  |  |  | 
639  | 2.37k  |   FONT_FORMAT font_format = FORMAT_UNKNOWN;  | 
640  | 2.37k  |   bool have_ros = false;  | 
641  | 2.37k  |   bool have_charstrings = false;  | 
642  | 2.37k  |   bool have_vstore = false;  | 
643  | 2.37k  |   size_t charset_offset = 0;  | 
644  | 2.37k  |   bool have_private = false;  | 
645  |  |  | 
646  | 2.37k  |   if (cff2) { | 
647  |  |     // Parse VariationStore first, since it might be referenced in other places  | 
648  |  |     // (e.g. FDArray) that might be parsed after it.  | 
649  | 1.19k  |     size_t dict_offset = dict.offset();  | 
650  | 13.2k  |     while (dict.offset() < dict.length()) { | 
651  | 12.2k  |       if (!ParseDictDataReadOperands(dict, operands, cff2)) { | 
652  | 28  |         return OTS_FAILURE();  | 
653  | 28  |       }  | 
654  | 12.2k  |       if (operands.back().second != DICT_OPERATOR) continue;  | 
655  |  |  | 
656  |  |       // got operator  | 
657  | 4.59k  |       const int32_t op = operands.back().first;  | 
658  | 4.59k  |       operands.pop_back();  | 
659  |  |  | 
660  | 4.59k  |       if (op == 18 && type == DICT_DATA_FDARRAY) { | 
661  | 540  |         have_private = true;  | 
662  | 540  |       }  | 
663  |  |  | 
664  | 4.59k  |       if (op == 24) {  // vstore | 
665  | 209  |         if (type != DICT_DATA_TOPLEVEL) { | 
666  | 2  |           return OTS_FAILURE();  | 
667  | 2  |         }  | 
668  | 207  |         if (operands.size() != 1) { | 
669  | 3  |           return OTS_FAILURE();  | 
670  | 3  |         }  | 
671  | 204  |         if (!CheckOffset(operands.back(), table.length())) { | 
672  | 7  |           return OTS_FAILURE();  | 
673  | 7  |         }  | 
674  |  |         // parse "VariationStore Data Contents"  | 
675  | 197  |         table.set_offset(operands.back().first);  | 
676  | 197  |         if (!ParseVariationStore(*out_cff, table)) { | 
677  | 81  |           return OTS_FAILURE();  | 
678  | 81  |         }  | 
679  | 116  |         break;  | 
680  | 197  |       }  | 
681  | 4.38k  |       operands.clear();  | 
682  | 4.38k  |     }  | 
683  | 1.07k  |     operands.clear();  | 
684  | 1.07k  |     dict.set_offset(dict_offset);  | 
685  |  |  | 
686  | 1.07k  |     if (type == DICT_DATA_FDARRAY && !have_private) { | 
687  | 3  |       return OTS_FAILURE();  // CFF2 FD must have PrivateDICT entry (even if 0, 0)  | 
688  | 3  |     }  | 
689  |  |  | 
690  | 1.07k  |   }  | 
691  |  |  | 
692  | 26.0k  |   while (dict.offset() < dict.length()) { | 
693  | 24.3k  |     if (!ParseDictDataReadOperands(dict, operands, cff2)) { | 
694  | 16  |       return OTS_FAILURE();  | 
695  | 16  |     }  | 
696  | 24.3k  |     if (operands.back().second != DICT_OPERATOR) continue;  | 
697  |  |  | 
698  |  |     // got operator  | 
699  | 8.91k  |     const int32_t op = operands.back().first;  | 
700  | 8.91k  |     operands.pop_back();  | 
701  |  |  | 
702  | 8.91k  |     if (cff2 && !ValidCFF2DictOp(op, type)) { | 
703  | 8  |       return OTS_FAILURE();  | 
704  | 8  |     }  | 
705  |  |  | 
706  | 8.90k  |     switch (op) { | 
707  |  |       // SID  | 
708  | 480  |       case 0:   // version  | 
709  | 825  |       case 1:   // Notice  | 
710  | 1.37k  |       case 2:   // Copyright  | 
711  | 1.91k  |       case 3:   // FullName  | 
712  | 2.26k  |       case 4:   // FamilyName  | 
713  | 2.39k  |       case (12 << 8) + 0:   // Copyright  | 
714  | 2.39k  |       case (12 << 8) + 21:  // PostScript  | 
715  | 2.40k  |       case (12 << 8) + 22:  // BaseFontName  | 
716  | 2.78k  |       case (12 << 8) + 38:  // FontName  | 
717  | 2.78k  |         if (operands.size() != 1) { | 
718  | 12  |           return OTS_FAILURE();  | 
719  | 12  |         }  | 
720  | 2.76k  |         if (!CheckSid(operands.back(), sid_max)) { | 
721  | 17  |           return OTS_FAILURE();  | 
722  | 17  |         }  | 
723  | 2.75k  |         break;  | 
724  |  |  | 
725  |  |       // array  | 
726  | 2.75k  |       case 5:   // FontBBox  | 
727  | 836  |       case 14:  // XUID  | 
728  | 1.13k  |       case (12 << 8) + 7:   // FontMatrix  | 
729  | 1.14k  |       case (12 << 8) + 23:  // BaseFontBlend (delta)  | 
730  | 1.14k  |         if (operands.empty()) { | 
731  | 1  |           return OTS_FAILURE();  | 
732  | 1  |         }  | 
733  | 1.14k  |         break;  | 
734  |  |  | 
735  |  |       // number  | 
736  | 1.14k  |       case 13:  // UniqueID  | 
737  | 37  |       case (12 << 8) + 2:   // ItalicAngle  | 
738  | 450  |       case (12 << 8) + 3:   // UnderlinePosition  | 
739  | 624  |       case (12 << 8) + 4:   // UnderlineThickness  | 
740  | 695  |       case (12 << 8) + 5:   // PaintType  | 
741  | 700  |       case (12 << 8) + 8:   // StrokeWidth  | 
742  | 718  |       case (12 << 8) + 20:  // SyntheticBase  | 
743  | 718  |         if (operands.size() != 1) { | 
744  | 4  |           return OTS_FAILURE();  | 
745  | 4  |         }  | 
746  | 714  |         break;  | 
747  | 714  |       case (12 << 8) + 31:  // CIDFontVersion  | 
748  | 184  |       case (12 << 8) + 32:  // CIDFontRevision  | 
749  | 195  |       case (12 << 8) + 33:  // CIDFontType  | 
750  | 375  |       case (12 << 8) + 34:  // CIDCount  | 
751  | 377  |       case (12 << 8) + 35:  // UIDBase  | 
752  | 377  |         if (operands.size() != 1) { | 
753  | 2  |           return OTS_FAILURE();  | 
754  | 2  |         }  | 
755  | 375  |         if (font_format != FORMAT_CID_KEYED) { | 
756  | 2  |           return OTS_FAILURE();  | 
757  | 2  |         }  | 
758  | 373  |         break;  | 
759  | 373  |       case (12 << 8) + 6:   // CharstringType  | 
760  | 3  |         if (operands.size() != 1) { | 
761  | 1  |           return OTS_FAILURE();  | 
762  | 1  |         }  | 
763  | 2  |         if(operands.back().second != DICT_OPERAND_INTEGER) { | 
764  | 1  |           return OTS_FAILURE();  | 
765  | 1  |         }  | 
766  | 1  |         if (operands.back().first != 2) { | 
767  |  |           // We only support the "Type 2 Charstring Format."  | 
768  |  |           // TODO(yusukes): Support Type 1 format? Is that still in use?  | 
769  | 1  |           return OTS_FAILURE();  | 
770  | 1  |         }  | 
771  | 0  |         break;  | 
772  |  |  | 
773  |  |       // boolean  | 
774  | 30  |       case (12 << 8) + 1:   // isFixedPitch  | 
775  | 30  |         if (operands.size() != 1) { | 
776  | 1  |           return OTS_FAILURE();  | 
777  | 1  |         }  | 
778  | 29  |         if (operands.back().second != DICT_OPERAND_INTEGER) { | 
779  | 1  |           return OTS_FAILURE();  | 
780  | 1  |         }  | 
781  | 28  |         if (operands.back().first >= 2 || operands.back().first < 0) { | 
782  | 4  |           return OTS_FAILURE();  | 
783  | 4  |         }  | 
784  | 24  |         break;  | 
785  |  |  | 
786  |  |       // offset(0)  | 
787  | 509  |       case 15:  // charset  | 
788  | 509  |         if (operands.size() != 1) { | 
789  | 2  |           return OTS_FAILURE();  | 
790  | 2  |         }  | 
791  | 507  |         if (operands.back().first <= 2 && operands.back().first >= 0) { | 
792  |  |           // predefined charset, ISOAdobe, Expert or ExpertSubset, is used.  | 
793  | 7  |           break;  | 
794  | 7  |         }  | 
795  | 500  |         if (!CheckOffset(operands.back(), table.length())) { | 
796  | 6  |           return OTS_FAILURE();  | 
797  | 6  |         }  | 
798  | 494  |         if (charset_offset) { | 
799  | 2  |           return OTS_FAILURE();  // multiple charset tables?  | 
800  | 2  |         }  | 
801  | 492  |         charset_offset = operands.back().first;  | 
802  | 492  |         break;  | 
803  |  |  | 
804  | 88  |       case 16: {  // Encoding | 
805  | 88  |         if (operands.size() != 1) { | 
806  | 1  |           return OTS_FAILURE();  | 
807  | 1  |         }  | 
808  | 87  |         if (operands.back().first <= 1 && operands.back().first >= 0) { | 
809  | 51  |           break;  // predefined encoding, "Standard" or "Expert", is used.  | 
810  | 51  |         }  | 
811  | 36  |         if (!CheckOffset(operands.back(), table.length())) { | 
812  | 6  |           return OTS_FAILURE();  | 
813  | 6  |         }  | 
814  |  |  | 
815  | 30  |         table.set_offset(operands.back().first);  | 
816  | 30  |         uint8_t format = 0;  | 
817  | 30  |         if (!table.ReadU8(&format)) { | 
818  | 0  |           return OTS_FAILURE();  | 
819  | 0  |         }  | 
820  | 30  |         if (format & 0x80) { | 
821  |  |           // supplemental encoding is not supported at the moment.  | 
822  | 1  |           return OTS_FAILURE();  | 
823  | 1  |         }  | 
824  |  |         // TODO(yusukes): support & parse supplemental encoding tables.  | 
825  | 29  |         break;  | 
826  | 30  |       }  | 
827  |  |  | 
828  | 759  |       case 17: {  // CharStrings | 
829  | 759  |         if (type != DICT_DATA_TOPLEVEL) { | 
830  | 1  |           return OTS_FAILURE();  | 
831  | 1  |         }  | 
832  | 758  |         if (operands.size() != 1) { | 
833  | 2  |           return OTS_FAILURE();  | 
834  | 2  |         }  | 
835  | 756  |         if (!CheckOffset(operands.back(), table.length())) { | 
836  | 10  |           return OTS_FAILURE();  | 
837  | 10  |         }  | 
838  |  |         // parse "14. CharStrings INDEX"  | 
839  | 746  |         table.set_offset(operands.back().first);  | 
840  | 746  |         ots::CFFIndex *charstring_index = out_cff->charstrings_index;  | 
841  | 746  |         if (!ParseIndex(table, *charstring_index, cff2)) { | 
842  | 17  |           return OTS_FAILURE();  | 
843  | 17  |         }  | 
844  | 729  |         if (charstring_index->count < 2) { | 
845  | 2  |           return OTS_FAILURE();  | 
846  | 2  |         }  | 
847  | 727  |         if (have_charstrings) { | 
848  | 0  |           return OTS_FAILURE();  // multiple charstring tables?  | 
849  | 0  |         }  | 
850  | 727  |         have_charstrings = true;  | 
851  | 727  |         if (charstring_index->count != glyphs) { | 
852  | 1  |           return OTS_FAILURE();  // CFF and maxp have different number of glyphs?  | 
853  | 1  |         }  | 
854  | 726  |         break;  | 
855  | 727  |       }  | 
856  |  |  | 
857  | 726  |       case 24: {  // vstore | 
858  | 85  |         if (!cff2) { | 
859  | 1  |           return OTS_FAILURE();  | 
860  | 1  |         }  | 
861  | 84  |         if (have_vstore) { | 
862  | 1  |           return OTS_FAILURE();  // multiple vstore tables?  | 
863  | 1  |         }  | 
864  | 83  |         have_vstore = true;  | 
865  |  |         // parsed above.  | 
866  | 83  |         break;  | 
867  | 84  |       }  | 
868  |  |  | 
869  | 629  |       case (12 << 8) + 36: {  // FDArray | 
870  | 629  |         if (type != DICT_DATA_TOPLEVEL) { | 
871  | 2  |           return OTS_FAILURE();  | 
872  | 2  |         }  | 
873  | 627  |         if (operands.size() != 1) { | 
874  | 4  |           return OTS_FAILURE();  | 
875  | 4  |         }  | 
876  | 623  |         if (!CheckOffset(operands.back(), table.length())) { | 
877  | 6  |           return OTS_FAILURE();  | 
878  | 6  |         }  | 
879  |  |  | 
880  |  |         // parse Font DICT INDEX.  | 
881  | 617  |         table.set_offset(operands.back().first);  | 
882  | 617  |         ots::CFFIndex sub_dict_index;  | 
883  | 617  |         if (!ParseIndex(table, sub_dict_index, cff2)) { | 
884  | 42  |           return OTS_FAILURE();  | 
885  | 42  |         }  | 
886  | 575  |         if (!ParseDictData(table, sub_dict_index,  | 
887  | 575  |                            glyphs, sid_max, DICT_DATA_FDARRAY,  | 
888  | 575  |                            out_cff)) { | 
889  | 97  |           return OTS_FAILURE();  | 
890  | 97  |         }  | 
891  | 478  |         if (out_cff->font_dict_length != 0) { | 
892  | 3  |           return OTS_FAILURE();  // two or more FDArray found.  | 
893  | 3  |         }  | 
894  | 475  |         out_cff->font_dict_length = sub_dict_index.count;  | 
895  | 475  |         break;  | 
896  | 478  |       }  | 
897  |  |  | 
898  | 398  |       case (12 << 8) + 37: {  // FDSelect | 
899  | 398  |         if (type != DICT_DATA_TOPLEVEL) { | 
900  | 3  |           return OTS_FAILURE();  | 
901  | 3  |         }  | 
902  | 395  |         if (operands.size() != 1) { | 
903  | 2  |           return OTS_FAILURE();  | 
904  | 2  |         }  | 
905  | 393  |         if (!CheckOffset(operands.back(), table.length())) { | 
906  | 7  |           return OTS_FAILURE();  | 
907  | 7  |         }  | 
908  |  |  | 
909  |  |         // parse FDSelect data structure  | 
910  | 386  |         table.set_offset(operands.back().first);  | 
911  | 386  |         uint8_t format = 0;  | 
912  | 386  |         if (!table.ReadU8(&format)) { | 
913  | 0  |           return OTS_FAILURE();  | 
914  | 0  |         }  | 
915  | 386  |         if (format == 0) { | 
916  | 666  |           for (uint16_t j = 0; j < glyphs; ++j) { | 
917  | 633  |             uint8_t fd_index = 0;  | 
918  | 633  |             if (!table.ReadU8(&fd_index)) { | 
919  | 3  |               return OTS_FAILURE();  | 
920  | 3  |             }  | 
921  | 630  |             (out_cff->fd_select)[j] = fd_index;  | 
922  | 630  |           }  | 
923  | 350  |         } else if (format == 3) { | 
924  | 187  |           uint16_t n_ranges = 0;  | 
925  | 187  |           if (!table.ReadU16(&n_ranges)) { | 
926  | 1  |             return OTS_FAILURE();  | 
927  | 1  |           }  | 
928  | 186  |           if (n_ranges == 0) { | 
929  | 1  |             return OTS_FAILURE();  | 
930  | 1  |           }  | 
931  |  |  | 
932  | 185  |           uint16_t last_gid = 0;  | 
933  | 185  |           uint8_t fd_index = 0;  | 
934  | 808  |           for (unsigned j = 0; j < n_ranges; ++j) { | 
935  | 635  |             uint16_t first = 0;  // GID  | 
936  | 635  |             if (!table.ReadU16(&first)) { | 
937  | 1  |               return OTS_FAILURE();  | 
938  | 1  |             }  | 
939  |  |  | 
940  |  |             // Sanity checks.  | 
941  | 634  |             if ((j == 0) && (first != 0)) { | 
942  | 2  |               return OTS_FAILURE();  | 
943  | 2  |             }  | 
944  | 632  |             if ((j != 0) && (last_gid >= first)) { | 
945  | 2  |               return OTS_FAILURE();  // not increasing order.  | 
946  | 2  |             }  | 
947  | 630  |             if (first >= glyphs) { | 
948  | 5  |               return OTS_FAILURE();  // invalid gid.  | 
949  | 5  |             }  | 
950  |  |  | 
951  |  |             // Copy the mapping to |out_cff->fd_select|.  | 
952  | 625  |             if (j != 0) { | 
953  | 66.1k  |               for (auto k = last_gid; k < first; ++k) { | 
954  | 65.7k  |                 if (!out_cff->fd_select.insert(  | 
955  | 65.7k  |                         std::make_pair(k, fd_index)).second) { | 
956  | 1  |                   return OTS_FAILURE();  | 
957  | 1  |                 }  | 
958  | 65.7k  |               }  | 
959  | 442  |             }  | 
960  |  |  | 
961  | 624  |             if (!table.ReadU8(&fd_index)) { | 
962  | 1  |               return OTS_FAILURE();  | 
963  | 1  |             }  | 
964  | 623  |             last_gid = first;  | 
965  | 623  |           }  | 
966  | 173  |           uint16_t sentinel = 0;  | 
967  | 173  |           if (!table.ReadU16(&sentinel)) { | 
968  | 0  |             return OTS_FAILURE();  | 
969  | 0  |           }  | 
970  | 173  |           if (last_gid >= sentinel) { | 
971  | 1  |             return OTS_FAILURE();  | 
972  | 1  |           }  | 
973  | 172  |           if (sentinel > glyphs) { | 
974  | 4  |             return OTS_FAILURE();  // invalid gid.  | 
975  | 4  |           }  | 
976  | 963  |           for (auto k = last_gid; k < sentinel; ++k) { | 
977  | 796  |             if (!out_cff->fd_select.insert(  | 
978  | 796  |                     std::make_pair(k, fd_index)).second) { | 
979  | 1  |               return OTS_FAILURE();  | 
980  | 1  |             }  | 
981  | 796  |           }  | 
982  | 168  |         } else if (cff2 && format == 4) { | 
983  | 161  |           uint32_t n_ranges = 0;  | 
984  | 161  |           if (!table.ReadU32(&n_ranges)) { | 
985  | 1  |             return OTS_FAILURE();  | 
986  | 1  |           }  | 
987  | 160  |           if (n_ranges == 0) { | 
988  | 1  |             return OTS_FAILURE();  | 
989  | 1  |           }  | 
990  |  |  | 
991  | 159  |           uint32_t last_gid = 0;  | 
992  | 159  |           uint16_t fd_index = 0;  | 
993  | 474  |           for (unsigned j = 0; j < n_ranges; ++j) { | 
994  | 364  |             uint32_t first = 0;  // GID  | 
995  | 364  |             if (!table.ReadU32(&first)) { | 
996  | 1  |               return OTS_FAILURE();  | 
997  | 1  |             }  | 
998  |  |  | 
999  |  |             // Sanity checks.  | 
1000  | 363  |             if ((j == 0) && (first != 0)) { | 
1001  | 16  |               return OTS_FAILURE();  | 
1002  | 16  |             }  | 
1003  | 347  |             if ((j != 0) && (last_gid >= first)) { | 
1004  | 2  |               return OTS_FAILURE();  // not increasing order.  | 
1005  | 2  |             }  | 
1006  | 345  |             if (first >= glyphs) { | 
1007  | 28  |               return OTS_FAILURE();  // invalid gid.  | 
1008  | 28  |             }  | 
1009  |  |  | 
1010  |  |             // Copy the mapping to |out_cff->fd_select|.  | 
1011  | 317  |             if (j != 0) { | 
1012  | 484  |               for (auto k = last_gid; k < first; ++k) { | 
1013  | 311  |                 if (!out_cff->fd_select.insert(  | 
1014  | 311  |                         std::make_pair(k, fd_index)).second) { | 
1015  | 1  |                   return OTS_FAILURE();  | 
1016  | 1  |                 }  | 
1017  | 311  |               }  | 
1018  | 174  |             }  | 
1019  |  |  | 
1020  | 316  |             if (!table.ReadU16(&fd_index)) { | 
1021  | 1  |               return OTS_FAILURE();  | 
1022  | 1  |             }  | 
1023  | 315  |             last_gid = first;  | 
1024  | 315  |           }  | 
1025  | 110  |           uint32_t sentinel = 0;  | 
1026  | 110  |           if (!table.ReadU32(&sentinel)) { | 
1027  | 1  |             return OTS_FAILURE();  | 
1028  | 1  |           }  | 
1029  | 109  |           if (last_gid >= sentinel) { | 
1030  | 1  |             return OTS_FAILURE();  | 
1031  | 1  |           }  | 
1032  | 108  |           if (sentinel > glyphs) { | 
1033  | 24  |             return OTS_FAILURE();  // invalid gid.  | 
1034  | 24  |           }  | 
1035  | 213  |           for (auto k = last_gid; k < sentinel; ++k) { | 
1036  | 130  |             if (!out_cff->fd_select.insert(  | 
1037  | 130  |                     std::make_pair(k, fd_index)).second) { | 
1038  | 1  |               return OTS_FAILURE();  | 
1039  | 1  |             }  | 
1040  | 130  |           }  | 
1041  | 84  |         } else { | 
1042  |  |           // unknown format  | 
1043  | 2  |           return OTS_FAILURE();  | 
1044  | 2  |         }  | 
1045  | 283  |         break;  | 
1046  | 386  |       }  | 
1047  |  |  | 
1048  |  |       // Private DICT (2 * number)  | 
1049  | 1.16k  |       case 18: { | 
1050  | 1.16k  |         if (operands.size() != 2) { | 
1051  | 4  |           return OTS_FAILURE();  | 
1052  | 4  |         }  | 
1053  | 1.15k  |         if (operands.back().second != DICT_OPERAND_INTEGER) { | 
1054  | 1  |           return OTS_FAILURE();  | 
1055  | 1  |         }  | 
1056  | 1.15k  |         const int32_t private_offset = operands.back().first;  | 
1057  | 1.15k  |         operands.pop_back();  | 
1058  | 1.15k  |         if (operands.back().second != DICT_OPERAND_INTEGER) { | 
1059  | 0  |           return OTS_FAILURE();  | 
1060  | 0  |         }  | 
1061  | 1.15k  |         const int32_t private_length = operands.back().first;  | 
1062  | 1.15k  |         if (private_offset > static_cast<int32_t>(table.length())) { | 
1063  | 3  |           return OTS_FAILURE();  | 
1064  | 3  |         }  | 
1065  | 1.15k  |         if (private_length >= static_cast<int32_t>(table.length()) || private_length < 0) { | 
1066  | 7  |           return OTS_FAILURE();  | 
1067  | 7  |         }  | 
1068  | 1.14k  |         if (private_length + private_offset > static_cast<int32_t>(table.length()) || private_length + private_offset < 0) { | 
1069  | 2  |           return OTS_FAILURE();  | 
1070  | 2  |         }  | 
1071  |  |         // parse "15. Private DICT data"  | 
1072  | 1.14k  |         if (!ParsePrivateDictData(table, private_offset, private_length,  | 
1073  | 1.14k  |                                   type, out_cff)) { | 
1074  | 97  |           return OTS_FAILURE();  | 
1075  | 97  |         }  | 
1076  | 1.04k  |         break;  | 
1077  | 1.14k  |       }  | 
1078  |  |  | 
1079  |  |       // ROS  | 
1080  | 1.04k  |       case (12 << 8) + 30:  | 
1081  | 218  |         if (font_format != FORMAT_UNKNOWN) { | 
1082  | 1  |           return OTS_FAILURE();  | 
1083  | 1  |         }  | 
1084  | 217  |         font_format = FORMAT_CID_KEYED;  | 
1085  | 217  |         if (operands.size() != 3) { | 
1086  | 1  |           return OTS_FAILURE();  | 
1087  | 1  |         }  | 
1088  |  |         // check SIDs  | 
1089  | 216  |         operands.pop_back();  // ignore the first number.  | 
1090  | 216  |         if (!CheckSid(operands.back(), sid_max)) { | 
1091  | 2  |           return OTS_FAILURE();  | 
1092  | 2  |         }  | 
1093  | 214  |         operands.pop_back();  | 
1094  | 214  |         if (!CheckSid(operands.back(), sid_max)) { | 
1095  | 4  |           return OTS_FAILURE();  | 
1096  | 4  |         }  | 
1097  | 210  |         if (have_ros) { | 
1098  | 0  |           return OTS_FAILURE();  // multiple ROS tables?  | 
1099  | 0  |         }  | 
1100  | 210  |         have_ros = true;  | 
1101  | 210  |         break;  | 
1102  |  |  | 
1103  | 2  |       default:  | 
1104  | 2  |         return OTS_FAILURE();  | 
1105  | 8.90k  |     }  | 
1106  | 8.41k  |     operands.clear();  | 
1107  |  |  | 
1108  | 8.41k  |     if (font_format == FORMAT_UNKNOWN) { | 
1109  | 1.61k  |       font_format = FORMAT_OTHER;  | 
1110  | 1.61k  |     }  | 
1111  | 8.41k  |   }  | 
1112  |  |  | 
1113  |  |   // parse "13. Charsets"  | 
1114  | 1.73k  |   if (charset_offset) { | 
1115  | 369  |     table.set_offset(charset_offset);  | 
1116  | 369  |     uint8_t format = 0;  | 
1117  | 369  |     if (!table.ReadU8(&format)) { | 
1118  | 0  |       return OTS_FAILURE();  | 
1119  | 0  |     }  | 
1120  | 369  |     switch (format) { | 
1121  | 131  |       case 0:  | 
1122  | 2.90k  |         for (uint16_t j = 1 /* .notdef is omitted */; j < glyphs; ++j) { | 
1123  | 2.77k  |           uint16_t sid = 0;  | 
1124  | 2.77k  |           if (!table.ReadU16(&sid)) { | 
1125  | 2  |             return OTS_FAILURE();  | 
1126  | 2  |           }  | 
1127  | 2.77k  |           if (!have_ros && (sid > sid_max)) { | 
1128  | 4  |             return OTS_FAILURE();  | 
1129  | 4  |           }  | 
1130  |  |           // TODO(yusukes): check CIDs when have_ros is true.  | 
1131  | 2.77k  |         }  | 
1132  | 125  |         break;  | 
1133  |  |  | 
1134  | 209  |       case 1:  | 
1135  | 237  |       case 2: { | 
1136  | 237  |         uint32_t total = 1;  // .notdef is omitted.  | 
1137  | 5.15k  |         while (total < glyphs) { | 
1138  | 4.92k  |           uint16_t sid = 0;  | 
1139  | 4.92k  |           if (!table.ReadU16(&sid)) { | 
1140  | 0  |             return OTS_FAILURE();  | 
1141  | 0  |           }  | 
1142  | 4.92k  |           if (!have_ros && (sid > sid_max)) { | 
1143  | 8  |             return OTS_FAILURE();  | 
1144  | 8  |           }  | 
1145  |  |           // TODO(yusukes): check CIDs when have_ros is true.  | 
1146  |  |  | 
1147  | 4.91k  |           if (format == 1) { | 
1148  | 557  |             uint8_t left = 0;  | 
1149  | 557  |             if (!table.ReadU8(&left)) { | 
1150  | 1  |               return OTS_FAILURE();  | 
1151  | 1  |             }  | 
1152  | 556  |             total += (left + 1);  | 
1153  | 4.36k  |           } else { | 
1154  | 4.36k  |             uint16_t left = 0;  | 
1155  | 4.36k  |             if (!table.ReadU16(&left)) { | 
1156  | 1  |               return OTS_FAILURE();  | 
1157  | 1  |             }  | 
1158  | 4.36k  |             total += (left + 1);  | 
1159  | 4.36k  |           }  | 
1160  | 4.91k  |         }  | 
1161  | 227  |         break;  | 
1162  | 237  |       }  | 
1163  |  |  | 
1164  | 227  |       default:  | 
1165  | 1  |         return OTS_FAILURE();  | 
1166  | 369  |     }  | 
1167  | 369  |   }  | 
1168  | 1.71k  |   return true;  | 
1169  | 1.73k  | }  | 
1170  |  |  | 
1171  |  | }  // namespace  | 
1172  |  |  | 
1173  |  | namespace ots { | 
1174  |  |  | 
1175  | 705  | bool OpenTypeCFF::ValidateFDSelect(uint16_t num_glyphs) { | 
1176  | 894  |   for (const auto& fd_select : this->fd_select) { | 
1177  | 894  |     if (fd_select.first >= num_glyphs) { | 
1178  | 0  |       return Error("Invalid glyph index in FDSelect: %d >= %d\n", | 
1179  | 0  |                    fd_select.first, num_glyphs);  | 
1180  | 0  |     }  | 
1181  | 894  |     if (fd_select.second >= this->font_dict_length) { | 
1182  | 15  |       return Error("Invalid FD index: %d >= %d\n", | 
1183  | 15  |                    fd_select.second, this->font_dict_length);  | 
1184  | 15  |     }  | 
1185  | 894  |   }  | 
1186  | 690  |   return true;  | 
1187  | 705  | }  | 
1188  |  |  | 
1189  | 632  | bool OpenTypeCFF::Parse(const uint8_t *data, size_t length) { | 
1190  | 632  |   Buffer table(data, length);  | 
1191  |  |  | 
1192  | 632  |   Font *font = GetFont();  | 
1193  |  |  | 
1194  | 632  |   this->m_data = data;  | 
1195  | 632  |   this->m_length = length;  | 
1196  |  |  | 
1197  |  |   // parse "6. Header" in the Adobe Compact Font Format Specification  | 
1198  | 632  |   uint8_t major = 0;  | 
1199  | 632  |   uint8_t minor = 0;  | 
1200  | 632  |   uint8_t hdr_size = 0;  | 
1201  | 632  |   uint8_t off_size = 0;  | 
1202  | 632  |   if (!table.ReadU8(&major) ||  | 
1203  | 632  |       !table.ReadU8(&minor) ||  | 
1204  | 631  |       !table.ReadU8(&hdr_size) ||  | 
1205  | 630  |       !table.ReadU8(&off_size)) { | 
1206  | 3  |     return Error("Failed to read table header"); | 
1207  | 3  |   }  | 
1208  |  |  | 
1209  | 629  |   if (off_size < 1 || off_size > 4) { | 
1210  | 3  |     return Error("Bad offSize: %d", off_size); | 
1211  | 3  |   }  | 
1212  |  |  | 
1213  | 626  |   if (major != 1 || minor != 0) { | 
1214  | 2  |     return Error("Unsupported table version: %d.%d", major, minor); | 
1215  | 2  |   }  | 
1216  |  |  | 
1217  | 624  |   this->major = major;  | 
1218  |  |  | 
1219  | 624  |   if (hdr_size != 4 || hdr_size >= length) { | 
1220  | 2  |     return Error("Bad hdrSize: %d", hdr_size); | 
1221  | 2  |   }  | 
1222  |  |  | 
1223  |  |   // parse "7. Name INDEX"  | 
1224  | 622  |   table.set_offset(hdr_size);  | 
1225  | 622  |   CFFIndex name_index;  | 
1226  | 622  |   if (!ParseIndex(table, name_index)) { | 
1227  | 5  |     return Error("Failed to parse Name INDEX"); | 
1228  | 5  |   }  | 
1229  | 617  |   if (name_index.count != 1 || name_index.offsets.size() != 2) { | 
1230  | 1  |     return Error("Name INDEX must contain only one entry, not %d", | 
1231  | 1  |                  name_index.count);  | 
1232  | 1  |   }  | 
1233  | 616  |   if (!ParseNameData(&table, name_index, &(this->name))) { | 
1234  | 13  |     return Error("Failed to parse Name INDEX data"); | 
1235  | 13  |   }  | 
1236  |  |  | 
1237  |  |   // parse "8. Top DICT INDEX"  | 
1238  | 603  |   table.set_offset(name_index.offset_to_next);  | 
1239  | 603  |   CFFIndex top_dict_index;  | 
1240  | 603  |   if (!ParseIndex(table, top_dict_index)) { | 
1241  | 6  |     return Error("Failed to parse Top DICT INDEX"); | 
1242  | 6  |   }  | 
1243  | 597  |   if (top_dict_index.count != 1) { | 
1244  | 1  |     return Error("Top DICT INDEX must contain only one entry, not %d", | 
1245  | 1  |                  top_dict_index.count);  | 
1246  | 1  |   }  | 
1247  |  |  | 
1248  |  |   // parse "10. String INDEX"  | 
1249  | 596  |   table.set_offset(top_dict_index.offset_to_next);  | 
1250  | 596  |   CFFIndex string_index;  | 
1251  | 596  |   if (!ParseIndex(table, string_index)) { | 
1252  | 10  |     return Error("Failed to parse String INDEX"); | 
1253  | 10  |   }  | 
1254  | 586  |   if (string_index.count >= 65000 - kNStdString) { | 
1255  | 0  |     return Error("Too many entries in String INDEX: %d", string_index.count); | 
1256  | 0  |   }  | 
1257  |  |  | 
1258  | 586  |   OpenTypeMAXP *maxp = static_cast<OpenTypeMAXP*>(  | 
1259  | 586  |     font->GetTypedTable(OTS_TAG_MAXP));  | 
1260  | 586  |   if (!maxp) { | 
1261  | 0  |     return Error("Required maxp table missing"); | 
1262  | 0  |   }  | 
1263  | 586  |   const uint16_t num_glyphs = maxp->num_glyphs;  | 
1264  | 586  |   const size_t sid_max = string_index.count + kNStdString;  | 
1265  |  |   // string_index.count == 0 is allowed.  | 
1266  |  |  | 
1267  |  |   // parse "9. Top DICT Data"  | 
1268  | 586  |   this->charstrings_index = new ots::CFFIndex;  | 
1269  | 586  |   if (!ParseDictData(table, top_dict_index,  | 
1270  | 586  |                      num_glyphs, sid_max,  | 
1271  | 586  |                      DICT_DATA_TOPLEVEL, this)) { | 
1272  | 231  |     return Error("Failed to parse Top DICT Data"); | 
1273  | 231  |   }  | 
1274  |  |  | 
1275  |  |   // parse "16. Global Subrs INDEX"  | 
1276  | 355  |   table.set_offset(string_index.offset_to_next);  | 
1277  | 355  |   CFFIndex global_subrs_index;  | 
1278  | 355  |   if (!ParseIndex(table, global_subrs_index)) { | 
1279  | 7  |     return Error("Failed to parse Global Subrs INDEX"); | 
1280  | 7  |   }  | 
1281  |  |  | 
1282  |  |   // Check if all fd and glyph indices in FDSelect are valid.  | 
1283  | 348  |   if (!ValidateFDSelect(num_glyphs)) { | 
1284  | 6  |     return Error("Failed to validate FDSelect"); | 
1285  | 6  |   }  | 
1286  |  |  | 
1287  |  |   // Check if all charstrings (font hinting code for each glyph) are valid.  | 
1288  | 342  |   if (!ValidateCFFCharStrings(*this, global_subrs_index, &table)) { | 
1289  | 164  |     return Error("Failed validating CharStrings INDEX"); | 
1290  | 164  |   }  | 
1291  |  |  | 
1292  | 178  |   return true;  | 
1293  | 342  | }  | 
1294  |  |  | 
1295  | 40  | bool OpenTypeCFF::Serialize(OTSStream *out) { | 
1296  | 40  |   if (!out->Write(this->m_data, this->m_length)) { | 
1297  | 0  |     return Error("Failed to write table"); | 
1298  | 0  |   }  | 
1299  | 40  |   return true;  | 
1300  | 40  | }  | 
1301  |  |  | 
1302  | 1.34k  | OpenTypeCFF::~OpenTypeCFF() { | 
1303  | 2.18k  |   for (size_t i = 0; i < this->local_subrs_per_font.size(); ++i) { | 
1304  | 836  |     delete (this->local_subrs_per_font)[i];  | 
1305  | 836  |   }  | 
1306  | 1.34k  |   delete this->charstrings_index;  | 
1307  | 1.34k  |   delete this->local_subrs;  | 
1308  | 1.34k  | }  | 
1309  |  |  | 
1310  | 708  | bool OpenTypeCFF2::Parse(const uint8_t *data, size_t length) { | 
1311  | 708  |   Buffer table(data, length);  | 
1312  |  |  | 
1313  | 708  |   Font *font = GetFont();  | 
1314  |  |  | 
1315  | 708  |   this->m_data = data;  | 
1316  | 708  |   this->m_length = length;  | 
1317  |  |  | 
1318  |  |   // parse "6. Header"  | 
1319  | 708  |   uint8_t major = 0;  | 
1320  | 708  |   uint8_t minor = 0;  | 
1321  | 708  |   uint8_t hdr_size = 0;  | 
1322  | 708  |   uint16_t top_dict_size = 0;  | 
1323  | 708  |   if (!table.ReadU8(&major) ||  | 
1324  | 708  |       !table.ReadU8(&minor) ||  | 
1325  | 707  |       !table.ReadU8(&hdr_size) ||  | 
1326  | 706  |       !table.ReadU16(&top_dict_size)) { | 
1327  | 3  |     return Error("Failed to read table header"); | 
1328  | 3  |   }  | 
1329  |  |  | 
1330  | 705  |   if (major != 2 || minor != 0) { | 
1331  | 10  |     return Error("Unsupported table version: %d.%d", major, minor); | 
1332  | 10  |   }  | 
1333  |  |  | 
1334  | 695  |   this->major = major;  | 
1335  |  |  | 
1336  | 695  |   if (hdr_size >= length) { | 
1337  | 1  |     return Error("Bad hdrSize: %d", hdr_size); | 
1338  | 1  |   }  | 
1339  |  |  | 
1340  | 694  |   if (top_dict_size == 0 || hdr_size + top_dict_size > length) { | 
1341  | 4  |     return Error("Bad topDictLength: %d", top_dict_size); | 
1342  | 4  |   }  | 
1343  |  |  | 
1344  | 690  |   OpenTypeMAXP *maxp = static_cast<OpenTypeMAXP*>(  | 
1345  | 690  |     font->GetTypedTable(OTS_TAG_MAXP));  | 
1346  | 690  |   if (!maxp) { | 
1347  | 0  |     return Error("Required maxp table missing"); | 
1348  | 0  |   }  | 
1349  | 690  |   const uint16_t num_glyphs = maxp->num_glyphs;  | 
1350  | 690  |   const size_t sid_max = kNStdString;  | 
1351  |  |  | 
1352  |  |   // parse "7. Top DICT Data"  | 
1353  | 690  |   ots::Buffer top_dict(data + hdr_size, top_dict_size);  | 
1354  | 690  |   table.set_offset(hdr_size);  | 
1355  | 690  |   this->charstrings_index = new ots::CFFIndex;  | 
1356  | 690  |   if (!ParseDictData(table, top_dict,  | 
1357  | 690  |                      num_glyphs, sid_max,  | 
1358  | 690  |                      DICT_DATA_TOPLEVEL, this)) { | 
1359  | 330  |     return Error("Failed to parse Top DICT Data"); | 
1360  | 330  |   }  | 
1361  |  |  | 
1362  |  |   // parse "9. Global Subrs INDEX"  | 
1363  | 360  |   table.set_offset(hdr_size + top_dict_size);  | 
1364  | 360  |   CFFIndex global_subrs_index;  | 
1365  | 360  |   if (!ParseIndex(table, global_subrs_index, true)) { | 
1366  | 3  |     return Error("Failed to parse Global Subrs INDEX"); | 
1367  | 3  |   }  | 
1368  |  |  | 
1369  |  |   // Check if all fd and glyph indices in FDSelect are valid.  | 
1370  | 357  |   if (!ValidateFDSelect(num_glyphs)) { | 
1371  | 9  |     return Error("Failed to validate FDSelect"); | 
1372  | 9  |   }  | 
1373  |  |  | 
1374  |  |   // Check if all charstrings (font hinting code for each glyph) are valid.  | 
1375  | 348  |   if (!ValidateCFFCharStrings(*this, global_subrs_index, &table)) { | 
1376  | 119  |     return Error("Failed validating CharStrings INDEX"); | 
1377  | 119  |   }  | 
1378  |  |  | 
1379  | 229  |   return true;  | 
1380  | 348  | }  | 
1381  |  |  | 
1382  | 27  | bool OpenTypeCFF2::Serialize(OTSStream *out) { | 
1383  | 27  |   if (!out->Write(this->m_data, this->m_length)) { | 
1384  | 0  |     return Error("Failed to write table"); | 
1385  | 0  |   }  | 
1386  | 27  |   return true;  | 
1387  | 27  | }  | 
1388  |  |  | 
1389  |  | }  // namespace ots  | 
1390  |  |  | 
1391  |  | #undef TABLE_NAME  |