| 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |