| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "name.h" | 5 #include "name.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cstring> | 8 #include <cstring> |
| 9 | 9 |
| 10 #include "cff.h" | 10 #include "cff.h" |
| 11 | 11 |
| 12 // name - Naming Table | 12 // name - Naming Table |
| 13 // http://www.microsoft.com/opentype/otspec/name.htm | 13 // http://www.microsoft.com/typography/otspec/name.htm |
| 14 |
| 15 #define TABLE_NAME "name" |
| 14 | 16 |
| 15 namespace { | 17 namespace { |
| 16 | 18 |
| 17 bool ValidInPsName(char c) { | 19 bool ValidInPsName(char c) { |
| 18 return (c > 0x20 && c < 0x7f && !std::strchr("[](){}<>/%", c)); | 20 return (c > 0x20 && c < 0x7f && !std::strchr("[](){}<>/%", c)); |
| 19 } | 21 } |
| 20 | 22 |
| 21 bool CheckPsNameAscii(const std::string& name) { | 23 bool CheckPsNameAscii(const std::string& name) { |
| 22 for (unsigned i = 0; i < name.size(); ++i) { | 24 for (unsigned i = 0; i < name.size(); ++i) { |
| 23 if (!ValidInPsName(name[i])) { | 25 if (!ValidInPsName(name[i])) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 namespace ots { | 59 namespace ots { |
| 58 | 60 |
| 59 bool ots_name_parse(OpenTypeFile* file, const uint8_t* data, size_t length) { | 61 bool ots_name_parse(OpenTypeFile* file, const uint8_t* data, size_t length) { |
| 60 Buffer table(data, length); | 62 Buffer table(data, length); |
| 61 | 63 |
| 62 OpenTypeNAME* name = new OpenTypeNAME; | 64 OpenTypeNAME* name = new OpenTypeNAME; |
| 63 file->name = name; | 65 file->name = name; |
| 64 | 66 |
| 65 uint16_t format = 0; | 67 uint16_t format = 0; |
| 66 if (!table.ReadU16(&format) || format > 1) { | 68 if (!table.ReadU16(&format) || format > 1) { |
| 67 return OTS_FAILURE(); | 69 return OTS_FAILURE_MSG("Failed to read name table format or bad format %d",
format); |
| 68 } | 70 } |
| 69 | 71 |
| 70 uint16_t count = 0; | 72 uint16_t count = 0; |
| 71 if (!table.ReadU16(&count)) { | 73 if (!table.ReadU16(&count)) { |
| 72 return OTS_FAILURE(); | 74 return OTS_FAILURE_MSG("Failed to read name count"); |
| 73 } | 75 } |
| 74 | 76 |
| 75 uint16_t string_offset = 0; | 77 uint16_t string_offset = 0; |
| 76 if (!table.ReadU16(&string_offset) || string_offset > length) { | 78 if (!table.ReadU16(&string_offset) || string_offset > length) { |
| 77 return OTS_FAILURE(); | 79 return OTS_FAILURE_MSG("Failed to read strings offset"); |
| 78 } | 80 } |
| 79 const char* string_base = reinterpret_cast<const char*>(data) + | 81 const char* string_base = reinterpret_cast<const char*>(data) + |
| 80 string_offset; | 82 string_offset; |
| 81 | 83 |
| 82 NameRecord prev_record; | 84 NameRecord prev_record; |
| 83 bool sort_required = false; | 85 bool sort_required = false; |
| 84 | 86 |
| 85 // Read all the names, discarding any with invalid IDs, | 87 // Read all the names, discarding any with invalid IDs, |
| 86 // and any where the offset/length would be outside the table. | 88 // and any where the offset/length would be outside the table. |
| 87 // A stricter alternative would be to reject the font if there | 89 // A stricter alternative would be to reject the font if there |
| 88 // are invalid name records, but it's not clear that is necessary. | 90 // are invalid name records, but it's not clear that is necessary. |
| 89 for (unsigned i = 0; i < count; ++i) { | 91 for (unsigned i = 0; i < count; ++i) { |
| 90 NameRecord rec; | 92 NameRecord rec; |
| 91 uint16_t name_length, name_offset; | 93 uint16_t name_length, name_offset = 0; |
| 92 if (!table.ReadU16(&rec.platform_id) || | 94 if (!table.ReadU16(&rec.platform_id) || |
| 93 !table.ReadU16(&rec.encoding_id) || | 95 !table.ReadU16(&rec.encoding_id) || |
| 94 !table.ReadU16(&rec.language_id) || | 96 !table.ReadU16(&rec.language_id) || |
| 95 !table.ReadU16(&rec.name_id) || | 97 !table.ReadU16(&rec.name_id) || |
| 96 !table.ReadU16(&name_length) || | 98 !table.ReadU16(&name_length) || |
| 97 !table.ReadU16(&name_offset)) { | 99 !table.ReadU16(&name_offset)) { |
| 98 return OTS_FAILURE(); | 100 return OTS_FAILURE_MSG("Failed to read name entry %d", i); |
| 99 } | 101 } |
| 100 // check platform & encoding, discard names with unknown values | 102 // check platform & encoding, discard names with unknown values |
| 101 switch (rec.platform_id) { | 103 switch (rec.platform_id) { |
| 102 case 0: // Unicode | 104 case 0: // Unicode |
| 103 if (rec.encoding_id > 6) { | 105 if (rec.encoding_id > 6) { |
| 104 continue; | 106 continue; |
| 105 } | 107 } |
| 106 break; | 108 break; |
| 107 case 1: // Macintosh | 109 case 1: // Macintosh |
| 108 if (rec.encoding_id > 32) { | 110 if (rec.encoding_id > 32) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 } | 161 } |
| 160 | 162 |
| 161 name->names.push_back(rec); | 163 name->names.push_back(rec); |
| 162 prev_record = rec; | 164 prev_record = rec; |
| 163 } | 165 } |
| 164 | 166 |
| 165 if (format == 1) { | 167 if (format == 1) { |
| 166 // extended name table format with language tags | 168 // extended name table format with language tags |
| 167 uint16_t lang_tag_count; | 169 uint16_t lang_tag_count; |
| 168 if (!table.ReadU16(&lang_tag_count)) { | 170 if (!table.ReadU16(&lang_tag_count)) { |
| 169 return OTS_FAILURE(); | 171 return OTS_FAILURE_MSG("Failed to read language tag count"); |
| 170 } | 172 } |
| 171 for (unsigned i = 0; i < lang_tag_count; ++i) { | 173 for (unsigned i = 0; i < lang_tag_count; ++i) { |
| 172 uint16_t tag_length = 0; | 174 uint16_t tag_length = 0; |
| 173 uint16_t tag_offset = 0; | 175 uint16_t tag_offset = 0; |
| 174 if (!table.ReadU16(&tag_length) || !table.ReadU16(&tag_offset)) { | 176 if (!table.ReadU16(&tag_length) || !table.ReadU16(&tag_offset)) { |
| 175 return OTS_FAILURE(); | 177 return OTS_FAILURE_MSG("Faile to read tag length or offset"); |
| 176 } | 178 } |
| 177 const unsigned tag_end = static_cast<unsigned>(string_offset) + | 179 const unsigned tag_end = static_cast<unsigned>(string_offset) + |
| 178 tag_offset + tag_length; | 180 tag_offset + tag_length; |
| 179 if (tag_end > length) { | 181 if (tag_end > length) { |
| 180 return OTS_FAILURE(); | 182 return OTS_FAILURE_MSG("bad end of tag %d > %ld for name entry %d", tag_
end, length, i); |
| 181 } | 183 } |
| 182 std::string tag(string_base + tag_offset, tag_length); | 184 std::string tag(string_base + tag_offset, tag_length); |
| 183 name->lang_tags.push_back(tag); | 185 name->lang_tags.push_back(tag); |
| 184 } | 186 } |
| 185 } | 187 } |
| 186 | 188 |
| 187 if (table.offset() > string_offset) { | 189 if (table.offset() > string_offset) { |
| 188 // the string storage apparently overlapped the name/tag records; | 190 // the string storage apparently overlapped the name/tag records; |
| 189 // consider this font to be badly broken | 191 // consider this font to be badly broken |
| 190 return OTS_FAILURE(); | 192 return OTS_FAILURE_MSG("Bad table offset %ld > %d", table.offset(), string_o
ffset); |
| 191 } | 193 } |
| 192 | 194 |
| 193 // check existence of required name strings (synthesize if necessary) | 195 // check existence of required name strings (synthesize if necessary) |
| 194 // [0 - copyright - skip] | 196 // [0 - copyright - skip] |
| 195 // 1 - family | 197 // 1 - family |
| 196 // 2 - subfamily | 198 // 2 - subfamily |
| 197 // [3 - unique ID - skip] | 199 // [3 - unique ID - skip] |
| 198 // 4 - full name | 200 // 4 - full name |
| 199 // 5 - version | 201 // 5 - version |
| 200 // 6 - postscript name | 202 // 6 - postscript name |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 uint16_t lang_tag_count = static_cast<uint16_t>(name->lang_tags.size()); | 275 uint16_t lang_tag_count = static_cast<uint16_t>(name->lang_tags.size()); |
| 274 uint16_t format = 0; | 276 uint16_t format = 0; |
| 275 size_t string_offset = 6 + name_count * 12; | 277 size_t string_offset = 6 + name_count * 12; |
| 276 | 278 |
| 277 if (name->lang_tags.size() > 0) { | 279 if (name->lang_tags.size() > 0) { |
| 278 // lang tags require a format-1 name table | 280 // lang tags require a format-1 name table |
| 279 format = 1; | 281 format = 1; |
| 280 string_offset += 2 + lang_tag_count * 4; | 282 string_offset += 2 + lang_tag_count * 4; |
| 281 } | 283 } |
| 282 if (string_offset > 0xffff) { | 284 if (string_offset > 0xffff) { |
| 283 return OTS_FAILURE(); | 285 return OTS_FAILURE_MSG("Bad string offset %ld", string_offset); |
| 284 } | 286 } |
| 285 if (!out->WriteU16(format) || | 287 if (!out->WriteU16(format) || |
| 286 !out->WriteU16(name_count) || | 288 !out->WriteU16(name_count) || |
| 287 !out->WriteU16(static_cast<uint16_t>(string_offset))) { | 289 !out->WriteU16(static_cast<uint16_t>(string_offset))) { |
| 288 return OTS_FAILURE(); | 290 return OTS_FAILURE_MSG("Failed to write name header"); |
| 289 } | 291 } |
| 290 | 292 |
| 291 std::string string_data; | 293 std::string string_data; |
| 292 for (std::vector<NameRecord>::const_iterator name_iter = name->names.begin(); | 294 for (std::vector<NameRecord>::const_iterator name_iter = name->names.begin(); |
| 293 name_iter != name->names.end(); name_iter++) { | 295 name_iter != name->names.end(); name_iter++) { |
| 294 const NameRecord& rec = *name_iter; | 296 const NameRecord& rec = *name_iter; |
| 295 if (string_data.size() + rec.text.size() > | 297 if (string_data.size() + rec.text.size() > |
| 296 std::numeric_limits<uint16_t>::max() || | 298 std::numeric_limits<uint16_t>::max() || |
| 297 !out->WriteU16(rec.platform_id) || | 299 !out->WriteU16(rec.platform_id) || |
| 298 !out->WriteU16(rec.encoding_id) || | 300 !out->WriteU16(rec.encoding_id) || |
| 299 !out->WriteU16(rec.language_id) || | 301 !out->WriteU16(rec.language_id) || |
| 300 !out->WriteU16(rec.name_id) || | 302 !out->WriteU16(rec.name_id) || |
| 301 !out->WriteU16(static_cast<uint16_t>(rec.text.size())) || | 303 !out->WriteU16(static_cast<uint16_t>(rec.text.size())) || |
| 302 !out->WriteU16(static_cast<uint16_t>(string_data.size())) ) { | 304 !out->WriteU16(static_cast<uint16_t>(string_data.size())) ) { |
| 303 return OTS_FAILURE(); | 305 return OTS_FAILURE_MSG("Faile to write name entry"); |
| 304 } | 306 } |
| 305 string_data.append(rec.text); | 307 string_data.append(rec.text); |
| 306 } | 308 } |
| 307 | 309 |
| 308 if (format == 1) { | 310 if (format == 1) { |
| 309 if (!out->WriteU16(lang_tag_count)) { | 311 if (!out->WriteU16(lang_tag_count)) { |
| 310 return OTS_FAILURE(); | 312 return OTS_FAILURE_MSG("Faile to write language tag count"); |
| 311 } | 313 } |
| 312 for (std::vector<std::string>::const_iterator tag_iter = | 314 for (std::vector<std::string>::const_iterator tag_iter = |
| 313 name->lang_tags.begin(); | 315 name->lang_tags.begin(); |
| 314 tag_iter != name->lang_tags.end(); tag_iter++) { | 316 tag_iter != name->lang_tags.end(); tag_iter++) { |
| 315 if (string_data.size() + tag_iter->size() > | 317 if (string_data.size() + tag_iter->size() > |
| 316 std::numeric_limits<uint16_t>::max() || | 318 std::numeric_limits<uint16_t>::max() || |
| 317 !out->WriteU16(static_cast<uint16_t>(tag_iter->size())) || | 319 !out->WriteU16(static_cast<uint16_t>(tag_iter->size())) || |
| 318 !out->WriteU16(static_cast<uint16_t>(string_data.size()))) { | 320 !out->WriteU16(static_cast<uint16_t>(string_data.size()))) { |
| 319 return OTS_FAILURE(); | 321 return OTS_FAILURE_MSG("Failed to write string"); |
| 320 } | 322 } |
| 321 string_data.append(*tag_iter); | 323 string_data.append(*tag_iter); |
| 322 } | 324 } |
| 323 } | 325 } |
| 324 | 326 |
| 325 if (!out->Write(string_data.data(), string_data.size())) { | 327 if (!out->Write(string_data.data(), string_data.size())) { |
| 326 return OTS_FAILURE(); | 328 return OTS_FAILURE_MSG("Faile to write string data"); |
| 327 } | 329 } |
| 328 | 330 |
| 329 return true; | 331 return true; |
| 330 } | 332 } |
| 331 | 333 |
| 332 void ots_name_free(OpenTypeFile* file) { | 334 void ots_name_free(OpenTypeFile* file) { |
| 333 delete file->name; | 335 delete file->name; |
| 334 } | 336 } |
| 335 | 337 |
| 336 } // namespace | 338 } // namespace |
| 339 |
| 340 #undef TABLE_NAME |
| OLD | NEW |