Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / third_party / ots / src / cff.cc
blob9c7204d999ebfcae7ddbacb88e641887edaef57c
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.
5 #include "cff.h"
7 #include <cstring>
8 #include <utility>
9 #include <vector>
11 #include "maxp.h"
12 #include "cff_type2_charstring.h"
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
18 #define TABLE_NAME "CFF"
20 namespace {
22 enum DICT_OPERAND_TYPE {
23 DICT_OPERAND_INTEGER,
24 DICT_OPERAND_REAL,
25 DICT_OPERATOR,
28 enum DICT_DATA_TYPE {
29 DICT_DATA_TOPLEVEL,
30 DICT_DATA_FDARRAY,
33 enum FONT_FORMAT {
34 FORMAT_UNKNOWN,
35 FORMAT_CID_KEYED,
36 FORMAT_OTHER, // Including synthetic fonts
39 // see Appendix. A
40 const size_t kNStdString = 390;
42 bool ReadOffset(ots::Buffer *table, uint8_t off_size, uint32_t *offset) {
43 if (off_size > 4) {
44 return OTS_FAILURE();
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();
53 tmp32 <<= 8;
54 tmp32 += tmp8;
56 *offset = tmp32;
57 return true;
60 bool ParseIndex(ots::Buffer *table, ots::CFFIndex *index) {
61 index->off_size = 0;
62 index->offsets.clear();
64 if (!table->ReadU16(&(index->count))) {
65 return OTS_FAILURE();
67 if (index->count == 0) {
68 // An empty INDEX.
69 index->offset_to_next = table->offset();
70 return true;
73 if (!table->ReadU8(&(index->off_size))) {
74 return OTS_FAILURE();
76 if ((index->off_size == 0) ||
77 (index->off_size > 4)) {
78 return OTS_FAILURE();
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.
86 if (object_data_offset >= table->length()) {
87 return OTS_FAILURE();
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();
95 if (rel_offset < 1) {
96 return OTS_FAILURE();
98 if (i == 0 && rel_offset != 1) {
99 return OTS_FAILURE();
102 if (rel_offset > table->length()) {
103 return OTS_FAILURE();
106 // does not underflow.
107 if (object_data_offset > table->length() - (rel_offset - 1)) {
108 return OTS_FAILURE();
111 index->offsets.push_back(
112 object_data_offset + (rel_offset - 1)); // less than length(), 1GB.
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();
123 index->offset_to_next = index->offsets.back();
124 return true;
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();
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();
140 table->set_offset(index.offsets[i - 1]);
141 if (!table->Read(name, length)) {
142 return OTS_FAILURE();
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();
152 // [, ], ... are not allowed.
153 if (std::strchr("[](){}<>/% ", name[j])) {
154 return OTS_FAILURE();
159 *out_name = reinterpret_cast<char *>(name);
160 return true;
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();
168 if (operand.first >= table_length) {
169 return OTS_FAILURE();
171 return true;
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();
179 if (operand.first > sid_max) {
180 return OTS_FAILURE();
182 return true;
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;
191 uint8_t nibble = 0;
192 size_t count = 0;
193 while (true) {
194 if (!table->ReadU8(&nibble)) {
195 return OTS_FAILURE();
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;
205 return OTS_FAILURE();
207 if ((nibble & 0x0f) == 0x0f) {
208 operands->push_back(std::make_pair(static_cast<uint32_t>(0),
209 DICT_OPERAND_REAL));
210 return true;
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();
221 if ((nibbles[i] == 0xe) && // minus
222 ((count > 0) || (i > 0))) {
223 return OTS_FAILURE(); // minus sign should be the first character.
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.
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.
241 ++count;
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();
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;
260 // reserved area.
261 return OTS_FAILURE();
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;
272 switch (b0) {
273 case 28: // shortint
274 if (!table->ReadU8(&b1) ||
275 !table->ReadU8(&b2)) {
276 return OTS_FAILURE();
278 operands->push_back(std::make_pair(
279 static_cast<uint32_t>((b1 << 8) + b2), DICT_OPERAND_INTEGER));
280 return true;
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();
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;
294 case 30: // binary coded decimal
295 return ParseDictDataBcd(table, operands);
297 default:
298 break;
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();
308 result = (b0 - 247) * 256 + b1 + 108;
309 } else if (b0 >= 251 && b0 <= 254) {
310 if (!table->ReadU8(&b1)) {
311 return OTS_FAILURE();
313 result = -(b0 - 251) * 256 + b1 - 108;
314 } else {
315 return OTS_FAILURE();
318 operands->push_back(std::make_pair(result, DICT_OPERAND_INTEGER));
319 return true;
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();
329 if (op <= 21) {
330 if (op == 12) {
331 return ParseDictDataEscapedOperator(table, operands);
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();
341 return ParseDictDataNumber(table, op, operands);
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;
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);
358 while (table.offset() < dict_length) {
359 if (!ParseDictDataReadNext(&table, &operands)) {
360 return OTS_FAILURE();
362 if (operands.empty()) {
363 return OTS_FAILURE();
365 if (operands.size() > 48) {
366 // An operator may be preceded by up to a maximum of 48 operands.
367 return OTS_FAILURE();
369 if (operands.back().second != DICT_OPERATOR) {
370 continue;
373 // got operator
374 const uint32_t op = operands.back().first;
375 operands.pop_back();
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();
388 break;
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();
404 break;
406 // Local Subrs INDEX, offset(self)
407 case 19: {
408 if (operands.size() != 1) {
409 return OTS_FAILURE();
411 if (operands.back().second != DICT_OPERAND_INTEGER) {
412 return OTS_FAILURE();
414 if (operands.back().first >= 1024 * 1024 * 1024) {
415 return OTS_FAILURE();
417 if (operands.back().first + offset >= table_length) {
418 return OTS_FAILURE();
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.
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?
433 local_subrs_index = new ots::CFFIndex;
434 out_cff->local_subrs = local_subrs_index;
436 if (!ParseIndex(&cff_table, local_subrs_index)) {
437 return OTS_FAILURE();
439 break;
442 // boolean
443 case (12U << 8) + 14: // ForceBold
444 if (operands.size() != 1) {
445 return OTS_FAILURE();
447 if (operands.back().second != DICT_OPERAND_INTEGER) {
448 return OTS_FAILURE();
450 if (operands.back().first >= 2) {
451 return OTS_FAILURE();
453 break;
455 default:
456 return OTS_FAILURE();
458 operands.clear();
461 return true;
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);
472 size_t dict_length = index.offsets[i] - index.offsets[i - 1];
473 ots::Buffer table(data + index.offsets[i - 1], dict_length);
475 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands;
477 FONT_FORMAT font_format = FORMAT_UNKNOWN;
478 bool have_ros = false;
479 uint16_t charstring_glyphs = 0;
480 size_t charset_offset = 0;
482 while (table.offset() < dict_length) {
483 if (!ParseDictDataReadNext(&table, &operands)) {
484 return OTS_FAILURE();
486 if (operands.empty()) {
487 return OTS_FAILURE();
489 if (operands.size() > 48) {
490 // An operator may be preceded by up to a maximum of 48 operands.
491 return OTS_FAILURE();
493 if (operands.back().second != DICT_OPERATOR) continue;
495 // got operator
496 const uint32_t op = operands.back().first;
497 operands.pop_back();
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();
513 if (!CheckSid(operands.back(), sid_max)) {
514 return OTS_FAILURE();
516 break;
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();
526 break;
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();
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();
548 if (font_format != FORMAT_CID_KEYED) {
549 return OTS_FAILURE();
551 break;
552 case (12U << 8) + 6: // CharstringType
553 if (operands.size() != 1) {
554 return OTS_FAILURE();
556 if(operands.back().second != DICT_OPERAND_INTEGER) {
557 return OTS_FAILURE();
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();
564 break;
566 // boolean
567 case (12U << 8) + 1: // isFixedPitch
568 if (operands.size() != 1) {
569 return OTS_FAILURE();
571 if (operands.back().second != DICT_OPERAND_INTEGER) {
572 return OTS_FAILURE();
574 if (operands.back().first >= 2) {
575 return OTS_FAILURE();
577 break;
579 // offset(0)
580 case 15: // charset
581 if (operands.size() != 1) {
582 return OTS_FAILURE();
584 if (operands.back().first <= 2) {
585 // predefined charset, ISOAdobe, Expert or ExpertSubset, is used.
586 break;
588 if (!CheckOffset(operands.back(), table_length)) {
589 return OTS_FAILURE();
591 if (charset_offset) {
592 return OTS_FAILURE(); // multiple charset tables?
594 charset_offset = operands.back().first;
595 break;
597 case 16: { // Encoding
598 if (operands.size() != 1) {
599 return OTS_FAILURE();
601 if (operands.back().first <= 1) {
602 break; // predefined encoding, "Standard" or "Expert", is used.
604 if (!CheckOffset(operands.back(), table_length)) {
605 return OTS_FAILURE();
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();
615 if (format & 0x80) {
616 // supplemental encoding is not supported at the moment.
617 return OTS_FAILURE();
619 // TODO(yusukes): support & parse supplemental encoding tables.
620 break;
623 case 17: { // CharStrings
624 if (type != DICT_DATA_TOPLEVEL) {
625 return OTS_FAILURE();
627 if (operands.size() != 1) {
628 return OTS_FAILURE();
630 if (!CheckOffset(operands.back(), table_length)) {
631 return OTS_FAILURE();
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();
640 if (charstring_index->count < 2) {
641 return OTS_FAILURE();
643 if (charstring_glyphs) {
644 return OTS_FAILURE(); // multiple charstring tables?
646 charstring_glyphs = charstring_index->count;
647 if (charstring_glyphs != glyphs) {
648 return OTS_FAILURE(); // CFF and maxp have different number of glyphs?
650 break;
653 case (12U << 8) + 36: { // FDArray
654 if (type != DICT_DATA_TOPLEVEL) {
655 return OTS_FAILURE();
657 if (operands.size() != 1) {
658 return OTS_FAILURE();
660 if (!CheckOffset(operands.back(), table_length)) {
661 return OTS_FAILURE();
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();
671 if (!ParseDictData(data, table_length,
672 sub_dict_index,
673 glyphs, sid_max, DICT_DATA_FDARRAY,
674 out_cff)) {
675 return OTS_FAILURE();
677 if (out_cff->font_dict_length != 0) {
678 return OTS_FAILURE(); // two or more FDArray found.
680 out_cff->font_dict_length = sub_dict_index.count;
681 break;
684 case (12U << 8) + 37: { // FDSelect
685 if (type != DICT_DATA_TOPLEVEL) {
686 return OTS_FAILURE();
688 if (operands.size() != 1) {
689 return OTS_FAILURE();
691 if (!CheckOffset(operands.back(), table_length)) {
692 return OTS_FAILURE();
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();
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();
708 (out_cff->fd_select)[j] = fd_index;
710 } else if (format == 3) {
711 uint16_t n_ranges = 0;
712 if (!cff_table.ReadU16(&n_ranges)) {
713 return OTS_FAILURE();
715 if (n_ranges == 0) {
716 return OTS_FAILURE();
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();
727 // Sanity checks.
728 if ((j == 0) && (first != 0)) {
729 return OTS_FAILURE();
731 if ((j != 0) && (last_gid >= first)) {
732 return OTS_FAILURE(); // not increasing order.
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();
745 if (!cff_table.ReadU8(&fd_index)) {
746 return OTS_FAILURE();
748 last_gid = first;
749 // TODO(yusukes): check GID?
751 uint16_t sentinel = 0;
752 if (!cff_table.ReadU16(&sentinel)) {
753 return OTS_FAILURE();
755 if (last_gid >= sentinel) {
756 return OTS_FAILURE();
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();
764 } else {
765 // unknown format
766 return OTS_FAILURE();
768 break;
771 // Private DICT (2 * number)
772 case 18: {
773 if (operands.size() != 2) {
774 return OTS_FAILURE();
776 if (operands.back().second != DICT_OPERAND_INTEGER) {
777 return OTS_FAILURE();
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();
784 const uint32_t private_length = operands.back().first;
785 if (private_offset > table_length) {
786 return OTS_FAILURE();
788 if (private_length >= table_length) {
789 return OTS_FAILURE();
791 if (private_length + private_offset > table_length) {
792 return OTS_FAILURE();
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();
800 break;
803 // ROS
804 case (12U << 8) + 30:
805 if (font_format != FORMAT_UNKNOWN) {
806 return OTS_FAILURE();
808 font_format = FORMAT_CID_KEYED;
809 if (operands.size() != 3) {
810 return OTS_FAILURE();
812 // check SIDs
813 operands.pop_back(); // ignore the first number.
814 if (!CheckSid(operands.back(), sid_max)) {
815 return OTS_FAILURE();
817 operands.pop_back();
818 if (!CheckSid(operands.back(), sid_max)) {
819 return OTS_FAILURE();
821 if (have_ros) {
822 return OTS_FAILURE(); // multiple ROS tables?
824 have_ros = true;
825 break;
827 default:
828 return OTS_FAILURE();
830 operands.clear();
832 if (font_format == FORMAT_UNKNOWN) {
833 font_format = FORMAT_OTHER;
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();
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();
852 if (!have_ros && (sid > sid_max)) {
853 return OTS_FAILURE();
855 // TODO(yusukes): check CIDs when have_ros is true.
857 break;
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();
867 if (!have_ros && (sid > sid_max)) {
868 return OTS_FAILURE();
870 // TODO(yusukes): check CIDs when have_ros is true.
872 if (format == 1) {
873 uint8_t left = 0;
874 if (!cff_table.ReadU8(&left)) {
875 return OTS_FAILURE();
877 total += (left + 1);
878 } else {
879 uint16_t left = 0;
880 if (!cff_table.ReadU16(&left)) {
881 return OTS_FAILURE();
883 total += (left + 1);
886 break;
889 default:
890 return OTS_FAILURE();
894 return true;
897 } // namespace
899 namespace ots {
901 bool ots_cff_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
902 Buffer table(data, length);
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;
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();
918 if (!table.ReadU8(&minor)) {
919 return OTS_FAILURE();
921 if (!table.ReadU8(&hdr_size)) {
922 return OTS_FAILURE();
924 if (!table.ReadU8(&off_size)) {
925 return OTS_FAILURE();
927 if ((off_size == 0) || (off_size > 4)) {
928 return OTS_FAILURE();
931 if ((major != 1) ||
932 (minor != 0) ||
933 (hdr_size != 4)) {
934 return OTS_FAILURE();
936 if (hdr_size >= length) {
937 return OTS_FAILURE();
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();
946 if (!ParseNameData(&table, name_index, &(file->cff->name))) {
947 return OTS_FAILURE();
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();
956 if (name_index.count != top_dict_index.count) {
957 return OTS_FAILURE();
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();
966 if (string_index.count >= 65000 - kNStdString) {
967 return OTS_FAILURE();
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.
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();
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();
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();
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);
1010 return true;
1013 bool ots_cff_should_serialise(OpenTypeFile *file) {
1014 return file->cff != NULL;
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();
1023 return true;
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];
1031 for (size_t i = 0; i < file->cff->local_subrs_per_font.size(); ++i) {
1032 delete (file->cff->local_subrs_per_font)[i];
1034 delete file->cff->local_subrs;
1035 delete file->cff;
1039 } // namespace ots
1041 #undef TABLE_NAME