1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/ots/src/cff.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1030 @@ 1.4 +// Copyright (c) 2012 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "cff.h" 1.9 + 1.10 +#include <cstring> 1.11 +#include <utility> 1.12 +#include <vector> 1.13 + 1.14 +#include "cff_type2_charstring.h" 1.15 + 1.16 +// CFF - PostScript font program (Compact Font Format) table 1.17 +// http://www.microsoft.com/typography/otspec/cff.htm 1.18 +// http://www.microsoft.com/typography/otspec/cffspec.htm 1.19 + 1.20 +#define TABLE_NAME "CFF" 1.21 + 1.22 +namespace { 1.23 + 1.24 +enum DICT_OPERAND_TYPE { 1.25 + DICT_OPERAND_INTEGER, 1.26 + DICT_OPERAND_REAL, 1.27 + DICT_OPERATOR, 1.28 +}; 1.29 + 1.30 +enum DICT_DATA_TYPE { 1.31 + DICT_DATA_TOPLEVEL, 1.32 + DICT_DATA_FDARRAY, 1.33 +}; 1.34 + 1.35 +enum FONT_FORMAT { 1.36 + FORMAT_UNKNOWN, 1.37 + FORMAT_CID_KEYED, 1.38 + FORMAT_OTHER, // Including synthetic fonts 1.39 +}; 1.40 + 1.41 +// see Appendix. A 1.42 +const size_t kNStdString = 390; 1.43 + 1.44 +bool ReadOffset(ots::Buffer *table, uint8_t off_size, uint32_t *offset) { 1.45 + if (off_size > 4) { 1.46 + return OTS_FAILURE(); 1.47 + } 1.48 + 1.49 + uint32_t tmp32 = 0; 1.50 + for (unsigned i = 0; i < off_size; ++i) { 1.51 + uint8_t tmp8 = 0; 1.52 + if (!table->ReadU8(&tmp8)) { 1.53 + return OTS_FAILURE(); 1.54 + } 1.55 + tmp32 <<= 8; 1.56 + tmp32 += tmp8; 1.57 + } 1.58 + *offset = tmp32; 1.59 + return true; 1.60 +} 1.61 + 1.62 +bool ParseIndex(ots::Buffer *table, ots::CFFIndex *index) { 1.63 + index->off_size = 0; 1.64 + index->offsets.clear(); 1.65 + 1.66 + if (!table->ReadU16(&(index->count))) { 1.67 + return OTS_FAILURE(); 1.68 + } 1.69 + if (index->count == 0) { 1.70 + // An empty INDEX. 1.71 + index->offset_to_next = table->offset(); 1.72 + return true; 1.73 + } 1.74 + 1.75 + if (!table->ReadU8(&(index->off_size))) { 1.76 + return OTS_FAILURE(); 1.77 + } 1.78 + if ((index->off_size == 0) || 1.79 + (index->off_size > 4)) { 1.80 + return OTS_FAILURE(); 1.81 + } 1.82 + 1.83 + const size_t array_size = (index->count + 1) * index->off_size; 1.84 + // less than ((64k + 1) * 4), thus does not overflow. 1.85 + const size_t object_data_offset = table->offset() + array_size; 1.86 + // does not overflow too, since offset() <= 1GB. 1.87 + 1.88 + if (object_data_offset >= table->length()) { 1.89 + return OTS_FAILURE(); 1.90 + } 1.91 + 1.92 + for (unsigned i = 0; i <= index->count; ++i) { // '<=' is not a typo. 1.93 + uint32_t rel_offset = 0; 1.94 + if (!ReadOffset(table, index->off_size, &rel_offset)) { 1.95 + return OTS_FAILURE(); 1.96 + } 1.97 + if (rel_offset < 1) { 1.98 + return OTS_FAILURE(); 1.99 + } 1.100 + if (i == 0 && rel_offset != 1) { 1.101 + return OTS_FAILURE(); 1.102 + } 1.103 + 1.104 + if (rel_offset > table->length()) { 1.105 + return OTS_FAILURE(); 1.106 + } 1.107 + 1.108 + // does not underflow. 1.109 + if (object_data_offset > table->length() - (rel_offset - 1)) { 1.110 + return OTS_FAILURE(); 1.111 + } 1.112 + 1.113 + index->offsets.push_back( 1.114 + object_data_offset + (rel_offset - 1)); // less than length(), 1GB. 1.115 + } 1.116 + 1.117 + for (unsigned i = 1; i < index->offsets.size(); ++i) { 1.118 + // We allow consecutive identical offsets here for zero-length strings. 1.119 + // See http://crbug.com/69341 for more details. 1.120 + if (index->offsets[i] < index->offsets[i - 1]) { 1.121 + return OTS_FAILURE(); 1.122 + } 1.123 + } 1.124 + 1.125 + index->offset_to_next = index->offsets.back(); 1.126 + return true; 1.127 +} 1.128 + 1.129 +bool ParseNameData( 1.130 + ots::Buffer *table, const ots::CFFIndex &index, std::string* out_name) { 1.131 + uint8_t name[256] = {0}; 1.132 + if (index.offsets.size() == 0) { // just in case. 1.133 + return OTS_FAILURE(); 1.134 + } 1.135 + for (unsigned i = 1; i < index.offsets.size(); ++i) { 1.136 + const size_t length = index.offsets[i] - index.offsets[i - 1]; 1.137 + // font names should be no longer than 127 characters. 1.138 + if (length > 127) { 1.139 + return OTS_FAILURE(); 1.140 + } 1.141 + 1.142 + table->set_offset(index.offsets[i - 1]); 1.143 + if (!table->Read(name, length)) { 1.144 + return OTS_FAILURE(); 1.145 + } 1.146 + 1.147 + for (size_t j = 0; j < length; ++j) { 1.148 + // setting the first byte to NUL is allowed. 1.149 + if (j == 0 && name[j] == 0) continue; 1.150 + // non-ASCII characters are not recommended (except the first character). 1.151 + if (name[j] < 33 || name[j] > 126) { 1.152 + return OTS_FAILURE(); 1.153 + } 1.154 + // [, ], ... are not allowed. 1.155 + if (std::strchr("[](){}<>/% ", name[j])) { 1.156 + return OTS_FAILURE(); 1.157 + } 1.158 + } 1.159 + } 1.160 + 1.161 + *out_name = reinterpret_cast<char *>(name); 1.162 + return true; 1.163 +} 1.164 + 1.165 +bool CheckOffset(const std::pair<uint32_t, DICT_OPERAND_TYPE>& operand, 1.166 + size_t table_length) { 1.167 + if (operand.second != DICT_OPERAND_INTEGER) { 1.168 + return OTS_FAILURE(); 1.169 + } 1.170 + if (operand.first >= table_length) { 1.171 + return OTS_FAILURE(); 1.172 + } 1.173 + return true; 1.174 +} 1.175 + 1.176 +bool CheckSid(const std::pair<uint32_t, DICT_OPERAND_TYPE>& operand, 1.177 + size_t sid_max) { 1.178 + if (operand.second != DICT_OPERAND_INTEGER) { 1.179 + return OTS_FAILURE(); 1.180 + } 1.181 + if (operand.first > sid_max) { 1.182 + return OTS_FAILURE(); 1.183 + } 1.184 + return true; 1.185 +} 1.186 + 1.187 +bool ParseDictDataBcd( 1.188 + ots::Buffer *table, 1.189 + std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) { 1.190 + bool read_decimal_point = false; 1.191 + bool read_e = false; 1.192 + 1.193 + uint8_t nibble = 0; 1.194 + size_t count = 0; 1.195 + while (true) { 1.196 + if (!table->ReadU8(&nibble)) { 1.197 + return OTS_FAILURE(); 1.198 + } 1.199 + if ((nibble & 0xf0) == 0xf0) { 1.200 + if ((nibble & 0xf) == 0xf) { 1.201 + // TODO(yusukes): would be better to store actual double value, 1.202 + // rather than the dummy integer. 1.203 + operands->push_back(std::make_pair(static_cast<uint32_t>(0), 1.204 + DICT_OPERAND_REAL)); 1.205 + return true; 1.206 + } 1.207 + return OTS_FAILURE(); 1.208 + } 1.209 + if ((nibble & 0x0f) == 0x0f) { 1.210 + operands->push_back(std::make_pair(static_cast<uint32_t>(0), 1.211 + DICT_OPERAND_REAL)); 1.212 + return true; 1.213 + } 1.214 + 1.215 + // check number format 1.216 + uint8_t nibbles[2]; 1.217 + nibbles[0] = (nibble & 0xf0) >> 8; 1.218 + nibbles[1] = (nibble & 0x0f); 1.219 + for (unsigned i = 0; i < 2; ++i) { 1.220 + if (nibbles[i] == 0xd) { // reserved number 1.221 + return OTS_FAILURE(); 1.222 + } 1.223 + if ((nibbles[i] == 0xe) && // minus 1.224 + ((count > 0) || (i > 0))) { 1.225 + return OTS_FAILURE(); // minus sign should be the first character. 1.226 + } 1.227 + if (nibbles[i] == 0xa) { // decimal point 1.228 + if (!read_decimal_point) { 1.229 + read_decimal_point = true; 1.230 + } else { 1.231 + return OTS_FAILURE(); // two or more points. 1.232 + } 1.233 + } 1.234 + if ((nibbles[i] == 0xb) || // E+ 1.235 + (nibbles[i] == 0xc)) { // E- 1.236 + if (!read_e) { 1.237 + read_e = true; 1.238 + } else { 1.239 + return OTS_FAILURE(); // two or more E's. 1.240 + } 1.241 + } 1.242 + } 1.243 + ++count; 1.244 + } 1.245 +} 1.246 + 1.247 +bool ParseDictDataEscapedOperator( 1.248 + ots::Buffer *table, 1.249 + std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) { 1.250 + uint8_t op = 0; 1.251 + if (!table->ReadU8(&op)) { 1.252 + return OTS_FAILURE(); 1.253 + } 1.254 + 1.255 + if ((op <= 14) || 1.256 + (op >= 17 && op <= 23) || 1.257 + (op >= 30 && op <= 38)) { 1.258 + operands->push_back(std::make_pair((12U << 8) + op, DICT_OPERATOR)); 1.259 + return true; 1.260 + } 1.261 + 1.262 + // reserved area. 1.263 + return OTS_FAILURE(); 1.264 +} 1.265 + 1.266 +bool ParseDictDataNumber( 1.267 + ots::Buffer *table, uint8_t b0, 1.268 + std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) { 1.269 + uint8_t b1 = 0; 1.270 + uint8_t b2 = 0; 1.271 + uint8_t b3 = 0; 1.272 + uint8_t b4 = 0; 1.273 + 1.274 + switch (b0) { 1.275 + case 28: // shortint 1.276 + if (!table->ReadU8(&b1) || 1.277 + !table->ReadU8(&b2)) { 1.278 + return OTS_FAILURE(); 1.279 + } 1.280 + operands->push_back(std::make_pair( 1.281 + static_cast<uint32_t>((b1 << 8) + b2), DICT_OPERAND_INTEGER)); 1.282 + return true; 1.283 + 1.284 + case 29: // longint 1.285 + if (!table->ReadU8(&b1) || 1.286 + !table->ReadU8(&b2) || 1.287 + !table->ReadU8(&b3) || 1.288 + !table->ReadU8(&b4)) { 1.289 + return OTS_FAILURE(); 1.290 + } 1.291 + operands->push_back(std::make_pair( 1.292 + static_cast<uint32_t>((b1 << 24) + (b2 << 16) + (b3 << 8) + b4), 1.293 + DICT_OPERAND_INTEGER)); 1.294 + return true; 1.295 + 1.296 + case 30: // binary coded decimal 1.297 + return ParseDictDataBcd(table, operands); 1.298 + 1.299 + default: 1.300 + break; 1.301 + } 1.302 + 1.303 + uint32_t result; 1.304 + if (b0 >=32 && b0 <=246) { 1.305 + result = b0 - 139; 1.306 + } else if (b0 >=247 && b0 <= 250) { 1.307 + if (!table->ReadU8(&b1)) { 1.308 + return OTS_FAILURE(); 1.309 + } 1.310 + result = (b0 - 247) * 256 + b1 + 108; 1.311 + } else if (b0 >= 251 && b0 <= 254) { 1.312 + if (!table->ReadU8(&b1)) { 1.313 + return OTS_FAILURE(); 1.314 + } 1.315 + result = -(b0 - 251) * 256 + b1 - 108; 1.316 + } else { 1.317 + return OTS_FAILURE(); 1.318 + } 1.319 + 1.320 + operands->push_back(std::make_pair(result, DICT_OPERAND_INTEGER)); 1.321 + return true; 1.322 +} 1.323 + 1.324 +bool ParseDictDataReadNext( 1.325 + ots::Buffer *table, 1.326 + std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) { 1.327 + uint8_t op = 0; 1.328 + if (!table->ReadU8(&op)) { 1.329 + return OTS_FAILURE(); 1.330 + } 1.331 + if (op <= 21) { 1.332 + if (op == 12) { 1.333 + return ParseDictDataEscapedOperator(table, operands); 1.334 + } 1.335 + operands->push_back(std::make_pair( 1.336 + static_cast<uint32_t>(op), DICT_OPERATOR)); 1.337 + return true; 1.338 + } else if (op <= 27 || op == 31 || op == 255) { 1.339 + // reserved area. 1.340 + return OTS_FAILURE(); 1.341 + } 1.342 + 1.343 + return ParseDictDataNumber(table, op, operands); 1.344 +} 1.345 + 1.346 +bool ParsePrivateDictData( 1.347 + const uint8_t *data, 1.348 + size_t table_length, size_t offset, size_t dict_length, 1.349 + DICT_DATA_TYPE type, ots::OpenTypeCFF *out_cff) { 1.350 + ots::Buffer table(data + offset, dict_length); 1.351 + std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands; 1.352 + 1.353 + // Since a Private DICT for FDArray might not have a Local Subr (e.g. Hiragino 1.354 + // Kaku Gothic Std W8), we create an empty Local Subr here to match the size 1.355 + // of FDArray the size of |local_subrs_per_font|. 1.356 + if (type == DICT_DATA_FDARRAY) { 1.357 + out_cff->local_subrs_per_font.push_back(new ots::CFFIndex); 1.358 + } 1.359 + 1.360 + while (table.offset() < dict_length) { 1.361 + if (!ParseDictDataReadNext(&table, &operands)) { 1.362 + return OTS_FAILURE(); 1.363 + } 1.364 + if (operands.empty()) { 1.365 + return OTS_FAILURE(); 1.366 + } 1.367 + if (operands.size() > 48) { 1.368 + // An operator may be preceded by up to a maximum of 48 operands. 1.369 + return OTS_FAILURE(); 1.370 + } 1.371 + if (operands.back().second != DICT_OPERATOR) { 1.372 + continue; 1.373 + } 1.374 + 1.375 + // got operator 1.376 + const uint32_t op = operands.back().first; 1.377 + operands.pop_back(); 1.378 + 1.379 + switch (op) { 1.380 + // array 1.381 + case 6: // BlueValues 1.382 + case 7: // OtherBlues 1.383 + case 8: // FamilyBlues 1.384 + case 9: // FamilyOtherBlues 1.385 + case (12U << 8) + 12: // StemSnapH (delta) 1.386 + case (12U << 8) + 13: // StemSnapV (delta) 1.387 + if (operands.empty()) { 1.388 + return OTS_FAILURE(); 1.389 + } 1.390 + break; 1.391 + 1.392 + // number 1.393 + case 10: // StdHW 1.394 + case 11: // StdVW 1.395 + case 20: // defaultWidthX 1.396 + case 21: // nominalWidthX 1.397 + case (12U << 8) + 9: // BlueScale 1.398 + case (12U << 8) + 10: // BlueShift 1.399 + case (12U << 8) + 11: // BlueFuzz 1.400 + case (12U << 8) + 17: // LanguageGroup 1.401 + case (12U << 8) + 18: // ExpansionFactor 1.402 + case (12U << 8) + 19: // initialRandomSeed 1.403 + if (operands.size() != 1) { 1.404 + return OTS_FAILURE(); 1.405 + } 1.406 + break; 1.407 + 1.408 + // Local Subrs INDEX, offset(self) 1.409 + case 19: { 1.410 + if (operands.size() != 1) { 1.411 + return OTS_FAILURE(); 1.412 + } 1.413 + if (operands.back().second != DICT_OPERAND_INTEGER) { 1.414 + return OTS_FAILURE(); 1.415 + } 1.416 + if (operands.back().first >= 1024 * 1024 * 1024) { 1.417 + return OTS_FAILURE(); 1.418 + } 1.419 + if (operands.back().first + offset >= table_length) { 1.420 + return OTS_FAILURE(); 1.421 + } 1.422 + // parse "16. Local Subrs INDEX" 1.423 + ots::Buffer cff_table(data, table_length); 1.424 + cff_table.set_offset(operands.back().first + offset); 1.425 + ots::CFFIndex *local_subrs_index = NULL; 1.426 + if (type == DICT_DATA_FDARRAY) { 1.427 + if (out_cff->local_subrs_per_font.empty()) { 1.428 + return OTS_FAILURE(); // not reached. 1.429 + } 1.430 + local_subrs_index = out_cff->local_subrs_per_font.back(); 1.431 + } else { // type == DICT_DATA_TOPLEVEL 1.432 + if (out_cff->local_subrs) { 1.433 + return OTS_FAILURE(); // two or more local_subrs? 1.434 + } 1.435 + local_subrs_index = new ots::CFFIndex; 1.436 + out_cff->local_subrs = local_subrs_index; 1.437 + } 1.438 + if (!ParseIndex(&cff_table, local_subrs_index)) { 1.439 + return OTS_FAILURE(); 1.440 + } 1.441 + break; 1.442 + } 1.443 + 1.444 + // boolean 1.445 + case (12U << 8) + 14: // ForceBold 1.446 + if (operands.size() != 1) { 1.447 + return OTS_FAILURE(); 1.448 + } 1.449 + if (operands.back().second != DICT_OPERAND_INTEGER) { 1.450 + return OTS_FAILURE(); 1.451 + } 1.452 + if (operands.back().first >= 2) { 1.453 + return OTS_FAILURE(); 1.454 + } 1.455 + break; 1.456 + 1.457 + default: 1.458 + return OTS_FAILURE(); 1.459 + } 1.460 + operands.clear(); 1.461 + } 1.462 + 1.463 + return true; 1.464 +} 1.465 + 1.466 +bool ParseDictData(const uint8_t *data, size_t table_length, 1.467 + const ots::CFFIndex &index, size_t sid_max, 1.468 + DICT_DATA_TYPE type, ots::OpenTypeCFF *out_cff) { 1.469 + for (unsigned i = 1; i < index.offsets.size(); ++i) { 1.470 + if (type == DICT_DATA_TOPLEVEL) { 1.471 + out_cff->char_strings_array.push_back(new ots::CFFIndex); 1.472 + } 1.473 + size_t dict_length = index.offsets[i] - index.offsets[i - 1]; 1.474 + ots::Buffer table(data + index.offsets[i - 1], dict_length); 1.475 + 1.476 + std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands; 1.477 + 1.478 + FONT_FORMAT font_format = FORMAT_UNKNOWN; 1.479 + bool have_ros = false; 1.480 + size_t glyphs = 0; 1.481 + size_t charset_offset = 0; 1.482 + 1.483 + while (table.offset() < dict_length) { 1.484 + if (!ParseDictDataReadNext(&table, &operands)) { 1.485 + return OTS_FAILURE(); 1.486 + } 1.487 + if (operands.empty()) { 1.488 + return OTS_FAILURE(); 1.489 + } 1.490 + if (operands.size() > 48) { 1.491 + // An operator may be preceded by up to a maximum of 48 operands. 1.492 + return OTS_FAILURE(); 1.493 + } 1.494 + if (operands.back().second != DICT_OPERATOR) continue; 1.495 + 1.496 + // got operator 1.497 + const uint32_t op = operands.back().first; 1.498 + operands.pop_back(); 1.499 + 1.500 + switch (op) { 1.501 + // SID 1.502 + case 0: // version 1.503 + case 1: // Notice 1.504 + case 2: // Copyright 1.505 + case 3: // FullName 1.506 + case 4: // FamilyName 1.507 + case (12U << 8) + 0: // Copyright 1.508 + case (12U << 8) + 21: // PostScript 1.509 + case (12U << 8) + 22: // BaseFontName 1.510 + case (12U << 8) + 38: // FontName 1.511 + if (operands.size() != 1) { 1.512 + return OTS_FAILURE(); 1.513 + } 1.514 + if (!CheckSid(operands.back(), sid_max)) { 1.515 + return OTS_FAILURE(); 1.516 + } 1.517 + break; 1.518 + 1.519 + // array 1.520 + case 5: // FontBBox 1.521 + case 14: // XUID 1.522 + case (12U << 8) + 7: // FontMatrix 1.523 + case (12U << 8) + 23: // BaseFontBlend (delta) 1.524 + if (operands.empty()) { 1.525 + return OTS_FAILURE(); 1.526 + } 1.527 + break; 1.528 + 1.529 + // number 1.530 + case 13: // UniqueID 1.531 + case (12U << 8) + 2: // ItalicAngle 1.532 + case (12U << 8) + 3: // UnderlinePosition 1.533 + case (12U << 8) + 4: // UnderlineThickness 1.534 + case (12U << 8) + 5: // PaintType 1.535 + case (12U << 8) + 8: // StrokeWidth 1.536 + case (12U << 8) + 20: // SyntheticBase 1.537 + if (operands.size() != 1) { 1.538 + return OTS_FAILURE(); 1.539 + } 1.540 + break; 1.541 + case (12U << 8) + 31: // CIDFontVersion 1.542 + case (12U << 8) + 32: // CIDFontRevision 1.543 + case (12U << 8) + 33: // CIDFontType 1.544 + case (12U << 8) + 34: // CIDCount 1.545 + case (12U << 8) + 35: // UIDBase 1.546 + if (operands.size() != 1) { 1.547 + return OTS_FAILURE(); 1.548 + } 1.549 + if (font_format != FORMAT_CID_KEYED) { 1.550 + return OTS_FAILURE(); 1.551 + } 1.552 + break; 1.553 + case (12U << 8) + 6: // CharstringType 1.554 + if (operands.size() != 1) { 1.555 + return OTS_FAILURE(); 1.556 + } 1.557 + if(operands.back().second != DICT_OPERAND_INTEGER) { 1.558 + return OTS_FAILURE(); 1.559 + } 1.560 + if (operands.back().first != 2) { 1.561 + // We only support the "Type 2 Charstring Format." 1.562 + // TODO(yusukes): Support Type 1 format? Is that still in use? 1.563 + return OTS_FAILURE(); 1.564 + } 1.565 + break; 1.566 + 1.567 + // boolean 1.568 + case (12U << 8) + 1: // isFixedPitch 1.569 + if (operands.size() != 1) { 1.570 + return OTS_FAILURE(); 1.571 + } 1.572 + if (operands.back().second != DICT_OPERAND_INTEGER) { 1.573 + return OTS_FAILURE(); 1.574 + } 1.575 + if (operands.back().first >= 2) { 1.576 + return OTS_FAILURE(); 1.577 + } 1.578 + break; 1.579 + 1.580 + // offset(0) 1.581 + case 15: // charset 1.582 + if (operands.size() != 1) { 1.583 + return OTS_FAILURE(); 1.584 + } 1.585 + if (operands.back().first <= 2) { 1.586 + // predefined charset, ISOAdobe, Expert or ExpertSubset, is used. 1.587 + break; 1.588 + } 1.589 + if (!CheckOffset(operands.back(), table_length)) { 1.590 + return OTS_FAILURE(); 1.591 + } 1.592 + if (charset_offset) { 1.593 + return OTS_FAILURE(); // multiple charset tables? 1.594 + } 1.595 + charset_offset = operands.back().first; 1.596 + break; 1.597 + 1.598 + case 16: { // Encoding 1.599 + if (operands.size() != 1) { 1.600 + return OTS_FAILURE(); 1.601 + } 1.602 + if (operands.back().first <= 1) { 1.603 + break; // predefined encoding, "Standard" or "Expert", is used. 1.604 + } 1.605 + if (!CheckOffset(operands.back(), table_length)) { 1.606 + return OTS_FAILURE(); 1.607 + } 1.608 + 1.609 + // parse sub dictionary INDEX. 1.610 + ots::Buffer cff_table(data, table_length); 1.611 + cff_table.set_offset(operands.back().first); 1.612 + uint8_t format = 0; 1.613 + if (!cff_table.ReadU8(&format)) { 1.614 + return OTS_FAILURE(); 1.615 + } 1.616 + if (format & 0x80) { 1.617 + // supplemental encoding is not supported at the moment. 1.618 + return OTS_FAILURE(); 1.619 + } 1.620 + // TODO(yusukes): support & parse supplemental encoding tables. 1.621 + break; 1.622 + } 1.623 + 1.624 + case 17: { // CharStrings 1.625 + if (type != DICT_DATA_TOPLEVEL) { 1.626 + return OTS_FAILURE(); 1.627 + } 1.628 + if (operands.size() != 1) { 1.629 + return OTS_FAILURE(); 1.630 + } 1.631 + if (!CheckOffset(operands.back(), table_length)) { 1.632 + return OTS_FAILURE(); 1.633 + } 1.634 + // parse "14. CharStrings INDEX" 1.635 + ots::Buffer cff_table(data, table_length); 1.636 + cff_table.set_offset(operands.back().first); 1.637 + ots::CFFIndex *charstring_index = out_cff->char_strings_array.back(); 1.638 + if (!ParseIndex(&cff_table, charstring_index)) { 1.639 + return OTS_FAILURE(); 1.640 + } 1.641 + if (charstring_index->count < 2) { 1.642 + return OTS_FAILURE(); 1.643 + } 1.644 + if (glyphs) { 1.645 + return OTS_FAILURE(); // multiple charstring tables? 1.646 + } 1.647 + glyphs = charstring_index->count; 1.648 + break; 1.649 + } 1.650 + 1.651 + case (12U << 8) + 36: { // FDArray 1.652 + if (type != DICT_DATA_TOPLEVEL) { 1.653 + return OTS_FAILURE(); 1.654 + } 1.655 + if (operands.size() != 1) { 1.656 + return OTS_FAILURE(); 1.657 + } 1.658 + if (!CheckOffset(operands.back(), table_length)) { 1.659 + return OTS_FAILURE(); 1.660 + } 1.661 + 1.662 + // parse sub dictionary INDEX. 1.663 + ots::Buffer cff_table(data, table_length); 1.664 + cff_table.set_offset(operands.back().first); 1.665 + ots::CFFIndex sub_dict_index; 1.666 + if (!ParseIndex(&cff_table, &sub_dict_index)) { 1.667 + return OTS_FAILURE(); 1.668 + } 1.669 + if (!ParseDictData(data, table_length, 1.670 + sub_dict_index, sid_max, DICT_DATA_FDARRAY, 1.671 + out_cff)) { 1.672 + return OTS_FAILURE(); 1.673 + } 1.674 + if (out_cff->font_dict_length != 0) { 1.675 + return OTS_FAILURE(); // two or more FDArray found. 1.676 + } 1.677 + out_cff->font_dict_length = sub_dict_index.count; 1.678 + break; 1.679 + } 1.680 + 1.681 + case (12U << 8) + 37: { // FDSelect 1.682 + if (type != DICT_DATA_TOPLEVEL) { 1.683 + return OTS_FAILURE(); 1.684 + } 1.685 + if (operands.size() != 1) { 1.686 + return OTS_FAILURE(); 1.687 + } 1.688 + if (!CheckOffset(operands.back(), table_length)) { 1.689 + return OTS_FAILURE(); 1.690 + } 1.691 + 1.692 + // parse FDSelect data structure 1.693 + ots::Buffer cff_table(data, table_length); 1.694 + cff_table.set_offset(operands.back().first); 1.695 + uint8_t format = 0; 1.696 + if (!cff_table.ReadU8(&format)) { 1.697 + return OTS_FAILURE(); 1.698 + } 1.699 + if (format == 0) { 1.700 + for (size_t j = 0; j < glyphs; ++j) { 1.701 + uint8_t fd_index = 0; 1.702 + if (!cff_table.ReadU8(&fd_index)) { 1.703 + return OTS_FAILURE(); 1.704 + } 1.705 + (out_cff->fd_select)[j] = fd_index; 1.706 + } 1.707 + } else if (format == 3) { 1.708 + uint16_t n_ranges = 0; 1.709 + if (!cff_table.ReadU16(&n_ranges)) { 1.710 + return OTS_FAILURE(); 1.711 + } 1.712 + if (n_ranges == 0) { 1.713 + return OTS_FAILURE(); 1.714 + } 1.715 + 1.716 + uint16_t last_gid = 0; 1.717 + uint8_t fd_index = 0; 1.718 + for (unsigned j = 0; j < n_ranges; ++j) { 1.719 + uint16_t first = 0; // GID 1.720 + if (!cff_table.ReadU16(&first)) { 1.721 + return OTS_FAILURE(); 1.722 + } 1.723 + 1.724 + // Sanity checks. 1.725 + if ((j == 0) && (first != 0)) { 1.726 + return OTS_FAILURE(); 1.727 + } 1.728 + if ((j != 0) && (last_gid >= first)) { 1.729 + return OTS_FAILURE(); // not increasing order. 1.730 + } 1.731 + 1.732 + // Copy the mapping to |out_cff->fd_select|. 1.733 + if (j != 0) { 1.734 + for (uint16_t k = last_gid; k < first; ++k) { 1.735 + if (!out_cff->fd_select.insert( 1.736 + std::make_pair(k, fd_index)).second) { 1.737 + return OTS_FAILURE(); 1.738 + } 1.739 + } 1.740 + } 1.741 + 1.742 + if (!cff_table.ReadU8(&fd_index)) { 1.743 + return OTS_FAILURE(); 1.744 + } 1.745 + last_gid = first; 1.746 + // TODO(yusukes): check GID? 1.747 + } 1.748 + uint16_t sentinel = 0; 1.749 + if (!cff_table.ReadU16(&sentinel)) { 1.750 + return OTS_FAILURE(); 1.751 + } 1.752 + if (last_gid >= sentinel) { 1.753 + return OTS_FAILURE(); 1.754 + } 1.755 + for (uint16_t k = last_gid; k < sentinel; ++k) { 1.756 + if (!out_cff->fd_select.insert( 1.757 + std::make_pair(k, fd_index)).second) { 1.758 + return OTS_FAILURE(); 1.759 + } 1.760 + } 1.761 + } else { 1.762 + // unknown format 1.763 + return OTS_FAILURE(); 1.764 + } 1.765 + break; 1.766 + } 1.767 + 1.768 + // Private DICT (2 * number) 1.769 + case 18: { 1.770 + if (operands.size() != 2) { 1.771 + return OTS_FAILURE(); 1.772 + } 1.773 + if (operands.back().second != DICT_OPERAND_INTEGER) { 1.774 + return OTS_FAILURE(); 1.775 + } 1.776 + const uint32_t private_offset = operands.back().first; 1.777 + operands.pop_back(); 1.778 + if (operands.back().second != DICT_OPERAND_INTEGER) { 1.779 + return OTS_FAILURE(); 1.780 + } 1.781 + const uint32_t private_length = operands.back().first; 1.782 + if (private_offset > table_length) { 1.783 + return OTS_FAILURE(); 1.784 + } 1.785 + if (private_length >= table_length) { 1.786 + return OTS_FAILURE(); 1.787 + } 1.788 + if (private_length + private_offset > table_length) { 1.789 + return OTS_FAILURE(); 1.790 + } 1.791 + // parse "15. Private DICT Data" 1.792 + if (!ParsePrivateDictData(data, table_length, 1.793 + private_offset, private_length, 1.794 + type, out_cff)) { 1.795 + return OTS_FAILURE(); 1.796 + } 1.797 + break; 1.798 + } 1.799 + 1.800 + // ROS 1.801 + case (12U << 8) + 30: 1.802 + if (font_format != FORMAT_UNKNOWN) { 1.803 + return OTS_FAILURE(); 1.804 + } 1.805 + font_format = FORMAT_CID_KEYED; 1.806 + if (operands.size() != 3) { 1.807 + return OTS_FAILURE(); 1.808 + } 1.809 + // check SIDs 1.810 + operands.pop_back(); // ignore the first number. 1.811 + if (!CheckSid(operands.back(), sid_max)) { 1.812 + return OTS_FAILURE(); 1.813 + } 1.814 + operands.pop_back(); 1.815 + if (!CheckSid(operands.back(), sid_max)) { 1.816 + return OTS_FAILURE(); 1.817 + } 1.818 + if (have_ros) { 1.819 + return OTS_FAILURE(); // multiple ROS tables? 1.820 + } 1.821 + have_ros = true; 1.822 + break; 1.823 + 1.824 + default: 1.825 + return OTS_FAILURE(); 1.826 + } 1.827 + operands.clear(); 1.828 + 1.829 + if (font_format == FORMAT_UNKNOWN) { 1.830 + font_format = FORMAT_OTHER; 1.831 + } 1.832 + } 1.833 + 1.834 + // parse "13. Charsets" 1.835 + if (charset_offset) { 1.836 + ots::Buffer cff_table(data, table_length); 1.837 + cff_table.set_offset(charset_offset); 1.838 + uint8_t format = 0; 1.839 + if (!cff_table.ReadU8(&format)) { 1.840 + return OTS_FAILURE(); 1.841 + } 1.842 + switch (format) { 1.843 + case 0: 1.844 + for (unsigned j = 1 /* .notdef is omitted */; j < glyphs; ++j) { 1.845 + uint16_t sid = 0; 1.846 + if (!cff_table.ReadU16(&sid)) { 1.847 + return OTS_FAILURE(); 1.848 + } 1.849 + if (!have_ros && (sid > sid_max)) { 1.850 + return OTS_FAILURE(); 1.851 + } 1.852 + // TODO(yusukes): check CIDs when have_ros is true. 1.853 + } 1.854 + break; 1.855 + 1.856 + case 1: 1.857 + case 2: { 1.858 + uint32_t total = 1; // .notdef is omitted. 1.859 + while (total < glyphs) { 1.860 + uint16_t sid = 0; 1.861 + if (!cff_table.ReadU16(&sid)) { 1.862 + return OTS_FAILURE(); 1.863 + } 1.864 + if (!have_ros && (sid > sid_max)) { 1.865 + return OTS_FAILURE(); 1.866 + } 1.867 + // TODO(yusukes): check CIDs when have_ros is true. 1.868 + 1.869 + if (format == 1) { 1.870 + uint8_t left = 0; 1.871 + if (!cff_table.ReadU8(&left)) { 1.872 + return OTS_FAILURE(); 1.873 + } 1.874 + total += (left + 1); 1.875 + } else { 1.876 + uint16_t left = 0; 1.877 + if (!cff_table.ReadU16(&left)) { 1.878 + return OTS_FAILURE(); 1.879 + } 1.880 + total += (left + 1); 1.881 + } 1.882 + } 1.883 + break; 1.884 + } 1.885 + 1.886 + default: 1.887 + return OTS_FAILURE(); 1.888 + } 1.889 + } 1.890 + } 1.891 + return true; 1.892 +} 1.893 + 1.894 +} // namespace 1.895 + 1.896 +namespace ots { 1.897 + 1.898 +bool ots_cff_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { 1.899 + Buffer table(data, length); 1.900 + 1.901 + file->cff = new OpenTypeCFF; 1.902 + file->cff->data = data; 1.903 + file->cff->length = length; 1.904 + file->cff->font_dict_length = 0; 1.905 + file->cff->local_subrs = NULL; 1.906 + 1.907 + // parse "6. Header" in the Adobe Compact Font Format Specification 1.908 + uint8_t major = 0; 1.909 + uint8_t minor = 0; 1.910 + uint8_t hdr_size = 0; 1.911 + uint8_t off_size = 0; 1.912 + if (!table.ReadU8(&major)) { 1.913 + return OTS_FAILURE(); 1.914 + } 1.915 + if (!table.ReadU8(&minor)) { 1.916 + return OTS_FAILURE(); 1.917 + } 1.918 + if (!table.ReadU8(&hdr_size)) { 1.919 + return OTS_FAILURE(); 1.920 + } 1.921 + if (!table.ReadU8(&off_size)) { 1.922 + return OTS_FAILURE(); 1.923 + } 1.924 + if ((off_size == 0) || (off_size > 4)) { 1.925 + return OTS_FAILURE(); 1.926 + } 1.927 + 1.928 + if ((major != 1) || 1.929 + (minor != 0) || 1.930 + (hdr_size != 4)) { 1.931 + return OTS_FAILURE(); 1.932 + } 1.933 + if (hdr_size >= length) { 1.934 + return OTS_FAILURE(); 1.935 + } 1.936 + 1.937 + // parse "7. Name INDEX" 1.938 + table.set_offset(hdr_size); 1.939 + CFFIndex name_index; 1.940 + if (!ParseIndex(&table, &name_index)) { 1.941 + return OTS_FAILURE(); 1.942 + } 1.943 + if (!ParseNameData(&table, name_index, &(file->cff->name))) { 1.944 + return OTS_FAILURE(); 1.945 + } 1.946 + 1.947 + // parse "8. Top DICT INDEX" 1.948 + table.set_offset(name_index.offset_to_next); 1.949 + CFFIndex top_dict_index; 1.950 + if (!ParseIndex(&table, &top_dict_index)) { 1.951 + return OTS_FAILURE(); 1.952 + } 1.953 + if (name_index.count != top_dict_index.count) { 1.954 + return OTS_FAILURE(); 1.955 + } 1.956 + 1.957 + // parse "10. String INDEX" 1.958 + table.set_offset(top_dict_index.offset_to_next); 1.959 + CFFIndex string_index; 1.960 + if (!ParseIndex(&table, &string_index)) { 1.961 + return OTS_FAILURE(); 1.962 + } 1.963 + if (string_index.count >= 65000 - kNStdString) { 1.964 + return OTS_FAILURE(); 1.965 + } 1.966 + 1.967 + const size_t sid_max = string_index.count + kNStdString; 1.968 + // string_index.count == 0 is allowed. 1.969 + 1.970 + // parse "9. Top DICT Data" 1.971 + if (!ParseDictData(data, length, top_dict_index, 1.972 + sid_max, DICT_DATA_TOPLEVEL, file->cff)) { 1.973 + return OTS_FAILURE(); 1.974 + } 1.975 + 1.976 + // parse "16. Global Subrs INDEX" 1.977 + table.set_offset(string_index.offset_to_next); 1.978 + CFFIndex global_subrs_index; 1.979 + if (!ParseIndex(&table, &global_subrs_index)) { 1.980 + return OTS_FAILURE(); 1.981 + } 1.982 + 1.983 + // Check if all fd_index in FDSelect are valid. 1.984 + std::map<uint16_t, uint8_t>::const_iterator iter; 1.985 + std::map<uint16_t, uint8_t>::const_iterator end = file->cff->fd_select.end(); 1.986 + for (iter = file->cff->fd_select.begin(); iter != end; ++iter) { 1.987 + if (iter->second >= file->cff->font_dict_length) { 1.988 + return OTS_FAILURE(); 1.989 + } 1.990 + } 1.991 + 1.992 + // Check if all charstrings (font hinting code for each glyph) are valid. 1.993 + for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) { 1.994 + if (!ValidateType2CharStringIndex(*(file->cff->char_strings_array.at(i)), 1.995 + global_subrs_index, 1.996 + file->cff->fd_select, 1.997 + file->cff->local_subrs_per_font, 1.998 + file->cff->local_subrs, 1.999 + &table)) { 1.1000 + return OTS_FAILURE(); 1.1001 + } 1.1002 + } 1.1003 + 1.1004 + return true; 1.1005 +} 1.1006 + 1.1007 +bool ots_cff_should_serialise(OpenTypeFile *file) { 1.1008 + return file->cff != NULL; 1.1009 +} 1.1010 + 1.1011 +bool ots_cff_serialise(OTSStream *out, OpenTypeFile *file) { 1.1012 + // TODO(yusukes): would be better to transcode the data, 1.1013 + // rather than simple memcpy. 1.1014 + if (!out->Write(file->cff->data, file->cff->length)) { 1.1015 + return OTS_FAILURE(); 1.1016 + } 1.1017 + return true; 1.1018 +} 1.1019 + 1.1020 +void ots_cff_free(OpenTypeFile *file) { 1.1021 + if (file->cff) { 1.1022 + for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) { 1.1023 + delete (file->cff->char_strings_array)[i]; 1.1024 + } 1.1025 + for (size_t i = 0; i < file->cff->local_subrs_per_font.size(); ++i) { 1.1026 + delete (file->cff->local_subrs_per_font)[i]; 1.1027 + } 1.1028 + delete file->cff->local_subrs; 1.1029 + delete file->cff; 1.1030 + } 1.1031 +} 1.1032 + 1.1033 +} // namespace ots