OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
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_type2_charstring.h" | |
13 | |
14 // CFF - PostScript font program (Compact Font Format) table | |
15 // http://www.microsoft.com/typography/otspec/cff.htm | |
16 // http://www.microsoft.com/typography/otspec/cffspec.htm | |
17 | |
18 #define TABLE_NAME "CFF" | |
19 | |
20 namespace { | |
21 | |
22 enum DICT_OPERAND_TYPE { | |
23 DICT_OPERAND_INTEGER, | |
24 DICT_OPERAND_REAL, | |
25 DICT_OPERATOR, | |
26 }; | |
27 | |
28 enum DICT_DATA_TYPE { | |
29 DICT_DATA_TOPLEVEL, | |
30 DICT_DATA_FDARRAY, | |
31 }; | |
32 | |
33 enum FONT_FORMAT { | |
34 FORMAT_UNKNOWN, | |
35 FORMAT_CID_KEYED, | |
36 FORMAT_OTHER, // Including synthetic fonts | |
37 }; | |
38 | |
39 // see Appendix. A | |
40 const size_t kNStdString = 390; | |
41 | |
42 bool ReadOffset(ots::Buffer *table, uint8_t off_size, uint32_t *offset) { | |
43 if (off_size > 4) { | |
44 return OTS_FAILURE(); | |
45 } | |
46 | |
47 uint32_t tmp32 = 0; | |
48 for (unsigned i = 0; i < off_size; ++i) { | |
49 uint8_t tmp8 = 0; | |
50 if (!table->ReadU8(&tmp8)) { | |
51 return OTS_FAILURE(); | |
52 } | |
53 tmp32 <<= 8; | |
54 tmp32 += tmp8; | |
55 } | |
56 *offset = tmp32; | |
57 return true; | |
58 } | |
59 | |
60 bool ParseIndex(ots::Buffer *table, ots::CFFIndex *index) { | |
61 index->off_size = 0; | |
62 index->offsets.clear(); | |
63 | |
64 if (!table->ReadU16(&(index->count))) { | |
65 return OTS_FAILURE(); | |
66 } | |
67 if (index->count == 0) { | |
68 // An empty INDEX. | |
69 index->offset_to_next = table->offset(); | |
70 return true; | |
71 } | |
72 | |
73 if (!table->ReadU8(&(index->off_size))) { | |
74 return OTS_FAILURE(); | |
75 } | |
76 if ((index->off_size == 0) || | |
77 (index->off_size > 4)) { | |
78 return OTS_FAILURE(); | |
79 } | |
80 | |
81 const size_t array_size = (index->count + 1) * index->off_size; | |
82 // less than ((64k + 1) * 4), thus does not overflow. | |
83 const size_t object_data_offset = table->offset() + array_size; | |
84 // does not overflow too, since offset() <= 1GB. | |
85 | |
86 if (object_data_offset >= table->length()) { | |
87 return OTS_FAILURE(); | |
88 } | |
89 | |
90 for (unsigned i = 0; i <= index->count; ++i) { // '<=' is not a typo. | |
91 uint32_t rel_offset = 0; | |
92 if (!ReadOffset(table, index->off_size, &rel_offset)) { | |
93 return OTS_FAILURE(); | |
94 } | |
95 if (rel_offset < 1) { | |
96 return OTS_FAILURE(); | |
97 } | |
98 if (i == 0 && rel_offset != 1) { | |
99 return OTS_FAILURE(); | |
100 } | |
101 | |
102 if (rel_offset > table->length()) { | |
103 return OTS_FAILURE(); | |
104 } | |
105 | |
106 // does not underflow. | |
107 if (object_data_offset > table->length() - (rel_offset - 1)) { | |
108 return OTS_FAILURE(); | |
109 } | |
110 | |
111 index->offsets.push_back( | |
112 object_data_offset + (rel_offset - 1)); // less than length(), 1GB. | |
113 } | |
114 | |
115 for (unsigned i = 1; i < index->offsets.size(); ++i) { | |
116 // We allow consecutive identical offsets here for zero-length strings. | |
117 // See http://crbug.com/69341 for more details. | |
118 if (index->offsets[i] < index->offsets[i - 1]) { | |
119 return OTS_FAILURE(); | |
120 } | |
121 } | |
122 | |
123 index->offset_to_next = index->offsets.back(); | |
124 return true; | |
125 } | |
126 | |
127 bool ParseNameData( | |
128 ots::Buffer *table, const ots::CFFIndex &index, std::string* out_name) { | |
129 uint8_t name[256] = {0}; | |
130 if (index.offsets.size() == 0) { // just in case. | |
131 return OTS_FAILURE(); | |
132 } | |
133 for (unsigned i = 1; i < index.offsets.size(); ++i) { | |
134 const size_t length = index.offsets[i] - index.offsets[i - 1]; | |
135 // font names should be no longer than 127 characters. | |
136 if (length > 127) { | |
137 return OTS_FAILURE(); | |
138 } | |
139 | |
140 table->set_offset(index.offsets[i - 1]); | |
141 if (!table->Read(name, length)) { | |
142 return OTS_FAILURE(); | |
143 } | |
144 | |
145 for (size_t j = 0; j < length; ++j) { | |
146 // setting the first byte to NUL is allowed. | |
147 if (j == 0 && name[j] == 0) continue; | |
148 // non-ASCII characters are not recommended (except the first character). | |
149 if (name[j] < 33 || name[j] > 126) { | |
150 return OTS_FAILURE(); | |
151 } | |
152 // [, ], ... are not allowed. | |
153 if (std::strchr("[](){}<>/% ", name[j])) { | |
154 return OTS_FAILURE(); | |
155 } | |
156 } | |
157 } | |
158 | |
159 *out_name = reinterpret_cast<char *>(name); | |
160 return true; | |
161 } | |
162 | |
163 bool CheckOffset(const std::pair<uint32_t, DICT_OPERAND_TYPE>& operand, | |
164 size_t table_length) { | |
165 if (operand.second != DICT_OPERAND_INTEGER) { | |
166 return OTS_FAILURE(); | |
167 } | |
168 if (operand.first >= table_length) { | |
169 return OTS_FAILURE(); | |
170 } | |
171 return true; | |
172 } | |
173 | |
174 bool CheckSid(const std::pair<uint32_t, DICT_OPERAND_TYPE>& operand, | |
175 size_t sid_max) { | |
176 if (operand.second != DICT_OPERAND_INTEGER) { | |
177 return OTS_FAILURE(); | |
178 } | |
179 if (operand.first > sid_max) { | |
180 return OTS_FAILURE(); | |
181 } | |
182 return true; | |
183 } | |
184 | |
185 bool ParseDictDataBcd( | |
186 ots::Buffer *table, | |
187 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) { | |
188 bool read_decimal_point = false; | |
189 bool read_e = false; | |
190 | |
191 uint8_t nibble = 0; | |
192 size_t count = 0; | |
193 while (true) { | |
194 if (!table->ReadU8(&nibble)) { | |
195 return OTS_FAILURE(); | |
196 } | |
197 if ((nibble & 0xf0) == 0xf0) { | |
198 if ((nibble & 0xf) == 0xf) { | |
199 // TODO(yusukes): would be better to store actual double value, | |
200 // rather than the dummy integer. | |
201 operands->push_back(std::make_pair(static_cast<uint32_t>(0), | |
202 DICT_OPERAND_REAL)); | |
203 return true; | |
204 } | |
205 return OTS_FAILURE(); | |
206 } | |
207 if ((nibble & 0x0f) == 0x0f) { | |
208 operands->push_back(std::make_pair(static_cast<uint32_t>(0), | |
209 DICT_OPERAND_REAL)); | |
210 return true; | |
211 } | |
212 | |
213 // check number format | |
214 uint8_t nibbles[2]; | |
215 nibbles[0] = (nibble & 0xf0) >> 8; | |
216 nibbles[1] = (nibble & 0x0f); | |
217 for (unsigned i = 0; i < 2; ++i) { | |
218 if (nibbles[i] == 0xd) { // reserved number | |
219 return OTS_FAILURE(); | |
220 } | |
221 if ((nibbles[i] == 0xe) && // minus | |
222 ((count > 0) || (i > 0))) { | |
223 return OTS_FAILURE(); // minus sign should be the first character. | |
224 } | |
225 if (nibbles[i] == 0xa) { // decimal point | |
226 if (!read_decimal_point) { | |
227 read_decimal_point = true; | |
228 } else { | |
229 return OTS_FAILURE(); // two or more points. | |
230 } | |
231 } | |
232 if ((nibbles[i] == 0xb) || // E+ | |
233 (nibbles[i] == 0xc)) { // E- | |
234 if (!read_e) { | |
235 read_e = true; | |
236 } else { | |
237 return OTS_FAILURE(); // two or more E's. | |
238 } | |
239 } | |
240 } | |
241 ++count; | |
242 } | |
243 } | |
244 | |
245 bool ParseDictDataEscapedOperator( | |
246 ots::Buffer *table, | |
247 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) { | |
248 uint8_t op = 0; | |
249 if (!table->ReadU8(&op)) { | |
250 return OTS_FAILURE(); | |
251 } | |
252 | |
253 if ((op <= 14) || | |
254 (op >= 17 && op <= 23) || | |
255 (op >= 30 && op <= 38)) { | |
256 operands->push_back(std::make_pair((12U << 8) + op, DICT_OPERATOR)); | |
257 return true; | |
258 } | |
259 | |
260 // reserved area. | |
261 return OTS_FAILURE(); | |
262 } | |
263 | |
264 bool ParseDictDataNumber( | |
265 ots::Buffer *table, uint8_t b0, | |
266 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) { | |
267 uint8_t b1 = 0; | |
268 uint8_t b2 = 0; | |
269 uint8_t b3 = 0; | |
270 uint8_t b4 = 0; | |
271 | |
272 switch (b0) { | |
273 case 28: // shortint | |
274 if (!table->ReadU8(&b1) || | |
275 !table->ReadU8(&b2)) { | |
276 return OTS_FAILURE(); | |
277 } | |
278 operands->push_back(std::make_pair( | |
279 static_cast<uint32_t>((b1 << 8) + b2), DICT_OPERAND_INTEGER)); | |
280 return true; | |
281 | |
282 case 29: // longint | |
283 if (!table->ReadU8(&b1) || | |
284 !table->ReadU8(&b2) || | |
285 !table->ReadU8(&b3) || | |
286 !table->ReadU8(&b4)) { | |
287 return OTS_FAILURE(); | |
288 } | |
289 operands->push_back(std::make_pair( | |
290 static_cast<uint32_t>((b1 << 24) + (b2 << 16) + (b3 << 8) + b4), | |
291 DICT_OPERAND_INTEGER)); | |
292 return true; | |
293 | |
294 case 30: // binary coded decimal | |
295 return ParseDictDataBcd(table, operands); | |
296 | |
297 default: | |
298 break; | |
299 } | |
300 | |
301 uint32_t result; | |
302 if (b0 >=32 && b0 <=246) { | |
303 result = b0 - 139; | |
304 } else if (b0 >=247 && b0 <= 250) { | |
305 if (!table->ReadU8(&b1)) { | |
306 return OTS_FAILURE(); | |
307 } | |
308 result = (b0 - 247) * 256 + b1 + 108; | |
309 } else if (b0 >= 251 && b0 <= 254) { | |
310 if (!table->ReadU8(&b1)) { | |
311 return OTS_FAILURE(); | |
312 } | |
313 result = -(b0 - 251) * 256 + b1 - 108; | |
314 } else { | |
315 return OTS_FAILURE(); | |
316 } | |
317 | |
318 operands->push_back(std::make_pair(result, DICT_OPERAND_INTEGER)); | |
319 return true; | |
320 } | |
321 | |
322 bool ParseDictDataReadNext( | |
323 ots::Buffer *table, | |
324 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) { | |
325 uint8_t op = 0; | |
326 if (!table->ReadU8(&op)) { | |
327 return OTS_FAILURE(); | |
328 } | |
329 if (op <= 21) { | |
330 if (op == 12) { | |
331 return ParseDictDataEscapedOperator(table, operands); | |
332 } | |
333 operands->push_back(std::make_pair( | |
334 static_cast<uint32_t>(op), DICT_OPERATOR)); | |
335 return true; | |
336 } else if (op <= 27 || op == 31 || op == 255) { | |
337 // reserved area. | |
338 return OTS_FAILURE(); | |
339 } | |
340 | |
341 return ParseDictDataNumber(table, op, operands); | |
342 } | |
343 | |
344 bool ParsePrivateDictData( | |
345 const uint8_t *data, | |
346 size_t table_length, size_t offset, size_t dict_length, | |
347 DICT_DATA_TYPE type, ots::OpenTypeCFF *out_cff) { | |
348 ots::Buffer table(data + offset, dict_length); | |
349 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands; | |
350 | |
351 // Since a Private DICT for FDArray might not have a Local Subr (e.g. Hiragino | |
352 // Kaku Gothic Std W8), we create an empty Local Subr here to match the size | |
353 // of FDArray the size of |local_subrs_per_font|. | |
354 if (type == DICT_DATA_FDARRAY) { | |
355 out_cff->local_subrs_per_font.push_back(new ots::CFFIndex); | |
356 } | |
357 | |
358 while (table.offset() < dict_length) { | |
359 if (!ParseDictDataReadNext(&table, &operands)) { | |
360 return OTS_FAILURE(); | |
361 } | |
362 if (operands.empty()) { | |
363 return OTS_FAILURE(); | |
364 } | |
365 if (operands.size() > 48) { | |
366 // An operator may be preceded by up to a maximum of 48 operands. | |
367 return OTS_FAILURE(); | |
368 } | |
369 if (operands.back().second != DICT_OPERATOR) { | |
370 continue; | |
371 } | |
372 | |
373 // got operator | |
374 const uint32_t op = operands.back().first; | |
375 operands.pop_back(); | |
376 | |
377 switch (op) { | |
378 // array | |
379 case 6: // BlueValues | |
380 case 7: // OtherBlues | |
381 case 8: // FamilyBlues | |
382 case 9: // FamilyOtherBlues | |
383 case (12U << 8) + 12: // StemSnapH (delta) | |
384 case (12U << 8) + 13: // StemSnapV (delta) | |
385 if (operands.empty()) { | |
386 return OTS_FAILURE(); | |
387 } | |
388 break; | |
389 | |
390 // number | |
391 case 10: // StdHW | |
392 case 11: // StdVW | |
393 case 20: // defaultWidthX | |
394 case 21: // nominalWidthX | |
395 case (12U << 8) + 9: // BlueScale | |
396 case (12U << 8) + 10: // BlueShift | |
397 case (12U << 8) + 11: // BlueFuzz | |
398 case (12U << 8) + 17: // LanguageGroup | |
399 case (12U << 8) + 18: // ExpansionFactor | |
400 case (12U << 8) + 19: // initialRandomSeed | |
401 if (operands.size() != 1) { | |
402 return OTS_FAILURE(); | |
403 } | |
404 break; | |
405 | |
406 // Local Subrs INDEX, offset(self) | |
407 case 19: { | |
408 if (operands.size() != 1) { | |
409 return OTS_FAILURE(); | |
410 } | |
411 if (operands.back().second != DICT_OPERAND_INTEGER) { | |
412 return OTS_FAILURE(); | |
413 } | |
414 if (operands.back().first >= 1024 * 1024 * 1024) { | |
415 return OTS_FAILURE(); | |
416 } | |
417 if (operands.back().first + offset >= table_length) { | |
418 return OTS_FAILURE(); | |
419 } | |
420 // parse "16. Local Subrs INDEX" | |
421 ots::Buffer cff_table(data, table_length); | |
422 cff_table.set_offset(operands.back().first + offset); | |
423 ots::CFFIndex *local_subrs_index = NULL; | |
424 if (type == DICT_DATA_FDARRAY) { | |
425 if (out_cff->local_subrs_per_font.empty()) { | |
426 return OTS_FAILURE(); // not reached. | |
427 } | |
428 local_subrs_index = out_cff->local_subrs_per_font.back(); | |
429 } else { // type == DICT_DATA_TOPLEVEL | |
430 if (out_cff->local_subrs) { | |
431 return OTS_FAILURE(); // two or more local_subrs? | |
432 } | |
433 local_subrs_index = new ots::CFFIndex; | |
434 out_cff->local_subrs = local_subrs_index; | |
435 } | |
436 if (!ParseIndex(&cff_table, local_subrs_index)) { | |
437 return OTS_FAILURE(); | |
438 } | |
439 break; | |
440 } | |
441 | |
442 // boolean | |
443 case (12U << 8) + 14: // ForceBold | |
444 if (operands.size() != 1) { | |
445 return OTS_FAILURE(); | |
446 } | |
447 if (operands.back().second != DICT_OPERAND_INTEGER) { | |
448 return OTS_FAILURE(); | |
449 } | |
450 if (operands.back().first >= 2) { | |
451 return OTS_FAILURE(); | |
452 } | |
453 break; | |
454 | |
455 default: | |
456 return OTS_FAILURE(); | |
457 } | |
458 operands.clear(); | |
459 } | |
460 | |
461 return true; | |
462 } | |
463 | |
464 bool ParseDictData(const uint8_t *data, size_t table_length, | |
465 const ots::CFFIndex &index, uint16_t glyphs, | |
466 size_t sid_max, DICT_DATA_TYPE type, | |
467 ots::OpenTypeCFF *out_cff) { | |
468 for (unsigned i = 1; i < index.offsets.size(); ++i) { | |
469 if (type == DICT_DATA_TOPLEVEL) { | |
470 out_cff->char_strings_array.push_back(new ots::CFFIndex); | |
471 } | |
472 size_t dict_length = index.offsets[i] - index.offsets[i - 1]; | |
473 ots::Buffer table(data + index.offsets[i - 1], dict_length); | |
474 | |
475 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands; | |
476 | |
477 FONT_FORMAT font_format = FORMAT_UNKNOWN; | |
478 bool have_ros = false; | |
479 uint16_t charstring_glyphs = 0; | |
480 size_t charset_offset = 0; | |
481 | |
482 while (table.offset() < dict_length) { | |
483 if (!ParseDictDataReadNext(&table, &operands)) { | |
484 return OTS_FAILURE(); | |
485 } | |
486 if (operands.empty()) { | |
487 return OTS_FAILURE(); | |
488 } | |
489 if (operands.size() > 48) { | |
490 // An operator may be preceded by up to a maximum of 48 operands. | |
491 return OTS_FAILURE(); | |
492 } | |
493 if (operands.back().second != DICT_OPERATOR) continue; | |
494 | |
495 // got operator | |
496 const uint32_t op = operands.back().first; | |
497 operands.pop_back(); | |
498 | |
499 switch (op) { | |
500 // SID | |
501 case 0: // version | |
502 case 1: // Notice | |
503 case 2: // Copyright | |
504 case 3: // FullName | |
505 case 4: // FamilyName | |
506 case (12U << 8) + 0: // Copyright | |
507 case (12U << 8) + 21: // PostScript | |
508 case (12U << 8) + 22: // BaseFontName | |
509 case (12U << 8) + 38: // FontName | |
510 if (operands.size() != 1) { | |
511 return OTS_FAILURE(); | |
512 } | |
513 if (!CheckSid(operands.back(), sid_max)) { | |
514 return OTS_FAILURE(); | |
515 } | |
516 break; | |
517 | |
518 // array | |
519 case 5: // FontBBox | |
520 case 14: // XUID | |
521 case (12U << 8) + 7: // FontMatrix | |
522 case (12U << 8) + 23: // BaseFontBlend (delta) | |
523 if (operands.empty()) { | |
524 return OTS_FAILURE(); | |
525 } | |
526 break; | |
527 | |
528 // number | |
529 case 13: // UniqueID | |
530 case (12U << 8) + 2: // ItalicAngle | |
531 case (12U << 8) + 3: // UnderlinePosition | |
532 case (12U << 8) + 4: // UnderlineThickness | |
533 case (12U << 8) + 5: // PaintType | |
534 case (12U << 8) + 8: // StrokeWidth | |
535 case (12U << 8) + 20: // SyntheticBase | |
536 if (operands.size() != 1) { | |
537 return OTS_FAILURE(); | |
538 } | |
539 break; | |
540 case (12U << 8) + 31: // CIDFontVersion | |
541 case (12U << 8) + 32: // CIDFontRevision | |
542 case (12U << 8) + 33: // CIDFontType | |
543 case (12U << 8) + 34: // CIDCount | |
544 case (12U << 8) + 35: // UIDBase | |
545 if (operands.size() != 1) { | |
546 return OTS_FAILURE(); | |
547 } | |
548 if (font_format != FORMAT_CID_KEYED) { | |
549 return OTS_FAILURE(); | |
550 } | |
551 break; | |
552 case (12U << 8) + 6: // CharstringType | |
553 if (operands.size() != 1) { | |
554 return OTS_FAILURE(); | |
555 } | |
556 if(operands.back().second != DICT_OPERAND_INTEGER) { | |
557 return OTS_FAILURE(); | |
558 } | |
559 if (operands.back().first != 2) { | |
560 // We only support the "Type 2 Charstring Format." | |
561 // TODO(yusukes): Support Type 1 format? Is that still in use? | |
562 return OTS_FAILURE(); | |
563 } | |
564 break; | |
565 | |
566 // boolean | |
567 case (12U << 8) + 1: // isFixedPitch | |
568 if (operands.size() != 1) { | |
569 return OTS_FAILURE(); | |
570 } | |
571 if (operands.back().second != DICT_OPERAND_INTEGER) { | |
572 return OTS_FAILURE(); | |
573 } | |
574 if (operands.back().first >= 2) { | |
575 return OTS_FAILURE(); | |
576 } | |
577 break; | |
578 | |
579 // offset(0) | |
580 case 15: // charset | |
581 if (operands.size() != 1) { | |
582 return OTS_FAILURE(); | |
583 } | |
584 if (operands.back().first <= 2) { | |
585 // predefined charset, ISOAdobe, Expert or ExpertSubset, is used. | |
586 break; | |
587 } | |
588 if (!CheckOffset(operands.back(), table_length)) { | |
589 return OTS_FAILURE(); | |
590 } | |
591 if (charset_offset) { | |
592 return OTS_FAILURE(); // multiple charset tables? | |
593 } | |
594 charset_offset = operands.back().first; | |
595 break; | |
596 | |
597 case 16: { // Encoding | |
598 if (operands.size() != 1) { | |
599 return OTS_FAILURE(); | |
600 } | |
601 if (operands.back().first <= 1) { | |
602 break; // predefined encoding, "Standard" or "Expert", is used. | |
603 } | |
604 if (!CheckOffset(operands.back(), table_length)) { | |
605 return OTS_FAILURE(); | |
606 } | |
607 | |
608 // parse sub dictionary INDEX. | |
609 ots::Buffer cff_table(data, table_length); | |
610 cff_table.set_offset(operands.back().first); | |
611 uint8_t format = 0; | |
612 if (!cff_table.ReadU8(&format)) { | |
613 return OTS_FAILURE(); | |
614 } | |
615 if (format & 0x80) { | |
616 // supplemental encoding is not supported at the moment. | |
617 return OTS_FAILURE(); | |
618 } | |
619 // TODO(yusukes): support & parse supplemental encoding tables. | |
620 break; | |
621 } | |
622 | |
623 case 17: { // CharStrings | |
624 if (type != DICT_DATA_TOPLEVEL) { | |
625 return OTS_FAILURE(); | |
626 } | |
627 if (operands.size() != 1) { | |
628 return OTS_FAILURE(); | |
629 } | |
630 if (!CheckOffset(operands.back(), table_length)) { | |
631 return OTS_FAILURE(); | |
632 } | |
633 // parse "14. CharStrings INDEX" | |
634 ots::Buffer cff_table(data, table_length); | |
635 cff_table.set_offset(operands.back().first); | |
636 ots::CFFIndex *charstring_index = out_cff->char_strings_array.back(); | |
637 if (!ParseIndex(&cff_table, charstring_index)) { | |
638 return OTS_FAILURE(); | |
639 } | |
640 if (charstring_index->count < 2) { | |
641 return OTS_FAILURE(); | |
642 } | |
643 if (charstring_glyphs) { | |
644 return OTS_FAILURE(); // multiple charstring tables? | |
645 } | |
646 charstring_glyphs = charstring_index->count; | |
647 if (charstring_glyphs != glyphs) { | |
648 return OTS_FAILURE(); // CFF and maxp have different number of glyp
hs? | |
649 } | |
650 break; | |
651 } | |
652 | |
653 case (12U << 8) + 36: { // FDArray | |
654 if (type != DICT_DATA_TOPLEVEL) { | |
655 return OTS_FAILURE(); | |
656 } | |
657 if (operands.size() != 1) { | |
658 return OTS_FAILURE(); | |
659 } | |
660 if (!CheckOffset(operands.back(), table_length)) { | |
661 return OTS_FAILURE(); | |
662 } | |
663 | |
664 // parse sub dictionary INDEX. | |
665 ots::Buffer cff_table(data, table_length); | |
666 cff_table.set_offset(operands.back().first); | |
667 ots::CFFIndex sub_dict_index; | |
668 if (!ParseIndex(&cff_table, &sub_dict_index)) { | |
669 return OTS_FAILURE(); | |
670 } | |
671 if (!ParseDictData(data, table_length, | |
672 sub_dict_index, | |
673 glyphs, sid_max, DICT_DATA_FDARRAY, | |
674 out_cff)) { | |
675 return OTS_FAILURE(); | |
676 } | |
677 if (out_cff->font_dict_length != 0) { | |
678 return OTS_FAILURE(); // two or more FDArray found. | |
679 } | |
680 out_cff->font_dict_length = sub_dict_index.count; | |
681 break; | |
682 } | |
683 | |
684 case (12U << 8) + 37: { // FDSelect | |
685 if (type != DICT_DATA_TOPLEVEL) { | |
686 return OTS_FAILURE(); | |
687 } | |
688 if (operands.size() != 1) { | |
689 return OTS_FAILURE(); | |
690 } | |
691 if (!CheckOffset(operands.back(), table_length)) { | |
692 return OTS_FAILURE(); | |
693 } | |
694 | |
695 // parse FDSelect data structure | |
696 ots::Buffer cff_table(data, table_length); | |
697 cff_table.set_offset(operands.back().first); | |
698 uint8_t format = 0; | |
699 if (!cff_table.ReadU8(&format)) { | |
700 return OTS_FAILURE(); | |
701 } | |
702 if (format == 0) { | |
703 for (uint16_t j = 0; j < glyphs; ++j) { | |
704 uint8_t fd_index = 0; | |
705 if (!cff_table.ReadU8(&fd_index)) { | |
706 return OTS_FAILURE(); | |
707 } | |
708 (out_cff->fd_select)[j] = fd_index; | |
709 } | |
710 } else if (format == 3) { | |
711 uint16_t n_ranges = 0; | |
712 if (!cff_table.ReadU16(&n_ranges)) { | |
713 return OTS_FAILURE(); | |
714 } | |
715 if (n_ranges == 0) { | |
716 return OTS_FAILURE(); | |
717 } | |
718 | |
719 uint16_t last_gid = 0; | |
720 uint8_t fd_index = 0; | |
721 for (unsigned j = 0; j < n_ranges; ++j) { | |
722 uint16_t first = 0; // GID | |
723 if (!cff_table.ReadU16(&first)) { | |
724 return OTS_FAILURE(); | |
725 } | |
726 | |
727 // Sanity checks. | |
728 if ((j == 0) && (first != 0)) { | |
729 return OTS_FAILURE(); | |
730 } | |
731 if ((j != 0) && (last_gid >= first)) { | |
732 return OTS_FAILURE(); // not increasing order. | |
733 } | |
734 | |
735 // Copy the mapping to |out_cff->fd_select|. | |
736 if (j != 0) { | |
737 for (uint16_t k = last_gid; k < first; ++k) { | |
738 if (!out_cff->fd_select.insert( | |
739 std::make_pair(k, fd_index)).second) { | |
740 return OTS_FAILURE(); | |
741 } | |
742 } | |
743 } | |
744 | |
745 if (!cff_table.ReadU8(&fd_index)) { | |
746 return OTS_FAILURE(); | |
747 } | |
748 last_gid = first; | |
749 // TODO(yusukes): check GID? | |
750 } | |
751 uint16_t sentinel = 0; | |
752 if (!cff_table.ReadU16(&sentinel)) { | |
753 return OTS_FAILURE(); | |
754 } | |
755 if (last_gid >= sentinel) { | |
756 return OTS_FAILURE(); | |
757 } | |
758 for (uint16_t k = last_gid; k < sentinel; ++k) { | |
759 if (!out_cff->fd_select.insert( | |
760 std::make_pair(k, fd_index)).second) { | |
761 return OTS_FAILURE(); | |
762 } | |
763 } | |
764 } else { | |
765 // unknown format | |
766 return OTS_FAILURE(); | |
767 } | |
768 break; | |
769 } | |
770 | |
771 // Private DICT (2 * number) | |
772 case 18: { | |
773 if (operands.size() != 2) { | |
774 return OTS_FAILURE(); | |
775 } | |
776 if (operands.back().second != DICT_OPERAND_INTEGER) { | |
777 return OTS_FAILURE(); | |
778 } | |
779 const uint32_t private_offset = operands.back().first; | |
780 operands.pop_back(); | |
781 if (operands.back().second != DICT_OPERAND_INTEGER) { | |
782 return OTS_FAILURE(); | |
783 } | |
784 const uint32_t private_length = operands.back().first; | |
785 if (private_offset > table_length) { | |
786 return OTS_FAILURE(); | |
787 } | |
788 if (private_length >= table_length) { | |
789 return OTS_FAILURE(); | |
790 } | |
791 if (private_length + private_offset > table_length) { | |
792 return OTS_FAILURE(); | |
793 } | |
794 // parse "15. Private DICT Data" | |
795 if (!ParsePrivateDictData(data, table_length, | |
796 private_offset, private_length, | |
797 type, out_cff)) { | |
798 return OTS_FAILURE(); | |
799 } | |
800 break; | |
801 } | |
802 | |
803 // ROS | |
804 case (12U << 8) + 30: | |
805 if (font_format != FORMAT_UNKNOWN) { | |
806 return OTS_FAILURE(); | |
807 } | |
808 font_format = FORMAT_CID_KEYED; | |
809 if (operands.size() != 3) { | |
810 return OTS_FAILURE(); | |
811 } | |
812 // check SIDs | |
813 operands.pop_back(); // ignore the first number. | |
814 if (!CheckSid(operands.back(), sid_max)) { | |
815 return OTS_FAILURE(); | |
816 } | |
817 operands.pop_back(); | |
818 if (!CheckSid(operands.back(), sid_max)) { | |
819 return OTS_FAILURE(); | |
820 } | |
821 if (have_ros) { | |
822 return OTS_FAILURE(); // multiple ROS tables? | |
823 } | |
824 have_ros = true; | |
825 break; | |
826 | |
827 default: | |
828 return OTS_FAILURE(); | |
829 } | |
830 operands.clear(); | |
831 | |
832 if (font_format == FORMAT_UNKNOWN) { | |
833 font_format = FORMAT_OTHER; | |
834 } | |
835 } | |
836 | |
837 // parse "13. Charsets" | |
838 if (charset_offset) { | |
839 ots::Buffer cff_table(data, table_length); | |
840 cff_table.set_offset(charset_offset); | |
841 uint8_t format = 0; | |
842 if (!cff_table.ReadU8(&format)) { | |
843 return OTS_FAILURE(); | |
844 } | |
845 switch (format) { | |
846 case 0: | |
847 for (uint16_t j = 1 /* .notdef is omitted */; j < glyphs; ++j) { | |
848 uint16_t sid = 0; | |
849 if (!cff_table.ReadU16(&sid)) { | |
850 return OTS_FAILURE(); | |
851 } | |
852 if (!have_ros && (sid > sid_max)) { | |
853 return OTS_FAILURE(); | |
854 } | |
855 // TODO(yusukes): check CIDs when have_ros is true. | |
856 } | |
857 break; | |
858 | |
859 case 1: | |
860 case 2: { | |
861 uint32_t total = 1; // .notdef is omitted. | |
862 while (total < glyphs) { | |
863 uint16_t sid = 0; | |
864 if (!cff_table.ReadU16(&sid)) { | |
865 return OTS_FAILURE(); | |
866 } | |
867 if (!have_ros && (sid > sid_max)) { | |
868 return OTS_FAILURE(); | |
869 } | |
870 // TODO(yusukes): check CIDs when have_ros is true. | |
871 | |
872 if (format == 1) { | |
873 uint8_t left = 0; | |
874 if (!cff_table.ReadU8(&left)) { | |
875 return OTS_FAILURE(); | |
876 } | |
877 total += (left + 1); | |
878 } else { | |
879 uint16_t left = 0; | |
880 if (!cff_table.ReadU16(&left)) { | |
881 return OTS_FAILURE(); | |
882 } | |
883 total += (left + 1); | |
884 } | |
885 } | |
886 break; | |
887 } | |
888 | |
889 default: | |
890 return OTS_FAILURE(); | |
891 } | |
892 } | |
893 } | |
894 return true; | |
895 } | |
896 | |
897 } // namespace | |
898 | |
899 namespace ots { | |
900 | |
901 bool ots_cff_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { | |
902 Buffer table(data, length); | |
903 | |
904 file->cff = new OpenTypeCFF; | |
905 file->cff->data = data; | |
906 file->cff->length = length; | |
907 file->cff->font_dict_length = 0; | |
908 file->cff->local_subrs = NULL; | |
909 | |
910 // parse "6. Header" in the Adobe Compact Font Format Specification | |
911 uint8_t major = 0; | |
912 uint8_t minor = 0; | |
913 uint8_t hdr_size = 0; | |
914 uint8_t off_size = 0; | |
915 if (!table.ReadU8(&major)) { | |
916 return OTS_FAILURE(); | |
917 } | |
918 if (!table.ReadU8(&minor)) { | |
919 return OTS_FAILURE(); | |
920 } | |
921 if (!table.ReadU8(&hdr_size)) { | |
922 return OTS_FAILURE(); | |
923 } | |
924 if (!table.ReadU8(&off_size)) { | |
925 return OTS_FAILURE(); | |
926 } | |
927 if ((off_size == 0) || (off_size > 4)) { | |
928 return OTS_FAILURE(); | |
929 } | |
930 | |
931 if ((major != 1) || | |
932 (minor != 0) || | |
933 (hdr_size != 4)) { | |
934 return OTS_FAILURE(); | |
935 } | |
936 if (hdr_size >= length) { | |
937 return OTS_FAILURE(); | |
938 } | |
939 | |
940 // parse "7. Name INDEX" | |
941 table.set_offset(hdr_size); | |
942 CFFIndex name_index; | |
943 if (!ParseIndex(&table, &name_index)) { | |
944 return OTS_FAILURE(); | |
945 } | |
946 if (!ParseNameData(&table, name_index, &(file->cff->name))) { | |
947 return OTS_FAILURE(); | |
948 } | |
949 | |
950 // parse "8. Top DICT INDEX" | |
951 table.set_offset(name_index.offset_to_next); | |
952 CFFIndex top_dict_index; | |
953 if (!ParseIndex(&table, &top_dict_index)) { | |
954 return OTS_FAILURE(); | |
955 } | |
956 if (name_index.count != top_dict_index.count) { | |
957 return OTS_FAILURE(); | |
958 } | |
959 | |
960 // parse "10. String INDEX" | |
961 table.set_offset(top_dict_index.offset_to_next); | |
962 CFFIndex string_index; | |
963 if (!ParseIndex(&table, &string_index)) { | |
964 return OTS_FAILURE(); | |
965 } | |
966 if (string_index.count >= 65000 - kNStdString) { | |
967 return OTS_FAILURE(); | |
968 } | |
969 | |
970 const uint16_t num_glyphs = file->maxp->num_glyphs; | |
971 const size_t sid_max = string_index.count + kNStdString; | |
972 // string_index.count == 0 is allowed. | |
973 | |
974 // parse "9. Top DICT Data" | |
975 if (!ParseDictData(data, length, top_dict_index, | |
976 num_glyphs, sid_max, | |
977 DICT_DATA_TOPLEVEL, file->cff)) { | |
978 return OTS_FAILURE(); | |
979 } | |
980 | |
981 // parse "16. Global Subrs INDEX" | |
982 table.set_offset(string_index.offset_to_next); | |
983 CFFIndex global_subrs_index; | |
984 if (!ParseIndex(&table, &global_subrs_index)) { | |
985 return OTS_FAILURE(); | |
986 } | |
987 | |
988 // Check if all fd_index in FDSelect are valid. | |
989 std::map<uint16_t, uint8_t>::const_iterator iter; | |
990 std::map<uint16_t, uint8_t>::const_iterator end = file->cff->fd_select.end(); | |
991 for (iter = file->cff->fd_select.begin(); iter != end; ++iter) { | |
992 if (iter->second >= file->cff->font_dict_length) { | |
993 return OTS_FAILURE(); | |
994 } | |
995 } | |
996 | |
997 // Check if all charstrings (font hinting code for each glyph) are valid. | |
998 for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) { | |
999 if (!ValidateType2CharStringIndex(file, | |
1000 *(file->cff->char_strings_array.at(i)), | |
1001 global_subrs_index, | |
1002 file->cff->fd_select, | |
1003 file->cff->local_subrs_per_font, | |
1004 file->cff->local_subrs, | |
1005 &table)) { | |
1006 return OTS_FAILURE_MSG("Failed validating charstring set %d", (int) i); | |
1007 } | |
1008 } | |
1009 | |
1010 return true; | |
1011 } | |
1012 | |
1013 bool ots_cff_should_serialise(OpenTypeFile *file) { | |
1014 return file->cff != NULL; | |
1015 } | |
1016 | |
1017 bool ots_cff_serialise(OTSStream *out, OpenTypeFile *file) { | |
1018 // TODO(yusukes): would be better to transcode the data, | |
1019 // rather than simple memcpy. | |
1020 if (!out->Write(file->cff->data, file->cff->length)) { | |
1021 return OTS_FAILURE(); | |
1022 } | |
1023 return true; | |
1024 } | |
1025 | |
1026 void ots_cff_free(OpenTypeFile *file) { | |
1027 if (file->cff) { | |
1028 for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) { | |
1029 delete (file->cff->char_strings_array)[i]; | |
1030 } | |
1031 for (size_t i = 0; i < file->cff->local_subrs_per_font.size(); ++i) { | |
1032 delete (file->cff->local_subrs_per_font)[i]; | |
1033 } | |
1034 delete file->cff->local_subrs; | |
1035 delete file->cff; | |
1036 } | |
1037 } | |
1038 | |
1039 } // namespace ots | |
1040 | |
1041 #undef TABLE_NAME | |
OLD | NEW |