| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "cmap.h" | 5 #include "cmap.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 }; | 29 }; |
| 30 | 30 |
| 31 struct Subtable314Range { | 31 struct Subtable314Range { |
| 32 uint16_t start_range; | 32 uint16_t start_range; |
| 33 uint16_t end_range; | 33 uint16_t end_range; |
| 34 int16_t id_delta; | 34 int16_t id_delta; |
| 35 uint16_t id_range_offset; | 35 uint16_t id_range_offset; |
| 36 uint32_t id_range_offset_offset; | 36 uint32_t id_range_offset_offset; |
| 37 }; | 37 }; |
| 38 | 38 |
| 39 // The maximum number of groups in format 12, 13 or 14 subtables. | |
| 40 // Note: 0xFFFF is the maximum number of glyphs in a single font file. | |
| 41 const unsigned kMaxCMAPGroups = 0xFFFF; | |
| 42 | |
| 43 // Glyph array size for the Mac Roman (format 0) table. | 39 // Glyph array size for the Mac Roman (format 0) table. |
| 44 const size_t kFormat0ArraySize = 256; | 40 const size_t kFormat0ArraySize = 256; |
| 45 | 41 |
| 46 // The upper limit of the Unicode code point. | 42 // The upper limit of the Unicode code point. |
| 47 const uint32_t kUnicodeUpperLimit = 0x10FFFF; | 43 const uint32_t kUnicodeUpperLimit = 0x10FFFF; |
| 48 | 44 |
| 49 // The maximum number of UVS records (See below). | 45 // The maximum number of UVS records (See below). |
| 50 const uint32_t kMaxCMAPSelectorRecords = 259; | 46 const uint32_t kMaxCMAPSelectorRecords = 259; |
| 51 // The range of UVSes are: | 47 // The range of UVSes are: |
| 52 // 0x180B-0x180D (3 code points) | 48 // 0x180B-0x180D (3 code points) |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 return OTS_FAILURE_MSG("can't read format 12 subtable language"); | 275 return OTS_FAILURE_MSG("can't read format 12 subtable language"); |
| 280 } | 276 } |
| 281 if (language) { | 277 if (language) { |
| 282 return OTS_FAILURE_MSG("format 12 subtable language should be zero (%d)", la
nguage); | 278 return OTS_FAILURE_MSG("format 12 subtable language should be zero (%d)", la
nguage); |
| 283 } | 279 } |
| 284 | 280 |
| 285 uint32_t num_groups = 0; | 281 uint32_t num_groups = 0; |
| 286 if (!subtable.ReadU32(&num_groups)) { | 282 if (!subtable.ReadU32(&num_groups)) { |
| 287 return OTS_FAILURE_MSG("can't read number of format 12 subtable groups"); | 283 return OTS_FAILURE_MSG("can't read number of format 12 subtable groups"); |
| 288 } | 284 } |
| 289 if (num_groups == 0 || num_groups > kMaxCMAPGroups) { | 285 if (num_groups == 0 || subtable.remaining() < num_groups * 12) { |
| 290 return OTS_FAILURE_MSG("Bad format 12 subtable group count %d", num_groups); | 286 return OTS_FAILURE_MSG("Bad format 12 subtable group count %d", num_groups); |
| 291 } | 287 } |
| 292 | 288 |
| 293 std::vector<ots::OpenTypeCMAPSubtableRange> &groups | 289 std::vector<ots::OpenTypeCMAPSubtableRange> &groups |
| 294 = font->cmap->subtable_3_10_12; | 290 = font->cmap->subtable_3_10_12; |
| 295 groups.resize(num_groups); | 291 groups.resize(num_groups); |
| 296 | 292 |
| 297 for (unsigned i = 0; i < num_groups; ++i) { | 293 for (unsigned i = 0; i < num_groups; ++i) { |
| 298 if (!subtable.ReadU32(&groups[i].start_range) || | 294 if (!subtable.ReadU32(&groups[i].start_range) || |
| 299 !subtable.ReadU32(&groups[i].end_range) || | 295 !subtable.ReadU32(&groups[i].end_range) || |
| 300 !subtable.ReadU32(&groups[i].start_glyph_id)) { | 296 !subtable.ReadU32(&groups[i].start_glyph_id)) { |
| 301 return OTS_FAILURE_MSG("can't read format 12 subtable group"); | 297 return OTS_FAILURE_MSG("can't read format 12 subtable group"); |
| 302 } | 298 } |
| 303 | 299 |
| 304 if (groups[i].start_range > kUnicodeUpperLimit || | 300 if (groups[i].start_range > kUnicodeUpperLimit || |
| 305 groups[i].end_range > kUnicodeUpperLimit || | 301 groups[i].end_range > kUnicodeUpperLimit || |
| 306 groups[i].start_glyph_id > 0xFFFF) { | 302 groups[i].start_glyph_id > 0xFFFF) { |
| 307 return OTS_FAILURE_MSG("bad format 12 subtable group (startCharCode=0x%4X,
endCharCode=0x%4X, startGlyphID=%d)", | 303 return OTS_FAILURE_MSG("bad format 12 subtable group (startCharCode=0x%4X,
endCharCode=0x%4X, startGlyphID=%d)", |
| 308 groups[i].start_range, groups[i].end_range, groups[
i].start_glyph_id); | 304 groups[i].start_range, groups[i].end_range, groups[
i].start_glyph_id); |
| 309 } | 305 } |
| 310 | 306 |
| 311 // [0xD800, 0xDFFF] are surrogate code points. | |
| 312 if (groups[i].start_range >= 0xD800 && | |
| 313 groups[i].start_range <= 0xDFFF) { | |
| 314 return OTS_FAILURE_MSG("format 12 subtable out of range group startCharCod
e (0x%4X)", groups[i].start_range); | |
| 315 } | |
| 316 if (groups[i].end_range >= 0xD800 && | |
| 317 groups[i].end_range <= 0xDFFF) { | |
| 318 return OTS_FAILURE_MSG("format 12 subtable out of range group endCharCode
(0x%4X)", groups[i].end_range); | |
| 319 } | |
| 320 if (groups[i].start_range < 0xD800 && | |
| 321 groups[i].end_range > 0xDFFF) { | |
| 322 return OTS_FAILURE_MSG("bad format 12 subtable group startCharCode (0x%4X)
or endCharCode (0x%4X)", | |
| 323 groups[i].start_range, groups[i].end_range); | |
| 324 } | |
| 325 | |
| 326 // We assert that the glyph value is within range. Because of the range | 307 // We assert that the glyph value is within range. Because of the range |
| 327 // limits, above, we don't need to worry about overflow. | 308 // limits, above, we don't need to worry about overflow. |
| 328 if (groups[i].end_range < groups[i].start_range) { | 309 if (groups[i].end_range < groups[i].start_range) { |
| 329 return OTS_FAILURE_MSG("format 12 subtable group endCharCode before startC
harCode (0x%4X < 0x%4X)", | 310 return OTS_FAILURE_MSG("format 12 subtable group endCharCode before startC
harCode (0x%4X < 0x%4X)", |
| 330 groups[i].end_range, groups[i].start_range); | 311 groups[i].end_range, groups[i].start_range); |
| 331 } | 312 } |
| 332 if ((groups[i].end_range - groups[i].start_range) + | 313 if ((groups[i].end_range - groups[i].start_range) + |
| 333 groups[i].start_glyph_id > num_glyphs) { | 314 groups[i].start_glyph_id > num_glyphs) { |
| 334 return OTS_FAILURE_MSG("bad format 12 subtable group startGlyphID (%d)", g
roups[i].start_glyph_id); | 315 return OTS_FAILURE_MSG("bad format 12 subtable group startGlyphID (%d)", g
roups[i].start_glyph_id); |
| 335 } | 316 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 return OTS_FAILURE_MSG("Cmap subtable language should be zero but is %d", la
nguage); | 349 return OTS_FAILURE_MSG("Cmap subtable language should be zero but is %d", la
nguage); |
| 369 } | 350 } |
| 370 | 351 |
| 371 uint32_t num_groups = 0; | 352 uint32_t num_groups = 0; |
| 372 if (!subtable.ReadU32(&num_groups)) { | 353 if (!subtable.ReadU32(&num_groups)) { |
| 373 return OTS_FAILURE_MSG("Can't read number of groups in a cmap subtable"); | 354 return OTS_FAILURE_MSG("Can't read number of groups in a cmap subtable"); |
| 374 } | 355 } |
| 375 | 356 |
| 376 // We limit the number of groups in the same way as in 3.10.12 tables. See | 357 // We limit the number of groups in the same way as in 3.10.12 tables. See |
| 377 // the comment there in | 358 // the comment there in |
| 378 if (num_groups == 0 || num_groups > kMaxCMAPGroups) { | 359 if (num_groups == 0 || subtable.remaining() < num_groups * 12) { |
| 379 return OTS_FAILURE_MSG("Bad format 13 subtable group count %d", num_groups); | 360 return OTS_FAILURE_MSG("Bad format 13 subtable group count %d", num_groups); |
| 380 } | 361 } |
| 381 | 362 |
| 382 std::vector<ots::OpenTypeCMAPSubtableRange> &groups | 363 std::vector<ots::OpenTypeCMAPSubtableRange> &groups |
| 383 = font->cmap->subtable_3_10_13; | 364 = font->cmap->subtable_3_10_13; |
| 384 groups.resize(num_groups); | 365 groups.resize(num_groups); |
| 385 | 366 |
| 386 for (unsigned i = 0; i < num_groups; ++i) { | 367 for (unsigned i = 0; i < num_groups; ++i) { |
| 387 if (!subtable.ReadU32(&groups[i].start_range) || | 368 if (!subtable.ReadU32(&groups[i].start_range) || |
| 388 !subtable.ReadU32(&groups[i].end_range) || | 369 !subtable.ReadU32(&groups[i].end_range) || |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 } | 457 } |
| 477 | 458 |
| 478 for (unsigned i = 0; i < num_records; ++i) { | 459 for (unsigned i = 0; i < num_records; ++i) { |
| 479 // Checks default UVS table | 460 // Checks default UVS table |
| 480 if (records[i].default_offset) { | 461 if (records[i].default_offset) { |
| 481 subtable.set_offset(records[i].default_offset); | 462 subtable.set_offset(records[i].default_offset); |
| 482 uint32_t num_ranges = 0; | 463 uint32_t num_ranges = 0; |
| 483 if (!subtable.ReadU32(&num_ranges)) { | 464 if (!subtable.ReadU32(&num_ranges)) { |
| 484 return OTS_FAILURE_MSG("Can't read number of ranges in record %d", i); | 465 return OTS_FAILURE_MSG("Can't read number of ranges in record %d", i); |
| 485 } | 466 } |
| 486 if (num_ranges == 0 || num_ranges > kMaxCMAPGroups) { | 467 if (num_ranges == 0 || subtable.remaining() < num_ranges * 4) { |
| 487 return OTS_FAILURE_MSG("Bad number of ranges (%d) in record %d", num_ran
ges, i); | 468 return OTS_FAILURE_MSG("Bad number of ranges (%d) in record %d", num_ran
ges, i); |
| 488 } | 469 } |
| 489 | 470 |
| 490 uint32_t last_unicode_value = 0; | 471 uint32_t last_unicode_value = 0; |
| 491 std::vector<ots::OpenTypeCMAPSubtableVSRange>& ranges | 472 std::vector<ots::OpenTypeCMAPSubtableVSRange>& ranges |
| 492 = records[i].ranges; | 473 = records[i].ranges; |
| 493 ranges.resize(num_ranges); | 474 ranges.resize(num_ranges); |
| 494 | 475 |
| 495 for (unsigned j = 0; j < num_ranges; ++j) { | 476 for (unsigned j = 0; j < num_ranges; ++j) { |
| 496 if (!subtable.ReadU24(&ranges[j].unicode_value) || | 477 if (!subtable.ReadU24(&ranges[j].unicode_value) || |
| (...skipping 13 matching lines...) Expand all Loading... |
| 510 } | 491 } |
| 511 } | 492 } |
| 512 | 493 |
| 513 // Checks non default UVS table | 494 // Checks non default UVS table |
| 514 if (records[i].non_default_offset) { | 495 if (records[i].non_default_offset) { |
| 515 subtable.set_offset(records[i].non_default_offset); | 496 subtable.set_offset(records[i].non_default_offset); |
| 516 uint32_t num_mappings = 0; | 497 uint32_t num_mappings = 0; |
| 517 if (!subtable.ReadU32(&num_mappings)) { | 498 if (!subtable.ReadU32(&num_mappings)) { |
| 518 return OTS_FAILURE_MSG("Can't read number of mappings in variation selec
tor record %d", i); | 499 return OTS_FAILURE_MSG("Can't read number of mappings in variation selec
tor record %d", i); |
| 519 } | 500 } |
| 520 if (num_mappings == 0) { | 501 if (num_mappings == 0 || subtable.remaining() < num_mappings * 5) { |
| 521 return OTS_FAILURE_MSG("Bad number of mappings (%d) in variation selecto
r record %d", num_mappings, i); | 502 return OTS_FAILURE_MSG("Bad number of mappings (%d) in variation selecto
r record %d", num_mappings, i); |
| 522 } | 503 } |
| 523 | 504 |
| 524 uint32_t last_unicode_value = 0; | 505 uint32_t last_unicode_value = 0; |
| 525 std::vector<ots::OpenTypeCMAPSubtableVSMapping>& mappings | 506 std::vector<ots::OpenTypeCMAPSubtableVSMapping>& mappings |
| 526 = records[i].mappings; | 507 = records[i].mappings; |
| 527 mappings.resize(num_mappings); | 508 mappings.resize(num_mappings); |
| 528 | 509 |
| 529 for (unsigned j = 0; j < num_mappings; ++j) { | 510 for (unsigned j = 0; j < num_mappings; ++j) { |
| 530 if (!subtable.ReadU24(&mappings[j].unicode_value) || | 511 if (!subtable.ReadU24(&mappings[j].unicode_value) || |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1097 font->cmap_reused = true; | 1078 font->cmap_reused = true; |
| 1098 } | 1079 } |
| 1099 | 1080 |
| 1100 void ots_cmap_free(Font *font) { | 1081 void ots_cmap_free(Font *font) { |
| 1101 delete font->cmap; | 1082 delete font->cmap; |
| 1102 } | 1083 } |
| 1103 | 1084 |
| 1104 } // namespace ots | 1085 } // namespace ots |
| 1105 | 1086 |
| 1106 #undef TABLE_NAME | 1087 #undef TABLE_NAME |
| OLD | NEW |