OLD | NEW |
1 // Copyright 2014 Google Inc. All Rights Reserved. | 1 // Copyright 2014 Google Inc. All Rights Reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 | 63 |
64 const size_t kCheckSumAdjustmentOffset = 8; | 64 const size_t kCheckSumAdjustmentOffset = 8; |
65 | 65 |
66 const size_t kEndPtsOfContoursOffset = 10; | 66 const size_t kEndPtsOfContoursOffset = 10; |
67 const size_t kCompositeGlyphBegin = 10; | 67 const size_t kCompositeGlyphBegin = 10; |
68 | 68 |
69 // 98% of Google Fonts have no glyph above 5k bytes | 69 // 98% of Google Fonts have no glyph above 5k bytes |
70 // Largest glyph ever observed was 72k bytes | 70 // Largest glyph ever observed was 72k bytes |
71 const size_t kDefaultGlyphBuf = 5120; | 71 const size_t kDefaultGlyphBuf = 5120; |
72 | 72 |
| 73 // Over 14k test fonts the max compression ratio seen to date was ~20. |
| 74 // >100 suggests you wrote a bad uncompressed size. |
| 75 const float kMaxPlausibleCompressionRatio = 100.0; |
| 76 |
73 // metadata for a TTC font entry | 77 // metadata for a TTC font entry |
74 struct TtcFont { | 78 struct TtcFont { |
75 uint32_t flavor; | 79 uint32_t flavor; |
76 uint32_t dst_offset; | 80 uint32_t dst_offset; |
77 uint32_t header_checksum; | 81 uint32_t header_checksum; |
78 std::vector<uint16_t> table_indices; | 82 std::vector<uint16_t> table_indices; |
79 }; | 83 }; |
80 | 84 |
81 struct WOFF2Header { | 85 struct WOFF2Header { |
82 uint32_t flavor; | 86 uint32_t flavor; |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 if (PREDICT_FALSE(!SizeOfComposite(composite_stream, &composite_size, | 475 if (PREDICT_FALSE(!SizeOfComposite(composite_stream, &composite_size, |
472 &have_instructions))) { | 476 &have_instructions))) { |
473 return FONT_COMPRESSION_FAILURE(); | 477 return FONT_COMPRESSION_FAILURE(); |
474 } | 478 } |
475 if (have_instructions) { | 479 if (have_instructions) { |
476 if (PREDICT_FALSE(!Read255UShort(&glyph_stream, &instruction_size))) { | 480 if (PREDICT_FALSE(!Read255UShort(&glyph_stream, &instruction_size))) { |
477 return FONT_COMPRESSION_FAILURE(); | 481 return FONT_COMPRESSION_FAILURE(); |
478 } | 482 } |
479 } | 483 } |
480 | 484 |
481 size_t size_needed = 2 + composite_size + instruction_size; | 485 size_t size_needed = 12 + composite_size + instruction_size; |
482 if (PREDICT_FALSE(glyph_buf_size < size_needed)) { | 486 if (PREDICT_FALSE(glyph_buf_size < size_needed)) { |
483 glyph_buf.reset(new uint8_t[size_needed]); | 487 glyph_buf.reset(new uint8_t[size_needed]); |
484 glyph_buf_size = size_needed; | 488 glyph_buf_size = size_needed; |
485 } | 489 } |
486 | 490 |
487 glyph_size = Store16(glyph_buf.get(), glyph_size, n_contours); | 491 glyph_size = Store16(glyph_buf.get(), glyph_size, n_contours); |
488 if (PREDICT_FALSE(!bbox_stream.Read(glyph_buf.get() + glyph_size, 8))) { | 492 if (PREDICT_FALSE(!bbox_stream.Read(glyph_buf.get() + glyph_size, 8))) { |
489 return FONT_COMPRESSION_FAILURE(); | 493 return FONT_COMPRESSION_FAILURE(); |
490 } | 494 } |
491 glyph_size += 8; | 495 glyph_size += 8; |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 bool has_proportional_lsbs = (hmtx_flags & 1) == 0; | 669 bool has_proportional_lsbs = (hmtx_flags & 1) == 0; |
666 bool has_monospace_lsbs = (hmtx_flags & 2) == 0; | 670 bool has_monospace_lsbs = (hmtx_flags & 2) == 0; |
667 | 671 |
668 // you say you transformed but there is little evidence of it | 672 // you say you transformed but there is little evidence of it |
669 if (has_proportional_lsbs && has_monospace_lsbs) { | 673 if (has_proportional_lsbs && has_monospace_lsbs) { |
670 return FONT_COMPRESSION_FAILURE(); | 674 return FONT_COMPRESSION_FAILURE(); |
671 } | 675 } |
672 | 676 |
673 assert(x_mins.size() == num_glyphs); | 677 assert(x_mins.size() == num_glyphs); |
674 | 678 |
| 679 // num_glyphs 0 is OK if there is no 'glyf' but cannot then xform 'hmtx'. |
| 680 if (PREDICT_FALSE(num_hmetrics > num_glyphs)) { |
| 681 return FONT_COMPRESSION_FAILURE(); |
| 682 } |
| 683 |
675 for (uint16_t i = 0; i < num_hmetrics; i++) { | 684 for (uint16_t i = 0; i < num_hmetrics; i++) { |
676 uint16_t advance_width; | 685 uint16_t advance_width; |
677 if (PREDICT_FALSE(!hmtx_buff_in.ReadU16(&advance_width))) { | 686 if (PREDICT_FALSE(!hmtx_buff_in.ReadU16(&advance_width))) { |
678 return FONT_COMPRESSION_FAILURE(); | 687 return FONT_COMPRESSION_FAILURE(); |
679 } | 688 } |
680 advance_widths.push_back(advance_width); | 689 advance_widths.push_back(advance_width); |
681 } | 690 } |
682 | 691 |
683 for (uint16_t i = 0; i < num_hmetrics; i++) { | 692 for (uint16_t i = 0; i < num_hmetrics; i++) { |
684 int16_t lsb; | 693 int16_t lsb; |
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1263 RebuildMetadata metadata; | 1272 RebuildMetadata metadata; |
1264 WOFF2Header hdr; | 1273 WOFF2Header hdr; |
1265 if (!ReadWOFF2Header(data, length, &hdr)) { | 1274 if (!ReadWOFF2Header(data, length, &hdr)) { |
1266 return FONT_COMPRESSION_FAILURE(); | 1275 return FONT_COMPRESSION_FAILURE(); |
1267 } | 1276 } |
1268 | 1277 |
1269 if (!WriteHeaders(data, length, &metadata, &hdr, out)) { | 1278 if (!WriteHeaders(data, length, &metadata, &hdr, out)) { |
1270 return FONT_COMPRESSION_FAILURE(); | 1279 return FONT_COMPRESSION_FAILURE(); |
1271 } | 1280 } |
1272 | 1281 |
| 1282 const float compression_ratio = (float) hdr.uncompressed_size / length; |
| 1283 if (compression_ratio > kMaxPlausibleCompressionRatio) { |
| 1284 #ifdef FONT_COMPRESSION_BIN |
| 1285 fprintf(stderr, "Implausible compression ratio %.01f\n", compression_ratio); |
| 1286 #endif |
| 1287 return FONT_COMPRESSION_FAILURE(); |
| 1288 } |
| 1289 |
1273 const uint8_t* src_buf = data + hdr.compressed_offset; | 1290 const uint8_t* src_buf = data + hdr.compressed_offset; |
1274 std::vector<uint8_t> uncompressed_buf(hdr.uncompressed_size); | 1291 std::vector<uint8_t> uncompressed_buf(hdr.uncompressed_size); |
1275 if (PREDICT_FALSE(!Woff2Uncompress(&uncompressed_buf[0], | 1292 if (PREDICT_FALSE(!Woff2Uncompress(&uncompressed_buf[0], |
1276 hdr.uncompressed_size, src_buf, | 1293 hdr.uncompressed_size, src_buf, |
1277 hdr.compressed_length))) { | 1294 hdr.compressed_length))) { |
1278 return FONT_COMPRESSION_FAILURE(); | 1295 return FONT_COMPRESSION_FAILURE(); |
1279 } | 1296 } |
1280 | 1297 |
1281 for (size_t i = 0; i < metadata.font_infos.size(); i++) { | 1298 for (size_t i = 0; i < metadata.font_infos.size(); i++) { |
1282 if (PREDICT_FALSE(!ReconstructFont(&uncompressed_buf[0], | 1299 if (PREDICT_FALSE(!ReconstructFont(&uncompressed_buf[0], |
1283 hdr.uncompressed_size, | 1300 hdr.uncompressed_size, |
1284 &metadata, &hdr, i, out))) { | 1301 &metadata, &hdr, i, out))) { |
1285 return FONT_COMPRESSION_FAILURE(); | 1302 return FONT_COMPRESSION_FAILURE(); |
1286 } | 1303 } |
1287 } | 1304 } |
1288 | 1305 |
1289 return true; | 1306 return true; |
1290 } | 1307 } |
1291 | 1308 |
1292 } // namespace woff2 | 1309 } // namespace woff2 |
OLD | NEW |