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

Side by Side Diff: third_party/woff2/src/woff2_enc.cc

Issue 1873123002: Update woff2 to 4e698b8 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: update BUILD.gn (win8 build fix?) Created 4 years, 8 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/woff2/src/woff2_enc.h ('k') | third_party/woff2/src/woff2_out.h » ('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 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,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 // 14 //
15 // Library for converting TTF format font files to their WOFF2 versions. 15 // Library for converting TTF format font files to their WOFF2 versions.
16 16
17 #include "./woff2_enc.h" 17 #include "./woff2_enc.h"
18 18
19 #include <stdlib.h> 19 #include <stdlib.h>
20 #include <complex> 20 #include <complex>
21 #include <cstring> 21 #include <cstring>
22 #include <limits> 22 #include <limits>
23 #include <string> 23 #include <string>
24 #include <vector> 24 #include <vector>
25 25
26 #include "./encode.h"
26 #include "./buffer.h" 27 #include "./buffer.h"
27 #include "./encode.h"
28 #include "./font.h" 28 #include "./font.h"
29 #include "./normalize.h" 29 #include "./normalize.h"
30 #include "./round.h" 30 #include "./round.h"
31 #include "./store_bytes.h" 31 #include "./store_bytes.h"
32 #include "./table_tags.h" 32 #include "./table_tags.h"
33 #include "./transform.h" 33 #include "./transform.h"
34 #include "./variable_length.h" 34 #include "./variable_length.h"
35 #include "./woff2_common.h" 35 #include "./woff2_common.h"
36 36
37
37 namespace woff2 { 38 namespace woff2 {
38 39
39 namespace { 40 namespace {
40 41
42
41 using std::string; 43 using std::string;
42 using std::vector; 44 using std::vector;
43 45
44 46
45 const size_t kWoff2HeaderSize = 48; 47 const size_t kWoff2HeaderSize = 48;
46 const size_t kWoff2EntrySize = 20; 48 const size_t kWoff2EntrySize = 20;
47 49
50
48 bool Compress(const uint8_t* data, const size_t len, 51 bool Compress(const uint8_t* data, const size_t len,
49 uint8_t* result, uint32_t* result_len, 52 uint8_t* result, uint32_t* result_len,
50 brotli::BrotliParams::Mode mode, int quality) { 53 brotli::BrotliParams::Mode mode, int quality) {
51 size_t compressed_len = *result_len; 54 size_t compressed_len = *result_len;
52 brotli::BrotliParams params; 55 brotli::BrotliParams params;
53 params.mode = mode; 56 params.mode = mode;
54 params.quality = quality; 57 params.quality = quality;
55 if (brotli::BrotliCompressBuffer(params, len, data, &compressed_len, result) 58 if (brotli::BrotliCompressBuffer(params, len, data, &compressed_len, result)
56 == 0) { 59 == 0) {
57 return false; 60 return false;
(...skipping 17 matching lines...) Expand all
75 } 78 }
76 79
77 int KnownTableIndex(uint32_t tag) { 80 int KnownTableIndex(uint32_t tag) {
78 for (int i = 0; i < 63; ++i) { 81 for (int i = 0; i < 63; ++i) {
79 if (tag == kKnownTags[i]) return i; 82 if (tag == kKnownTags[i]) return i;
80 } 83 }
81 return 63; 84 return 63;
82 } 85 }
83 86
84 void StoreTableEntry(const Table& table, size_t* offset, uint8_t* dst) { 87 void StoreTableEntry(const Table& table, size_t* offset, uint8_t* dst) {
85 uint8_t flag_byte = KnownTableIndex(table.tag); 88 uint8_t flag_byte = (table.flags & 0xC0) | KnownTableIndex(table.tag);
86 dst[(*offset)++] = flag_byte; 89 dst[(*offset)++] = flag_byte;
87 // The index here is treated as a set of flag bytes because 90 // The index here is treated as a set of flag bytes because
88 // bits 6 and 7 of the byte are reserved for future use as flags. 91 // bits 6 and 7 of the byte are reserved for future use as flags.
89 // 0x3f or 63 means an arbitrary table tag. 92 // 0x3f or 63 means an arbitrary table tag.
90 if ((flag_byte & 0x3f) == 0x3f) { 93 if ((flag_byte & 0x3f) == 0x3f) {
91 StoreU32(table.tag, offset, dst); 94 StoreU32(table.tag, offset, dst);
92 } 95 }
93 StoreBase128(table.src_length, offset, dst); 96 StoreBase128(table.src_length, offset, dst);
94 if ((table.flags & kWoff2FlagsTransform) != 0) { 97 if ((table.flags & kWoff2FlagsTransform) != 0) {
95 StoreBase128(table.transform_length, offset, dst); 98 StoreBase128(table.transform_length, offset, dst);
96 } 99 }
97 } 100 }
98 101
99 size_t TableEntrySize(const Table& table) { 102 size_t TableEntrySize(const Table& table) {
100 uint8_t flag_byte = KnownTableIndex(table.tag); 103 uint8_t flag_byte = KnownTableIndex(table.tag);
101 size_t size = ((flag_byte & 0x3f) != 0x3f) ? 1 : 5; 104 size_t size = ((flag_byte & 0x3f) != 0x3f) ? 1 : 5;
102 size += Base128Size(table.src_length); 105 size += Base128Size(table.src_length);
103 if ((table.flags & kWoff2FlagsTransform) != 0) { 106 if ((table.flags & kWoff2FlagsTransform) != 0) {
104 size += Base128Size(table.transform_length); 107 size += Base128Size(table.transform_length);
105 } 108 }
106 return size; 109 return size;
107 } 110 }
108 111
109 size_t ComputeWoff2Length(const FontCollection& font_collection, 112 size_t ComputeWoff2Length(const FontCollection& font_collection,
110 const std::vector<Table>& tables, 113 const std::vector<Table>& tables,
111 std::map<uint32_t, uint16_t> index_by_offset, 114 std::map<uint32_t, uint16_t> index_by_offset,
115 size_t compressed_data_length,
112 size_t extended_metadata_length) { 116 size_t extended_metadata_length) {
113 size_t size = kWoff2HeaderSize; 117 size_t size = kWoff2HeaderSize;
114 118
115 for (const auto& table : tables) { 119 for (const auto& table : tables) {
116 size += TableEntrySize(table); 120 size += TableEntrySize(table);
117 } 121 }
118 122
119 // for collections only, collection tables 123 // for collections only, collection tables
120 if (font_collection.fonts.size() > 1) { 124 if (font_collection.fonts.size() > 1) {
121 size += 4; // UInt32 Version of TTC Header 125 size += 4; // UInt32 Version of TTC Header
122 size += Size255UShort(font_collection.fonts.size()); // 255UInt16 numFonts 126 size += Size255UShort(font_collection.fonts.size()); // 255UInt16 numFonts
123 127
124 size += 4 * font_collection.fonts.size(); // UInt32 flavor for each 128 size += 4 * font_collection.fonts.size(); // UInt32 flavor for each
125 129
126 for (const auto& font : font_collection.fonts) { 130 for (const auto& font : font_collection.fonts) {
127 size += Size255UShort(font.tables.size()); // 255UInt16 numTables 131 size += Size255UShort(font.tables.size()); // 255UInt16 numTables
128 for (const auto& entry : font.tables) { 132 for (const auto& entry : font.tables) {
129 const Font::Table& table = entry.second; 133 const Font::Table& table = entry.second;
130 // no collection entry for xform table 134 // no collection entry for xform table
131 if (table.tag & 0x80808080) continue; 135 if (table.tag & 0x80808080) continue;
132 136
133 uint16_t table_index = index_by_offset[table.offset]; 137 uint16_t table_index = index_by_offset[table.offset];
134 size += Size255UShort(table_index); // 255UInt16 index entry 138 size += Size255UShort(table_index); // 255UInt16 index entry
135 } 139 }
136 } 140 }
137 } 141 }
138 142
139 // compressed data 143 // compressed data
140 for (const auto& table : tables) { 144 size += compressed_data_length;
141 size += table.dst_length; 145 size = Round4(size);
142 size = Round4(size);
143 }
144 146
145 size += extended_metadata_length; 147 size += extended_metadata_length;
146 return size; 148 return size;
147 } 149 }
148 150
149 size_t ComputeTTFLength(const std::vector<Table>& tables) { 151 size_t ComputeTTFLength(const std::vector<Table>& tables) {
150 size_t size = 12 + 16 * tables.size(); // sfnt header 152 size_t size = 12 + 16 * tables.size(); // sfnt header
151 for (const auto& table : tables) { 153 for (const auto& table : tables) {
152 size += Round4(table.src_length); 154 size += Round4(table.src_length);
153 } 155 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 } 212 }
211 213
212 uint32_t CompressedBufferSize(uint32_t original_size) { 214 uint32_t CompressedBufferSize(uint32_t original_size) {
213 return 1.2 * original_size + 10240; 215 return 1.2 * original_size + 10240;
214 } 216 }
215 217
216 bool TransformFontCollection(FontCollection* font_collection) { 218 bool TransformFontCollection(FontCollection* font_collection) {
217 for (auto& font : font_collection->fonts) { 219 for (auto& font : font_collection->fonts) {
218 if (!TransformGlyfAndLocaTables(&font)) { 220 if (!TransformGlyfAndLocaTables(&font)) {
219 #ifdef FONT_COMPRESSION_BIN 221 #ifdef FONT_COMPRESSION_BIN
220 fprintf(stderr, "Font transformation failed.\n"); 222 fprintf(stderr, "glyf/loca transformation failed.\n");
221 #endif 223 #endif
222 return FONT_COMPRESSION_FAILURE(); 224 return FONT_COMPRESSION_FAILURE();
223 } 225 }
224 } 226 }
225 227
226 return true; 228 return true;
227 } 229 }
228 230
229 bool ConvertTTFToWOFF2(const uint8_t *data, size_t length, 231 bool ConvertTTFToWOFF2(const uint8_t *data, size_t length,
230 uint8_t *result, size_t *result_length) { 232 uint8_t *result, size_t *result_length) {
(...skipping 10 matching lines...) Expand all
241 #ifdef FONT_COMPRESSION_BIN 243 #ifdef FONT_COMPRESSION_BIN
242 fprintf(stderr, "Parsing of the input font failed.\n"); 244 fprintf(stderr, "Parsing of the input font failed.\n");
243 #endif 245 #endif
244 return FONT_COMPRESSION_FAILURE(); 246 return FONT_COMPRESSION_FAILURE();
245 } 247 }
246 248
247 if (!NormalizeFontCollection(&font_collection)) { 249 if (!NormalizeFontCollection(&font_collection)) {
248 return FONT_COMPRESSION_FAILURE(); 250 return FONT_COMPRESSION_FAILURE();
249 } 251 }
250 252
251 if (!TransformFontCollection(&font_collection)) { 253 if (params.allow_transforms && !TransformFontCollection(&font_collection)) {
252 return FONT_COMPRESSION_FAILURE(); 254 return FONT_COMPRESSION_FAILURE();
255 } else {
256 // glyf/loca use 11 to flag "not transformed"
257 for (auto& font : font_collection.fonts) {
258 Font::Table* glyf_table = font.FindTable(kGlyfTableTag);
259 Font::Table* loca_table = font.FindTable(kLocaTableTag);
260 if (glyf_table) {
261 glyf_table->flag_byte |= 0xc0;
262 }
263 if (loca_table) {
264 loca_table->flag_byte |= 0xc0;
265 }
266 }
253 } 267 }
254 268
255 // Although the compressed size of each table in the final woff2 file won't 269 // Although the compressed size of each table in the final woff2 file won't
256 // be larger than its transform_length, we have to allocate a large enough 270 // be larger than its transform_length, we have to allocate a large enough
257 // buffer for the compressor, since the compressor can potentially increase 271 // buffer for the compressor, since the compressor can potentially increase
258 // the size. If the compressor overflows this, it should return false and 272 // the size. If the compressor overflows this, it should return false and
259 // then this function will also return false. 273 // then this function will also return false.
260 274
261 size_t total_transform_length = 0; 275 size_t total_transform_length = 0;
262 for (const auto& font : font_collection.fonts) { 276 for (const auto& font : font_collection.fonts) {
(...skipping 21 matching lines...) Expand all
284 if (!Woff2Compress(transform_buf.data(), total_transform_length, 298 if (!Woff2Compress(transform_buf.data(), total_transform_length,
285 &compression_buf[0], 299 &compression_buf[0],
286 &total_compressed_length, 300 &total_compressed_length,
287 params.brotli_quality)) { 301 params.brotli_quality)) {
288 #ifdef FONT_COMPRESSION_BIN 302 #ifdef FONT_COMPRESSION_BIN
289 fprintf(stderr, "Compression of combined table failed.\n"); 303 fprintf(stderr, "Compression of combined table failed.\n");
290 #endif 304 #endif
291 return FONT_COMPRESSION_FAILURE(); 305 return FONT_COMPRESSION_FAILURE();
292 } 306 }
293 307
308 #ifdef FONT_COMPRESSION_BIN
309 fprintf(stderr, "Compressed %zu to %u.\n", total_transform_length,
310 total_compressed_length);
311 #endif
312
294 // Compress the extended metadata 313 // Compress the extended metadata
295 // TODO(user): how does this apply to collections 314 // TODO(user): how does this apply to collections
296 uint32_t compressed_metadata_buf_length = 315 uint32_t compressed_metadata_buf_length =
297 CompressedBufferSize(params.extended_metadata.length()); 316 CompressedBufferSize(params.extended_metadata.length());
298 std::vector<uint8_t> compressed_metadata_buf(compressed_metadata_buf_length); 317 std::vector<uint8_t> compressed_metadata_buf(compressed_metadata_buf_length);
299 318
300 if (params.extended_metadata.length() > 0) { 319 if (params.extended_metadata.length() > 0) {
301 if (!TextCompress((const uint8_t*)params.extended_metadata.data(), 320 if (!TextCompress((const uint8_t*)params.extended_metadata.data(),
302 params.extended_metadata.length(), 321 params.extended_metadata.length(),
303 compressed_metadata_buf.data(), 322 compressed_metadata_buf.data(),
(...skipping 20 matching lines...) Expand all
324 } 343 }
325 344
326 if (index_by_offset.find(src_table.offset) == index_by_offset.end()) { 345 if (index_by_offset.find(src_table.offset) == index_by_offset.end()) {
327 index_by_offset[src_table.offset] = tables.size(); 346 index_by_offset[src_table.offset] = tables.size();
328 } else { 347 } else {
329 return false; 348 return false;
330 } 349 }
331 350
332 Table table; 351 Table table;
333 table.tag = src_table.tag; 352 table.tag = src_table.tag;
334 table.flags = 0; 353 table.flags = src_table.flag_byte;
335 table.src_length = src_table.length; 354 table.src_length = src_table.length;
336 table.transform_length = src_table.length; 355 table.transform_length = src_table.length;
337 const uint8_t* transformed_data = src_table.data; 356 const uint8_t* transformed_data = src_table.data;
338 const Font::Table* transformed_table = 357 const Font::Table* transformed_table =
339 font.FindTable(src_table.tag ^ 0x80808080); 358 font.FindTable(src_table.tag ^ 0x80808080);
340 if (transformed_table != NULL) { 359 if (transformed_table != NULL) {
360 table.flags = transformed_table->flag_byte;
341 table.flags |= kWoff2FlagsTransform; 361 table.flags |= kWoff2FlagsTransform;
342 table.transform_length = transformed_table->length; 362 table.transform_length = transformed_table->length;
343 transformed_data = transformed_table->data; 363 transformed_data = transformed_table->data;
344 } 364
345 if (tables.empty()) {
346 table.dst_length = total_compressed_length;
347 table.dst_data = &compression_buf[0];
348 } else {
349 table.dst_length = 0;
350 table.dst_data = NULL;
351 } 365 }
352 tables.push_back(table); 366 tables.push_back(table);
353 } 367 }
354 } 368 }
355 369
356 size_t woff2_length = ComputeWoff2Length(font_collection, tables, 370 size_t woff2_length = ComputeWoff2Length(font_collection, tables,
357 index_by_offset, compressed_metadata_buf_length); 371 index_by_offset, total_compressed_length, compressed_metadata_buf_length);
358 if (woff2_length > *result_length) { 372 if (woff2_length > *result_length) {
359 #ifdef FONT_COMPRESSION_BIN 373 #ifdef FONT_COMPRESSION_BIN
360 fprintf(stderr, "Result allocation was too small (%zd vs %zd bytes).\n", 374 fprintf(stderr, "Result allocation was too small (%zd vs %zd bytes).\n",
361 *result_length, woff2_length); 375 *result_length, woff2_length);
362 #endif 376 #endif
363 return FONT_COMPRESSION_FAILURE(); 377 return FONT_COMPRESSION_FAILURE();
364 } 378 }
365 *result_length = woff2_length; 379 *result_length = woff2_length;
366 380
367 const Font& first_font = font_collection.fonts[0]; 381 const Font& first_font = font_collection.fonts[0];
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 } 451 }
438 uint16_t index = index_by_offset[table_offset]; 452 uint16_t index = index_by_offset[table_offset];
439 Store255UShort(index, &offset, result); 453 Store255UShort(index, &offset, result);
440 454
441 } 455 }
442 456
443 } 457 }
444 } 458 }
445 459
446 // compressed data format (http://www.w3.org/TR/WOFF2/#table_format) 460 // compressed data format (http://www.w3.org/TR/WOFF2/#table_format)
447 for (const auto& table : tables) { 461
448 StoreBytes(table.dst_data, table.dst_length, &offset, result); 462 StoreBytes(&compression_buf[0], total_compressed_length, &offset, result);
449 offset = Round4(offset); 463 offset = Round4(offset);
450 } 464
451 StoreBytes(compressed_metadata_buf.data(), compressed_metadata_buf_length, 465 StoreBytes(compressed_metadata_buf.data(), compressed_metadata_buf_length,
452 &offset, result); 466 &offset, result);
453 467
454 if (*result_length != offset) { 468 if (*result_length != offset) {
455 #ifdef FONT_COMPRESSION_BIN 469 #ifdef FONT_COMPRESSION_BIN
456 fprintf(stderr, "Mismatch between computed and actual length " 470 fprintf(stderr, "Mismatch between computed and actual length "
457 "(%zd vs %zd)\n", *result_length, offset); 471 "(%zd vs %zd)\n", *result_length, offset);
458 #endif 472 #endif
459 return FONT_COMPRESSION_FAILURE(); 473 return FONT_COMPRESSION_FAILURE();
460 } 474 }
461 return true; 475 return true;
462 } 476 }
463 477
464 } // namespace woff2 478 } // namespace woff2
OLDNEW
« no previous file with comments | « third_party/woff2/src/woff2_enc.h ('k') | third_party/woff2/src/woff2_out.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698