Index: src/cff.cc |
diff --git a/src/cff.cc b/src/cff.cc |
old mode 100644 |
new mode 100755 |
index 7866614ced2cf27830be5bcf83ec01064008efad..9c7204d999ebfcae7ddbacb88e641887edaef57c |
--- a/src/cff.cc |
+++ b/src/cff.cc |
@@ -5,15 +5,18 @@ |
#include "cff.h" |
#include <cstring> |
-#include <utility> // std::pair |
+#include <utility> |
#include <vector> |
+#include "maxp.h" |
#include "cff_type2_charstring.h" |
// CFF - PostScript font program (Compact Font Format) table |
// http://www.microsoft.com/typography/otspec/cff.htm |
// http://www.microsoft.com/typography/otspec/cffspec.htm |
+#define TABLE_NAME "CFF" |
+ |
namespace { |
enum DICT_OPERAND_TYPE { |
@@ -415,8 +418,8 @@ bool ParsePrivateDictData( |
return OTS_FAILURE(); |
} |
// parse "16. Local Subrs INDEX" |
- ots::Buffer table(data, table_length); |
- table.set_offset(operands.back().first + offset); |
+ ots::Buffer cff_table(data, table_length); |
+ cff_table.set_offset(operands.back().first + offset); |
ots::CFFIndex *local_subrs_index = NULL; |
if (type == DICT_DATA_FDARRAY) { |
if (out_cff->local_subrs_per_font.empty()) { |
@@ -430,7 +433,7 @@ bool ParsePrivateDictData( |
local_subrs_index = new ots::CFFIndex; |
out_cff->local_subrs = local_subrs_index; |
} |
- if (!ParseIndex(&table, local_subrs_index)) { |
+ if (!ParseIndex(&cff_table, local_subrs_index)) { |
return OTS_FAILURE(); |
} |
break; |
@@ -459,8 +462,9 @@ bool ParsePrivateDictData( |
} |
bool ParseDictData(const uint8_t *data, size_t table_length, |
- const ots::CFFIndex &index, size_t sid_max, |
- DICT_DATA_TYPE type, ots::OpenTypeCFF *out_cff) { |
+ const ots::CFFIndex &index, uint16_t glyphs, |
+ size_t sid_max, DICT_DATA_TYPE type, |
+ ots::OpenTypeCFF *out_cff) { |
for (unsigned i = 1; i < index.offsets.size(); ++i) { |
if (type == DICT_DATA_TOPLEVEL) { |
out_cff->char_strings_array.push_back(new ots::CFFIndex); |
@@ -472,7 +476,7 @@ bool ParseDictData(const uint8_t *data, size_t table_length, |
FONT_FORMAT font_format = FORMAT_UNKNOWN; |
bool have_ros = false; |
- uint16_t glyphs = 0; |
+ uint16_t charstring_glyphs = 0; |
size_t charset_offset = 0; |
while (table.offset() < dict_length) { |
@@ -602,10 +606,10 @@ bool ParseDictData(const uint8_t *data, size_t table_length, |
} |
// parse sub dictionary INDEX. |
- ots::Buffer table(data, table_length); |
- table.set_offset(operands.back().first); |
+ ots::Buffer cff_table(data, table_length); |
+ cff_table.set_offset(operands.back().first); |
uint8_t format = 0; |
- if (!table.ReadU8(&format)) { |
+ if (!cff_table.ReadU8(&format)) { |
return OTS_FAILURE(); |
} |
if (format & 0x80) { |
@@ -627,19 +631,22 @@ bool ParseDictData(const uint8_t *data, size_t table_length, |
return OTS_FAILURE(); |
} |
// parse "14. CharStrings INDEX" |
- ots::Buffer table(data, table_length); |
- table.set_offset(operands.back().first); |
+ ots::Buffer cff_table(data, table_length); |
+ cff_table.set_offset(operands.back().first); |
ots::CFFIndex *charstring_index = out_cff->char_strings_array.back(); |
- if (!ParseIndex(&table, charstring_index)) { |
+ if (!ParseIndex(&cff_table, charstring_index)) { |
return OTS_FAILURE(); |
} |
if (charstring_index->count < 2) { |
return OTS_FAILURE(); |
} |
- if (glyphs) { |
+ if (charstring_glyphs) { |
return OTS_FAILURE(); // multiple charstring tables? |
} |
- glyphs = charstring_index->count; |
+ charstring_glyphs = charstring_index->count; |
+ if (charstring_glyphs != glyphs) { |
+ return OTS_FAILURE(); // CFF and maxp have different number of glyphs? |
+ } |
break; |
} |
@@ -655,14 +662,15 @@ bool ParseDictData(const uint8_t *data, size_t table_length, |
} |
// parse sub dictionary INDEX. |
- ots::Buffer table(data, table_length); |
- table.set_offset(operands.back().first); |
+ ots::Buffer cff_table(data, table_length); |
+ cff_table.set_offset(operands.back().first); |
ots::CFFIndex sub_dict_index; |
- if (!ParseIndex(&table, &sub_dict_index)) { |
+ if (!ParseIndex(&cff_table, &sub_dict_index)) { |
return OTS_FAILURE(); |
} |
if (!ParseDictData(data, table_length, |
- sub_dict_index, sid_max, DICT_DATA_FDARRAY, |
+ sub_dict_index, |
+ glyphs, sid_max, DICT_DATA_FDARRAY, |
out_cff)) { |
return OTS_FAILURE(); |
} |
@@ -685,23 +693,23 @@ bool ParseDictData(const uint8_t *data, size_t table_length, |
} |
// parse FDSelect data structure |
- ots::Buffer table(data, table_length); |
- table.set_offset(operands.back().first); |
+ ots::Buffer cff_table(data, table_length); |
+ cff_table.set_offset(operands.back().first); |
uint8_t format = 0; |
- if (!table.ReadU8(&format)) { |
+ if (!cff_table.ReadU8(&format)) { |
return OTS_FAILURE(); |
} |
if (format == 0) { |
for (uint16_t j = 0; j < glyphs; ++j) { |
uint8_t fd_index = 0; |
- if (!table.ReadU8(&fd_index)) { |
+ if (!cff_table.ReadU8(&fd_index)) { |
return OTS_FAILURE(); |
} |
(out_cff->fd_select)[j] = fd_index; |
} |
} else if (format == 3) { |
uint16_t n_ranges = 0; |
- if (!table.ReadU16(&n_ranges)) { |
+ if (!cff_table.ReadU16(&n_ranges)) { |
return OTS_FAILURE(); |
} |
if (n_ranges == 0) { |
@@ -712,7 +720,7 @@ bool ParseDictData(const uint8_t *data, size_t table_length, |
uint8_t fd_index = 0; |
for (unsigned j = 0; j < n_ranges; ++j) { |
uint16_t first = 0; // GID |
- if (!table.ReadU16(&first)) { |
+ if (!cff_table.ReadU16(&first)) { |
return OTS_FAILURE(); |
} |
@@ -734,14 +742,14 @@ bool ParseDictData(const uint8_t *data, size_t table_length, |
} |
} |
- if (!table.ReadU8(&fd_index)) { |
+ if (!cff_table.ReadU8(&fd_index)) { |
return OTS_FAILURE(); |
} |
last_gid = first; |
// TODO(yusukes): check GID? |
} |
uint16_t sentinel = 0; |
- if (!table.ReadU16(&sentinel)) { |
+ if (!cff_table.ReadU16(&sentinel)) { |
return OTS_FAILURE(); |
} |
if (last_gid >= sentinel) { |
@@ -828,17 +836,17 @@ bool ParseDictData(const uint8_t *data, size_t table_length, |
// parse "13. Charsets" |
if (charset_offset) { |
- ots::Buffer table(data, table_length); |
- table.set_offset(charset_offset); |
+ ots::Buffer cff_table(data, table_length); |
+ cff_table.set_offset(charset_offset); |
uint8_t format = 0; |
- if (!table.ReadU8(&format)) { |
+ if (!cff_table.ReadU8(&format)) { |
return OTS_FAILURE(); |
} |
switch (format) { |
case 0: |
for (uint16_t j = 1 /* .notdef is omitted */; j < glyphs; ++j) { |
uint16_t sid = 0; |
- if (!table.ReadU16(&sid)) { |
+ if (!cff_table.ReadU16(&sid)) { |
return OTS_FAILURE(); |
} |
if (!have_ros && (sid > sid_max)) { |
@@ -853,7 +861,7 @@ bool ParseDictData(const uint8_t *data, size_t table_length, |
uint32_t total = 1; // .notdef is omitted. |
while (total < glyphs) { |
uint16_t sid = 0; |
- if (!table.ReadU16(&sid)) { |
+ if (!cff_table.ReadU16(&sid)) { |
return OTS_FAILURE(); |
} |
if (!have_ros && (sid > sid_max)) { |
@@ -863,13 +871,13 @@ bool ParseDictData(const uint8_t *data, size_t table_length, |
if (format == 1) { |
uint8_t left = 0; |
- if (!table.ReadU8(&left)) { |
+ if (!cff_table.ReadU8(&left)) { |
return OTS_FAILURE(); |
} |
total += (left + 1); |
} else { |
uint16_t left = 0; |
- if (!table.ReadU16(&left)) { |
+ if (!cff_table.ReadU16(&left)) { |
return OTS_FAILURE(); |
} |
total += (left + 1); |
@@ -959,12 +967,14 @@ bool ots_cff_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { |
return OTS_FAILURE(); |
} |
+ const uint16_t num_glyphs = file->maxp->num_glyphs; |
const size_t sid_max = string_index.count + kNStdString; |
// string_index.count == 0 is allowed. |
// parse "9. Top DICT Data" |
if (!ParseDictData(data, length, top_dict_index, |
- sid_max, DICT_DATA_TOPLEVEL, file->cff)) { |
+ num_glyphs, sid_max, |
+ DICT_DATA_TOPLEVEL, file->cff)) { |
return OTS_FAILURE(); |
} |
@@ -986,13 +996,14 @@ bool ots_cff_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { |
// Check if all charstrings (font hinting code for each glyph) are valid. |
for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) { |
- if (!ValidateType2CharStringIndex(*(file->cff->char_strings_array.at(i)), |
+ if (!ValidateType2CharStringIndex(file, |
+ *(file->cff->char_strings_array.at(i)), |
global_subrs_index, |
file->cff->fd_select, |
file->cff->local_subrs_per_font, |
file->cff->local_subrs, |
&table)) { |
- return OTS_FAILURE(); |
+ return OTS_FAILURE_MSG("Failed validating charstring set %d", (int) i); |
} |
} |
@@ -1026,3 +1037,5 @@ void ots_cff_free(OpenTypeFile *file) { |
} |
} // namespace ots |
+ |
+#undef TABLE_NAME |