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 3// found in the LICENSE file. 4 5#include "cmap.h" 6 7#include <algorithm> 8#include <set> 9#include <utility> 10#include <vector> 11 12#include "maxp.h" 13#include "os2.h" 14 15// cmap - Character To Glyph Index Mapping Table 16// http://www.microsoft.com/opentype/otspec/cmap.htm 17 18namespace { 19 20struct CMAPSubtableHeader { 21 uint16_t platform; 22 uint16_t encoding; 23 uint32_t offset; 24 uint16_t format; 25 uint32_t length; 26}; 27 28struct Subtable314Range { 29 uint16_t start_range; 30 uint16_t end_range; 31 int16_t id_delta; 32 uint16_t id_range_offset; 33 uint32_t id_range_offset_offset; 34}; 35 36// The maximum number of groups in format 12, 13 or 14 subtables. 37// Note: 0xFFFF is the maximum number of glyphs in a single font file. 38const unsigned kMaxCMAPGroups = 0xFFFF; 39 40// Glyph array size for the Mac Roman (format 0) table. 41const size_t kFormat0ArraySize = 256; 42 43// The upper limit of the Unicode code point. 44const uint32_t kUnicodeUpperLimit = 0x10FFFF; 45 46// The maximum number of UVS records (See below). 47const uint32_t kMaxCMAPSelectorRecords = 259; 48// The range of UVSes are: 49// 0x180B-0x180D (3 code points) 50// 0xFE00-0xFE0F (16 code points) 51// 0xE0100-0xE01EF (240 code points) 52const uint32_t kMongolianVSStart = 0x180B; 53const uint32_t kMongolianVSEnd = 0x180D; 54const uint32_t kVSStart = 0xFE00; 55const uint32_t kVSEnd = 0xFE0F; 56const uint32_t kIVSStart = 0xE0100; 57const uint32_t kIVSEnd = 0xE01EF; 58const uint32_t kUVSUpperLimit = 0xFFFFFF; 59 60// Parses Format 4 tables 61bool ParseFormat4(ots::OpenTypeFile *file, int platform, int encoding, 62 const uint8_t *data, size_t length, uint16_t num_glyphs) { 63 ots::Buffer subtable(data, length); 64 65 // 0.3.4, 3.0.4 or 3.1.4 subtables are complex and, rather than expanding the 66 // whole thing and recompacting it, we validate it and include it verbatim 67 // in the output. 68 69 if (!file->os2) { 70 return OTS_FAILURE(); 71 } 72 73 if (!subtable.Skip(4)) { 74 return OTS_FAILURE(); 75 } 76 uint16_t language = 0; 77 if (!subtable.ReadU16(&language)) { 78 return OTS_FAILURE(); 79 } 80 if (language) { 81 // Platform ID 3 (windows) subtables should have language '0'. 82 return OTS_FAILURE(); 83 } 84 85 uint16_t segcountx2, search_range, entry_selector, range_shift; 86 segcountx2 = search_range = entry_selector = range_shift = 0; 87 if (!subtable.ReadU16(&segcountx2) || 88 !subtable.ReadU16(&search_range) || 89 !subtable.ReadU16(&entry_selector) || 90 !subtable.ReadU16(&range_shift)) { 91 return OTS_FAILURE(); 92 } 93 94 if (segcountx2 & 1 || search_range & 1) { 95 return OTS_FAILURE(); 96 } 97 const uint16_t segcount = segcountx2 >> 1; 98 // There must be at least one segment according the spec. 99 if (segcount < 1) { 100 return OTS_FAILURE(); 101 } 102 103 // log2segcount is the maximal x s.t. 2^x < segcount 104 unsigned log2segcount = 0; 105 while (1u << (log2segcount + 1) <= segcount) { 106 log2segcount++; 107 } 108 109 const uint16_t expected_search_range = 2 * 1u << log2segcount; 110 if (expected_search_range != search_range) { 111 return OTS_FAILURE(); 112 } 113 114 if (entry_selector != log2segcount) { 115 return OTS_FAILURE(); 116 } 117 118 const uint16_t expected_range_shift = segcountx2 - search_range; 119 if (range_shift != expected_range_shift) { 120 return OTS_FAILURE(); 121 } 122 123 std::vector<Subtable314Range> ranges(segcount); 124 125 for (unsigned i = 0; i < segcount; ++i) { 126 if (!subtable.ReadU16(&ranges[i].end_range)) { 127 return OTS_FAILURE(); 128 } 129 } 130 131 uint16_t padding; 132 if (!subtable.ReadU16(&padding)) { 133 return OTS_FAILURE(); 134 } 135 if (padding) { 136 return OTS_FAILURE(); 137 } 138 139 for (unsigned i = 0; i < segcount; ++i) { 140 if (!subtable.ReadU16(&ranges[i].start_range)) { 141 return OTS_FAILURE(); 142 } 143 } 144 for (unsigned i = 0; i < segcount; ++i) { 145 if (!subtable.ReadS16(&ranges[i].id_delta)) { 146 return OTS_FAILURE(); 147 } 148 } 149 for (unsigned i = 0; i < segcount; ++i) { 150 ranges[i].id_range_offset_offset = subtable.offset(); 151 if (!subtable.ReadU16(&ranges[i].id_range_offset)) { 152 return OTS_FAILURE(); 153 } 154 155 if (ranges[i].id_range_offset & 1) { 156 // Some font generators seem to put 65535 on id_range_offset 157 // for 0xFFFF-0xFFFF range. 158 // (e.g., many fonts in http://www.princexml.com/fonts/) 159 if (i == segcount - 1u) { 160 OTS_WARNING("bad id_range_offset"); 161 ranges[i].id_range_offset = 0; 162 // The id_range_offset value in the transcoded font will not change 163 // since this table is not actually "transcoded" yet. 164 } else { 165 return OTS_FAILURE(); 166 } 167 } 168 } 169 170 // ranges must be ascending order, based on the end_code. Ranges may not 171 // overlap. 172 for (unsigned i = 1; i < segcount; ++i) { 173 if ((i == segcount - 1u) && 174 (ranges[i - 1].start_range == 0xffff) && 175 (ranges[i - 1].end_range == 0xffff) && 176 (ranges[i].start_range == 0xffff) && 177 (ranges[i].end_range == 0xffff)) { 178 // Some fonts (e.g., Germania.ttf) have multiple 0xffff terminators. 179 // We'll accept them as an exception. 180 OTS_WARNING("multiple 0xffff terminators found"); 181 continue; 182 } 183 184 // Note: some Linux fonts (e.g., LucidaSansOblique.ttf, bsmi00lp.ttf) have 185 // unsorted table... 186 if (ranges[i].end_range <= ranges[i - 1].end_range) { 187 return OTS_FAILURE(); 188 } 189 if (ranges[i].start_range <= ranges[i - 1].end_range) { 190 return OTS_FAILURE(); 191 } 192 193 // On many fonts, the value of {first, last}_char_index are incorrect. 194 // Fix them. 195 if (file->os2->first_char_index != 0xFFFF && 196 ranges[i].start_range != 0xFFFF && 197 file->os2->first_char_index > ranges[i].start_range) { 198 file->os2->first_char_index = ranges[i].start_range; 199 } 200 if (file->os2->last_char_index != 0xFFFF && 201 ranges[i].end_range != 0xFFFF && 202 file->os2->last_char_index < ranges[i].end_range) { 203 file->os2->last_char_index = ranges[i].end_range; 204 } 205 } 206 207 // The last range must end at 0xffff 208 if (ranges[segcount - 1].end_range != 0xffff) { 209 return OTS_FAILURE(); 210 } 211 212 // A format 4 CMAP subtable is complex. To be safe we simulate a lookup of 213 // each code-point defined in the table and make sure that they are all valid 214 // glyphs and that we don't access anything out-of-bounds. 215 for (unsigned i = 0; i < segcount; ++i) { 216 for (unsigned cp = ranges[i].start_range; cp <= ranges[i].end_range; ++cp) { 217 const uint16_t code_point = cp; 218 if (ranges[i].id_range_offset == 0) { 219 // this is explictly allowed to overflow in the spec 220 const uint16_t glyph = code_point + ranges[i].id_delta; 221 if (glyph >= num_glyphs) { 222 return OTS_FAILURE(); 223 } 224 } else { 225 const uint16_t range_delta = code_point - ranges[i].start_range; 226 // this might seem odd, but it's true. The offset is relative to the 227 // location of the offset value itself. 228 const uint32_t glyph_id_offset = ranges[i].id_range_offset_offset + 229 ranges[i].id_range_offset + 230 range_delta * 2; 231 // We need to be able to access a 16-bit value from this offset 232 if (glyph_id_offset + 1 >= length) { 233 return OTS_FAILURE(); 234 } 235 uint16_t glyph; 236 std::memcpy(&glyph, data + glyph_id_offset, 2); 237 glyph = ntohs(glyph); 238 if (glyph >= num_glyphs) { 239 return OTS_FAILURE(); 240 } 241 } 242 } 243 } 244 245 // We accept the table. 246 // TODO(yusukes): transcode the subtable. 247 if (platform == 3 && encoding == 0) { 248 file->cmap->subtable_3_0_4_data = data; 249 file->cmap->subtable_3_0_4_length = length; 250 } else if (platform == 3 && encoding == 1) { 251 file->cmap->subtable_3_1_4_data = data; 252 file->cmap->subtable_3_1_4_length = length; 253 } else if (platform == 0 && encoding == 3) { 254 file->cmap->subtable_0_3_4_data = data; 255 file->cmap->subtable_0_3_4_length = length; 256 } else { 257 return OTS_FAILURE(); 258 } 259 260 return true; 261} 262 263bool Parse31012(ots::OpenTypeFile *file, 264 const uint8_t *data, size_t length, uint16_t num_glyphs) { 265 ots::Buffer subtable(data, length); 266 267 // Format 12 tables are simple. We parse these and fully serialise them 268 // later. 269 270 if (!subtable.Skip(8)) { 271 return OTS_FAILURE(); 272 } 273 uint32_t language = 0; 274 if (!subtable.ReadU32(&language)) { 275 return OTS_FAILURE(); 276 } 277 if (language) { 278 return OTS_FAILURE(); 279 } 280 281 uint32_t num_groups = 0; 282 if (!subtable.ReadU32(&num_groups)) { 283 return OTS_FAILURE(); 284 } 285 if (num_groups == 0 || num_groups > kMaxCMAPGroups) { 286 return OTS_FAILURE(); 287 } 288 289 std::vector<ots::OpenTypeCMAPSubtableRange> &groups 290 = file->cmap->subtable_3_10_12; 291 groups.resize(num_groups); 292 293 for (unsigned i = 0; i < num_groups; ++i) { 294 if (!subtable.ReadU32(&groups[i].start_range) || 295 !subtable.ReadU32(&groups[i].end_range) || 296 !subtable.ReadU32(&groups[i].start_glyph_id)) { 297 return OTS_FAILURE(); 298 } 299 300 if (groups[i].start_range > kUnicodeUpperLimit || 301 groups[i].end_range > kUnicodeUpperLimit || 302 groups[i].start_glyph_id > 0xFFFF) { 303 return OTS_FAILURE(); 304 } 305 306 // [0xD800, 0xDFFF] are surrogate code points. 307 if (groups[i].start_range >= 0xD800 && 308 groups[i].start_range <= 0xDFFF) { 309 return OTS_FAILURE(); 310 } 311 if (groups[i].end_range >= 0xD800 && 312 groups[i].end_range <= 0xDFFF) { 313 return OTS_FAILURE(); 314 } 315 if (groups[i].start_range < 0xD800 && 316 groups[i].end_range > 0xDFFF) { 317 return OTS_FAILURE(); 318 } 319 320 // We assert that the glyph value is within range. Because of the range 321 // limits, above, we don't need to worry about overflow. 322 if (groups[i].end_range < groups[i].start_range) { 323 return OTS_FAILURE(); 324 } 325 if ((groups[i].end_range - groups[i].start_range) + 326 groups[i].start_glyph_id > num_glyphs) { 327 return OTS_FAILURE(); 328 } 329 } 330 331 // the groups must be sorted by start code and may not overlap 332 for (unsigned i = 1; i < num_groups; ++i) { 333 if (groups[i].start_range <= groups[i - 1].start_range) { 334 return OTS_FAILURE(); 335 } 336 if (groups[i].start_range <= groups[i - 1].end_range) { 337 return OTS_FAILURE(); 338 } 339 } 340 341 return true; 342} 343 344bool Parse31013(ots::OpenTypeFile *file, 345 const uint8_t *data, size_t length, uint16_t num_glyphs) { 346 ots::Buffer subtable(data, length); 347 348 // Format 13 tables are simple. We parse these and fully serialise them 349 // later. 350 351 if (!subtable.Skip(8)) { 352 return OTS_FAILURE(); 353 } 354 uint16_t language = 0; 355 if (!subtable.ReadU16(&language)) { 356 return OTS_FAILURE(); 357 } 358 if (language) { 359 return OTS_FAILURE(); 360 } 361 362 uint32_t num_groups = 0; 363 if (!subtable.ReadU32(&num_groups)) { 364 return OTS_FAILURE(); 365 } 366 367 // We limit the number of groups in the same way as in 3.10.12 tables. See 368 // the comment there in 369 if (num_groups == 0 || num_groups > kMaxCMAPGroups) { 370 return OTS_FAILURE(); 371 } 372 373 std::vector<ots::OpenTypeCMAPSubtableRange> &groups 374 = file->cmap->subtable_3_10_13; 375 groups.resize(num_groups); 376 377 for (unsigned i = 0; i < num_groups; ++i) { 378 if (!subtable.ReadU32(&groups[i].start_range) || 379 !subtable.ReadU32(&groups[i].end_range) || 380 !subtable.ReadU32(&groups[i].start_glyph_id)) { 381 return OTS_FAILURE(); 382 } 383 384 // We conservatively limit all of the values to protect some parsers from 385 // overflows 386 if (groups[i].start_range > kUnicodeUpperLimit || 387 groups[i].end_range > kUnicodeUpperLimit || 388 groups[i].start_glyph_id > 0xFFFF) { 389 return OTS_FAILURE(); 390 } 391 392 if (groups[i].start_glyph_id >= num_glyphs) { 393 return OTS_FAILURE(); 394 } 395 } 396 397 // the groups must be sorted by start code and may not overlap 398 for (unsigned i = 1; i < num_groups; ++i) { 399 if (groups[i].start_range <= groups[i - 1].start_range) { 400 return OTS_FAILURE(); 401 } 402 if (groups[i].start_range <= groups[i - 1].end_range) { 403 return OTS_FAILURE(); 404 } 405 } 406 407 return true; 408} 409 410bool Parse0514(ots::OpenTypeFile *file, 411 const uint8_t *data, size_t length, uint16_t num_glyphs) { 412 // Unicode Variation Selector table 413 ots::Buffer subtable(data, length); 414 415 // Format 14 tables are simple. We parse these and fully serialise them 416 // later. 417 418 // Skip format (USHORT) and length (ULONG) 419 if (!subtable.Skip(6)) { 420 return OTS_FAILURE(); 421 } 422 423 uint32_t num_records = 0; 424 if (!subtable.ReadU32(&num_records)) { 425 return OTS_FAILURE(); 426 } 427 if (num_records == 0 || num_records > kMaxCMAPSelectorRecords) { 428 return OTS_FAILURE(); 429 } 430 431 std::vector<ots::OpenTypeCMAPSubtableVSRecord>& records 432 = file->cmap->subtable_0_5_14; 433 records.resize(num_records); 434 435 for (unsigned i = 0; i < num_records; ++i) { 436 if (!subtable.ReadU24(&records[i].var_selector) || 437 !subtable.ReadU32(&records[i].default_offset) || 438 !subtable.ReadU32(&records[i].non_default_offset)) { 439 return OTS_FAILURE(); 440 } 441 // Checks the value of variation selector 442 if (!((records[i].var_selector >= kMongolianVSStart && 443 records[i].var_selector <= kMongolianVSEnd) || 444 (records[i].var_selector >= kVSStart && 445 records[i].var_selector <= kVSEnd) || 446 (records[i].var_selector >= kIVSStart && 447 records[i].var_selector <= kIVSEnd))) { 448 return OTS_FAILURE(); 449 } 450 if (i > 0 && 451 records[i-1].var_selector >= records[i].var_selector) { 452 return OTS_FAILURE(); 453 } 454 455 // Checks offsets 456 if (!records[i].default_offset && !records[i].non_default_offset) { 457 return OTS_FAILURE(); 458 } 459 if (records[i].default_offset && 460 records[i].default_offset >= length) { 461 return OTS_FAILURE(); 462 } 463 if (records[i].non_default_offset && 464 records[i].non_default_offset >= length) { 465 return OTS_FAILURE(); 466 } 467 } 468 469 for (unsigned i = 0; i < num_records; ++i) { 470 // Checks default UVS table 471 if (records[i].default_offset) { 472 subtable.set_offset(records[i].default_offset); 473 uint32_t num_ranges = 0; 474 if (!subtable.ReadU32(&num_ranges)) { 475 return OTS_FAILURE(); 476 } 477 if (!num_ranges || num_ranges > kMaxCMAPGroups) { 478 return OTS_FAILURE(); 479 } 480 481 uint32_t last_unicode_value = 0; 482 std::vector<ots::OpenTypeCMAPSubtableVSRange>& ranges 483 = records[i].ranges; 484 ranges.resize(num_ranges); 485 486 for (unsigned j = 0; j < num_ranges; ++j) { 487 if (!subtable.ReadU24(&ranges[j].unicode_value) || 488 !subtable.ReadU8(&ranges[j].additional_count)) { 489 return OTS_FAILURE(); 490 } 491 const uint32_t check_value = 492 ranges[j].unicode_value + ranges[j].additional_count; 493 if (ranges[j].unicode_value == 0 || 494 ranges[j].unicode_value > kUnicodeUpperLimit || 495 check_value > kUVSUpperLimit || 496 (last_unicode_value && 497 ranges[j].unicode_value <= last_unicode_value)) { 498 return OTS_FAILURE(); 499 } 500 last_unicode_value = check_value; 501 } 502 } 503 504 // Checks non default UVS table 505 if (records[i].non_default_offset) { 506 subtable.set_offset(records[i].non_default_offset); 507 uint32_t num_mappings = 0; 508 if (!subtable.ReadU32(&num_mappings)) { 509 return OTS_FAILURE(); 510 } 511 if (!num_mappings || num_mappings > kMaxCMAPGroups) { 512 return OTS_FAILURE(); 513 } 514 515 uint32_t last_unicode_value = 0; 516 std::vector<ots::OpenTypeCMAPSubtableVSMapping>& mappings 517 = records[i].mappings; 518 mappings.resize(num_mappings); 519 520 for (unsigned j = 0; j < num_mappings; ++j) { 521 if (!subtable.ReadU24(&mappings[j].unicode_value) || 522 !subtable.ReadU16(&mappings[j].glyph_id)) { 523 return OTS_FAILURE(); 524 } 525 if (mappings[j].glyph_id == 0 || 526 mappings[j].unicode_value == 0 || 527 mappings[j].unicode_value > kUnicodeUpperLimit || 528 (last_unicode_value && 529 mappings[j].unicode_value <= last_unicode_value)) { 530 return OTS_FAILURE(); 531 } 532 last_unicode_value = mappings[j].unicode_value; 533 } 534 } 535 } 536 537 if (subtable.offset() != length) { 538 return OTS_FAILURE(); 539 } 540 file->cmap->subtable_0_5_14_length = subtable.offset(); 541 return true; 542} 543 544bool Parse100(ots::OpenTypeFile *file, const uint8_t *data, size_t length) { 545 // Mac Roman table 546 ots::Buffer subtable(data, length); 547 548 if (!subtable.Skip(4)) { 549 return OTS_FAILURE(); 550 } 551 uint16_t language = 0; 552 if (!subtable.ReadU16(&language)) { 553 return OTS_FAILURE(); 554 } 555 if (language) { 556 // simsun.ttf has non-zero language id. 557 OTS_WARNING("language id should be zero: %u", language); 558 } 559 560 file->cmap->subtable_1_0_0.reserve(kFormat0ArraySize); 561 for (size_t i = 0; i < kFormat0ArraySize; ++i) { 562 uint8_t glyph_id = 0; 563 if (!subtable.ReadU8(&glyph_id)) { 564 return OTS_FAILURE(); 565 } 566 file->cmap->subtable_1_0_0.push_back(glyph_id); 567 } 568 569 return true; 570} 571 572} // namespace 573 574namespace ots { 575 576bool ots_cmap_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { 577 Buffer table(data, length); 578 file->cmap = new OpenTypeCMAP; 579 580 uint16_t version = 0; 581 uint16_t num_tables = 0; 582 if (!table.ReadU16(&version) || 583 !table.ReadU16(&num_tables)) { 584 return OTS_FAILURE(); 585 } 586 587 if (version != 0) { 588 return OTS_FAILURE(); 589 } 590 if (!num_tables) { 591 return OTS_FAILURE(); 592 } 593 594 std::vector<CMAPSubtableHeader> subtable_headers; 595 596 // read the subtable headers 597 subtable_headers.reserve(num_tables); 598 for (unsigned i = 0; i < num_tables; ++i) { 599 CMAPSubtableHeader subt; 600 601 if (!table.ReadU16(&subt.platform) || 602 !table.ReadU16(&subt.encoding) || 603 !table.ReadU32(&subt.offset)) { 604 return OTS_FAILURE(); 605 } 606 607 subtable_headers.push_back(subt); 608 } 609 610 const size_t data_offset = table.offset(); 611 612 // make sure that all the offsets are valid. 613 uint32_t last_id = 0; 614 for (unsigned i = 0; i < num_tables; ++i) { 615 if (subtable_headers[i].offset > 1024 * 1024 * 1024) { 616 return OTS_FAILURE(); 617 } 618 if (subtable_headers[i].offset < data_offset || 619 subtable_headers[i].offset >= length) { 620 return OTS_FAILURE(); 621 } 622 623 // check if the table is sorted first by platform ID, then by encoding ID. 624 uint32_t current_id 625 = (subtable_headers[i].platform << 16) + subtable_headers[i].encoding; 626 if ((i != 0) && (last_id >= current_id)) { 627 return OTS_FAILURE(); 628 } 629 last_id = current_id; 630 } 631 632 // the format of the table is the first couple of bytes in the table. The 633 // length of the table is stored in a format-specific way. 634 for (unsigned i = 0; i < num_tables; ++i) { 635 table.set_offset(subtable_headers[i].offset); 636 if (!table.ReadU16(&subtable_headers[i].format)) { 637 return OTS_FAILURE(); 638 } 639 640 uint16_t len = 0; 641 switch (subtable_headers[i].format) { 642 case 0: 643 case 4: 644 if (!table.ReadU16(&len)) { 645 return OTS_FAILURE(); 646 } 647 subtable_headers[i].length = len; 648 break; 649 case 12: 650 case 13: 651 if (!table.Skip(2)) { 652 return OTS_FAILURE(); 653 } 654 if (!table.ReadU32(&subtable_headers[i].length)) { 655 return OTS_FAILURE(); 656 } 657 break; 658 case 14: 659 if (!table.ReadU32(&subtable_headers[i].length)) { 660 return OTS_FAILURE(); 661 } 662 break; 663 default: 664 subtable_headers[i].length = 0; 665 break; 666 } 667 } 668 669 // Now, verify that all the lengths are sane 670 for (unsigned i = 0; i < num_tables; ++i) { 671 if (!subtable_headers[i].length) continue; 672 if (subtable_headers[i].length > 1024 * 1024 * 1024) { 673 return OTS_FAILURE(); 674 } 675 // We know that both the offset and length are < 1GB, so the following 676 // addition doesn't overflow 677 const uint32_t end_byte 678 = subtable_headers[i].offset + subtable_headers[i].length; 679 if (end_byte > length) { 680 return OTS_FAILURE(); 681 } 682 } 683 684 // check that the cmap subtables are not overlapping. 685 std::set<std::pair<uint32_t, uint32_t> > uniq_checker; 686 std::vector<std::pair<uint32_t, uint8_t> > overlap_checker; 687 for (unsigned i = 0; i < num_tables; ++i) { 688 const uint32_t end_byte 689 = subtable_headers[i].offset + subtable_headers[i].length; 690 691 if (!uniq_checker.insert(std::make_pair(subtable_headers[i].offset, 692 end_byte)).second) { 693 // Sometimes Unicode table and MS table share exactly the same data. 694 // We'll allow this. 695 continue; 696 } 697 overlap_checker.push_back( 698 std::make_pair(subtable_headers[i].offset, 699 static_cast<uint8_t>(1) /* start */)); 700 overlap_checker.push_back( 701 std::make_pair(end_byte, static_cast<uint8_t>(0) /* end */)); 702 } 703 std::sort(overlap_checker.begin(), overlap_checker.end()); 704 int overlap_count = 0; 705 for (unsigned i = 0; i < overlap_checker.size(); ++i) { 706 overlap_count += (overlap_checker[i].second ? 1 : -1); 707 if (overlap_count > 1) { 708 return OTS_FAILURE(); 709 } 710 } 711 712 // we grab the number of glyphs in the file from the maxp table to make sure 713 // that the character map isn't referencing anything beyound this range. 714 if (!file->maxp) { 715 return OTS_FAILURE(); 716 } 717 const uint16_t num_glyphs = file->maxp->num_glyphs; 718 719 // We only support a subset of the possible character map tables. Microsoft 720 // 'strongly recommends' that everyone supports the Unicode BMP table with 721 // the UCS-4 table for non-BMP glyphs. We'll pass the following subtables: 722 // Platform ID Encoding ID Format 723 // 0 0 4 (Unicode Default) 724 // 0 3 4 (Unicode BMP) 725 // 0 3 12 (Unicode UCS-4) 726 // 0 5 14 (Unicode Variation Sequences) 727 // 1 0 0 (Mac Roman) 728 // 3 0 4 (MS Symbol) 729 // 3 1 4 (MS Unicode BMP) 730 // 3 10 12 (MS Unicode UCS-4) 731 // 3 10 13 (MS UCS-4 Fallback mapping) 732 // 733 // Note: 734 // * 0-0-4 table is (usually) written as a 3-1-4 table. If 3-1-4 table 735 // also exists, the 0-0-4 table is ignored. 736 // * Unlike 0-0-4 table, 0-3-4 table is written as a 0-3-4 table. 737 // Some fonts which include 0-5-14 table seems to be required 0-3-4 738 // table. The 0-3-4 table will be wriiten even if 3-1-4 table also exists. 739 // * 0-3-12 table is written as a 3-10-12 table. If 3-10-12 table also 740 // exists, the 0-3-12 table is ignored. 741 // 742 743 for (unsigned i = 0; i < num_tables; ++i) { 744 if (subtable_headers[i].platform == 0) { 745 // Unicode platform 746 747 if ((subtable_headers[i].encoding == 0) && 748 (subtable_headers[i].format == 4)) { 749 // parse and output the 0-0-4 table as 3-1-4 table. Sometimes the 0-0-4 750 // table actually points to MS symbol data and thus should be parsed as 751 // 3-0-4 table (e.g., marqueem.ttf and quixotic.ttf). This error will be 752 // recovered in ots_cmap_serialise(). 753 if (!ParseFormat4(file, 3, 1, data + subtable_headers[i].offset, 754 subtable_headers[i].length, num_glyphs)) { 755 return OTS_FAILURE(); 756 } 757 } else if ((subtable_headers[i].encoding == 3) && 758 (subtable_headers[i].format == 4)) { 759 // parse and output the 0-3-4 table as 0-3-4 table. 760 if (!ParseFormat4(file, 0, 3, data + subtable_headers[i].offset, 761 subtable_headers[i].length, num_glyphs)) { 762 return OTS_FAILURE(); 763 } 764 } else if ((subtable_headers[i].encoding == 3) && 765 (subtable_headers[i].format == 12)) { 766 // parse and output the 0-3-12 table as 3-10-12 table. 767 if (!Parse31012(file, data + subtable_headers[i].offset, 768 subtable_headers[i].length, num_glyphs)) { 769 return OTS_FAILURE(); 770 } 771 } else if ((subtable_headers[i].encoding == 5) && 772 (subtable_headers[i].format == 14)) { 773 if (!Parse0514(file, data + subtable_headers[i].offset, 774 subtable_headers[i].length, num_glyphs)) { 775 return OTS_FAILURE(); 776 } 777 } 778 } else if (subtable_headers[i].platform == 1) { 779 // Mac platform 780 781 if ((subtable_headers[i].encoding == 0) && 782 (subtable_headers[i].format == 0)) { 783 // parse and output the 1-0-0 table. 784 if (!Parse100(file, data + subtable_headers[i].offset, 785 subtable_headers[i].length)) { 786 return OTS_FAILURE(); 787 } 788 } 789 } else if (subtable_headers[i].platform == 3) { 790 // MS platform 791 792 switch (subtable_headers[i].encoding) { 793 case 0: 794 case 1: 795 if (subtable_headers[i].format == 4) { 796 // parse 3-0-4 or 3-1-4 table. 797 if (!ParseFormat4(file, subtable_headers[i].platform, 798 subtable_headers[i].encoding, 799 data + subtable_headers[i].offset, 800 subtable_headers[i].length, num_glyphs)) { 801 return OTS_FAILURE(); 802 } 803 } 804 break; 805 case 10: 806 if (subtable_headers[i].format == 12) { 807 file->cmap->subtable_3_10_12.clear(); 808 if (!Parse31012(file, data + subtable_headers[i].offset, 809 subtable_headers[i].length, num_glyphs)) { 810 return OTS_FAILURE(); 811 } 812 } else if (subtable_headers[i].format == 13) { 813 file->cmap->subtable_3_10_13.clear(); 814 if (!Parse31013(file, data + subtable_headers[i].offset, 815 subtable_headers[i].length, num_glyphs)) { 816 return OTS_FAILURE(); 817 } 818 } 819 break; 820 } 821 } 822 } 823 824 return true; 825} 826 827bool ots_cmap_should_serialise(OpenTypeFile *file) { 828 return file->cmap != NULL; 829} 830 831bool ots_cmap_serialise(OTSStream *out, OpenTypeFile *file) { 832 const bool have_034 = file->cmap->subtable_0_3_4_data != NULL; 833 const bool have_0514 = file->cmap->subtable_0_5_14.size() != 0; 834 const bool have_100 = file->cmap->subtable_1_0_0.size() != 0; 835 const bool have_304 = file->cmap->subtable_3_0_4_data != NULL; 836 // MS Symbol and MS Unicode tables should not co-exist. 837 // See the comment above in 0-0-4 parser. 838 const bool have_314 = (!have_304) && file->cmap->subtable_3_1_4_data; 839 const bool have_31012 = file->cmap->subtable_3_10_12.size() != 0; 840 const bool have_31013 = file->cmap->subtable_3_10_13.size() != 0; 841 const unsigned num_subtables = static_cast<unsigned>(have_034) + 842 static_cast<unsigned>(have_0514) + 843 static_cast<unsigned>(have_100) + 844 static_cast<unsigned>(have_304) + 845 static_cast<unsigned>(have_314) + 846 static_cast<unsigned>(have_31012) + 847 static_cast<unsigned>(have_31013); 848 const off_t table_start = out->Tell(); 849 850 // Some fonts don't have 3-0-4 MS Symbol nor 3-1-4 Unicode BMP tables 851 // (e.g., old fonts for Mac). We don't support them except for color bitmap 852 // fonts. 853 if (!have_304 && !have_314 && !have_034) { 854 if (!(file->cbdt && file->cblc)) { 855 return OTS_FAILURE(); 856 } 857 } 858 859 if (!out->WriteU16(0) || 860 !out->WriteU16(num_subtables)) { 861 return OTS_FAILURE(); 862 } 863 864 const off_t record_offset = out->Tell(); 865 if (!out->Pad(num_subtables * 8)) { 866 return OTS_FAILURE(); 867 } 868 869 const off_t offset_034 = out->Tell(); 870 if (have_034) { 871 if (!out->Write(file->cmap->subtable_0_3_4_data, 872 file->cmap->subtable_0_3_4_length)) { 873 return OTS_FAILURE(); 874 } 875 } 876 877 const off_t offset_0514 = out->Tell(); 878 if (have_0514) { 879 const std::vector<ots::OpenTypeCMAPSubtableVSRecord> &records 880 = file->cmap->subtable_0_5_14; 881 const unsigned num_records = records.size(); 882 if (!out->WriteU16(14) || 883 !out->WriteU32(file->cmap->subtable_0_5_14_length) || 884 !out->WriteU32(num_records)) { 885 return OTS_FAILURE(); 886 } 887 for (unsigned i = 0; i < num_records; ++i) { 888 if (!out->WriteU24(records[i].var_selector) || 889 !out->WriteU32(records[i].default_offset) || 890 !out->WriteU32(records[i].non_default_offset)) { 891 return OTS_FAILURE(); 892 } 893 } 894 for (unsigned i = 0; i < num_records; ++i) { 895 if (records[i].default_offset) { 896 const std::vector<ots::OpenTypeCMAPSubtableVSRange> &ranges 897 = records[i].ranges; 898 const unsigned num_ranges = ranges.size(); 899 if (!out->Seek(records[i].default_offset + offset_0514) || 900 !out->WriteU32(num_ranges)) { 901 return OTS_FAILURE(); 902 } 903 for (unsigned j = 0; j < num_ranges; ++j) { 904 if (!out->WriteU24(ranges[j].unicode_value) || 905 !out->WriteU8(ranges[j].additional_count)) { 906 return OTS_FAILURE(); 907 } 908 } 909 } 910 if (records[i].non_default_offset) { 911 const std::vector<ots::OpenTypeCMAPSubtableVSMapping> &mappings 912 = records[i].mappings; 913 const unsigned num_mappings = mappings.size(); 914 if (!out->Seek(records[i].non_default_offset + offset_0514) || 915 !out->WriteU32(num_mappings)) { 916 return OTS_FAILURE(); 917 } 918 for (unsigned j = 0; j < num_mappings; ++j) { 919 if (!out->WriteU24(mappings[j].unicode_value) || 920 !out->WriteU16(mappings[j].glyph_id)) { 921 return OTS_FAILURE(); 922 } 923 } 924 } 925 } 926 } 927 928 const off_t offset_100 = out->Tell(); 929 if (have_100) { 930 if (!out->WriteU16(0) || // format 931 !out->WriteU16(6 + kFormat0ArraySize) || // length 932 !out->WriteU16(0)) { // language 933 return OTS_FAILURE(); 934 } 935 if (!out->Write(&(file->cmap->subtable_1_0_0[0]), kFormat0ArraySize)) { 936 return OTS_FAILURE(); 937 } 938 } 939 940 const off_t offset_304 = out->Tell(); 941 if (have_304) { 942 if (!out->Write(file->cmap->subtable_3_0_4_data, 943 file->cmap->subtable_3_0_4_length)) { 944 return OTS_FAILURE(); 945 } 946 } 947 948 const off_t offset_314 = out->Tell(); 949 if (have_314) { 950 if (!out->Write(file->cmap->subtable_3_1_4_data, 951 file->cmap->subtable_3_1_4_length)) { 952 return OTS_FAILURE(); 953 } 954 } 955 956 const off_t offset_31012 = out->Tell(); 957 if (have_31012) { 958 std::vector<OpenTypeCMAPSubtableRange> &groups 959 = file->cmap->subtable_3_10_12; 960 const unsigned num_groups = groups.size(); 961 if (!out->WriteU16(12) || 962 !out->WriteU16(0) || 963 !out->WriteU32(num_groups * 12 + 16) || 964 !out->WriteU32(0) || 965 !out->WriteU32(num_groups)) { 966 return OTS_FAILURE(); 967 } 968 969 for (unsigned i = 0; i < num_groups; ++i) { 970 if (!out->WriteU32(groups[i].start_range) || 971 !out->WriteU32(groups[i].end_range) || 972 !out->WriteU32(groups[i].start_glyph_id)) { 973 return OTS_FAILURE(); 974 } 975 } 976 } 977 978 const off_t offset_31013 = out->Tell(); 979 if (have_31013) { 980 std::vector<OpenTypeCMAPSubtableRange> &groups 981 = file->cmap->subtable_3_10_13; 982 const unsigned num_groups = groups.size(); 983 if (!out->WriteU16(13) || 984 !out->WriteU16(0) || 985 !out->WriteU32(num_groups * 12 + 14) || 986 !out->WriteU32(0) || 987 !out->WriteU32(num_groups)) { 988 return OTS_FAILURE(); 989 } 990 991 for (unsigned i = 0; i < num_groups; ++i) { 992 if (!out->WriteU32(groups[i].start_range) || 993 !out->WriteU32(groups[i].end_range) || 994 !out->WriteU32(groups[i].start_glyph_id)) { 995 return OTS_FAILURE(); 996 } 997 } 998 } 999 1000 const off_t table_end = out->Tell(); 1001 // We might have hanging bytes from the above's checksum which the OTSStream 1002 // then merges into the table of offsets. 1003 OTSStream::ChecksumState saved_checksum = out->SaveChecksumState(); 1004 out->ResetChecksum(); 1005 1006 // Now seek back and write the table of offsets 1007 if (!out->Seek(record_offset)) { 1008 return OTS_FAILURE(); 1009 } 1010 1011 if (have_034) { 1012 if (!out->WriteU16(0) || 1013 !out->WriteU16(3) || 1014 !out->WriteU32(offset_034 - table_start)) { 1015 return OTS_FAILURE(); 1016 } 1017 } 1018 1019 if (have_0514) { 1020 if (!out->WriteU16(0) || 1021 !out->WriteU16(5) || 1022 !out->WriteU32(offset_0514 - table_start)) { 1023 return OTS_FAILURE(); 1024 } 1025 } 1026 1027 if (have_100) { 1028 if (!out->WriteU16(1) || 1029 !out->WriteU16(0) || 1030 !out->WriteU32(offset_100 - table_start)) { 1031 return OTS_FAILURE(); 1032 } 1033 } 1034 1035 if (have_304) { 1036 if (!out->WriteU16(3) || 1037 !out->WriteU16(0) || 1038 !out->WriteU32(offset_304 - table_start)) { 1039 return OTS_FAILURE(); 1040 } 1041 } 1042 1043 if (have_314) { 1044 if (!out->WriteU16(3) || 1045 !out->WriteU16(1) || 1046 !out->WriteU32(offset_314 - table_start)) { 1047 return OTS_FAILURE(); 1048 } 1049 } 1050 1051 if (have_31012) { 1052 if (!out->WriteU16(3) || 1053 !out->WriteU16(10) || 1054 !out->WriteU32(offset_31012 - table_start)) { 1055 return OTS_FAILURE(); 1056 } 1057 } 1058 1059 if (have_31013) { 1060 if (!out->WriteU16(3) || 1061 !out->WriteU16(10) || 1062 !out->WriteU32(offset_31013 - table_start)) { 1063 return OTS_FAILURE(); 1064 } 1065 } 1066 1067 if (!out->Seek(table_end)) { 1068 return OTS_FAILURE(); 1069 } 1070 out->RestoreChecksum(saved_checksum); 1071 1072 return true; 1073} 1074 1075void ots_cmap_free(OpenTypeFile *file) { 1076 delete file->cmap; 1077} 1078 1079} // namespace ots 1080