Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(639)

Side by Side Diff: third_party/ots/src/cmap.cc

Issue 1252363005: Update OTS to revision a7a3b94 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/ots/src/cff_type2_charstring.cc ('k') | third_party/ots/src/cvt.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 // 0xE0100-0xE01EF (240 code points) 54 // 0xE0100-0xE01EF (240 code points)
55 const uint32_t kMongolianVSStart = 0x180B; 55 const uint32_t kMongolianVSStart = 0x180B;
56 const uint32_t kMongolianVSEnd = 0x180D; 56 const uint32_t kMongolianVSEnd = 0x180D;
57 const uint32_t kVSStart = 0xFE00; 57 const uint32_t kVSStart = 0xFE00;
58 const uint32_t kVSEnd = 0xFE0F; 58 const uint32_t kVSEnd = 0xFE0F;
59 const uint32_t kIVSStart = 0xE0100; 59 const uint32_t kIVSStart = 0xE0100;
60 const uint32_t kIVSEnd = 0xE01EF; 60 const uint32_t kIVSEnd = 0xE01EF;
61 const uint32_t kUVSUpperLimit = 0xFFFFFF; 61 const uint32_t kUVSUpperLimit = 0xFFFFFF;
62 62
63 // Parses Format 4 tables 63 // Parses Format 4 tables
64 bool ParseFormat4(ots::OpenTypeFile *file, int platform, int encoding, 64 bool ParseFormat4(ots::Font *font, int platform, int encoding,
65 const uint8_t *data, size_t length, uint16_t num_glyphs) { 65 const uint8_t *data, size_t length, uint16_t num_glyphs) {
66 ots::Buffer subtable(data, length); 66 ots::Buffer subtable(data, length);
67 67
68 // 0.3.4, 3.0.4 or 3.1.4 subtables are complex and, rather than expanding the 68 // 0.3.4, 3.0.4 or 3.1.4 subtables are complex and, rather than expanding the
69 // whole thing and recompacting it, we validate it and include it verbatim 69 // whole thing and recompacting it, we validate it and include it verbatim
70 // in the output. 70 // in the output.
71 71
72 if (!file->os2) { 72 if (!font->os2) {
73 return OTS_FAILURE_MSG("Required OS/2 table missing"); 73 return OTS_FAILURE_MSG("Required OS/2 table missing");
74 } 74 }
75 75
76 if (!subtable.Skip(4)) { 76 if (!subtable.Skip(4)) {
77 return OTS_FAILURE_MSG("Can't read 4 bytes at start of cmap format 4 subtabl e"); 77 return OTS_FAILURE_MSG("Can't read 4 bytes at start of cmap format 4 subtabl e");
78 } 78 }
79 uint16_t language = 0; 79 uint16_t language = 0;
80 if (!subtable.ReadU16(&language)) { 80 if (!subtable.ReadU16(&language)) {
81 return OTS_FAILURE_MSG("Can't read language"); 81 return OTS_FAILURE_MSG("Can't read language");
82 } 82 }
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 // unsorted table... 188 // unsorted table...
189 if (ranges[i].end_range <= ranges[i - 1].end_range) { 189 if (ranges[i].end_range <= ranges[i - 1].end_range) {
190 return OTS_FAILURE_MSG("Out of order end range (%d <= %d)", ranges[i].end_ range, ranges[i-1].end_range); 190 return OTS_FAILURE_MSG("Out of order end range (%d <= %d)", ranges[i].end_ range, ranges[i-1].end_range);
191 } 191 }
192 if (ranges[i].start_range <= ranges[i - 1].end_range) { 192 if (ranges[i].start_range <= ranges[i - 1].end_range) {
193 return OTS_FAILURE_MSG("out of order start range (%d <= %d)", ranges[i].st art_range, ranges[i-1].end_range); 193 return OTS_FAILURE_MSG("out of order start range (%d <= %d)", ranges[i].st art_range, ranges[i-1].end_range);
194 } 194 }
195 195
196 // On many fonts, the value of {first, last}_char_index are incorrect. 196 // On many fonts, the value of {first, last}_char_index are incorrect.
197 // Fix them. 197 // Fix them.
198 if (file->os2->first_char_index != 0xFFFF && 198 if (font->os2->first_char_index != 0xFFFF &&
199 ranges[i].start_range != 0xFFFF && 199 ranges[i].start_range != 0xFFFF &&
200 file->os2->first_char_index > ranges[i].start_range) { 200 font->os2->first_char_index > ranges[i].start_range) {
201 file->os2->first_char_index = ranges[i].start_range; 201 font->os2->first_char_index = ranges[i].start_range;
202 } 202 }
203 if (file->os2->last_char_index != 0xFFFF && 203 if (font->os2->last_char_index != 0xFFFF &&
204 ranges[i].end_range != 0xFFFF && 204 ranges[i].end_range != 0xFFFF &&
205 file->os2->last_char_index < ranges[i].end_range) { 205 font->os2->last_char_index < ranges[i].end_range) {
206 file->os2->last_char_index = ranges[i].end_range; 206 font->os2->last_char_index = ranges[i].end_range;
207 } 207 }
208 } 208 }
209 209
210 // The last range must end at 0xffff 210 // The last range must end at 0xffff
211 if (ranges[segcount - 1].start_range != 0xffff || ranges[segcount - 1].end_ran ge != 0xffff) { 211 if (ranges[segcount - 1].start_range != 0xffff || ranges[segcount - 1].end_ran ge != 0xffff) {
212 return OTS_FAILURE_MSG("Final segment start and end must be 0xFFFF (0x%04X-0 x%04X)", 212 return OTS_FAILURE_MSG("Final segment start and end must be 0xFFFF (0x%04X-0 x%04X)",
213 ranges[segcount - 1].start_range, ranges[segcount - 1 ].end_range); 213 ranges[segcount - 1].start_range, ranges[segcount - 1 ].end_range);
214 } 214 }
215 215
216 // A format 4 CMAP subtable is complex. To be safe we simulate a lookup of 216 // A format 4 CMAP subtable is complex. To be safe we simulate a lookup of
(...skipping 25 matching lines...) Expand all
242 if (glyph >= num_glyphs) { 242 if (glyph >= num_glyphs) {
243 return OTS_FAILURE_MSG("Range glyph reference too high (%d > %d)", gly ph, num_glyphs - 1); 243 return OTS_FAILURE_MSG("Range glyph reference too high (%d > %d)", gly ph, num_glyphs - 1);
244 } 244 }
245 } 245 }
246 } 246 }
247 } 247 }
248 248
249 // We accept the table. 249 // We accept the table.
250 // TODO(yusukes): transcode the subtable. 250 // TODO(yusukes): transcode the subtable.
251 if (platform == 3 && encoding == 0) { 251 if (platform == 3 && encoding == 0) {
252 file->cmap->subtable_3_0_4_data = data; 252 font->cmap->subtable_3_0_4_data = data;
253 file->cmap->subtable_3_0_4_length = length; 253 font->cmap->subtable_3_0_4_length = length;
254 } else if (platform == 3 && encoding == 1) { 254 } else if (platform == 3 && encoding == 1) {
255 file->cmap->subtable_3_1_4_data = data; 255 font->cmap->subtable_3_1_4_data = data;
256 file->cmap->subtable_3_1_4_length = length; 256 font->cmap->subtable_3_1_4_length = length;
257 } else if (platform == 0 && encoding == 3) { 257 } else if (platform == 0 && encoding == 3) {
258 file->cmap->subtable_0_3_4_data = data; 258 font->cmap->subtable_0_3_4_data = data;
259 file->cmap->subtable_0_3_4_length = length; 259 font->cmap->subtable_0_3_4_length = length;
260 } else { 260 } else {
261 return OTS_FAILURE_MSG("Unknown cmap subtable type (platform=%d, encoding=%d )", platform, encoding); 261 return OTS_FAILURE_MSG("Unknown cmap subtable type (platform=%d, encoding=%d )", platform, encoding);
262 } 262 }
263 263
264 return true; 264 return true;
265 } 265 }
266 266
267 bool Parse31012(ots::OpenTypeFile *file, 267 bool Parse31012(ots::Font *font,
268 const uint8_t *data, size_t length, uint16_t num_glyphs) { 268 const uint8_t *data, size_t length, uint16_t num_glyphs) {
269 ots::Buffer subtable(data, length); 269 ots::Buffer subtable(data, length);
270 270
271 // Format 12 tables are simple. We parse these and fully serialise them 271 // Format 12 tables are simple. We parse these and fully serialise them
272 // later. 272 // later.
273 273
274 if (!subtable.Skip(8)) { 274 if (!subtable.Skip(8)) {
275 return OTS_FAILURE_MSG("failed to skip the first 8 bytes of format 12 subtab le"); 275 return OTS_FAILURE_MSG("failed to skip the first 8 bytes of format 12 subtab le");
276 } 276 }
277 uint32_t language = 0; 277 uint32_t language = 0;
278 if (!subtable.ReadU32(&language)) { 278 if (!subtable.ReadU32(&language)) {
279 return OTS_FAILURE_MSG("can't read format 12 subtable language"); 279 return OTS_FAILURE_MSG("can't read format 12 subtable language");
280 } 280 }
281 if (language) { 281 if (language) {
282 return OTS_FAILURE_MSG("format 12 subtable language should be zero (%d)", la nguage); 282 return OTS_FAILURE_MSG("format 12 subtable language should be zero (%d)", la nguage);
283 } 283 }
284 284
285 uint32_t num_groups = 0; 285 uint32_t num_groups = 0;
286 if (!subtable.ReadU32(&num_groups)) { 286 if (!subtable.ReadU32(&num_groups)) {
287 return OTS_FAILURE_MSG("can't read number of format 12 subtable groups"); 287 return OTS_FAILURE_MSG("can't read number of format 12 subtable groups");
288 } 288 }
289 if (num_groups == 0 || num_groups > kMaxCMAPGroups) { 289 if (num_groups == 0 || num_groups > kMaxCMAPGroups) {
290 return OTS_FAILURE_MSG("Bad format 12 subtable group count %d", num_groups); 290 return OTS_FAILURE_MSG("Bad format 12 subtable group count %d", num_groups);
291 } 291 }
292 292
293 std::vector<ots::OpenTypeCMAPSubtableRange> &groups 293 std::vector<ots::OpenTypeCMAPSubtableRange> &groups
294 = file->cmap->subtable_3_10_12; 294 = font->cmap->subtable_3_10_12;
295 groups.resize(num_groups); 295 groups.resize(num_groups);
296 296
297 for (unsigned i = 0; i < num_groups; ++i) { 297 for (unsigned i = 0; i < num_groups; ++i) {
298 if (!subtable.ReadU32(&groups[i].start_range) || 298 if (!subtable.ReadU32(&groups[i].start_range) ||
299 !subtable.ReadU32(&groups[i].end_range) || 299 !subtable.ReadU32(&groups[i].end_range) ||
300 !subtable.ReadU32(&groups[i].start_glyph_id)) { 300 !subtable.ReadU32(&groups[i].start_glyph_id)) {
301 return OTS_FAILURE_MSG("can't read format 12 subtable group"); 301 return OTS_FAILURE_MSG("can't read format 12 subtable group");
302 } 302 }
303 303
304 if (groups[i].start_range > kUnicodeUpperLimit || 304 if (groups[i].start_range > kUnicodeUpperLimit ||
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 } 343 }
344 if (groups[i].start_range <= groups[i - 1].end_range) { 344 if (groups[i].start_range <= groups[i - 1].end_range) {
345 return OTS_FAILURE_MSG("overlapping format 12 subtable groups (startCharCo de=0x%4X <= endCharCode=0x%4X of previous group)", 345 return OTS_FAILURE_MSG("overlapping format 12 subtable groups (startCharCo de=0x%4X <= endCharCode=0x%4X of previous group)",
346 groups[i].start_range, groups[i-1].end_range); 346 groups[i].start_range, groups[i-1].end_range);
347 } 347 }
348 } 348 }
349 349
350 return true; 350 return true;
351 } 351 }
352 352
353 bool Parse31013(ots::OpenTypeFile *file, 353 bool Parse31013(ots::Font *font,
354 const uint8_t *data, size_t length, uint16_t num_glyphs) { 354 const uint8_t *data, size_t length, uint16_t num_glyphs) {
355 ots::Buffer subtable(data, length); 355 ots::Buffer subtable(data, length);
356 356
357 // Format 13 tables are simple. We parse these and fully serialise them 357 // Format 13 tables are simple. We parse these and fully serialise them
358 // later. 358 // later.
359 359
360 if (!subtable.Skip(8)) { 360 if (!subtable.Skip(8)) {
361 return OTS_FAILURE_MSG("Bad cmap subtable length"); 361 return OTS_FAILURE_MSG("Bad cmap subtable length");
362 } 362 }
363 uint32_t language = 0; 363 uint32_t language = 0;
364 if (!subtable.ReadU32(&language)) { 364 if (!subtable.ReadU32(&language)) {
365 return OTS_FAILURE_MSG("Can't read cmap subtable language"); 365 return OTS_FAILURE_MSG("Can't read cmap subtable language");
366 } 366 }
367 if (language) { 367 if (language) {
368 return OTS_FAILURE_MSG("Cmap subtable language should be zero but is %d", la nguage); 368 return OTS_FAILURE_MSG("Cmap subtable language should be zero but is %d", la nguage);
369 } 369 }
370 370
371 uint32_t num_groups = 0; 371 uint32_t num_groups = 0;
372 if (!subtable.ReadU32(&num_groups)) { 372 if (!subtable.ReadU32(&num_groups)) {
373 return OTS_FAILURE_MSG("Can't read number of groups in a cmap subtable"); 373 return OTS_FAILURE_MSG("Can't read number of groups in a cmap subtable");
374 } 374 }
375 375
376 // We limit the number of groups in the same way as in 3.10.12 tables. See 376 // We limit the number of groups in the same way as in 3.10.12 tables. See
377 // the comment there in 377 // the comment there in
378 if (num_groups == 0 || num_groups > kMaxCMAPGroups) { 378 if (num_groups == 0 || num_groups > kMaxCMAPGroups) {
379 return OTS_FAILURE_MSG("Bad format 13 subtable group count %d", num_groups); 379 return OTS_FAILURE_MSG("Bad format 13 subtable group count %d", num_groups);
380 } 380 }
381 381
382 std::vector<ots::OpenTypeCMAPSubtableRange> &groups 382 std::vector<ots::OpenTypeCMAPSubtableRange> &groups
383 = file->cmap->subtable_3_10_13; 383 = font->cmap->subtable_3_10_13;
384 groups.resize(num_groups); 384 groups.resize(num_groups);
385 385
386 for (unsigned i = 0; i < num_groups; ++i) { 386 for (unsigned i = 0; i < num_groups; ++i) {
387 if (!subtable.ReadU32(&groups[i].start_range) || 387 if (!subtable.ReadU32(&groups[i].start_range) ||
388 !subtable.ReadU32(&groups[i].end_range) || 388 !subtable.ReadU32(&groups[i].end_range) ||
389 !subtable.ReadU32(&groups[i].start_glyph_id)) { 389 !subtable.ReadU32(&groups[i].start_glyph_id)) {
390 return OTS_FAILURE_MSG("Can't read subrange structure in a cmap subtable") ; 390 return OTS_FAILURE_MSG("Can't read subrange structure in a cmap subtable") ;
391 } 391 }
392 392
393 // We conservatively limit all of the values to protect some parsers from 393 // We conservatively limit all of the values to protect some parsers from
(...skipping 15 matching lines...) Expand all
409 return OTS_FAILURE_MSG("Overlapping subrange starts (%d >= %d)", groups[i] . start_range, groups[i-1].start_range); 409 return OTS_FAILURE_MSG("Overlapping subrange starts (%d >= %d)", groups[i] . start_range, groups[i-1].start_range);
410 } 410 }
411 if (groups[i].start_range <= groups[i - 1].end_range) { 411 if (groups[i].start_range <= groups[i - 1].end_range) {
412 return OTS_FAILURE_MSG("Overlapping subranges (%d <= %d)", groups[i].start _range, groups[i-1].end_range); 412 return OTS_FAILURE_MSG("Overlapping subranges (%d <= %d)", groups[i].start _range, groups[i-1].end_range);
413 } 413 }
414 } 414 }
415 415
416 return true; 416 return true;
417 } 417 }
418 418
419 bool Parse0514(ots::OpenTypeFile *file, 419 bool Parse0514(ots::Font *font,
420 const uint8_t *data, size_t length, uint16_t num_glyphs) { 420 const uint8_t *data, size_t length, uint16_t num_glyphs) {
421 // Unicode Variation Selector table 421 // Unicode Variation Selector table
422 ots::Buffer subtable(data, length); 422 ots::Buffer subtable(data, length);
423 423
424 // Format 14 tables are simple. We parse these and fully serialise them 424 // Format 14 tables are simple. We parse these and fully serialise them
425 // later. 425 // later.
426 426
427 // Skip format (USHORT) and length (ULONG) 427 // Skip format (USHORT) and length (ULONG)
428 if (!subtable.Skip(6)) { 428 if (!subtable.Skip(6)) {
429 return OTS_FAILURE_MSG("Can't read start of cmap subtable"); 429 return OTS_FAILURE_MSG("Can't read start of cmap subtable");
430 } 430 }
431 431
432 uint32_t num_records = 0; 432 uint32_t num_records = 0;
433 if (!subtable.ReadU32(&num_records)) { 433 if (!subtable.ReadU32(&num_records)) {
434 return OTS_FAILURE_MSG("Can't read number of records in cmap subtable"); 434 return OTS_FAILURE_MSG("Can't read number of records in cmap subtable");
435 } 435 }
436 if (num_records == 0 || num_records > kMaxCMAPSelectorRecords) { 436 if (num_records == 0 || num_records > kMaxCMAPSelectorRecords) {
437 return OTS_FAILURE_MSG("Bad format 14 subtable records count %d", num_record s); 437 return OTS_FAILURE_MSG("Bad format 14 subtable records count %d", num_record s);
438 } 438 }
439 439
440 std::vector<ots::OpenTypeCMAPSubtableVSRecord>& records 440 std::vector<ots::OpenTypeCMAPSubtableVSRecord>& records
441 = file->cmap->subtable_0_5_14; 441 = font->cmap->subtable_0_5_14;
442 records.resize(num_records); 442 records.resize(num_records);
443 443
444 for (unsigned i = 0; i < num_records; ++i) { 444 for (unsigned i = 0; i < num_records; ++i) {
445 if (!subtable.ReadU24(&records[i].var_selector) || 445 if (!subtable.ReadU24(&records[i].var_selector) ||
446 !subtable.ReadU32(&records[i].default_offset) || 446 !subtable.ReadU32(&records[i].default_offset) ||
447 !subtable.ReadU32(&records[i].non_default_offset)) { 447 !subtable.ReadU32(&records[i].non_default_offset)) {
448 return OTS_FAILURE_MSG("Can't read record structure of record %d in cmap s ubtale", i); 448 return OTS_FAILURE_MSG("Can't read record structure of record %d in cmap s ubtale", i);
449 } 449 }
450 // Checks the value of variation selector 450 // Checks the value of variation selector
451 if (!((records[i].var_selector >= kMongolianVSStart && 451 if (!((records[i].var_selector >= kMongolianVSStart &&
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 return OTS_FAILURE_MSG("Bad mapping (%04X -> %d) in mapping %d of vari ation selector %d", mappings[j].unicode_value, mappings[j].glyph_id, j, i); 539 return OTS_FAILURE_MSG("Bad mapping (%04X -> %d) in mapping %d of vari ation selector %d", mappings[j].unicode_value, mappings[j].glyph_id, j, i);
540 } 540 }
541 last_unicode_value = mappings[j].unicode_value; 541 last_unicode_value = mappings[j].unicode_value;
542 } 542 }
543 } 543 }
544 } 544 }
545 545
546 if (subtable.offset() != length) { 546 if (subtable.offset() != length) {
547 return OTS_FAILURE_MSG("Bad subtable offset (%ld != %ld)", subtable.offset() , length); 547 return OTS_FAILURE_MSG("Bad subtable offset (%ld != %ld)", subtable.offset() , length);
548 } 548 }
549 file->cmap->subtable_0_5_14_length = subtable.offset(); 549 font->cmap->subtable_0_5_14_length = subtable.offset();
550 return true; 550 return true;
551 } 551 }
552 552
553 bool Parse100(ots::OpenTypeFile *file, const uint8_t *data, size_t length) { 553 bool Parse100(ots::Font *font, const uint8_t *data, size_t length) {
554 // Mac Roman table 554 // Mac Roman table
555 ots::Buffer subtable(data, length); 555 ots::Buffer subtable(data, length);
556 556
557 if (!subtable.Skip(4)) { 557 if (!subtable.Skip(4)) {
558 return OTS_FAILURE_MSG("Bad cmap subtable"); 558 return OTS_FAILURE_MSG("Bad cmap subtable");
559 } 559 }
560 uint16_t language = 0; 560 uint16_t language = 0;
561 if (!subtable.ReadU16(&language)) { 561 if (!subtable.ReadU16(&language)) {
562 return OTS_FAILURE_MSG("Can't read language in cmap subtable"); 562 return OTS_FAILURE_MSG("Can't read language in cmap subtable");
563 } 563 }
564 if (language) { 564 if (language) {
565 // simsun.ttf has non-zero language id. 565 // simsun.ttf has non-zero language id.
566 OTS_WARNING("language id should be zero: %u", language); 566 OTS_WARNING("language id should be zero: %u", language);
567 } 567 }
568 568
569 file->cmap->subtable_1_0_0.reserve(kFormat0ArraySize); 569 font->cmap->subtable_1_0_0.reserve(kFormat0ArraySize);
570 for (size_t i = 0; i < kFormat0ArraySize; ++i) { 570 for (size_t i = 0; i < kFormat0ArraySize; ++i) {
571 uint8_t glyph_id = 0; 571 uint8_t glyph_id = 0;
572 if (!subtable.ReadU8(&glyph_id)) { 572 if (!subtable.ReadU8(&glyph_id)) {
573 return OTS_FAILURE_MSG("Can't read glyph id at array[%ld] in cmap subtable ", i); 573 return OTS_FAILURE_MSG("Can't read glyph id at array[%ld] in cmap subtable ", i);
574 } 574 }
575 file->cmap->subtable_1_0_0.push_back(glyph_id); 575 font->cmap->subtable_1_0_0.push_back(glyph_id);
576 } 576 }
577 577
578 return true; 578 return true;
579 } 579 }
580 580
581 } // namespace 581 } // namespace
582 582
583 namespace ots { 583 namespace ots {
584 584
585 bool ots_cmap_parse(OpenTypeFile *file, const uint8_t *data, size_t length) { 585 bool ots_cmap_parse(Font *font, const uint8_t *data, size_t length) {
586 Buffer table(data, length); 586 Buffer table(data, length);
587 file->cmap = new OpenTypeCMAP; 587 font->cmap = new OpenTypeCMAP;
588 588
589 uint16_t version = 0; 589 uint16_t version = 0;
590 uint16_t num_tables = 0; 590 uint16_t num_tables = 0;
591 if (!table.ReadU16(&version) || 591 if (!table.ReadU16(&version) ||
592 !table.ReadU16(&num_tables)) { 592 !table.ReadU16(&num_tables)) {
593 return OTS_FAILURE_MSG("Can't read structure of cmap"); 593 return OTS_FAILURE_MSG("Can't read structure of cmap");
594 } 594 }
595 595
596 if (version != 0) { 596 if (version != 0) {
597 return OTS_FAILURE_MSG("Non zero cmap version (%d)", version); 597 return OTS_FAILURE_MSG("Non zero cmap version (%d)", version);
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 int overlap_count = 0; 731 int overlap_count = 0;
732 for (unsigned i = 0; i < overlap_checker.size(); ++i) { 732 for (unsigned i = 0; i < overlap_checker.size(); ++i) {
733 overlap_count += (overlap_checker[i].second ? 1 : -1); 733 overlap_count += (overlap_checker[i].second ? 1 : -1);
734 if (overlap_count > 1) { 734 if (overlap_count > 1) {
735 return OTS_FAILURE_MSG("Excessive overlap count %d", overlap_count); 735 return OTS_FAILURE_MSG("Excessive overlap count %d", overlap_count);
736 } 736 }
737 } 737 }
738 738
739 // we grab the number of glyphs in the file from the maxp table to make sure 739 // we grab the number of glyphs in the file from the maxp table to make sure
740 // that the character map isn't referencing anything beyound this range. 740 // that the character map isn't referencing anything beyound this range.
741 if (!file->maxp) { 741 if (!font->maxp) {
742 return OTS_FAILURE_MSG("No maxp table in font! Needed by cmap."); 742 return OTS_FAILURE_MSG("No maxp table in font! Needed by cmap.");
743 } 743 }
744 const uint16_t num_glyphs = file->maxp->num_glyphs; 744 const uint16_t num_glyphs = font->maxp->num_glyphs;
745 745
746 // We only support a subset of the possible character map tables. Microsoft 746 // We only support a subset of the possible character map tables. Microsoft
747 // 'strongly recommends' that everyone supports the Unicode BMP table with 747 // 'strongly recommends' that everyone supports the Unicode BMP table with
748 // the UCS-4 table for non-BMP glyphs. We'll pass the following subtables: 748 // the UCS-4 table for non-BMP glyphs. We'll pass the following subtables:
749 // Platform ID Encoding ID Format 749 // Platform ID Encoding ID Format
750 // 0 0 4 (Unicode Default) 750 // 0 0 4 (Unicode Default)
751 // 0 1 4 (Unicode 1.1) 751 // 0 1 4 (Unicode 1.1)
752 // 0 3 4 (Unicode BMP) 752 // 0 3 4 (Unicode BMP)
753 // 0 3 12 (Unicode UCS-4) 753 // 0 3 12 (Unicode UCS-4)
754 // 0 5 14 (Unicode Variation Sequences) 754 // 0 5 14 (Unicode Variation Sequences)
(...skipping 16 matching lines...) Expand all
771 for (unsigned i = 0; i < num_tables; ++i) { 771 for (unsigned i = 0; i < num_tables; ++i) {
772 if (subtable_headers[i].platform == 0) { 772 if (subtable_headers[i].platform == 0) {
773 // Unicode platform 773 // Unicode platform
774 774
775 if ((subtable_headers[i].encoding == 0 || subtable_headers[i].encoding == 1) && 775 if ((subtable_headers[i].encoding == 0 || subtable_headers[i].encoding == 1) &&
776 (subtable_headers[i].format == 4)) { 776 (subtable_headers[i].format == 4)) {
777 // parse and output the 0-0-4 and 0-1-4 tables as 3-1-4 table. Sometimes the 0-0-4 777 // parse and output the 0-0-4 and 0-1-4 tables as 3-1-4 table. Sometimes the 0-0-4
778 // table actually points to MS symbol data and thus should be parsed as 778 // table actually points to MS symbol data and thus should be parsed as
779 // 3-0-4 table (e.g., marqueem.ttf and quixotic.ttf). This error will be 779 // 3-0-4 table (e.g., marqueem.ttf and quixotic.ttf). This error will be
780 // recovered in ots_cmap_serialise(). 780 // recovered in ots_cmap_serialise().
781 if (!ParseFormat4(file, 3, 1, data + subtable_headers[i].offset, 781 if (!ParseFormat4(font, 3, 1, data + subtable_headers[i].offset,
782 subtable_headers[i].length, num_glyphs)) { 782 subtable_headers[i].length, num_glyphs)) {
783 return OTS_FAILURE_MSG("Failed to parse format 4 cmap subtable %d", i) ; 783 return OTS_FAILURE_MSG("Failed to parse format 4 cmap subtable %d", i) ;
784 } 784 }
785 } else if ((subtable_headers[i].encoding == 3) && 785 } else if ((subtable_headers[i].encoding == 3) &&
786 (subtable_headers[i].format == 4)) { 786 (subtable_headers[i].format == 4)) {
787 // parse and output the 0-3-4 table as 0-3-4 table. 787 // parse and output the 0-3-4 table as 0-3-4 table.
788 if (!ParseFormat4(file, 0, 3, data + subtable_headers[i].offset, 788 if (!ParseFormat4(font, 0, 3, data + subtable_headers[i].offset,
789 subtable_headers[i].length, num_glyphs)) { 789 subtable_headers[i].length, num_glyphs)) {
790 return OTS_FAILURE_MSG("Failed to parse format 4 cmap subtable %d", i) ; 790 return OTS_FAILURE_MSG("Failed to parse format 4 cmap subtable %d", i) ;
791 } 791 }
792 } else if ((subtable_headers[i].encoding == 3) && 792 } else if ((subtable_headers[i].encoding == 3) &&
793 (subtable_headers[i].format == 12)) { 793 (subtable_headers[i].format == 12)) {
794 // parse and output the 0-3-12 table as 3-10-12 table. 794 // parse and output the 0-3-12 table as 3-10-12 table.
795 if (!Parse31012(file, data + subtable_headers[i].offset, 795 if (!Parse31012(font, data + subtable_headers[i].offset,
796 subtable_headers[i].length, num_glyphs)) { 796 subtable_headers[i].length, num_glyphs)) {
797 return OTS_FAILURE_MSG("Failed to parse format 12 cmap subtable %d", i ); 797 return OTS_FAILURE_MSG("Failed to parse format 12 cmap subtable %d", i );
798 } 798 }
799 } else if ((subtable_headers[i].encoding == 5) && 799 } else if ((subtable_headers[i].encoding == 5) &&
800 (subtable_headers[i].format == 14)) { 800 (subtable_headers[i].format == 14)) {
801 if (!Parse0514(file, data + subtable_headers[i].offset, 801 if (!Parse0514(font, data + subtable_headers[i].offset,
802 subtable_headers[i].length, num_glyphs)) { 802 subtable_headers[i].length, num_glyphs)) {
803 return OTS_FAILURE_MSG("Failed to parse format 14 cmap subtable %d", i ); 803 return OTS_FAILURE_MSG("Failed to parse format 14 cmap subtable %d", i );
804 } 804 }
805 } 805 }
806 } else if (subtable_headers[i].platform == 1) { 806 } else if (subtable_headers[i].platform == 1) {
807 // Mac platform 807 // Mac platform
808 808
809 if ((subtable_headers[i].encoding == 0) && 809 if ((subtable_headers[i].encoding == 0) &&
810 (subtable_headers[i].format == 0)) { 810 (subtable_headers[i].format == 0)) {
811 // parse and output the 1-0-0 table. 811 // parse and output the 1-0-0 table.
812 if (!Parse100(file, data + subtable_headers[i].offset, 812 if (!Parse100(font, data + subtable_headers[i].offset,
813 subtable_headers[i].length)) { 813 subtable_headers[i].length)) {
814 return OTS_FAILURE(); 814 return OTS_FAILURE();
815 } 815 }
816 } 816 }
817 } else if (subtable_headers[i].platform == 3) { 817 } else if (subtable_headers[i].platform == 3) {
818 // MS platform 818 // MS platform
819 819
820 switch (subtable_headers[i].encoding) { 820 switch (subtable_headers[i].encoding) {
821 case 0: 821 case 0:
822 case 1: 822 case 1:
823 if (subtable_headers[i].format == 4) { 823 if (subtable_headers[i].format == 4) {
824 // parse 3-0-4 or 3-1-4 table. 824 // parse 3-0-4 or 3-1-4 table.
825 if (!ParseFormat4(file, subtable_headers[i].platform, 825 if (!ParseFormat4(font, subtable_headers[i].platform,
826 subtable_headers[i].encoding, 826 subtable_headers[i].encoding,
827 data + subtable_headers[i].offset, 827 data + subtable_headers[i].offset,
828 subtable_headers[i].length, num_glyphs)) { 828 subtable_headers[i].length, num_glyphs)) {
829 return OTS_FAILURE(); 829 return OTS_FAILURE();
830 } 830 }
831 } 831 }
832 break; 832 break;
833 case 10: 833 case 10:
834 if (subtable_headers[i].format == 12) { 834 if (subtable_headers[i].format == 12) {
835 file->cmap->subtable_3_10_12.clear(); 835 font->cmap->subtable_3_10_12.clear();
836 if (!Parse31012(file, data + subtable_headers[i].offset, 836 if (!Parse31012(font, data + subtable_headers[i].offset,
837 subtable_headers[i].length, num_glyphs)) { 837 subtable_headers[i].length, num_glyphs)) {
838 return OTS_FAILURE(); 838 return OTS_FAILURE();
839 } 839 }
840 } else if (subtable_headers[i].format == 13) { 840 } else if (subtable_headers[i].format == 13) {
841 file->cmap->subtable_3_10_13.clear(); 841 font->cmap->subtable_3_10_13.clear();
842 if (!Parse31013(file, data + subtable_headers[i].offset, 842 if (!Parse31013(font, data + subtable_headers[i].offset,
843 subtable_headers[i].length, num_glyphs)) { 843 subtable_headers[i].length, num_glyphs)) {
844 return OTS_FAILURE(); 844 return OTS_FAILURE();
845 } 845 }
846 } 846 }
847 break; 847 break;
848 } 848 }
849 } 849 }
850 } 850 }
851 851
852 return true; 852 return true;
853 } 853 }
854 854
855 bool ots_cmap_should_serialise(OpenTypeFile *file) { 855 bool ots_cmap_should_serialise(Font *font) {
856 return file->cmap != NULL; 856 return font->cmap != NULL;
857 } 857 }
858 858
859 bool ots_cmap_serialise(OTSStream *out, OpenTypeFile *file) { 859 bool ots_cmap_serialise(OTSStream *out, Font *font) {
860 const bool have_034 = file->cmap->subtable_0_3_4_data != NULL; 860 const bool have_034 = font->cmap->subtable_0_3_4_data != NULL;
861 const bool have_0514 = file->cmap->subtable_0_5_14.size() != 0; 861 const bool have_0514 = font->cmap->subtable_0_5_14.size() != 0;
862 const bool have_100 = file->cmap->subtable_1_0_0.size() != 0; 862 const bool have_100 = font->cmap->subtable_1_0_0.size() != 0;
863 const bool have_304 = file->cmap->subtable_3_0_4_data != NULL; 863 const bool have_304 = font->cmap->subtable_3_0_4_data != NULL;
864 // MS Symbol and MS Unicode tables should not co-exist. 864 // MS Symbol and MS Unicode tables should not co-exist.
865 // See the comment above in 0-0-4 parser. 865 // See the comment above in 0-0-4 parser.
866 const bool have_314 = (!have_304) && file->cmap->subtable_3_1_4_data; 866 const bool have_314 = (!have_304) && font->cmap->subtable_3_1_4_data;
867 const bool have_31012 = file->cmap->subtable_3_10_12.size() != 0; 867 const bool have_31012 = font->cmap->subtable_3_10_12.size() != 0;
868 const bool have_31013 = file->cmap->subtable_3_10_13.size() != 0; 868 const bool have_31013 = font->cmap->subtable_3_10_13.size() != 0;
869 const uint16_t num_subtables = static_cast<uint16_t>(have_034) + 869 const uint16_t num_subtables = static_cast<uint16_t>(have_034) +
870 static_cast<uint16_t>(have_0514) + 870 static_cast<uint16_t>(have_0514) +
871 static_cast<uint16_t>(have_100) + 871 static_cast<uint16_t>(have_100) +
872 static_cast<uint16_t>(have_304) + 872 static_cast<uint16_t>(have_304) +
873 static_cast<uint16_t>(have_314) + 873 static_cast<uint16_t>(have_314) +
874 static_cast<uint16_t>(have_31012) + 874 static_cast<uint16_t>(have_31012) +
875 static_cast<uint16_t>(have_31013); 875 static_cast<uint16_t>(have_31013);
876 const off_t table_start = out->Tell(); 876 const off_t table_start = out->Tell();
877 877
878 // Some fonts don't have 3-0-4 MS Symbol nor 3-1-4 Unicode BMP tables 878 // Some fonts don't have 3-0-4 MS Symbol nor 3-1-4 Unicode BMP tables
879 // (e.g., old fonts for Mac). We don't support them. 879 // (e.g., old fonts for Mac). We don't support them.
880 if (!have_304 && !have_314 && !have_034 && !have_31012 && !have_31013) { 880 if (!have_304 && !have_314 && !have_034 && !have_31012 && !have_31013) {
881 return OTS_FAILURE_MSG("no supported subtables were found"); 881 return OTS_FAILURE_MSG("no supported subtables were found");
882 } 882 }
883 883
884 if (!out->WriteU16(0) || 884 if (!out->WriteU16(0) ||
885 !out->WriteU16(num_subtables)) { 885 !out->WriteU16(num_subtables)) {
886 return OTS_FAILURE(); 886 return OTS_FAILURE();
887 } 887 }
888 888
889 const off_t record_offset = out->Tell(); 889 const off_t record_offset = out->Tell();
890 if (!out->Pad(num_subtables * 8)) { 890 if (!out->Pad(num_subtables * 8)) {
891 return OTS_FAILURE(); 891 return OTS_FAILURE();
892 } 892 }
893 893
894 const off_t offset_034 = out->Tell(); 894 const off_t offset_034 = out->Tell();
895 if (have_034) { 895 if (have_034) {
896 if (!out->Write(file->cmap->subtable_0_3_4_data, 896 if (!out->Write(font->cmap->subtable_0_3_4_data,
897 file->cmap->subtable_0_3_4_length)) { 897 font->cmap->subtable_0_3_4_length)) {
898 return OTS_FAILURE(); 898 return OTS_FAILURE();
899 } 899 }
900 } 900 }
901 901
902 const off_t offset_0514 = out->Tell(); 902 const off_t offset_0514 = out->Tell();
903 if (have_0514) { 903 if (have_0514) {
904 const std::vector<ots::OpenTypeCMAPSubtableVSRecord> &records 904 const std::vector<ots::OpenTypeCMAPSubtableVSRecord> &records
905 = file->cmap->subtable_0_5_14; 905 = font->cmap->subtable_0_5_14;
906 const unsigned num_records = records.size(); 906 const unsigned num_records = records.size();
907 if (!out->WriteU16(14) || 907 if (!out->WriteU16(14) ||
908 !out->WriteU32(file->cmap->subtable_0_5_14_length) || 908 !out->WriteU32(font->cmap->subtable_0_5_14_length) ||
909 !out->WriteU32(num_records)) { 909 !out->WriteU32(num_records)) {
910 return OTS_FAILURE(); 910 return OTS_FAILURE();
911 } 911 }
912 for (unsigned i = 0; i < num_records; ++i) { 912 for (unsigned i = 0; i < num_records; ++i) {
913 if (!out->WriteU24(records[i].var_selector) || 913 if (!out->WriteU24(records[i].var_selector) ||
914 !out->WriteU32(records[i].default_offset) || 914 !out->WriteU32(records[i].default_offset) ||
915 !out->WriteU32(records[i].non_default_offset)) { 915 !out->WriteU32(records[i].non_default_offset)) {
916 return OTS_FAILURE(); 916 return OTS_FAILURE();
917 } 917 }
918 } 918 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 } 950 }
951 } 951 }
952 952
953 const off_t offset_100 = out->Tell(); 953 const off_t offset_100 = out->Tell();
954 if (have_100) { 954 if (have_100) {
955 if (!out->WriteU16(0) || // format 955 if (!out->WriteU16(0) || // format
956 !out->WriteU16(6 + kFormat0ArraySize) || // length 956 !out->WriteU16(6 + kFormat0ArraySize) || // length
957 !out->WriteU16(0)) { // language 957 !out->WriteU16(0)) { // language
958 return OTS_FAILURE(); 958 return OTS_FAILURE();
959 } 959 }
960 if (!out->Write(&(file->cmap->subtable_1_0_0[0]), kFormat0ArraySize)) { 960 if (!out->Write(&(font->cmap->subtable_1_0_0[0]), kFormat0ArraySize)) {
961 return OTS_FAILURE(); 961 return OTS_FAILURE();
962 } 962 }
963 } 963 }
964 964
965 const off_t offset_304 = out->Tell(); 965 const off_t offset_304 = out->Tell();
966 if (have_304) { 966 if (have_304) {
967 if (!out->Write(file->cmap->subtable_3_0_4_data, 967 if (!out->Write(font->cmap->subtable_3_0_4_data,
968 file->cmap->subtable_3_0_4_length)) { 968 font->cmap->subtable_3_0_4_length)) {
969 return OTS_FAILURE(); 969 return OTS_FAILURE();
970 } 970 }
971 } 971 }
972 972
973 const off_t offset_314 = out->Tell(); 973 const off_t offset_314 = out->Tell();
974 if (have_314) { 974 if (have_314) {
975 if (!out->Write(file->cmap->subtable_3_1_4_data, 975 if (!out->Write(font->cmap->subtable_3_1_4_data,
976 file->cmap->subtable_3_1_4_length)) { 976 font->cmap->subtable_3_1_4_length)) {
977 return OTS_FAILURE(); 977 return OTS_FAILURE();
978 } 978 }
979 } 979 }
980 980
981 const off_t offset_31012 = out->Tell(); 981 const off_t offset_31012 = out->Tell();
982 if (have_31012) { 982 if (have_31012) {
983 std::vector<OpenTypeCMAPSubtableRange> &groups 983 std::vector<OpenTypeCMAPSubtableRange> &groups
984 = file->cmap->subtable_3_10_12; 984 = font->cmap->subtable_3_10_12;
985 const unsigned num_groups = groups.size(); 985 const unsigned num_groups = groups.size();
986 if (!out->WriteU16(12) || 986 if (!out->WriteU16(12) ||
987 !out->WriteU16(0) || 987 !out->WriteU16(0) ||
988 !out->WriteU32(num_groups * 12 + 16) || 988 !out->WriteU32(num_groups * 12 + 16) ||
989 !out->WriteU32(0) || 989 !out->WriteU32(0) ||
990 !out->WriteU32(num_groups)) { 990 !out->WriteU32(num_groups)) {
991 return OTS_FAILURE(); 991 return OTS_FAILURE();
992 } 992 }
993 993
994 for (unsigned i = 0; i < num_groups; ++i) { 994 for (unsigned i = 0; i < num_groups; ++i) {
995 if (!out->WriteU32(groups[i].start_range) || 995 if (!out->WriteU32(groups[i].start_range) ||
996 !out->WriteU32(groups[i].end_range) || 996 !out->WriteU32(groups[i].end_range) ||
997 !out->WriteU32(groups[i].start_glyph_id)) { 997 !out->WriteU32(groups[i].start_glyph_id)) {
998 return OTS_FAILURE(); 998 return OTS_FAILURE();
999 } 999 }
1000 } 1000 }
1001 } 1001 }
1002 1002
1003 const off_t offset_31013 = out->Tell(); 1003 const off_t offset_31013 = out->Tell();
1004 if (have_31013) { 1004 if (have_31013) {
1005 std::vector<OpenTypeCMAPSubtableRange> &groups 1005 std::vector<OpenTypeCMAPSubtableRange> &groups
1006 = file->cmap->subtable_3_10_13; 1006 = font->cmap->subtable_3_10_13;
1007 const unsigned num_groups = groups.size(); 1007 const unsigned num_groups = groups.size();
1008 if (!out->WriteU16(13) || 1008 if (!out->WriteU16(13) ||
1009 !out->WriteU16(0) || 1009 !out->WriteU16(0) ||
1010 !out->WriteU32(num_groups * 12 + 16) || 1010 !out->WriteU32(num_groups * 12 + 16) ||
1011 !out->WriteU32(0) || 1011 !out->WriteU32(0) ||
1012 !out->WriteU32(num_groups)) { 1012 !out->WriteU32(num_groups)) {
1013 return OTS_FAILURE(); 1013 return OTS_FAILURE();
1014 } 1014 }
1015 1015
1016 for (unsigned i = 0; i < num_groups; ++i) { 1016 for (unsigned i = 0; i < num_groups; ++i) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 } 1085 }
1086 } 1086 }
1087 1087
1088 if (!out->Seek(table_end)) { 1088 if (!out->Seek(table_end)) {
1089 return OTS_FAILURE(); 1089 return OTS_FAILURE();
1090 } 1090 }
1091 1091
1092 return true; 1092 return true;
1093 } 1093 }
1094 1094
1095 void ots_cmap_free(OpenTypeFile *file) { 1095 void ots_cmap_reuse(Font *font, Font *other) {
1096 delete file->cmap; 1096 font->cmap = other->cmap;
1097 font->cmap_reused = true;
1098 }
1099
1100 void ots_cmap_free(Font *font) {
1101 delete font->cmap;
1097 } 1102 }
1098 1103
1099 } // namespace ots 1104 } // namespace ots
1100 1105
1101 #undef TABLE_NAME 1106 #undef TABLE_NAME
OLDNEW
« no previous file with comments | « third_party/ots/src/cff_type2_charstring.cc ('k') | third_party/ots/src/cvt.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698