| 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
|
|
|