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.
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"
22 enum DICT_OPERAND_TYPE
{
36 FORMAT_OTHER
, // Including synthetic fonts
40 const size_t kNStdString
= 390;
42 bool ReadOffset(ots::Buffer
*table
, uint8_t off_size
, uint32_t *offset
) {
48 for (unsigned i
= 0; i
< off_size
; ++i
) {
50 if (!table
->ReadU8(&tmp8
)) {
60 bool ParseIndex(ots::Buffer
*table
, ots::CFFIndex
*index
) {
62 index
->offsets
.clear();
64 if (!table
->ReadU16(&(index
->count
))) {
67 if (index
->count
== 0) {
69 index
->offset_to_next
= table
->offset();
73 if (!table
->ReadU8(&(index
->off_size
))) {
76 if ((index
->off_size
== 0) ||
77 (index
->off_size
> 4)) {
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()) {
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
)) {
98 if (i
== 0 && rel_offset
!= 1) {
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();
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.
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
);
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();
174 bool CheckSid(const std::pair
<uint32_t, DICT_OPERAND_TYPE
>& operand
,
176 if (operand
.second
!= DICT_OPERAND_INTEGER
) {
177 return OTS_FAILURE();
179 if (operand
.first
> sid_max
) {
180 return OTS_FAILURE();
185 bool ParseDictDataBcd(
187 std::vector
<std::pair
<uint32_t, DICT_OPERAND_TYPE
> > *operands
) {
188 bool read_decimal_point
= false;
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),
205 return OTS_FAILURE();
207 if ((nibble
& 0x0f) == 0x0f) {
208 operands
->push_back(std::make_pair(static_cast<uint32_t>(0),
213 // check number format
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;
229 return OTS_FAILURE(); // two or more points.
232 if ((nibbles
[i
] == 0xb) || // E+
233 (nibbles
[i
] == 0xc)) { // E-
237 return OTS_FAILURE(); // two or more E's.
245 bool ParseDictDataEscapedOperator(
247 std::vector
<std::pair
<uint32_t, DICT_OPERAND_TYPE
> > *operands
) {
249 if (!table
->ReadU8(&op
)) {
250 return OTS_FAILURE();
254 (op
>= 17 && op
<= 23) ||
255 (op
>= 30 && op
<= 38)) {
256 operands
->push_back(std::make_pair((12U << 8) + op
, DICT_OPERATOR
));
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
) {
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
));
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
));
294 case 30: // binary coded decimal
295 return ParseDictDataBcd(table
, operands
);
302 if (b0
>=32 && b0
<=246) {
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;
315 return OTS_FAILURE();
318 operands
->push_back(std::make_pair(result
, DICT_OPERAND_INTEGER
));
322 bool ParseDictDataReadNext(
324 std::vector
<std::pair
<uint32_t, DICT_OPERAND_TYPE
> > *operands
) {
326 if (!table
->ReadU8(&op
)) {
327 return OTS_FAILURE();
331 return ParseDictDataEscapedOperator(table
, operands
);
333 operands
->push_back(std::make_pair(
334 static_cast<uint32_t>(op
), DICT_OPERATOR
));
336 } else if (op
<= 27 || op
== 31 || op
== 255) {
338 return OTS_FAILURE();
341 return ParseDictDataNumber(table
, op
, operands
);
344 bool ParsePrivateDictData(
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
) {
374 const uint32_t op
= operands
.back().first
;
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();
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();
406 // Local Subrs INDEX, offset(self)
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();
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();
456 return OTS_FAILURE();
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;
496 const uint32_t op
= operands
.back().first
;
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();
521 case (12U << 8) + 7: // FontMatrix
522 case (12U << 8) + 23: // BaseFontBlend (delta)
523 if (operands
.empty()) {
524 return OTS_FAILURE();
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();
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();
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();
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();
581 if (operands
.size() != 1) {
582 return OTS_FAILURE();
584 if (operands
.back().first
<= 2) {
585 // predefined charset, ISOAdobe, Expert or ExpertSubset, is used.
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
;
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
);
612 if (!cff_table
.ReadU8(&format
)) {
613 return OTS_FAILURE();
616 // supplemental encoding is not supported at the moment.
617 return OTS_FAILURE();
619 // TODO(yusukes): support & parse supplemental encoding tables.
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?
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
,
673 glyphs
, sid_max
, DICT_DATA_FDARRAY
,
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
;
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
);
699 if (!cff_table
.ReadU8(&format
)) {
700 return OTS_FAILURE();
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();
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();
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|.
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();
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();
766 return OTS_FAILURE();
771 // Private DICT (2 * number)
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
;
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
,
798 return OTS_FAILURE();
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();
813 operands
.pop_back(); // ignore the first number.
814 if (!CheckSid(operands
.back(), sid_max
)) {
815 return OTS_FAILURE();
818 if (!CheckSid(operands
.back(), sid_max
)) {
819 return OTS_FAILURE();
822 return OTS_FAILURE(); // multiple ROS tables?
828 return OTS_FAILURE();
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
);
842 if (!cff_table
.ReadU8(&format
)) {
843 return OTS_FAILURE();
847 for (uint16_t j
= 1 /* .notdef is omitted */; j
< glyphs
; ++j
) {
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.
861 uint32_t total
= 1; // .notdef is omitted.
862 while (total
< glyphs
) {
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.
874 if (!cff_table
.ReadU8(&left
)) {
875 return OTS_FAILURE();
880 if (!cff_table
.ReadU16(&left
)) {
881 return OTS_FAILURE();
890 return OTS_FAILURE();
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
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();
934 return OTS_FAILURE();
936 if (hdr_size
>= length
) {
937 return OTS_FAILURE();
940 // parse "7. Name INDEX"
941 table
.set_offset(hdr_size
);
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
,
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
)),
1002 file
->cff
->fd_select
,
1003 file
->cff
->local_subrs_per_font
,
1004 file
->cff
->local_subrs
,
1006 return OTS_FAILURE_MSG("Failed validating charstring set %d", (int) i
);
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();
1026 void ots_cff_free(OpenTypeFile
*file
) {
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
;