| 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 "ots.h" | 5 #include "ots.h" |
| 6 | 6 |
| 7 #include <sys/types.h> | 7 #include <sys/types.h> |
| 8 #include <zlib.h> | 8 #include <zlib.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 } | 277 } |
| 278 | 278 |
| 279 uint32_t reported_total_sfnt_size; | 279 uint32_t reported_total_sfnt_size; |
| 280 if (!file.ReadU32(&reported_total_sfnt_size)) { | 280 if (!file.ReadU32(&reported_total_sfnt_size)) { |
| 281 return OTS_FAILURE_MSG_HDR("error reading total sfnt size"); | 281 return OTS_FAILURE_MSG_HDR("error reading total sfnt size"); |
| 282 } | 282 } |
| 283 | 283 |
| 284 // We don't care about these fields of the header: | 284 // We don't care about these fields of the header: |
| 285 // uint16_t major_version, minor_version | 285 // uint16_t major_version, minor_version |
| 286 if (!file.Skip(2 * 2)) { | 286 if (!file.Skip(2 * 2)) { |
| 287 return OTS_FAILURE_MSG_HDR("error skipping WOFF header fields"); | 287 return OTS_FAILURE_MSG_HDR("Failed to read 'majorVersion' or 'minorVersion'"
); |
| 288 } | 288 } |
| 289 | 289 |
| 290 // Checks metadata block size. | 290 // Checks metadata block size. |
| 291 uint32_t meta_offset; | 291 uint32_t meta_offset; |
| 292 uint32_t meta_length; | 292 uint32_t meta_length; |
| 293 uint32_t meta_length_orig; | 293 uint32_t meta_length_orig; |
| 294 if (!file.ReadU32(&meta_offset) || | 294 if (!file.ReadU32(&meta_offset) || |
| 295 !file.ReadU32(&meta_length) || | 295 !file.ReadU32(&meta_length) || |
| 296 !file.ReadU32(&meta_length_orig)) { | 296 !file.ReadU32(&meta_length_orig)) { |
| 297 return OTS_FAILURE_MSG_HDR("error reading WOFF header fields"); | 297 return OTS_FAILURE_MSG_HDR("Failed to read header metadata block fields"); |
| 298 } | 298 } |
| 299 if (meta_offset) { | 299 if (meta_offset) { |
| 300 if (meta_offset >= length || length - meta_offset < meta_length) { | 300 if (meta_offset >= length || length - meta_offset < meta_length) { |
| 301 return OTS_FAILURE_MSG_HDR("invalid metadata block location/size"); | 301 return OTS_FAILURE_MSG_HDR("Invalid metadata block offset or length"); |
| 302 } | 302 } |
| 303 } | 303 } |
| 304 | 304 |
| 305 // Checks private data block size. | 305 // Checks private data block size. |
| 306 uint32_t priv_offset; | 306 uint32_t priv_offset; |
| 307 uint32_t priv_length; | 307 uint32_t priv_length; |
| 308 if (!file.ReadU32(&priv_offset) || | 308 if (!file.ReadU32(&priv_offset) || |
| 309 !file.ReadU32(&priv_length)) { | 309 !file.ReadU32(&priv_length)) { |
| 310 return OTS_FAILURE_MSG_HDR("error reading WOFF header fields"); | 310 return OTS_FAILURE_MSG_HDR("Failed to read header private block fields"); |
| 311 } | 311 } |
| 312 if (priv_offset) { | 312 if (priv_offset) { |
| 313 if (priv_offset >= length || length - priv_offset < priv_length) { | 313 if (priv_offset >= length || length - priv_offset < priv_length) { |
| 314 return OTS_FAILURE_MSG_HDR("invalid private block location/size"); | 314 return OTS_FAILURE_MSG_HDR("Invalid private block offset or length"); |
| 315 } | 315 } |
| 316 } | 316 } |
| 317 | 317 |
| 318 // Next up is the list of tables. | 318 // Next up is the list of tables. |
| 319 std::vector<OpenTypeTable> tables; | 319 std::vector<OpenTypeTable> tables; |
| 320 | 320 |
| 321 uint32_t first_index = 0; | 321 uint32_t first_index = 0; |
| 322 uint32_t last_index = 0; | 322 uint32_t last_index = 0; |
| 323 // Size of sfnt header plus size of table records. | 323 // Size of sfnt header plus size of table records. |
| 324 uint64_t total_sfnt_size = 12 + 16 * header->num_tables; | 324 uint64_t total_sfnt_size = 12 + 16 * header->num_tables; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 // Blocks must follow immediately after the previous block. | 359 // Blocks must follow immediately after the previous block. |
| 360 // (Except for padding with a maximum of three null bytes) | 360 // (Except for padding with a maximum of three null bytes) |
| 361 uint64_t block_end = ots::Round4( | 361 uint64_t block_end = ots::Round4( |
| 362 static_cast<uint64_t>(tables[last_index].offset) + | 362 static_cast<uint64_t>(tables[last_index].offset) + |
| 363 static_cast<uint64_t>(tables[last_index].length)); | 363 static_cast<uint64_t>(tables[last_index].length)); |
| 364 if (block_end > std::numeric_limits<uint32_t>::max()) { | 364 if (block_end > std::numeric_limits<uint32_t>::max()) { |
| 365 return OTS_FAILURE_MSG_HDR("invalid table location/size"); | 365 return OTS_FAILURE_MSG_HDR("invalid table location/size"); |
| 366 } | 366 } |
| 367 if (meta_offset) { | 367 if (meta_offset) { |
| 368 if (block_end != meta_offset) { | 368 if (block_end != meta_offset) { |
| 369 return OTS_FAILURE_MSG_HDR("invalid metadata block location"); | 369 return OTS_FAILURE_MSG_HDR("Invalid metadata block offset"); |
| 370 } | 370 } |
| 371 block_end = ots::Round4(static_cast<uint64_t>(meta_offset) + | 371 block_end = ots::Round4(static_cast<uint64_t>(meta_offset) + |
| 372 static_cast<uint64_t>(meta_length)); | 372 static_cast<uint64_t>(meta_length)); |
| 373 if (block_end > std::numeric_limits<uint32_t>::max()) { | 373 if (block_end > std::numeric_limits<uint32_t>::max()) { |
| 374 return OTS_FAILURE_MSG_HDR("invalid metadata block size"); | 374 return OTS_FAILURE_MSG_HDR("Invalid metadata block length"); |
| 375 } | 375 } |
| 376 } | 376 } |
| 377 if (priv_offset) { | 377 if (priv_offset) { |
| 378 if (block_end != priv_offset) { | 378 if (block_end != priv_offset) { |
| 379 return OTS_FAILURE_MSG_HDR("invalid private block location"); | 379 return OTS_FAILURE_MSG_HDR("Invalid private block offset"); |
| 380 } | 380 } |
| 381 block_end = ots::Round4(static_cast<uint64_t>(priv_offset) + | 381 block_end = ots::Round4(static_cast<uint64_t>(priv_offset) + |
| 382 static_cast<uint64_t>(priv_length)); | 382 static_cast<uint64_t>(priv_length)); |
| 383 if (block_end > std::numeric_limits<uint32_t>::max()) { | 383 if (block_end > std::numeric_limits<uint32_t>::max()) { |
| 384 return OTS_FAILURE_MSG_HDR("invalid private block size"); | 384 return OTS_FAILURE_MSG_HDR("Invalid private block length"); |
| 385 } | 385 } |
| 386 } | 386 } |
| 387 if (block_end != ots::Round4(length)) { | 387 if (block_end != ots::Round4(length)) { |
| 388 return OTS_FAILURE_MSG_HDR("file length mismatch (trailing junk?)"); | 388 return OTS_FAILURE_MSG_HDR("File length mismatch (trailing junk?)"); |
| 389 } | 389 } |
| 390 | 390 |
| 391 return ProcessGeneric(header, woff_tag, output, data, length, tables, file); | 391 return ProcessGeneric(header, woff_tag, output, data, length, tables, file); |
| 392 } | 392 } |
| 393 | 393 |
| 394 bool ProcessWOFF2(ots::OpenTypeFile *header, | 394 bool ProcessWOFF2(ots::OpenTypeFile *header, |
| 395 ots::OTSStream *output, const uint8_t *data, size_t length) { | 395 ots::OTSStream *output, const uint8_t *data, size_t length) { |
| 396 size_t decompressed_size = ots::ComputeWOFF2FinalSize(data, length); | 396 size_t decompressed_size = ots::ComputeWOFF2FinalSize(data, length); |
| 397 if (decompressed_size == 0) { | 397 if (decompressed_size == 0) { |
| 398 return OTS_FAILURE(); | 398 return OTS_FAILURE_MSG_HDR("Size of decompressed WOFF 2.0 is set to 0"); |
| 399 } | 399 } |
| 400 // decompressed font must be <= 30MB | 400 // decompressed font must be <= 30MB |
| 401 if (decompressed_size > 30 * 1024 * 1024) { | 401 if (decompressed_size > 30 * 1024 * 1024) { |
| 402 return OTS_FAILURE(); | 402 return OTS_FAILURE_MSG_HDR("Size of decompressed WOFF 2.0 font exceeds 30MB"
); |
| 403 } | 403 } |
| 404 | 404 |
| 405 std::vector<uint8_t> decompressed_buffer(decompressed_size); | 405 std::vector<uint8_t> decompressed_buffer(decompressed_size); |
| 406 if (!ots::ConvertWOFF2ToTTF(header, &decompressed_buffer[0], decompressed_size
, | 406 if (!ots::ConvertWOFF2ToSFNT(header, &decompressed_buffer[0], decompressed_siz
e, |
| 407 data, length)) { | 407 data, length)) { |
| 408 return OTS_FAILURE(); | 408 return OTS_FAILURE_MSG_HDR("Failed to convert WOFF 2.0 font to SFNT"); |
| 409 } | 409 } |
| 410 return ProcessTTF(header, output, &decompressed_buffer[0], decompressed_size); | 410 return ProcessTTF(header, output, &decompressed_buffer[0], decompressed_size); |
| 411 } | 411 } |
| 412 | 412 |
| 413 ots::TableAction GetTableAction(ots::OpenTypeFile *header, uint32_t tag) { | 413 ots::TableAction GetTableAction(ots::OpenTypeFile *header, uint32_t tag) { |
| 414 ots::TableAction action = ots::TABLE_ACTION_DEFAULT; | 414 ots::TableAction action = ots::TABLE_ACTION_DEFAULT; |
| 415 | 415 |
| 416 action = header->context->GetTableAction(htonl(tag)); | 416 action = header->context->GetTableAction(htonl(tag)); |
| 417 | 417 |
| 418 if (action == ots::TABLE_ACTION_DEFAULT) { | 418 if (action == ots::TABLE_ACTION_DEFAULT) { |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 if (header->version != Tag("OTTO")) { | 592 if (header->version != Tag("OTTO")) { |
| 593 return OTS_FAILURE_MSG_HDR("wrong font version for PostScript glyph data")
; | 593 return OTS_FAILURE_MSG_HDR("wrong font version for PostScript glyph data")
; |
| 594 } | 594 } |
| 595 if (header->glyf || header->loca) { | 595 if (header->glyf || header->loca) { |
| 596 // mixing outline formats is not recommended | 596 // mixing outline formats is not recommended |
| 597 return OTS_FAILURE_MSG_HDR("font contains both PS and TT glyphs"); | 597 return OTS_FAILURE_MSG_HDR("font contains both PS and TT glyphs"); |
| 598 } | 598 } |
| 599 } else { | 599 } else { |
| 600 if (!header->glyf || !header->loca) { | 600 if (!header->glyf || !header->loca) { |
| 601 // No TrueType glyph found. | 601 // No TrueType glyph found. |
| 602 // Note: bitmap-only fonts are not supported. | 602 #define PASSTHRU_TABLE(TAG) (table_map.find(Tag(TAG)) != table_map.end() && \ |
| 603 return OTS_FAILURE_MSG_HDR("neither PS nor TT glyphs present"); | 603 GetTableAction(header, Tag(TAG)) == ots::TABLE_ACTI
ON_PASSTHRU) |
| 604 // We don't sanitise bitmap table, but don't reject bitmap-only fonts if |
| 605 // we keep the tables. |
| 606 if (!PASSTHRU_TABLE("CBDT") || !PASSTHRU_TABLE("CBLC")) { |
| 607 return OTS_FAILURE_MSG_HDR("no supported glyph shapes table(s) present")
; |
| 608 } |
| 609 #undef PASSTHRU_TABLE |
| 604 } | 610 } |
| 605 } | 611 } |
| 606 | 612 |
| 607 uint16_t num_output_tables = 0; | 613 uint16_t num_output_tables = 0; |
| 608 for (unsigned i = 0; ; ++i) { | 614 for (unsigned i = 0; ; ++i) { |
| 609 if (table_parsers[i].parse == NULL) { | 615 if (table_parsers[i].parse == NULL) { |
| 610 break; | 616 break; |
| 611 } | 617 } |
| 612 | 618 |
| 613 if (table_parsers[i].should_serialise(header)) { | 619 if (table_parsers[i].should_serialise(header)) { |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 return OTS_FAILURE_MSG_HDR("error writing output"); | 775 return OTS_FAILURE_MSG_HDR("error writing output"); |
| 770 } | 776 } |
| 771 | 777 |
| 772 return true; | 778 return true; |
| 773 } | 779 } |
| 774 | 780 |
| 775 } // namespace | 781 } // namespace |
| 776 | 782 |
| 777 namespace ots { | 783 namespace ots { |
| 778 | 784 |
| 779 void EnableWOFF2() { | |
| 780 } | |
| 781 | |
| 782 bool IsValidVersionTag(uint32_t tag) { | 785 bool IsValidVersionTag(uint32_t tag) { |
| 783 return tag == Tag("\x00\x01\x00\x00") || | 786 return tag == Tag("\x00\x01\x00\x00") || |
| 784 // OpenType fonts with CFF data have 'OTTO' tag. | 787 // OpenType fonts with CFF data have 'OTTO' tag. |
| 785 tag == Tag("OTTO") || | 788 tag == Tag("OTTO") || |
| 786 // Older Mac fonts might have 'true' or 'typ1' tag. | 789 // Older Mac fonts might have 'true' or 'typ1' tag. |
| 787 tag == Tag("true") || | 790 tag == Tag("true") || |
| 788 tag == Tag("typ1"); | 791 tag == Tag("typ1"); |
| 789 } | 792 } |
| 790 | 793 |
| 791 bool OTSContext::Process(OTSStream *output, | 794 bool OTSContext::Process(OTSStream *output, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 815 return result; | 818 return result; |
| 816 } | 819 } |
| 817 | 820 |
| 818 // For backward compatibility | 821 // For backward compatibility |
| 819 bool Process(OTSStream *output, const uint8_t *data, size_t length) { | 822 bool Process(OTSStream *output, const uint8_t *data, size_t length) { |
| 820 static OTSContext context; | 823 static OTSContext context; |
| 821 return context.Process(output, data, length); | 824 return context.Process(output, data, length); |
| 822 } | 825 } |
| 823 | 826 |
| 824 } // namespace ots | 827 } // namespace ots |
| OLD | NEW |