| 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" | |
| 11 | |
| 12 // name - Naming Table | 10 // name - Naming Table |
| 13 // http://www.microsoft.com/typography/otspec/name.htm | 11 // http://www.microsoft.com/typography/otspec/name.htm |
| 14 | 12 |
| 15 #define TABLE_NAME "name" | 13 #define TABLE_NAME "name" |
| 16 | 14 |
| 17 namespace { | 15 namespace { |
| 18 | 16 |
| 19 bool ValidInPsName(char c) { | 17 bool ValidInPsName(char c) { |
| 20 return (c > 0x20 && c < 0x7f && !std::strchr("[](){}<>/%", c)); | 18 return (c > 0x20 && c < 0x7f && !std::strchr("[](){}<>/%", c)); |
| 21 } | 19 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 51 (*target)[j++] = '\0'; | 49 (*target)[j++] = '\0'; |
| 52 (*target)[j++] = source[i]; | 50 (*target)[j++] = source[i]; |
| 53 } | 51 } |
| 54 } | 52 } |
| 55 | 53 |
| 56 } // namespace | 54 } // namespace |
| 57 | 55 |
| 58 | 56 |
| 59 namespace ots { | 57 namespace ots { |
| 60 | 58 |
| 61 bool ots_name_parse(OpenTypeFile* file, const uint8_t* data, size_t length) { | 59 bool ots_name_parse(Font *font, const uint8_t* data, size_t length) { |
| 62 Buffer table(data, length); | 60 Buffer table(data, length); |
| 63 | 61 |
| 64 OpenTypeNAME* name = new OpenTypeNAME; | 62 OpenTypeNAME* name = new OpenTypeNAME; |
| 65 file->name = name; | 63 font->name = name; |
| 66 | 64 |
| 67 uint16_t format = 0; | 65 uint16_t format = 0; |
| 68 if (!table.ReadU16(&format) || format > 1) { | 66 if (!table.ReadU16(&format) || format > 1) { |
| 69 return OTS_FAILURE_MSG("Failed to read name table format or bad format %d",
format); | 67 return OTS_FAILURE_MSG("Failed to read name table format or bad format %d",
format); |
| 70 } | 68 } |
| 71 | 69 |
| 72 uint16_t count = 0; | 70 uint16_t count = 0; |
| 73 if (!table.ReadU16(&count)) { | 71 if (!table.ReadU16(&count)) { |
| 74 return OTS_FAILURE_MSG("Failed to read name count"); | 72 return OTS_FAILURE_MSG("Failed to read name count"); |
| 75 } | 73 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 name_offset + name_length; | 132 name_offset + name_length; |
| 135 if (name_end > length) { | 133 if (name_end > length) { |
| 136 continue; | 134 continue; |
| 137 } | 135 } |
| 138 rec.text.resize(name_length); | 136 rec.text.resize(name_length); |
| 139 rec.text.assign(string_base + name_offset, name_length); | 137 rec.text.assign(string_base + name_offset, name_length); |
| 140 | 138 |
| 141 if (rec.name_id == 6) { | 139 if (rec.name_id == 6) { |
| 142 // PostScript name: check that it is valid, if not then discard it | 140 // PostScript name: check that it is valid, if not then discard it |
| 143 if (rec.platform_id == 1) { | 141 if (rec.platform_id == 1) { |
| 144 if (file->cff && !file->cff->name.empty()) { | 142 if (!CheckPsNameAscii(rec.text)) { |
| 145 rec.text = file->cff->name; | |
| 146 } else if (!CheckPsNameAscii(rec.text)) { | |
| 147 continue; | 143 continue; |
| 148 } | 144 } |
| 149 } else if (rec.platform_id == 0 || rec.platform_id == 3) { | 145 } else if (rec.platform_id == 0 || rec.platform_id == 3) { |
| 150 if (file->cff && !file->cff->name.empty()) { | 146 if (!CheckPsNameUtf16Be(rec.text)) { |
| 151 AssignToUtf16BeFromAscii(&rec.text, file->cff->name); | |
| 152 } else if (!CheckPsNameUtf16Be(rec.text)) { | |
| 153 continue; | 147 continue; |
| 154 } | 148 } |
| 155 } | 149 } |
| 156 } | 150 } |
| 157 | 151 |
| 158 if ((i > 0) && !(prev_record < rec)) { | 152 if ((i > 0) && !(prev_record < rec)) { |
| 159 OTS_WARNING("name records are not sorted."); | 153 OTS_WARNING("name records are not sorted."); |
| 160 sort_required = true; | 154 sort_required = true; |
| 161 } | 155 } |
| 162 | 156 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 static const uint16_t kStdNameCount = 7; | 197 static const uint16_t kStdNameCount = 7; |
| 204 static const char* kStdNames[kStdNameCount] = { | 198 static const char* kStdNames[kStdNameCount] = { |
| 205 NULL, | 199 NULL, |
| 206 "OTS derived font", | 200 "OTS derived font", |
| 207 "Unspecified", | 201 "Unspecified", |
| 208 NULL, | 202 NULL, |
| 209 "OTS derived font", | 203 "OTS derived font", |
| 210 "1.000", | 204 "1.000", |
| 211 "OTS-derived-font" | 205 "OTS-derived-font" |
| 212 }; | 206 }; |
| 213 // The spec says that "In CFF OpenType fonts, these two name strings, when | |
| 214 // translated to ASCII, must also be identical to the font name as stored in | |
| 215 // the CFF's Name INDEX." And actually, Mac OS X's font parser requires that. | |
| 216 if (file->cff && !file->cff->name.empty()) { | |
| 217 kStdNames[6] = file->cff->name.c_str(); | |
| 218 } | |
| 219 | 207 |
| 220 // scan the names to check whether the required "standard" ones are present; | 208 // scan the names to check whether the required "standard" ones are present; |
| 221 // if not, we'll add our fixed versions here | 209 // if not, we'll add our fixed versions here |
| 222 bool mac_name[kStdNameCount] = { 0 }; | 210 bool mac_name[kStdNameCount] = { 0 }; |
| 223 bool win_name[kStdNameCount] = { 0 }; | 211 bool win_name[kStdNameCount] = { 0 }; |
| 224 for (std::vector<NameRecord>::iterator name_iter = name->names.begin(); | 212 for (std::vector<NameRecord>::iterator name_iter = name->names.begin(); |
| 225 name_iter != name->names.end(); name_iter++) { | 213 name_iter != name->names.end(); name_iter++) { |
| 226 const uint16_t id = name_iter->name_id; | 214 const uint16_t id = name_iter->name_id; |
| 227 if (id >= kStdNameCount || kStdNames[id] == NULL) { | 215 if (id >= kStdNameCount || kStdNames[id] == NULL) { |
| 228 continue; | 216 continue; |
| 229 } | 217 } |
| 230 if (name_iter->platform_id == 1) { | 218 if (name_iter->platform_id == 1) { |
| 231 mac_name[id] = true; | 219 mac_name[id] = true; |
| 232 continue; | 220 continue; |
| 233 } | 221 } |
| 234 if (name_iter->platform_id == 3) { | 222 if (name_iter->platform_id == 3) { |
| 235 win_name[id] = true; | 223 win_name[id] = true; |
| 236 continue; | 224 continue; |
| 237 } | 225 } |
| 238 } | 226 } |
| 239 | 227 |
| 240 for (uint16_t i = 0; i < kStdNameCount; ++i) { | 228 for (uint16_t i = 0; i < kStdNameCount; ++i) { |
| 241 if (kStdNames[i] == NULL) { | 229 if (kStdNames[i] == NULL) { |
| 242 continue; | 230 continue; |
| 243 } | 231 } |
| 244 if (!mac_name[i]) { | 232 if (!mac_name[i] && !win_name[i]) { |
| 245 NameRecord rec(1 /* platform_id */, 0 /* encoding_id */, | 233 NameRecord mac_rec(1 /* platform_id */, 0 /* encoding_id */, |
| 246 0 /* language_id */ , i /* name_id */); | 234 0 /* language_id */ , i /* name_id */); |
| 247 rec.text.assign(kStdNames[i]); | 235 mac_rec.text.assign(kStdNames[i]); |
| 248 name->names.push_back(rec); | 236 |
| 249 sort_required = true; | 237 NameRecord win_rec(3 /* platform_id */, 1 /* encoding_id */, |
| 250 } | 238 1033 /* language_id */ , i /* name_id */); |
| 251 if (!win_name[i]) { | 239 AssignToUtf16BeFromAscii(&win_rec.text, std::string(kStdNames[i])); |
| 252 NameRecord rec(3 /* platform_id */, 1 /* encoding_id */, | 240 |
| 253 1033 /* language_id */ , i /* name_id */); | 241 name->names.push_back(mac_rec); |
| 254 AssignToUtf16BeFromAscii(&rec.text, std::string(kStdNames[i])); | 242 name->names.push_back(win_rec); |
| 255 name->names.push_back(rec); | |
| 256 sort_required = true; | 243 sort_required = true; |
| 257 } | 244 } |
| 258 } | 245 } |
| 259 | 246 |
| 260 if (sort_required) { | 247 if (sort_required) { |
| 261 std::sort(name->names.begin(), name->names.end()); | 248 std::sort(name->names.begin(), name->names.end()); |
| 262 } | 249 } |
| 263 | 250 |
| 264 return true; | 251 return true; |
| 265 } | 252 } |
| 266 | 253 |
| 267 bool ots_name_should_serialise(OpenTypeFile* file) { | 254 bool ots_name_should_serialise(Font *font) { |
| 268 return file->name != NULL; | 255 return font->name != NULL; |
| 269 } | 256 } |
| 270 | 257 |
| 271 bool ots_name_serialise(OTSStream* out, OpenTypeFile* file) { | 258 bool ots_name_serialise(OTSStream* out, Font *font) { |
| 272 const OpenTypeNAME* name = file->name; | 259 const OpenTypeNAME* name = font->name; |
| 273 | 260 |
| 274 uint16_t name_count = static_cast<uint16_t>(name->names.size()); | 261 uint16_t name_count = static_cast<uint16_t>(name->names.size()); |
| 275 uint16_t lang_tag_count = static_cast<uint16_t>(name->lang_tags.size()); | 262 uint16_t lang_tag_count = static_cast<uint16_t>(name->lang_tags.size()); |
| 276 uint16_t format = 0; | 263 uint16_t format = 0; |
| 277 size_t string_offset = 6 + name_count * 12; | 264 size_t string_offset = 6 + name_count * 12; |
| 278 | 265 |
| 279 if (name->lang_tags.size() > 0) { | 266 if (name->lang_tags.size() > 0) { |
| 280 // lang tags require a format-1 name table | 267 // lang tags require a format-1 name table |
| 281 format = 1; | 268 format = 1; |
| 282 string_offset += 2 + lang_tag_count * 4; | 269 string_offset += 2 + lang_tag_count * 4; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 } | 311 } |
| 325 } | 312 } |
| 326 | 313 |
| 327 if (!out->Write(string_data.data(), string_data.size())) { | 314 if (!out->Write(string_data.data(), string_data.size())) { |
| 328 return OTS_FAILURE_MSG("Faile to write string data"); | 315 return OTS_FAILURE_MSG("Faile to write string data"); |
| 329 } | 316 } |
| 330 | 317 |
| 331 return true; | 318 return true; |
| 332 } | 319 } |
| 333 | 320 |
| 334 void ots_name_free(OpenTypeFile* file) { | 321 void ots_name_reuse(Font *font, Font *other) { |
| 335 delete file->name; | 322 font->name = other->name; |
| 323 font->name_reused = true; |
| 324 } |
| 325 |
| 326 void ots_name_free(Font *font) { |
| 327 delete font->name; |
| 336 } | 328 } |
| 337 | 329 |
| 338 } // namespace | 330 } // namespace |
| 339 | 331 |
| 340 #undef TABLE_NAME | 332 #undef TABLE_NAME |
| OLD | NEW |