ReactOS 0.4.16-dev-2332-g4cba65d
sfwoff2.c
Go to the documentation of this file.
1/****************************************************************************
2 *
3 * sfwoff2.c
4 *
5 * WOFF2 format management (base).
6 *
7 * Copyright (C) 2019-2020 by
8 * Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
9 *
10 * This file is part of the FreeType project, and may only be used,
11 * modified, and distributed under the terms of the FreeType project
12 * license, LICENSE.TXT. By continuing to use, modify, or distribute
13 * this file you indicate that you have read the license and
14 * understand and accept it fully.
15 *
16 */
17
18#include "sfwoff2.h"
19#include "woff2tags.h"
20#include <freetype/tttags.h>
23
24
25#ifdef FT_CONFIG_OPTION_USE_BROTLI
26
27#include <brotli/decode.h>
28
29#endif
30
31
32 /**************************************************************************
33 *
34 * The macro FT_COMPONENT is used in trace mode. It is an implicit
35 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
36 * messages during execution.
37 */
38#undef FT_COMPONENT
39#define FT_COMPONENT sfwoff2
40
41
42#define READ_255USHORT( var ) FT_SET_ERROR( Read255UShort( stream, &var ) )
43
44#define READ_BASE128( var ) FT_SET_ERROR( ReadBase128( stream, &var ) )
45
46 /* `var' should be FT_ULong */
47#define ROUND4( var ) ( ( var + 3 ) & ~3UL )
48
49#define WRITE_USHORT( p, v ) \
50 do \
51 { \
52 *(p)++ = (FT_Byte)( (v) >> 8 ); \
53 *(p)++ = (FT_Byte)( (v) >> 0 ); \
54 \
55 } while ( 0 )
56
57#define WRITE_ULONG( p, v ) \
58 do \
59 { \
60 *(p)++ = (FT_Byte)( (v) >> 24 ); \
61 *(p)++ = (FT_Byte)( (v) >> 16 ); \
62 *(p)++ = (FT_Byte)( (v) >> 8 ); \
63 *(p)++ = (FT_Byte)( (v) >> 0 ); \
64 \
65 } while ( 0 )
66
67#define WRITE_SHORT( p, v ) \
68 do \
69 { \
70 *(p)++ = (FT_Byte)( (v) >> 8 ); \
71 *(p)++ = (FT_Byte)( (v) >> 0 ); \
72 \
73 } while ( 0 )
74
75#define WRITE_SFNT_BUF( buf, s ) \
76 write_buf( &sfnt, sfnt_size, &dest_offset, buf, s, memory )
77
78#define WRITE_SFNT_BUF_AT( offset, buf, s ) \
79 write_buf( &sfnt, sfnt_size, &offset, buf, s, memory )
80
81#define N_CONTOUR_STREAM 0
82#define N_POINTS_STREAM 1
83#define FLAG_STREAM 2
84#define GLYPH_STREAM 3
85#define COMPOSITE_STREAM 4
86#define BBOX_STREAM 5
87#define INSTRUCTION_STREAM 6
88
89
90 static void
92 {
93 FT_Memory memory = stream->memory;
94
95
96 FT_FREE( stream->base );
97
98 stream->size = 0;
99 stream->base = NULL;
100 stream->close = NULL;
101 }
102
103
104 FT_CALLBACK_DEF( int )
106 const void* b )
107 {
108 WOFF2_Table table1 = *(WOFF2_Table*)a;
109 WOFF2_Table table2 = *(WOFF2_Table*)b;
110
111 FT_ULong tag1 = table1->Tag;
112 FT_ULong tag2 = table2->Tag;
113
114
115 if ( tag1 > tag2 )
116 return 1;
117 else if ( tag1 < tag2 )
118 return -1;
119 else
120 return 0;
121 }
122
123
124 static FT_Error
127 {
128 const FT_Byte oneMoreByteCode1 = 255;
129 const FT_Byte oneMoreByteCode2 = 254;
130 const FT_Byte wordCode = 253;
131 const FT_UShort lowestUCode = 253;
132
135 FT_Byte result_byte = 0;
136 FT_UShort result_short = 0;
137
138
139 if ( FT_READ_BYTE( code ) )
140 return error;
141 if ( code == wordCode )
142 {
143 /* Read next two bytes and store `FT_UShort' value. */
144 if ( FT_READ_USHORT( result_short ) )
145 return error;
146 *value = result_short;
147 return FT_Err_Ok;
148 }
149 else if ( code == oneMoreByteCode1 )
150 {
151 if ( FT_READ_BYTE( result_byte ) )
152 return error;
153 *value = result_byte + lowestUCode;
154 return FT_Err_Ok;
155 }
156 else if ( code == oneMoreByteCode2 )
157 {
158 if ( FT_READ_BYTE( result_byte ) )
159 return error;
160 *value = result_byte + lowestUCode * 2;
161 return FT_Err_Ok;
162 }
163 else
164 {
165 *value = code;
166 return FT_Err_Ok;
167 }
168 }
169
170
171 static FT_Error
173 FT_ULong* value )
174 {
175 FT_ULong result = 0;
176 FT_Int i;
179
180
181 for ( i = 0; i < 5; ++i )
182 {
183 code = 0;
184 if ( FT_READ_BYTE( code ) )
185 return error;
186
187 /* Leading zeros are invalid. */
188 if ( i == 0 && code == 0x80 )
189 return FT_THROW( Invalid_Table );
190
191 /* If any of top seven bits are set then we're about to overflow. */
192 if ( result & 0xfe000000 )
193 return FT_THROW( Invalid_Table );
194
195 result = ( result << 7 ) | ( code & 0x7f );
196
197 /* Spin until most significant bit of data byte is false. */
198 if ( ( code & 0x80 ) == 0 )
199 {
200 *value = result;
201 return FT_Err_Ok;
202 }
203 }
204
205 /* Make sure not to exceed the size bound. */
206 return FT_THROW( Invalid_Table );
207 }
208
209
210 /* Extend memory of `dst_bytes' buffer and copy data from `src'. */
211 static FT_Error
212 write_buf( FT_Byte** dst_bytes,
213 FT_ULong* dst_size,
215 FT_Byte* src,
218 {
220 /* We are reallocating memory for `dst', so its pointer may change. */
221 FT_Byte* dst = *dst_bytes;
222
223
224 /* Check whether we are within limits. */
225 if ( ( *offset + size ) > WOFF2_DEFAULT_MAX_SIZE )
226 return FT_THROW( Array_Too_Large );
227
228 /* Reallocate `dst'. */
229 if ( ( *offset + size ) > *dst_size )
230 {
231 FT_TRACE6(( "Reallocating %lu to %lu.\n",
232 *dst_size, (*offset + size) ));
233 if ( FT_REALLOC( dst,
234 (FT_ULong)( *dst_size ),
235 (FT_ULong)( *offset + size ) ) )
236 goto Exit;
237
238 *dst_size = *offset + size;
239 }
240
241 /* Copy data. */
242 ft_memcpy( dst + *offset, src, size );
243
244 *offset += size;
245 /* Set pointer of `dst' to its correct value. */
246 *dst_bytes = dst;
247
248 Exit:
249 return error;
250 }
251
252
253 /* Pad buffer to closest multiple of 4. */
254 static FT_Error
255 pad4( FT_Byte** sfnt_bytes,
256 FT_ULong* sfnt_size,
257 FT_ULong* out_offset,
259 {
260 FT_Byte* sfnt = *sfnt_bytes;
261 FT_ULong dest_offset = *out_offset;
262
263 FT_Byte zeroes[] = { 0, 0, 0 };
264 FT_ULong pad_bytes;
265
266
267 if ( dest_offset + 3 < dest_offset )
268 return FT_THROW( Invalid_Table );
269
270 pad_bytes = ROUND4( dest_offset ) - dest_offset;
271 if ( pad_bytes > 0 )
272 {
273 if ( WRITE_SFNT_BUF( &zeroes[0], pad_bytes ) )
274 return FT_THROW( Invalid_Table );
275 }
276
277 *sfnt_bytes = sfnt;
278 *out_offset = dest_offset;
279 return FT_Err_Ok;
280 }
281
282
283 /* Calculate table checksum of `buf'. */
284 static FT_ULong
286 FT_ULong size )
287 {
288 FT_ULong checksum = 0;
289 FT_ULong aligned_size = size & ~3UL;
290 FT_ULong i;
291 FT_ULong v;
292
293
294 for ( i = 0; i < aligned_size; i += 4 )
295 checksum += ( (FT_ULong)buf[i ] << 24 ) |
296 ( (FT_ULong)buf[i + 1] << 16 ) |
297 ( (FT_ULong)buf[i + 2] << 8 ) |
298 ( (FT_ULong)buf[i + 3] << 0 );
299
300 /* If size is not aligned to 4, treat as if it is padded with 0s. */
301 if ( size != aligned_size )
302 {
303 v = 0;
304 for ( i = aligned_size ; i < size; ++i )
305 v |= (FT_ULong)buf[i] << ( 24 - 8 * ( i & 3 ) );
306 checksum += v;
307 }
308
309 return checksum;
310 }
311
312
313 static FT_Error
315 FT_ULong dst_size,
316 const FT_Byte* src,
317 FT_ULong src_size )
318 {
319#ifdef FT_CONFIG_OPTION_USE_BROTLI
320
321 /* this cast is only of importance on 32bit systems; */
322 /* we don't validate it */
323 FT_Offset uncompressed_size = (FT_Offset)dst_size;
324 BrotliDecoderResult result;
325
326
327 result = BrotliDecoderDecompress( src_size,
328 src,
329 &uncompressed_size,
330 dst );
331
332 if ( result != BROTLI_DECODER_RESULT_SUCCESS ||
333 uncompressed_size != dst_size )
334 {
335 FT_ERROR(( "woff2_decompress: Stream length mismatch.\n" ));
336 return FT_THROW( Invalid_Table );
337 }
338
339 FT_TRACE2(( "woff2_decompress: Brotli stream decompressed.\n" ));
340 return FT_Err_Ok;
341
342#else /* !FT_CONFIG_OPTION_USE_BROTLI */
343
344 FT_ERROR(( "woff2_decompress: Brotli support not available.\n" ));
345 return FT_THROW( Unimplemented_Feature );
346
347#endif /* !FT_CONFIG_OPTION_USE_BROTLI */
348 }
349
350
351 static WOFF2_Table
353 FT_UShort num_tables,
354 FT_ULong tag )
355 {
356 FT_Int i;
357
358
359 for ( i = 0; i < num_tables; i++ )
360 {
361 if ( tables[i]->Tag == tag )
362 return tables[i];
363 }
364 return NULL;
365 }
366
367
368 /* Read `numberOfHMetrics' field from `hhea' table. */
369 static FT_Error
371 FT_UShort* num_hmetrics )
372 {
374 FT_UShort num_metrics;
375
376
377 if ( FT_STREAM_SKIP( 34 ) )
378 return FT_THROW( Invalid_Table );
379
380 if ( FT_READ_USHORT( num_metrics ) )
381 return FT_THROW( Invalid_Table );
382
383 *num_hmetrics = num_metrics;
384
385 return error;
386 }
387
388
389 /* An auxiliary function for overflow-safe addition. */
390 static FT_Int
392 FT_Int base_val )
393 {
394 /* Precondition: 0 <= base_val < 65536 (to avoid overflow). */
395 return ( flag & 1 ) ? base_val : -base_val;
396 }
397
398
399 /* An auxiliary function for overflow-safe addition. */
400 static FT_Int
402 FT_Int b,
403 FT_Int* result )
404 {
405 if ( ( ( a > 0 ) && ( b > FT_INT_MAX - a ) ) ||
406 ( ( a < 0 ) && ( b < FT_INT_MIN - a ) ) )
407 return FT_THROW( Invalid_Table );
408
409 *result = a + b;
410 return FT_Err_Ok;
411 }
412
413
414 /*
415 * Decode variable-length (flag, xCoordinate, yCoordinate) triplet for a
416 * simple glyph. See
417 *
418 * https://www.w3.org/TR/WOFF2/#triplet_decoding
419 */
420 static FT_Error
421 triplet_decode( const FT_Byte* flags_in,
422 const FT_Byte* in,
424 FT_ULong n_points,
426 FT_ULong* in_bytes_used )
427 {
428 FT_Int x = 0;
429 FT_Int y = 0;
430 FT_Int dx;
431 FT_Int dy;
432 FT_Int b0, b1, b2;
433
434 FT_ULong triplet_index = 0;
435 FT_ULong data_bytes;
436
437 FT_UInt i;
438
439
440 if ( n_points > in_size )
441 return FT_THROW( Invalid_Table );
442
443 for ( i = 0; i < n_points; ++i )
444 {
445 FT_Byte flag = flags_in[i];
446 FT_Bool on_curve = !( flag >> 7 );
447
448
449 flag &= 0x7f;
450 if ( flag < 84 )
451 data_bytes = 1;
452 else if ( flag < 120 )
453 data_bytes = 2;
454 else if ( flag < 124 )
455 data_bytes = 3;
456 else
457 data_bytes = 4;
458
459 /* Overflow checks */
460 if ( triplet_index + data_bytes > in_size ||
461 triplet_index + data_bytes < triplet_index )
462 return FT_THROW( Invalid_Table );
463
464 if ( flag < 10 )
465 {
466 dx = 0;
467 dy = with_sign( flag,
468 ( ( flag & 14 ) << 7 ) + in[triplet_index] );
469 }
470 else if ( flag < 20 )
471 {
472 dx = with_sign( flag,
473 ( ( ( flag - 10 ) & 14 ) << 7 ) +
474 in[triplet_index] );
475 dy = 0;
476 }
477 else if ( flag < 84 )
478 {
479 b0 = flag - 20;
480 b1 = in[triplet_index];
481 dx = with_sign( flag,
482 1 + ( b0 & 0x30 ) + ( b1 >> 4 ) );
483 dy = with_sign( flag >> 1,
484 1 + ( ( b0 & 0x0c ) << 2 ) + ( b1 & 0x0f ) );
485 }
486 else if ( flag < 120 )
487 {
488 b0 = flag - 84;
489 dx = with_sign( flag,
490 1 + ( ( b0 / 12 ) << 8 ) + in[triplet_index] );
491 dy = with_sign( flag >> 1,
492 1 + ( ( ( b0 % 12 ) >> 2 ) << 8 ) +
493 in[triplet_index + 1] );
494 }
495 else if ( flag < 124 )
496 {
497 b2 = in[triplet_index + 1];
498 dx = with_sign( flag,
499 ( in[triplet_index] << 4 ) + ( b2 >> 4 ) );
500 dy = with_sign( flag >> 1,
501 ( ( b2 & 0x0f ) << 8 ) + in[triplet_index + 2] );
502 }
503 else
504 {
505 dx = with_sign( flag,
506 ( in[triplet_index] << 8 ) +
507 in[triplet_index + 1] );
508 dy = with_sign( flag >> 1,
509 ( in[triplet_index + 2] << 8 ) +
510 in[triplet_index + 3] );
511 }
512
513 triplet_index += data_bytes;
514
515 if ( safe_int_addition( x, dx, &x ) )
516 return FT_THROW( Invalid_Table );
517
518 if ( safe_int_addition( y, dy, &y ) )
519 return FT_THROW( Invalid_Table );
520
521 result[i].x = x;
522 result[i].y = y;
523 result[i].on_curve = on_curve;
524 }
525
526 *in_bytes_used = triplet_index;
527 return FT_Err_Ok;
528 }
529
530
531 /* Store decoded points in glyph buffer. */
532 static FT_Error
534 const WOFF2_Point points,
535 FT_UShort n_contours,
536 FT_UShort instruction_len,
537 FT_Byte* dst,
538 FT_ULong dst_size,
539 FT_ULong* glyph_size )
540 {
541 FT_UInt flag_offset = 10 + ( 2 * n_contours ) + 2 + instruction_len;
542 FT_Byte last_flag = 0xFFU;
543 FT_Byte repeat_count = 0;
544 FT_Int last_x = 0;
545 FT_Int last_y = 0;
546 FT_UInt x_bytes = 0;
547 FT_UInt y_bytes = 0;
548 FT_UInt xy_bytes;
549 FT_UInt i;
550 FT_UInt x_offset;
551 FT_UInt y_offset;
553
554
555 for ( i = 0; i < n_points; ++i )
556 {
557 const WOFF2_PointRec point = points[i];
558
559 FT_Byte flag = point.on_curve ? GLYF_ON_CURVE : 0;
560 FT_Int dx = point.x - last_x;
561 FT_Int dy = point.y - last_y;
562
563
564 if ( dx == 0 )
566 else if ( dx > -256 && dx < 256 )
567 {
568 flag |= GLYF_X_SHORT | ( dx > 0 ? GLYF_THIS_X_IS_SAME : 0 );
569 x_bytes += 1;
570 }
571 else
572 x_bytes += 2;
573
574 if ( dy == 0 )
576 else if ( dy > -256 && dy < 256 )
577 {
578 flag |= GLYF_Y_SHORT | ( dy > 0 ? GLYF_THIS_Y_IS_SAME : 0 );
579 y_bytes += 1;
580 }
581 else
582 y_bytes += 2;
583
584 if ( flag == last_flag && repeat_count != 255 )
585 {
586 dst[flag_offset - 1] |= GLYF_REPEAT;
587 repeat_count++;
588 }
589 else
590 {
591 if ( repeat_count != 0 )
592 {
593 if ( flag_offset >= dst_size )
594 return FT_THROW( Invalid_Table );
595
596 dst[flag_offset++] = repeat_count;
597 }
598 if ( flag_offset >= dst_size )
599 return FT_THROW( Invalid_Table );
600
601 dst[flag_offset++] = flag;
602 repeat_count = 0;
603 }
604
605 last_x = point.x;
606 last_y = point.y;
607 last_flag = flag;
608 }
609
610 if ( repeat_count != 0 )
611 {
612 if ( flag_offset >= dst_size )
613 return FT_THROW( Invalid_Table );
614
615 dst[flag_offset++] = repeat_count;
616 }
617
618 xy_bytes = x_bytes + y_bytes;
619 if ( xy_bytes < x_bytes ||
620 flag_offset + xy_bytes < flag_offset ||
621 flag_offset + xy_bytes > dst_size )
622 return FT_THROW( Invalid_Table );
623
624 x_offset = flag_offset;
625 y_offset = flag_offset + x_bytes;
626 last_x = 0;
627 last_y = 0;
628
629 for ( i = 0; i < n_points; ++i )
630 {
631 FT_Int dx = points[i].x - last_x;
632 FT_Int dy = points[i].y - last_y;
633
634
635 if ( dx == 0 )
636 ;
637 else if ( dx > -256 && dx < 256 )
638 dst[x_offset++] = (FT_Byte)FT_ABS( dx );
639 else
640 {
641 pointer = dst + x_offset;
643 x_offset += 2;
644 }
645
646 last_x += dx;
647
648 if ( dy == 0 )
649 ;
650 else if ( dy > -256 && dy < 256 )
651 dst[y_offset++] = (FT_Byte)FT_ABS( dy );
652 else
653 {
654 pointer = dst + y_offset;
656 y_offset += 2;
657 }
658
659 last_y += dy;
660 }
661
662 *glyph_size = y_offset;
663 return FT_Err_Ok;
664 }
665
666
667 static void
669 const WOFF2_Point points,
670 FT_Byte* dst,
671 FT_UShort* src_x_min )
672 {
673 FT_Int x_min = 0;
674 FT_Int y_min = 0;
675 FT_Int x_max = 0;
676 FT_Int y_max = 0;
677
678 FT_UInt i;
679
682
683
684 if ( n_points > 0 )
685 {
686 x_min = points[0].x;
687 y_min = points[0].y;
688 x_max = points[0].x;
689 y_max = points[0].y;
690 }
691
692 for ( i = 1; i < n_points; ++i )
693 {
694 FT_Int x = points[i].x;
695 FT_Int y = points[i].y;
696
697
698 x_min = FT_MIN( x, x_min );
699 y_min = FT_MIN( y, y_min );
700 x_max = FT_MAX( x, x_max );
701 y_max = FT_MAX( y, y_max );
702 }
703
704 /* Write values to `glyf' record. */
705 offset = 2;
706 pointer = dst + offset;
707
708 WRITE_SHORT( pointer, x_min );
709 WRITE_SHORT( pointer, y_min );
710 WRITE_SHORT( pointer, x_max );
711 WRITE_SHORT( pointer, y_max );
712
713 *src_x_min = (FT_UShort)x_min;
714 }
715
716
717 static FT_Error
720 FT_ULong* size,
721 FT_Bool* have_instructions )
722 {
724 FT_ULong start_offset = offset;
725 FT_Bool we_have_inst = FALSE;
727
728
729 if ( FT_STREAM_SEEK( start_offset ) )
730 goto Exit;
731 while ( flags & FLAG_MORE_COMPONENTS )
732 {
733 FT_ULong arg_size;
734
735
736 if ( FT_READ_USHORT( flags ) )
737 goto Exit;
738 we_have_inst |= ( flags & FLAG_WE_HAVE_INSTRUCTIONS ) != 0;
739 /* glyph index */
740 arg_size = 2;
742 arg_size += 4;
743 else
744 arg_size += 2;
745
747 arg_size += 2;
749 arg_size += 4;
750 else if ( flags & FLAG_WE_HAVE_A_TWO_BY_TWO )
751 arg_size += 8;
752
753 if ( FT_STREAM_SKIP( arg_size ) )
754 goto Exit;
755 }
756
757 *size = FT_STREAM_POS() - start_offset;
758 *have_instructions = we_have_inst;
759
760 Exit:
761 return error;
762 }
763
764
765 /* Store loca values (provided by `reconstruct_glyf') to output stream. */
766 static FT_Error
767 store_loca( FT_ULong* loca_values,
768 FT_ULong loca_values_size,
769 FT_UShort index_format,
771 FT_Byte** sfnt_bytes,
772 FT_ULong* sfnt_size,
773 FT_ULong* out_offset,
775 {
777 FT_Byte* sfnt = *sfnt_bytes;
778 FT_ULong dest_offset = *out_offset;
779
780 FT_Byte* loca_buf = NULL;
781 FT_Byte* dst = NULL;
782
783 FT_UInt i = 0;
784 FT_ULong loca_buf_size;
785
786 const FT_ULong offset_size = index_format ? 4 : 2;
787
788
789 if ( ( loca_values_size << 2 ) >> 2 != loca_values_size )
790 goto Fail;
791
792 loca_buf_size = loca_values_size * offset_size;
793 if ( FT_NEW_ARRAY( loca_buf, loca_buf_size ) )
794 goto Fail;
795
796 dst = loca_buf;
797 for ( i = 0; i < loca_values_size; i++ )
798 {
799 FT_ULong value = loca_values[i];
800
801
802 if ( index_format )
804 else
805 WRITE_USHORT( dst, ( value >> 1 ) );
806 }
807
808 *checksum = compute_ULong_sum( loca_buf, loca_buf_size );
809 /* Write `loca' table to sfnt buffer. */
810 if ( WRITE_SFNT_BUF( loca_buf, loca_buf_size ) )
811 goto Fail;
812
813 /* Set pointer `sfnt_bytes' to its correct value. */
814 *sfnt_bytes = sfnt;
815 *out_offset = dest_offset;
816
817 FT_FREE( loca_buf );
818 return error;
819
820 Fail:
821 if ( !error )
822 error = FT_THROW( Invalid_Table );
823
824 FT_FREE( loca_buf );
825
826 return error;
827 }
828
829
830 static FT_Error
832 FT_ULong* glyf_checksum,
833 FT_ULong* loca_checksum,
834 FT_Byte** sfnt_bytes,
835 FT_ULong* sfnt_size,
836 FT_ULong* out_offset,
839 {
841 FT_Byte* sfnt = *sfnt_bytes;
842
843 /* current position in stream */
844 const FT_ULong pos = FT_STREAM_POS();
845
846 FT_UInt num_substreams = 7;
847
848 FT_UShort num_glyphs;
849 FT_UShort index_format;
850 FT_ULong expected_loca_length;
852 FT_UInt i;
853 FT_ULong points_size;
854 FT_ULong bitmap_length;
855 FT_ULong glyph_buf_size;
856 FT_ULong bbox_bitmap_offset;
857
858 const FT_ULong glyf_start = *out_offset;
859 FT_ULong dest_offset = *out_offset;
860
861 WOFF2_Substream substreams = NULL;
862
863 FT_ULong* loca_values = NULL;
864 FT_UShort* n_points_arr = NULL;
865 FT_Byte* glyph_buf = NULL;
867
868
869 if ( FT_NEW_ARRAY( substreams, num_substreams ) )
870 goto Fail;
871
872 if ( FT_STREAM_SKIP( 4 ) )
873 goto Fail;
874 if ( FT_READ_USHORT( num_glyphs ) )
875 goto Fail;
876 if ( FT_READ_USHORT( index_format ) )
877 goto Fail;
878
879 FT_TRACE4(( "num_glyphs = %u; index_format = %u\n",
880 num_glyphs, index_format ));
881
882 info->num_glyphs = num_glyphs;
883
884 /* Calculate expected length of loca and compare. */
885 /* See https://www.w3.org/TR/WOFF2/#conform-mustRejectLoca */
886 /* index_format = 0 => Short version `loca'. */
887 /* index_format = 1 => Long version `loca'. */
888 expected_loca_length = ( index_format ? 4 : 2 ) *
889 ( (FT_ULong)num_glyphs + 1 );
890 if ( info->loca_table->dst_length != expected_loca_length )
891 goto Fail;
892
893 offset = ( 2 + num_substreams ) * 4;
894 if ( offset > info->glyf_table->TransformLength )
895 goto Fail;
896
897 for ( i = 0; i < num_substreams; ++i )
898 {
899 FT_ULong substream_size;
900
901
902 if ( FT_READ_ULONG( substream_size ) )
903 goto Fail;
904 if ( substream_size > info->glyf_table->TransformLength - offset )
905 goto Fail;
906
907 substreams[i].start = pos + offset;
908 substreams[i].offset = pos + offset;
909 substreams[i].size = substream_size;
910
911 FT_TRACE5(( " Substream %d: offset = %lu; size = %lu;\n",
912 i, substreams[i].offset, substreams[i].size ));
913 offset += substream_size;
914 }
915
916 if ( FT_NEW_ARRAY( loca_values, num_glyphs + 1 ) )
917 goto Fail;
918
919 points_size = 0;
920 bbox_bitmap_offset = substreams[BBOX_STREAM].offset;
921
922 /* Size of bboxBitmap = 4 * floor((numGlyphs + 31) / 32) */
923 bitmap_length = ( ( num_glyphs + 31U ) >> 5 ) << 2;
924 substreams[BBOX_STREAM].offset += bitmap_length;
925
926 glyph_buf_size = WOFF2_DEFAULT_GLYPH_BUF;
927 if ( FT_NEW_ARRAY( glyph_buf, glyph_buf_size ) )
928 goto Fail;
929
930 if ( FT_NEW_ARRAY( info->x_mins, num_glyphs ) )
931 goto Fail;
932
933 for ( i = 0; i < num_glyphs; ++i )
934 {
935 FT_ULong glyph_size = 0;
936 FT_UShort n_contours = 0;
937 FT_Bool have_bbox = FALSE;
938 FT_Byte bbox_bitmap;
939 FT_ULong bbox_offset;
940 FT_UShort x_min = 0;
941
942
943 /* Set `have_bbox'. */
944 bbox_offset = bbox_bitmap_offset + ( i >> 3 );
945 if ( FT_STREAM_SEEK( bbox_offset ) ||
946 FT_READ_BYTE( bbox_bitmap ) )
947 goto Fail;
948 if ( bbox_bitmap & ( 0x80 >> ( i & 7 ) ) )
949 have_bbox = TRUE;
950
951 /* Read value from `nContourStream'. */
952 if ( FT_STREAM_SEEK( substreams[N_CONTOUR_STREAM].offset ) ||
953 FT_READ_USHORT( n_contours ) )
954 goto Fail;
955 substreams[N_CONTOUR_STREAM].offset += 2;
956
957 if ( n_contours == 0xffff )
958 {
959 /* composite glyph */
960 FT_Bool have_instructions = FALSE;
961 FT_UShort instruction_size = 0;
962 FT_ULong composite_size;
963 FT_ULong size_needed;
965
966
967 /* Composite glyphs must have explicit bbox. */
968 if ( !have_bbox )
969 goto Fail;
970
972 substreams[COMPOSITE_STREAM].offset,
973 &composite_size,
974 &have_instructions) )
975 goto Fail;
976
977 if ( have_instructions )
978 {
979 if ( FT_STREAM_SEEK( substreams[GLYPH_STREAM].offset ) ||
980 READ_255USHORT( instruction_size ) )
981 goto Fail;
982 substreams[GLYPH_STREAM].offset = FT_STREAM_POS();
983 }
984
985 size_needed = 12 + composite_size + instruction_size;
986 if ( glyph_buf_size < size_needed )
987 {
988 if ( FT_RENEW_ARRAY( glyph_buf, glyph_buf_size, size_needed ) )
989 goto Fail;
990 glyph_buf_size = size_needed;
991 }
992
993 pointer = glyph_buf + glyph_size;
994 WRITE_USHORT( pointer, n_contours );
995 glyph_size += 2;
996
997 /* Read x_min for current glyph. */
998 if ( FT_STREAM_SEEK( substreams[BBOX_STREAM].offset ) ||
999 FT_READ_USHORT( x_min ) )
1000 goto Fail;
1001 /* No increment here because we read again. */
1002
1003 if ( FT_STREAM_SEEK( substreams[BBOX_STREAM].offset ) ||
1004 FT_STREAM_READ( glyph_buf + glyph_size, 8 ) )
1005 goto Fail;
1006
1007 substreams[BBOX_STREAM].offset += 8;
1008 glyph_size += 8;
1009
1010 if ( FT_STREAM_SEEK( substreams[COMPOSITE_STREAM].offset ) ||
1011 FT_STREAM_READ( glyph_buf + glyph_size, composite_size ) )
1012 goto Fail;
1013
1014 substreams[COMPOSITE_STREAM].offset += composite_size;
1015 glyph_size += composite_size;
1016
1017 if ( have_instructions )
1018 {
1019 pointer = glyph_buf + glyph_size;
1020 WRITE_USHORT( pointer, instruction_size );
1021 glyph_size += 2;
1022
1023 if ( FT_STREAM_SEEK( substreams[INSTRUCTION_STREAM].offset ) ||
1024 FT_STREAM_READ( glyph_buf + glyph_size, instruction_size ) )
1025 goto Fail;
1026
1027 substreams[INSTRUCTION_STREAM].offset += instruction_size;
1028 glyph_size += instruction_size;
1029 }
1030 }
1031 else if ( n_contours > 0 )
1032 {
1033 /* simple glyph */
1034 FT_ULong total_n_points = 0;
1035 FT_UShort n_points_contour;
1036 FT_UInt j;
1037 FT_ULong flag_size;
1038 FT_ULong triplet_size;
1039 FT_ULong triplet_bytes_used;
1040 FT_Byte* flags_buf = NULL;
1041 FT_Byte* triplet_buf = NULL;
1042 FT_UShort instruction_size;
1043 FT_ULong size_needed;
1044 FT_Int end_point;
1045 FT_UInt contour_ix;
1046
1047 FT_Byte* pointer = NULL;
1048
1049
1050 if ( FT_NEW_ARRAY( n_points_arr, n_contours ) )
1051 goto Fail;
1052
1053 if ( FT_STREAM_SEEK( substreams[N_POINTS_STREAM].offset ) )
1054 goto Fail;
1055
1056 for ( j = 0; j < n_contours; ++j )
1057 {
1058 if ( READ_255USHORT( n_points_contour ) )
1059 goto Fail;
1060 n_points_arr[j] = n_points_contour;
1061 /* Prevent negative/overflow. */
1062 if ( total_n_points + n_points_contour < total_n_points )
1063 goto Fail;
1064 total_n_points += n_points_contour;
1065 }
1066 substreams[N_POINTS_STREAM].offset = FT_STREAM_POS();
1067
1068 flag_size = total_n_points;
1069 if ( flag_size > substreams[FLAG_STREAM].size )
1070 goto Fail;
1071
1072 flags_buf = stream->base + substreams[FLAG_STREAM].offset;
1073 triplet_buf = stream->base + substreams[GLYPH_STREAM].offset;
1074
1075 if ( substreams[GLYPH_STREAM].size <
1076 ( substreams[GLYPH_STREAM].offset -
1077 substreams[GLYPH_STREAM].start ) )
1078 goto Fail;
1079
1080 triplet_size = substreams[GLYPH_STREAM].size -
1081 ( substreams[GLYPH_STREAM].offset -
1082 substreams[GLYPH_STREAM].start );
1083 triplet_bytes_used = 0;
1084
1085 /* Create array to store point information. */
1086 points_size = total_n_points;
1087 if ( FT_NEW_ARRAY( points, points_size ) )
1088 goto Fail;
1089
1090 if ( triplet_decode( flags_buf,
1091 triplet_buf,
1092 triplet_size,
1093 total_n_points,
1094 points,
1095 &triplet_bytes_used ) )
1096 goto Fail;
1097
1098 substreams[FLAG_STREAM].offset += flag_size;
1099 substreams[GLYPH_STREAM].offset += triplet_bytes_used;
1100
1101 if ( FT_STREAM_SEEK( substreams[GLYPH_STREAM].offset ) ||
1102 READ_255USHORT( instruction_size ) )
1103 goto Fail;
1104
1105 substreams[GLYPH_STREAM].offset = FT_STREAM_POS();
1106
1107 if ( total_n_points >= ( 1 << 27 ) )
1108 goto Fail;
1109
1110 size_needed = 12 +
1111 ( 2 * n_contours ) +
1112 ( 5 * total_n_points ) +
1113 instruction_size;
1114 if ( glyph_buf_size < size_needed )
1115 {
1116 if ( FT_RENEW_ARRAY( glyph_buf, glyph_buf_size, size_needed ) )
1117 goto Fail;
1118 glyph_buf_size = size_needed;
1119 }
1120
1121 pointer = glyph_buf + glyph_size;
1122 WRITE_USHORT( pointer, n_contours );
1123 glyph_size += 2;
1124
1125 if ( have_bbox )
1126 {
1127 /* Read x_min for current glyph. */
1128 if ( FT_STREAM_SEEK( substreams[BBOX_STREAM].offset ) ||
1129 FT_READ_USHORT( x_min ) )
1130 goto Fail;
1131 /* No increment here because we read again. */
1132
1133 if ( FT_STREAM_SEEK( substreams[BBOX_STREAM].offset ) ||
1134 FT_STREAM_READ( glyph_buf + glyph_size, 8 ) )
1135 goto Fail;
1136 substreams[BBOX_STREAM].offset += 8;
1137 }
1138 else
1139 compute_bbox( total_n_points, points, glyph_buf, &x_min );
1140
1141 glyph_size = CONTOUR_OFFSET_END_POINT;
1142
1143 pointer = glyph_buf + glyph_size;
1144 end_point = -1;
1145
1146 for ( contour_ix = 0; contour_ix < n_contours; ++contour_ix )
1147 {
1148 end_point += n_points_arr[contour_ix];
1149 if ( end_point >= 65536 )
1150 goto Fail;
1151
1152 WRITE_SHORT( pointer, end_point );
1153 glyph_size += 2;
1154 }
1155
1156 WRITE_USHORT( pointer, instruction_size );
1157 glyph_size += 2;
1158
1159 if ( FT_STREAM_SEEK( substreams[INSTRUCTION_STREAM].offset ) ||
1160 FT_STREAM_READ( glyph_buf + glyph_size, instruction_size ) )
1161 goto Fail;
1162
1163 substreams[INSTRUCTION_STREAM].offset += instruction_size;
1164 glyph_size += instruction_size;
1165
1166 if ( store_points( total_n_points,
1167 points,
1168 n_contours,
1169 instruction_size,
1170 glyph_buf,
1171 glyph_buf_size,
1172 &glyph_size ) )
1173 goto Fail;
1174
1175 FT_FREE( points );
1176 FT_FREE( n_points_arr );
1177 }
1178 else
1179 {
1180 /* Empty glyph. */
1181 /* Must not have a bbox. */
1182 if ( have_bbox )
1183 {
1184 FT_ERROR(( "Empty glyph has a bbox.\n" ));
1185 goto Fail;
1186 }
1187 }
1188
1189 loca_values[i] = dest_offset - glyf_start;
1190
1191 if ( WRITE_SFNT_BUF( glyph_buf, glyph_size ) )
1192 goto Fail;
1193
1194 if ( pad4( &sfnt, sfnt_size, &dest_offset, memory ) )
1195 goto Fail;
1196
1197 *glyf_checksum += compute_ULong_sum( glyph_buf, glyph_size );
1198
1199 /* Store x_mins, may be required to reconstruct `hmtx'. */
1200 if ( n_contours > 0 )
1201 info->x_mins[i] = (FT_Short)x_min;
1202 }
1203
1204 info->glyf_table->dst_length = dest_offset - info->glyf_table->dst_offset;
1205 info->loca_table->dst_offset = dest_offset;
1206
1207 /* `loca[n]' will be equal to the length of the `glyf' table. */
1208 loca_values[num_glyphs] = info->glyf_table->dst_length;
1209
1210 if ( store_loca( loca_values,
1211 num_glyphs + 1,
1212 index_format,
1213 loca_checksum,
1214 &sfnt,
1215 sfnt_size,
1216 &dest_offset,
1217 memory ) )
1218 goto Fail;
1219
1220 info->loca_table->dst_length = dest_offset - info->loca_table->dst_offset;
1221
1222 FT_TRACE4(( " loca table info:\n" ));
1223 FT_TRACE4(( " dst_offset = %lu\n", info->loca_table->dst_offset ));
1224 FT_TRACE4(( " dst_length = %lu\n", info->loca_table->dst_length ));
1225 FT_TRACE4(( " checksum = %09lx\n", *loca_checksum ));
1226
1227 /* Set pointer `sfnt_bytes' to its correct value. */
1228 *sfnt_bytes = sfnt;
1229 *out_offset = dest_offset;
1230
1231 FT_FREE( substreams );
1232 FT_FREE( loca_values );
1233 FT_FREE( n_points_arr );
1234 FT_FREE( glyph_buf );
1235 FT_FREE( points );
1236
1237 return error;
1238
1239 Fail:
1240 if ( !error )
1241 error = FT_THROW( Invalid_Table );
1242
1243 /* Set pointer `sfnt_bytes' to its correct value. */
1244 *sfnt_bytes = sfnt;
1245
1246 FT_FREE( substreams );
1247 FT_FREE( loca_values );
1248 FT_FREE( n_points_arr );
1249 FT_FREE( glyph_buf );
1250 FT_FREE( points );
1251
1252 return error;
1253 }
1254
1255
1256 /* Get `x_mins' for untransformed `glyf' table. */
1257 static FT_Error
1260 FT_UShort num_tables,
1263 {
1264 FT_UShort num_glyphs;
1265 FT_UShort index_format;
1266 FT_ULong glyf_offset;
1267 FT_UShort glyf_offset_short;
1268 FT_ULong loca_offset;
1269 FT_Int i;
1271 FT_ULong offset_size;
1272
1273 /* At this point of time those tables might not have been read yet. */
1274 const WOFF2_Table maxp_table = find_table( tables, num_tables,
1275 TTAG_maxp );
1276 const WOFF2_Table head_table = find_table( tables, num_tables,
1277 TTAG_head );
1278
1279
1280 if ( !maxp_table )
1281 {
1282 FT_ERROR(( "`maxp' table is missing.\n" ));
1283 return FT_THROW( Invalid_Table );
1284 }
1285
1286 if ( !head_table )
1287 {
1288 FT_ERROR(( "`head' table is missing.\n" ));
1289 return FT_THROW( Invalid_Table );
1290 }
1291
1292 if ( !info->loca_table )
1293 {
1294 FT_ERROR(( "`loca' table is missing.\n" ));
1295 return FT_THROW( Invalid_Table );
1296 }
1297
1298 /* Read `numGlyphs' field from `maxp' table. */
1299 if ( FT_STREAM_SEEK( maxp_table->src_offset ) || FT_STREAM_SKIP( 8 ) )
1300 return error;
1301
1302 if ( FT_READ_USHORT( num_glyphs ) )
1303 return error;
1304
1305 info->num_glyphs = num_glyphs;
1306
1307 /* Read `indexToLocFormat' field from `head' table. */
1308 if ( FT_STREAM_SEEK( head_table->src_offset ) ||
1309 FT_STREAM_SKIP( 50 ) )
1310 return error;
1311
1312 if ( FT_READ_USHORT( index_format ) )
1313 return error;
1314
1315 offset_size = index_format ? 4 : 2;
1316
1317 /* Create `x_mins' array. */
1318 if ( FT_NEW_ARRAY( info->x_mins, num_glyphs ) )
1319 return error;
1320
1321 loca_offset = info->loca_table->src_offset;
1322
1323 for ( i = 0; i < num_glyphs; ++i )
1324 {
1325 if ( FT_STREAM_SEEK( loca_offset ) )
1326 return error;
1327
1328 loca_offset += offset_size;
1329
1330 if ( index_format )
1331 {
1332 if ( FT_READ_ULONG( glyf_offset ) )
1333 return error;
1334 }
1335 else
1336 {
1337 if ( FT_READ_USHORT( glyf_offset_short ) )
1338 return error;
1339
1340 glyf_offset = (FT_ULong)( glyf_offset_short );
1341 glyf_offset = glyf_offset << 1;
1342 }
1343
1344 glyf_offset += info->glyf_table->src_offset;
1345
1346 if ( FT_STREAM_SEEK( glyf_offset ) || FT_STREAM_SKIP( 2 ) )
1347 return error;
1348
1349 if ( FT_READ_SHORT( info->x_mins[i] ) )
1350 return error;
1351 }
1352
1353 return error;
1354 }
1355
1356
1357 static FT_Error
1359 FT_UShort num_glyphs,
1360 FT_UShort num_hmetrics,
1361 FT_Short* x_mins,
1363 FT_Byte** sfnt_bytes,
1364 FT_ULong* sfnt_size,
1365 FT_ULong* out_offset,
1367 {
1369 FT_Byte* sfnt = *sfnt_bytes;
1370 FT_ULong dest_offset = *out_offset;
1371
1372 FT_Byte hmtx_flags;
1373 FT_Bool has_proportional_lsbs, has_monospace_lsbs;
1374 FT_ULong hmtx_table_size;
1375 FT_Int i;
1376
1377 FT_UShort* advance_widths = NULL;
1378 FT_Short* lsbs = NULL;
1379 FT_Byte* hmtx_table = NULL;
1380 FT_Byte* dst = NULL;
1381
1382
1383 if ( FT_READ_BYTE( hmtx_flags ) )
1384 goto Fail;
1385
1386 has_proportional_lsbs = ( hmtx_flags & 1 ) == 0;
1387 has_monospace_lsbs = ( hmtx_flags & 2 ) == 0;
1388
1389 /* Bits 2-7 are reserved and MUST be zero. */
1390 if ( ( hmtx_flags & 0xFC ) != 0 )
1391 goto Fail;
1392
1393 /* Are you REALLY transformed? */
1394 if ( has_proportional_lsbs && has_monospace_lsbs )
1395 goto Fail;
1396
1397 /* Cannot have a transformed `hmtx' without `glyf'. */
1398 if ( ( num_hmetrics > num_glyphs ) ||
1399 ( num_hmetrics < 1 ) )
1400 goto Fail;
1401
1402 /* Must have at least one entry. */
1403 if ( num_hmetrics < 1 )
1404 goto Fail;
1405
1406 if ( FT_NEW_ARRAY( advance_widths, num_hmetrics ) ||
1407 FT_NEW_ARRAY( lsbs, num_glyphs ) )
1408 goto Fail;
1409
1410 /* Read `advanceWidth' stream. Always present. */
1411 for ( i = 0; i < num_hmetrics; i++ )
1412 {
1413 FT_UShort advance_width;
1414
1415
1416 if ( FT_READ_USHORT( advance_width ) )
1417 goto Fail;
1418
1419 advance_widths[i] = advance_width;
1420 }
1421
1422 /* lsb values for proportional glyphs. */
1423 for ( i = 0; i < num_hmetrics; i++ )
1424 {
1425 FT_Short lsb;
1426
1427
1428 if ( has_proportional_lsbs )
1429 {
1430 if ( FT_READ_SHORT( lsb ) )
1431 goto Fail;
1432 }
1433 else
1434 lsb = x_mins[i];
1435
1436 lsbs[i] = lsb;
1437 }
1438
1439 /* lsb values for monospaced glyphs. */
1440 for ( i = num_hmetrics; i < num_glyphs; i++ )
1441 {
1442 FT_Short lsb;
1443
1444
1445 if ( has_monospace_lsbs )
1446 {
1447 if ( FT_READ_SHORT( lsb ) )
1448 goto Fail;
1449 }
1450 else
1451 lsb = x_mins[i];
1452
1453 lsbs[i] = lsb;
1454 }
1455
1456 /* Build the hmtx table. */
1457 hmtx_table_size = 2 * num_hmetrics + 2 * num_glyphs;
1458 if ( FT_NEW_ARRAY( hmtx_table, hmtx_table_size ) )
1459 goto Fail;
1460
1461 dst = hmtx_table;
1462 FT_TRACE6(( "hmtx values: \n" ));
1463 for ( i = 0; i < num_glyphs; i++ )
1464 {
1465 if ( i < num_hmetrics )
1466 {
1467 WRITE_SHORT( dst, advance_widths[i] );
1468 FT_TRACE6(( "%d ", advance_widths[i] ));
1469 }
1470
1471 WRITE_SHORT( dst, lsbs[i] );
1472 FT_TRACE6(( "%d ", lsbs[i] ));
1473 }
1474 FT_TRACE6(( "\n" ));
1475
1476 *checksum = compute_ULong_sum( hmtx_table, hmtx_table_size );
1477 /* Write `hmtx' table to sfnt buffer. */
1478 if ( WRITE_SFNT_BUF( hmtx_table, hmtx_table_size ) )
1479 goto Fail;
1480
1481 /* Set pointer `sfnt_bytes' to its correct value. */
1482 *sfnt_bytes = sfnt;
1483 *out_offset = dest_offset;
1484
1485 FT_FREE( advance_widths );
1486 FT_FREE( lsbs );
1487 FT_FREE( hmtx_table );
1488
1489 return error;
1490
1491 Fail:
1492 FT_FREE( advance_widths );
1493 FT_FREE( lsbs );
1494 FT_FREE( hmtx_table );
1495
1496 if ( !error )
1497 error = FT_THROW( Invalid_Table );
1498
1499 return error;
1500 }
1501
1502
1503 static FT_Error
1504 reconstruct_font( FT_Byte* transformed_buf,
1505 FT_ULong transformed_buf_size,
1507 WOFF2_Header woff2,
1509 FT_Byte** sfnt_bytes,
1510 FT_ULong* sfnt_size,
1512 {
1513 /* Memory management of `transformed_buf' is handled by the caller. */
1514
1517 FT_Byte* buf_cursor = NULL;
1518 FT_Byte* table_entry = NULL;
1519
1520 /* We are reallocating memory for `sfnt', so its pointer may change. */
1521 FT_Byte* sfnt = *sfnt_bytes;
1522
1523 FT_UShort num_tables = woff2->num_tables;
1524 FT_ULong dest_offset = 12 + num_tables * 16UL;
1525
1526 FT_ULong checksum = 0;
1527 FT_ULong loca_checksum = 0;
1528 FT_Int nn = 0;
1529 FT_UShort num_hmetrics = 0;
1530 FT_ULong font_checksum = info->header_checksum;
1531 FT_Bool is_glyf_xform = FALSE;
1532
1533 FT_ULong table_entry_offset = 12;
1534
1535
1536 /* A few table checks before reconstruction. */
1537 /* `glyf' must be present with `loca'. */
1538 info->glyf_table = find_table( indices, num_tables, TTAG_glyf );
1539 info->loca_table = find_table( indices, num_tables, TTAG_loca );
1540
1541 if ( ( info->glyf_table == NULL ) ^ ( info->loca_table == NULL ) )
1542 {
1543 FT_ERROR(( "One of `glyf'/`loca' tables missing.\n" ));
1544 return FT_THROW( Invalid_Table );
1545 }
1546
1547 /* Both `glyf' and `loca' must have same transformation. */
1548 if ( info->glyf_table != NULL )
1549 {
1550 if ( ( info->glyf_table->flags & WOFF2_FLAGS_TRANSFORM ) !=
1551 ( info->loca_table->flags & WOFF2_FLAGS_TRANSFORM ) )
1552 {
1553 FT_ERROR(( "Transformation mismatch"
1554 " between `glyf' and `loca' table." ));
1555 return FT_THROW( Invalid_Table );
1556 }
1557 }
1558
1559 /* Create buffer for table entries. */
1560 if ( FT_NEW_ARRAY( table_entry, 16 ) )
1561 goto Fail;
1562
1563 /* Create a stream for the uncompressed buffer. */
1564 if ( FT_NEW( stream ) )
1565 goto Fail;
1566 FT_Stream_OpenMemory( stream, transformed_buf, transformed_buf_size );
1567
1568 FT_ASSERT( FT_STREAM_POS() == 0 );
1569
1570 /* Reconstruct/copy tables to output stream. */
1571 for ( nn = 0; nn < num_tables; nn++ )
1572 {
1573 WOFF2_TableRec table = *( indices[nn] );
1574
1575
1576 FT_TRACE3(( "Seeking to %ld with table size %ld.\n",
1577 table.src_offset, table.src_length ));
1578 FT_TRACE3(( "Table tag: %c%c%c%c.\n",
1579 (FT_Char)( table.Tag >> 24 ),
1580 (FT_Char)( table.Tag >> 16 ),
1581 (FT_Char)( table.Tag >> 8 ),
1582 (FT_Char)( table.Tag ) ));
1583
1584 if ( FT_STREAM_SEEK( table.src_offset ) )
1585 goto Fail;
1586
1587 if ( table.src_offset + table.src_length > transformed_buf_size )
1588 goto Fail;
1589
1590 /* Get stream size for fields of `hmtx' table. */
1591 if ( table.Tag == TTAG_hhea )
1592 {
1593 if ( read_num_hmetrics( stream, &num_hmetrics ) )
1594 goto Fail;
1595 }
1596
1597 info->num_hmetrics = num_hmetrics;
1598
1599 checksum = 0;
1601 {
1602 /* Check whether `head' is at least 12 bytes. */
1603 if ( table.Tag == TTAG_head )
1604 {
1605 if ( table.src_length < 12 )
1606 goto Fail;
1607
1608 buf_cursor = transformed_buf + table.src_offset + 8;
1609 /* Set checkSumAdjustment = 0 */
1610 WRITE_ULONG( buf_cursor, 0 );
1611 }
1612
1613 table.dst_offset = dest_offset;
1614
1615 checksum = compute_ULong_sum( transformed_buf + table.src_offset,
1616 table.src_length );
1617 FT_TRACE4(( "Checksum = %09lx.\n", checksum ));
1618
1619 if ( WRITE_SFNT_BUF( transformed_buf + table.src_offset,
1620 table.src_length ) )
1621 goto Fail;
1622 }
1623 else
1624 {
1625 FT_TRACE3(( "This table is transformed.\n" ));
1626
1627 if ( table.Tag == TTAG_glyf )
1628 {
1629 is_glyf_xform = TRUE;
1630 table.dst_offset = dest_offset;
1631
1633 &checksum,
1634 &loca_checksum,
1635 &sfnt,
1636 sfnt_size,
1637 &dest_offset,
1638 info,
1639 memory ) )
1640 goto Fail;
1641
1642 FT_TRACE4(( "Checksum = %09lx.\n", checksum ));
1643 }
1644
1645 else if ( table.Tag == TTAG_loca )
1646 checksum = loca_checksum;
1647
1648 else if ( table.Tag == TTAG_hmtx )
1649 {
1650 /* If glyf is not transformed and hmtx is, handle separately. */
1651 if ( !is_glyf_xform )
1652 {
1653 if ( get_x_mins( stream, indices, num_tables, info, memory ) )
1654 goto Fail;
1655 }
1656
1657 table.dst_offset = dest_offset;
1658
1660 info->num_glyphs,
1661 info->num_hmetrics,
1662 info->x_mins,
1663 &checksum,
1664 &sfnt,
1665 sfnt_size,
1666 &dest_offset,
1667 memory ) )
1668 goto Fail;
1669 }
1670 else
1671 {
1672 /* Unknown transform. */
1673 FT_ERROR(( "Unknown table transform.\n" ));
1674 goto Fail;
1675 }
1676 }
1677
1678 font_checksum += checksum;
1679
1680 buf_cursor = &table_entry[0];
1681 WRITE_ULONG( buf_cursor, table.Tag );
1682 WRITE_ULONG( buf_cursor, checksum );
1683 WRITE_ULONG( buf_cursor, table.dst_offset );
1684 WRITE_ULONG( buf_cursor, table.dst_length );
1685
1686 WRITE_SFNT_BUF_AT( table_entry_offset, table_entry, 16 );
1687
1688 /* Update checksum. */
1689 font_checksum += compute_ULong_sum( table_entry, 16 );
1690
1691 if ( pad4( &sfnt, sfnt_size, &dest_offset, memory ) )
1692 goto Fail;
1693
1694 /* Sanity check. */
1695 if ( (FT_ULong)( table.dst_offset + table.dst_length ) > dest_offset )
1696 {
1697 FT_ERROR(( "Table was partially written.\n" ));
1698 goto Fail;
1699 }
1700 }
1701
1702 /* Update `head' checkSumAdjustment. */
1703 info->head_table = find_table( indices, num_tables, TTAG_head );
1704 if ( !info->head_table )
1705 {
1706 FT_ERROR(( "`head' table is missing.\n" ));
1707 goto Fail;
1708 }
1709
1710 if ( info->head_table->dst_length < 12 )
1711 goto Fail;
1712
1713 buf_cursor = sfnt + info->head_table->dst_offset + 8;
1714 font_checksum = 0xB1B0AFBA - font_checksum;
1715
1716 WRITE_ULONG( buf_cursor, font_checksum );
1717
1718 FT_TRACE2(( "Final checksum = %09lx.\n", font_checksum ));
1719
1720 woff2->actual_sfnt_size = dest_offset;
1721
1722 /* Set pointer of sfnt stream to its correct value. */
1723 *sfnt_bytes = sfnt;
1724
1725 FT_FREE( table_entry );
1727 FT_FREE( stream );
1728
1729 return error;
1730
1731 Fail:
1732 if ( !error )
1733 error = FT_THROW( Invalid_Table );
1734
1735 /* Set pointer of sfnt stream to its correct value. */
1736 *sfnt_bytes = sfnt;
1737
1738 FT_FREE( table_entry );
1740 FT_FREE( stream );
1741
1742 return error;
1743 }
1744
1745
1746 /* Replace `face->root.stream' with a stream containing the extracted */
1747 /* SFNT of a WOFF2 font. */
1748
1751 TT_Face face,
1752 FT_Int* face_instance_index,
1753 FT_Long* num_faces )
1754 {
1755 FT_Memory memory = stream->memory;
1757 FT_Int face_index;
1758
1759 WOFF2_HeaderRec woff2;
1760 WOFF2_InfoRec info = { 0, 0, 0, NULL, NULL, NULL, NULL };
1763 WOFF2_Table* temp_indices = NULL;
1764 WOFF2_Table last_table;
1765
1766 FT_Int nn;
1767 FT_ULong j;
1769 FT_UShort xform_version;
1770 FT_ULong src_offset = 0;
1771
1772 FT_UInt glyf_index;
1773 FT_UInt loca_index;
1774 FT_UInt32 file_offset;
1775
1776 FT_Byte* sfnt = NULL;
1777 FT_Stream sfnt_stream = NULL;
1778 FT_Byte* sfnt_header;
1779 FT_ULong sfnt_size;
1780
1781 FT_Byte* uncompressed_buf = NULL;
1782
1783 static const FT_Frame_Field woff2_header_fields[] =
1784 {
1785#undef FT_STRUCTURE
1786#define FT_STRUCTURE WOFF2_HeaderRec
1787
1788 FT_FRAME_START( 48 ),
1790 FT_FRAME_ULONG ( flavor ),
1792 FT_FRAME_USHORT ( num_tables ),
1794 FT_FRAME_ULONG ( totalSfntSize ),
1795 FT_FRAME_ULONG ( totalCompressedSize ),
1796 FT_FRAME_SKIP_BYTES( 2 * 2 ),
1797 FT_FRAME_ULONG ( metaOffset ),
1798 FT_FRAME_ULONG ( metaLength ),
1799 FT_FRAME_ULONG ( metaOrigLength ),
1800 FT_FRAME_ULONG ( privOffset ),
1801 FT_FRAME_ULONG ( privLength ),
1803 };
1804
1805
1806 FT_ASSERT( stream == face->root.stream );
1807 FT_ASSERT( FT_STREAM_POS() == 0 );
1808
1809 face_index = FT_ABS( *face_instance_index ) & 0xFFFF;
1810
1811 /* Read WOFF2 Header. */
1812 if ( FT_STREAM_READ_FIELDS( woff2_header_fields, &woff2 ) )
1813 return error;
1814
1815 FT_TRACE4(( "signature -> 0x%lX\n", woff2.signature ));
1816 FT_TRACE2(( "flavor -> 0x%08lx\n", woff2.flavor ));
1817 FT_TRACE4(( "length -> %lu\n", woff2.length ));
1818 FT_TRACE2(( "num_tables -> %hu\n", woff2.num_tables ));
1819 FT_TRACE4(( "totalSfntSize -> %lu\n", woff2.totalSfntSize ));
1820 FT_TRACE4(( "metaOffset -> %lu\n", woff2.metaOffset ));
1821 FT_TRACE4(( "metaLength -> %lu\n", woff2.metaLength ));
1822 FT_TRACE4(( "privOffset -> %lu\n", woff2.privOffset ));
1823 FT_TRACE4(( "privLength -> %lu\n", woff2.privLength ));
1824
1825 /* Make sure we don't recurse back here. */
1826 if ( woff2.flavor == TTAG_wOF2 )
1827 return FT_THROW( Invalid_Table );
1828
1829 /* Miscellaneous checks. */
1830 if ( woff2.length != stream->size ||
1831 woff2.num_tables == 0 ||
1832 48 + woff2.num_tables * 20UL >= woff2.length ||
1833 ( woff2.metaOffset == 0 && ( woff2.metaLength != 0 ||
1834 woff2.metaOrigLength != 0 ) ) ||
1835 ( woff2.metaLength != 0 && woff2.metaOrigLength == 0 ) ||
1836 ( woff2.metaOffset >= woff2.length ) ||
1837 ( woff2.length - woff2.metaOffset < woff2.metaLength ) ||
1838 ( woff2.privOffset == 0 && woff2.privLength != 0 ) ||
1839 ( woff2.privOffset >= woff2.length ) ||
1840 ( woff2.length - woff2.privOffset < woff2.privLength ) )
1841 {
1842 FT_ERROR(( "woff2_open_font: invalid WOFF2 header\n" ));
1843 return FT_THROW( Invalid_Table );
1844 }
1845
1846 FT_TRACE2(( "woff2_open_font: WOFF2 Header is valid.\n" ));
1847
1848 woff2.ttc_fonts = NULL;
1849
1850 /* Read table directory. */
1851 if ( FT_NEW_ARRAY( tables, woff2.num_tables ) ||
1852 FT_NEW_ARRAY( indices, woff2.num_tables ) )
1853 goto Exit;
1854
1855 FT_TRACE2((
1856 "\n"
1857 " tag flags transform origLen transformLen offset\n"
1858 " -----------------------------------------------------------\n" ));
1859 /* " XXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX" */
1860
1861 for ( nn = 0; nn < woff2.num_tables; nn++ )
1862 {
1863 WOFF2_Table table = tables + nn;
1864
1865
1866 if ( FT_READ_BYTE( table->FlagByte ) )
1867 goto Exit;
1868
1869 if ( ( table->FlagByte & 0x3f ) == 0x3f )
1870 {
1871 if ( FT_READ_ULONG( table->Tag ) )
1872 goto Exit;
1873 }
1874 else
1875 {
1876 table->Tag = woff2_known_tags( table->FlagByte & 0x3f );
1877 if ( !table->Tag )
1878 {
1879 FT_ERROR(( "woff2_open_font: Unknown table tag." ));
1880 error = FT_THROW( Invalid_Table );
1881 goto Exit;
1882 }
1883 }
1884
1885 flags = 0;
1886 xform_version = ( table->FlagByte >> 6 ) & 0x03;
1887
1888 /* 0 means xform for glyph/loca, non-0 for others. */
1889 if ( table->Tag == TTAG_glyf || table->Tag == TTAG_loca )
1890 {
1891 if ( xform_version == 0 )
1893 }
1894 else if ( xform_version != 0 )
1896
1897 flags |= xform_version;
1898
1899 if ( READ_BASE128( table->dst_length ) )
1900 goto Exit;
1901
1902 table->TransformLength = table->dst_length;
1903
1904 if ( ( flags & WOFF2_FLAGS_TRANSFORM ) != 0 )
1905 {
1906 if ( READ_BASE128( table->TransformLength ) )
1907 goto Exit;
1908
1909 if ( table->Tag == TTAG_loca && table->TransformLength )
1910 {
1911 FT_ERROR(( "woff2_open_font: Invalid loca `transformLength'.\n" ));
1912 error = FT_THROW( Invalid_Table );
1913 goto Exit;
1914 }
1915 }
1916
1917 if ( src_offset + table->TransformLength < src_offset )
1918 {
1919 FT_ERROR(( "woff2_open_font: invalid WOFF2 table directory.\n" ));
1920 error = FT_THROW( Invalid_Table );
1921 goto Exit;
1922 }
1923
1924 table->src_offset = src_offset;
1925 table->src_length = table->TransformLength;
1926 src_offset += table->TransformLength;
1927 table->flags = flags;
1928
1929 FT_TRACE2(( " %c%c%c%c %08d %08d %08ld %08ld %08ld\n",
1930 (FT_Char)( table->Tag >> 24 ),
1931 (FT_Char)( table->Tag >> 16 ),
1932 (FT_Char)( table->Tag >> 8 ),
1933 (FT_Char)( table->Tag ),
1934 table->FlagByte & 0x3f,
1935 ( table->FlagByte >> 6 ) & 0x03,
1936 table->dst_length,
1937 table->TransformLength,
1938 table->src_offset ));
1939
1940 indices[nn] = table;
1941 }
1942
1943 /* End of last table is uncompressed size. */
1944 last_table = indices[woff2.num_tables - 1];
1945
1946 woff2.uncompressed_size = last_table->src_offset +
1947 last_table->src_length;
1948 if ( woff2.uncompressed_size < last_table->src_offset )
1949 {
1950 error = FT_THROW( Invalid_Table );
1951 goto Exit;
1952 }
1953
1954 FT_TRACE2(( "Table directory parsed.\n" ));
1955
1956 /* Check for and read collection directory. */
1957 woff2.num_fonts = 1;
1958 woff2.header_version = 0;
1959
1960 if ( woff2.flavor == TTAG_ttcf )
1961 {
1962 FT_TRACE2(( "Font is a TTC, reading collection directory.\n" ));
1963
1964 if ( FT_READ_ULONG( woff2.header_version ) )
1965 goto Exit;
1966
1967 if ( woff2.header_version != 0x00010000 &&
1968 woff2.header_version != 0x00020000 )
1969 {
1970 error = FT_THROW( Invalid_Table );
1971 goto Exit;
1972 }
1973
1974 if ( READ_255USHORT( woff2.num_fonts ) )
1975 goto Exit;
1976
1977 if ( !woff2.num_fonts )
1978 {
1979 error = FT_THROW( Invalid_Table );
1980 goto Exit;
1981 }
1982
1983 FT_TRACE4(( "Number of fonts in TTC: %d\n", woff2.num_fonts ));
1984
1985 if ( FT_NEW_ARRAY( woff2.ttc_fonts, woff2.num_fonts ) )
1986 goto Exit;
1987
1988 for ( nn = 0; nn < woff2.num_fonts; nn++ )
1989 {
1990 WOFF2_TtcFont ttc_font = woff2.ttc_fonts + nn;
1991
1992
1993 if ( READ_255USHORT( ttc_font->num_tables ) )
1994 goto Exit;
1995 if ( FT_READ_ULONG( ttc_font->flavor ) )
1996 goto Exit;
1997
1998 if ( FT_NEW_ARRAY( ttc_font->table_indices, ttc_font->num_tables ) )
1999 goto Exit;
2000
2001 FT_TRACE5(( "Number of tables in font %d: %d\n",
2002 nn, ttc_font->num_tables ));
2003
2004#ifdef FT_DEBUG_LEVEL_TRACE
2005 if ( ttc_font->num_tables )
2006 FT_TRACE6(( " Indices: " ));
2007#endif
2008
2009 glyf_index = 0;
2010 loca_index = 0;
2011
2012 for ( j = 0; j < ttc_font->num_tables; j++ )
2013 {
2014 FT_UShort table_index;
2016
2017
2018 if ( READ_255USHORT( table_index ) )
2019 goto Exit;
2020
2021 FT_TRACE6(( "%hu ", table_index ));
2022 if ( table_index >= woff2.num_tables )
2023 {
2024 FT_ERROR(( "woff2_open_font: invalid table index\n" ));
2025 error = FT_THROW( Invalid_Table );
2026 goto Exit;
2027 }
2028
2029 ttc_font->table_indices[j] = table_index;
2030
2031 table = indices[table_index];
2032 if ( table->Tag == TTAG_loca )
2033 loca_index = table_index;
2034 if ( table->Tag == TTAG_glyf )
2035 glyf_index = table_index;
2036 }
2037
2038#ifdef FT_DEBUG_LEVEL_TRACE
2039 if ( ttc_font->num_tables )
2040 FT_TRACE6(( "\n" ));
2041#endif
2042
2043 /* glyf and loca must be consecutive */
2044 if ( glyf_index > 0 || loca_index > 0 )
2045 {
2046 if ( glyf_index > loca_index ||
2047 loca_index - glyf_index != 1 )
2048 {
2049 error = FT_THROW( Invalid_Table );
2050 goto Exit;
2051 }
2052 }
2053 }
2054
2055 /* Collection directory reading complete. */
2056 FT_TRACE2(( "WOFF2 collection directory is valid.\n" ));
2057 }
2058 else
2059 woff2.ttc_fonts = NULL;
2060
2062 file_offset = ROUND4( woff2.compressed_offset +
2063 woff2.totalCompressedSize );
2064
2065 /* Some more checks before we start reading the tables. */
2066 if ( file_offset > woff2.length )
2067 {
2068 error = FT_THROW( Invalid_Table );
2069 goto Exit;
2070 }
2071
2072 if ( woff2.metaOffset )
2073 {
2074 if ( file_offset != woff2.metaOffset )
2075 {
2076 error = FT_THROW( Invalid_Table );
2077 goto Exit;
2078 }
2079 file_offset = ROUND4(woff2.metaOffset + woff2.metaLength);
2080 }
2081
2082 if ( woff2.privOffset )
2083 {
2084 if ( file_offset != woff2.privOffset )
2085 {
2086 error = FT_THROW( Invalid_Table );
2087 goto Exit;
2088 }
2089 file_offset = ROUND4(woff2.privOffset + woff2.privLength);
2090 }
2091
2092 if ( file_offset != ( ROUND4( woff2.length ) ) )
2093 {
2094 error = FT_THROW( Invalid_Table );
2095 goto Exit;
2096 }
2097
2098 /* Validate requested face index. */
2099 *num_faces = woff2.num_fonts;
2100 /* value -(N+1) requests information on index N */
2101 if ( *face_instance_index < 0 )
2102 face_index--;
2103
2104 if ( face_index >= woff2.num_fonts )
2105 {
2106 if ( *face_instance_index >= 0 )
2107 {
2108 error = FT_THROW( Invalid_Argument );
2109 goto Exit;
2110 }
2111 else
2112 face_index = 0;
2113 }
2114
2115 /* Only retain tables of the requested face in a TTC. */
2116 if ( woff2.header_version )
2117 {
2118 WOFF2_TtcFont ttc_font = woff2.ttc_fonts + face_index;
2119
2120
2121 /* Create a temporary array. */
2122 if ( FT_NEW_ARRAY( temp_indices,
2123 ttc_font->num_tables ) )
2124 goto Exit;
2125
2126 FT_TRACE4(( "Storing tables for TTC face index %d.\n", face_index ));
2127 for ( nn = 0; nn < ttc_font->num_tables; nn++ )
2128 temp_indices[nn] = indices[ttc_font->table_indices[nn]];
2129
2130 /* Resize array to required size. */
2132 woff2.num_tables,
2133 ttc_font->num_tables ) )
2134 goto Exit;
2135
2136 for ( nn = 0; nn < ttc_font->num_tables; nn++ )
2137 indices[nn] = temp_indices[nn];
2138
2139 FT_FREE( temp_indices );
2140
2141 /* Change header values. */
2142 woff2.flavor = ttc_font->flavor;
2143 woff2.num_tables = ttc_font->num_tables;
2144 }
2145
2146 /* We need to allocate this much at the minimum. */
2147 sfnt_size = 12 + woff2.num_tables * 16UL;
2148 /* This is what we normally expect. */
2149 /* Initially trust `totalSfntSize' and change later as required. */
2150 if ( woff2.totalSfntSize > sfnt_size )
2151 {
2152 /* However, adjust the value to something reasonable. */
2153
2154 /* Factor 64 is heuristic. */
2155 if ( ( woff2.totalSfntSize >> 6 ) > woff2.length )
2156 sfnt_size = woff2.length << 6;
2157 else
2158 sfnt_size = woff2.totalSfntSize;
2159
2160 /* Value 1<<26 = 67108864 is heuristic. */
2161 if (sfnt_size >= (1 << 26))
2162 sfnt_size = 1 << 26;
2163
2164#ifdef FT_DEBUG_LEVEL_TRACE
2165 if ( sfnt_size != woff2.totalSfntSize )
2166 FT_TRACE4(( "adjusting estimate of uncompressed font size"
2167 " to %lu bytes\n",
2168 sfnt_size ));
2169#endif
2170 }
2171
2172 /* Write sfnt header. */
2173 if ( FT_ALLOC( sfnt, sfnt_size ) ||
2174 FT_NEW( sfnt_stream ) )
2175 goto Exit;
2176
2177 sfnt_header = sfnt;
2178
2179 WRITE_ULONG( sfnt_header, woff2.flavor );
2180
2181 if ( woff2.num_tables )
2182 {
2183 FT_UInt searchRange, entrySelector, rangeShift, x;
2184
2185
2186 x = woff2.num_tables;
2187 entrySelector = 0;
2188 while ( x )
2189 {
2190 x >>= 1;
2191 entrySelector += 1;
2192 }
2193 entrySelector--;
2194
2195 searchRange = ( 1 << entrySelector ) * 16;
2196 rangeShift = ( woff2.num_tables * 16 ) - searchRange;
2197
2198 WRITE_USHORT( sfnt_header, woff2.num_tables );
2199 WRITE_USHORT( sfnt_header, searchRange );
2200 WRITE_USHORT( sfnt_header, entrySelector );
2201 WRITE_USHORT( sfnt_header, rangeShift );
2202 }
2203
2204 info.header_checksum = compute_ULong_sum( sfnt, 12 );
2205
2206 /* Sort tables by tag. */
2208 woff2.num_tables,
2209 sizeof ( WOFF2_Table ),
2210 compare_tags );
2211
2212 if ( woff2.uncompressed_size < 1 )
2213 {
2214 error = FT_THROW( Invalid_Table );
2215 goto Exit;
2216 }
2217
2218 if ( woff2.uncompressed_size > sfnt_size )
2219 {
2220 FT_ERROR(( "woff2_open_font: SFNT table lengths are too large.\n" ));
2221 error = FT_THROW( Invalid_Table );
2222 goto Exit;
2223 }
2224
2225 /* Allocate memory for uncompressed table data. */
2226 if ( FT_ALLOC( uncompressed_buf, woff2.uncompressed_size ) ||
2228 goto Exit;
2229
2230 /* Uncompress the stream. */
2231 error = woff2_decompress( uncompressed_buf,
2232 woff2.uncompressed_size,
2233 stream->cursor,
2234 woff2.totalCompressedSize );
2235
2236 FT_FRAME_EXIT();
2237
2238 if ( error )
2239 goto Exit;
2240
2241 error = reconstruct_font( uncompressed_buf,
2242 woff2.uncompressed_size,
2243 indices,
2244 &woff2,
2245 &info,
2246 &sfnt,
2247 &sfnt_size,
2248 memory );
2249
2250 if ( error )
2251 goto Exit;
2252
2253 /* Resize `sfnt' to actual size of sfnt stream. */
2254 if ( woff2.actual_sfnt_size < sfnt_size )
2255 {
2256 FT_TRACE5(( "Trimming sfnt stream from %lu to %lu.\n",
2257 sfnt_size, woff2.actual_sfnt_size ));
2258 if ( FT_REALLOC( sfnt,
2259 (FT_ULong)( sfnt_size ),
2260 (FT_ULong)( woff2.actual_sfnt_size ) ) )
2261 goto Exit;
2262 }
2263
2264 /* `reconstruct_font' has done all the work. */
2265 /* Swap out stream and return. */
2266 FT_Stream_OpenMemory( sfnt_stream, sfnt, woff2.actual_sfnt_size );
2267 sfnt_stream->memory = stream->memory;
2268 sfnt_stream->close = stream_close;
2269
2271 face->root.stream,
2272 ( face->root.face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
2273
2274 face->root.stream = sfnt_stream;
2275 face->root.face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
2276
2277 /* Set face_index to 0 or -1. */
2278 if ( *face_instance_index >= 0 )
2279 *face_instance_index = 0;
2280 else
2281 *face_instance_index = -1;
2282
2283 FT_TRACE2(( "woff2_open_font: SFNT synthesized.\n" ));
2284
2285 Exit:
2286 FT_FREE( tables );
2287 FT_FREE( indices );
2288 FT_FREE( uncompressed_buf );
2289 FT_FREE( info.x_mins );
2290
2291 if ( woff2.ttc_fonts )
2292 {
2293 WOFF2_TtcFont ttc_font = woff2.ttc_fonts;
2294
2295
2296 for ( nn = 0; nn < woff2.num_fonts; nn++ )
2297 {
2298 FT_FREE( ttc_font->table_indices );
2299 ttc_font++;
2300 }
2301
2302 FT_FREE( woff2.ttc_fonts );
2303 }
2304
2305 if ( error )
2306 {
2307 FT_FREE( sfnt );
2308 if ( sfnt_stream )
2309 {
2310 FT_Stream_Close( sfnt_stream );
2311 FT_FREE( sfnt_stream );
2312 }
2313 }
2314
2315 return error;
2316 }
2317
2318
2319#undef READ_255USHORT
2320#undef READ_BASE128
2321#undef ROUND4
2322#undef WRITE_USHORT
2323#undef WRITE_ULONG
2324#undef WRITE_SHORT
2325#undef WRITE_SFNT_BUF
2326#undef WRITE_SFNT_BUF_AT
2327
2328#undef N_CONTOUR_STREAM
2329#undef N_POINTS_STREAM
2330#undef FLAG_STREAM
2331#undef GLYPH_STREAM
2332#undef COMPOSITE_STREAM
2333#undef BBOX_STREAM
2334#undef INSTRUCTION_STREAM
2335
2336
2337/* END */
#define FT_CALLBACK_DEF(x)
#define FT_LOCAL_DEF(x)
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
struct nls_table * tables
Definition: nls_base.c:22
POINTL point
Definition: edittest.c:50
int Fail
Definition: ehthrow.cxx:24
#define FT_FACE_FLAG_EXTERNAL_STREAM
Definition: freetype.h:1207
return FT_Err_Ok
Definition: ftbbox.c:526
#define FT_ASSERT(condition)
Definition: ftdebug.h:241
#define FT_ERROR(varformat)
Definition: ftdebug.h:211
#define FT_TRACE5(varformat)
Definition: ftdebug.h:192
#define FT_TRACE3(varformat)
Definition: ftdebug.h:190
#define FT_TRACE6(varformat)
Definition: ftdebug.h:193
#define FT_THROW(e)
Definition: ftdebug.h:243
#define FT_TRACE2(varformat)
Definition: ftdebug.h:189
#define FT_TRACE4(varformat)
Definition: ftdebug.h:191
#define FT_REALLOC(ptr, cursz, newsz)
Definition: ftmemory.h:314
#define FT_NEW_ARRAY(ptr, count)
Definition: ftmemory.h:341
#define FT_NEW(ptr)
Definition: ftmemory.h:339
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:311
#define FT_FREE(ptr)
Definition: ftmemory.h:337
#define FT_RENEW_ARRAY(ptr, curcnt, newcnt)
Definition: ftmemory.h:344
#define FT_ABS(a)
Definition: ftobjs.h:73
#define FT_MIN(a, b)
Definition: ftobjs.h:70
#define FT_MAX(a, b)
Definition: ftobjs.h:71
#define ft_memcpy
Definition: ftstdlib.h:82
#define FT_INT_MIN
Definition: ftstdlib.h:64
#define FT_INT_MAX
Definition: ftstdlib.h:63
#define ft_qsort
Definition: ftstdlib.h:122
#define FT_FRAME_ENTER(size)
Definition: ftstream.h:548
#define FT_READ_USHORT(var)
Definition: ftstream.h:339
#define FT_FRAME_END
Definition: ftstream.h:118
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:525
#define FT_READ_ULONG(var)
Definition: ftstream.h:343
#define FT_STREAM_POS()
Definition: ftstream.h:522
FT_Stream_Close(FT_Stream stream)
Definition: ftstream.c:48
#define FT_FRAME_ULONG(f)
Definition: ftstream.h:121
#define FT_READ_BYTE(var)
Definition: ftstream.h:336
#define FT_FRAME_EXIT()
Definition: ftstream.h:553
#define FT_FRAME_SKIP_BYTES(count)
Definition: ftstream.h:147
#define FT_STREAM_READ_FIELDS(fields, object)
Definition: ftstream.h:544
#define FT_STREAM_SKIP(distance)
Definition: ftstream.h:529
FT_Stream_Free(FT_Stream stream, FT_Int external)
Definition: ftobjs.c:257
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:533
#define FT_FRAME_START(size)
Definition: ftstream.h:117
FT_Stream_OpenMemory(FT_Stream stream, const FT_Byte *base, FT_ULong size)
Definition: ftstream.c:34
#define FT_FRAME_USHORT(f)
Definition: ftstream.h:123
#define FT_READ_SHORT(var)
Definition: ftstream.h:338
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:64
signed char FT_Char
Definition: fttypes.h:143
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
unsigned long FT_ULong
Definition: fttypes.h:253
unsigned char FT_Byte
Definition: fttypes.h:154
int FT_Error
Definition: fttypes.h:299
signed long FT_Long
Definition: fttypes.h:242
unsigned short FT_UShort
Definition: fttypes.h:209
signed short FT_Short
Definition: fttypes.h:198
unsigned int FT_UInt
Definition: fttypes.h:231
size_t FT_Offset
Definition: fttypes.h:323
signed int FT_Int
Definition: fttypes.h:220
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
const GLdouble * v
Definition: gl.h:2040
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint GLsizei GLenum const GLvoid * indices
Definition: gl.h:1545
GLenum src
Definition: glext.h:6340
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLsizei const GLvoid * pointer
Definition: glext.h:5848
GLenum GLuint GLint GLenum face
Definition: glext.h:7025
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint in
Definition: glext.h:9616
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint64EXT * result
Definition: glext.h:11304
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei const GLfloat * points
Definition: glext.h:8112
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define b
Definition: ke_i.h:79
GLint dy
Definition: linetemp.h:97
if(dx< 0)
Definition: linetemp.h:194
GLint dx
Definition: linetemp.h:97
#define error(str)
Definition: mkdosfs.c:1605
static CRYPT_DATA_BLOB b2[]
Definition: msg.c:538
static CRYPT_DATA_BLOB b1[]
Definition: msg.c:529
static char memory[1024 *256]
Definition: process.c:122
static HANDLE PIO_APC_ROUTINE PVOID PIO_STATUS_BLOCK ULONG PVOID ULONG in_size
Definition: file.c:100
static FT_Error ReadBase128(FT_Stream stream, FT_ULong *value)
Definition: sfwoff2.c:172
#define FLAG_STREAM
Definition: sfwoff2.c:83
static FT_Error woff2_decompress(FT_Byte *dst, FT_ULong dst_size, const FT_Byte *src, FT_ULong src_size)
Definition: sfwoff2.c:314
#define WRITE_ULONG(p, v)
Definition: sfwoff2.c:57
static void compute_bbox(FT_ULong n_points, const WOFF2_Point points, FT_Byte *dst, FT_UShort *src_x_min)
Definition: sfwoff2.c:668
static FT_Error get_x_mins(FT_Stream stream, WOFF2_Table *tables, FT_UShort num_tables, WOFF2_Info info, FT_Memory memory)
Definition: sfwoff2.c:1258
#define INSTRUCTION_STREAM
Definition: sfwoff2.c:87
static FT_Error read_num_hmetrics(FT_Stream stream, FT_UShort *num_hmetrics)
Definition: sfwoff2.c:370
#define N_POINTS_STREAM
Definition: sfwoff2.c:82
#define READ_255USHORT(var)
Definition: sfwoff2.c:42
static WOFF2_Table find_table(WOFF2_Table *tables, FT_UShort num_tables, FT_ULong tag)
Definition: sfwoff2.c:352
static FT_Error reconstruct_hmtx(FT_Stream stream, FT_UShort num_glyphs, FT_UShort num_hmetrics, FT_Short *x_mins, FT_ULong *checksum, FT_Byte **sfnt_bytes, FT_ULong *sfnt_size, FT_ULong *out_offset, FT_Memory memory)
Definition: sfwoff2.c:1358
#define ROUND4(var)
Definition: sfwoff2.c:47
static FT_Error store_loca(FT_ULong *loca_values, FT_ULong loca_values_size, FT_UShort index_format, FT_ULong *checksum, FT_Byte **sfnt_bytes, FT_ULong *sfnt_size, FT_ULong *out_offset, FT_Memory memory)
Definition: sfwoff2.c:767
#define GLYPH_STREAM
Definition: sfwoff2.c:84
static FT_Int safe_int_addition(FT_Int a, FT_Int b, FT_Int *result)
Definition: sfwoff2.c:401
#define BBOX_STREAM
Definition: sfwoff2.c:86
static FT_Error reconstruct_glyf(FT_Stream stream, FT_ULong *glyf_checksum, FT_ULong *loca_checksum, FT_Byte **sfnt_bytes, FT_ULong *sfnt_size, FT_ULong *out_offset, WOFF2_Info info, FT_Memory memory)
Definition: sfwoff2.c:831
static FT_ULong compute_ULong_sum(FT_Byte *buf, FT_ULong size)
Definition: sfwoff2.c:285
static FT_Error reconstruct_font(FT_Byte *transformed_buf, FT_ULong transformed_buf_size, WOFF2_Table *indices, WOFF2_Header woff2, WOFF2_Info info, FT_Byte **sfnt_bytes, FT_ULong *sfnt_size, FT_Memory memory)
Definition: sfwoff2.c:1504
#define WRITE_SFNT_BUF(buf, s)
Definition: sfwoff2.c:75
static FT_Error pad4(FT_Byte **sfnt_bytes, FT_ULong *sfnt_size, FT_ULong *out_offset, FT_Memory memory)
Definition: sfwoff2.c:255
compare_tags(const void *a, const void *b)
Definition: sfwoff2.c:105
static FT_Error store_points(FT_ULong n_points, const WOFF2_Point points, FT_UShort n_contours, FT_UShort instruction_len, FT_Byte *dst, FT_ULong dst_size, FT_ULong *glyph_size)
Definition: sfwoff2.c:533
static FT_Error write_buf(FT_Byte **dst_bytes, FT_ULong *dst_size, FT_ULong *offset, FT_Byte *src, FT_ULong size, FT_Memory memory)
Definition: sfwoff2.c:212
#define WRITE_SFNT_BUF_AT(offset, buf, s)
Definition: sfwoff2.c:78
static FT_Error Read255UShort(FT_Stream stream, FT_UShort *value)
Definition: sfwoff2.c:125
#define READ_BASE128(var)
Definition: sfwoff2.c:44
static FT_Error triplet_decode(const FT_Byte *flags_in, const FT_Byte *in, FT_ULong in_size, FT_ULong n_points, WOFF2_Point result, FT_ULong *in_bytes_used)
Definition: sfwoff2.c:421
#define WRITE_SHORT(p, v)
Definition: sfwoff2.c:67
#define COMPOSITE_STREAM
Definition: sfwoff2.c:85
static void stream_close(FT_Stream stream)
Definition: sfwoff2.c:91
#define N_CONTOUR_STREAM
Definition: sfwoff2.c:81
static FT_Int with_sign(FT_Byte flag, FT_Int base_val)
Definition: sfwoff2.c:391
#define WRITE_USHORT(p, v)
Definition: sfwoff2.c:49
static FT_Error compositeGlyph_size(FT_Stream stream, FT_ULong offset, FT_ULong *size, FT_Bool *have_instructions)
Definition: sfwoff2.c:718
woff2_open_font(FT_Stream stream, TT_Face face, FT_Int *face_instance_index, FT_Long *num_faces)
Definition: sfwoff2.c:1750
#define GLYF_THIS_Y_IS_SAME
Definition: sfwoff2.h:57
#define FLAG_WE_HAVE_AN_X_AND_Y_SCALE
Definition: sfwoff2.h:47
#define GLYF_X_SHORT
Definition: sfwoff2.h:53
#define WOFF2_FLAGS_TRANSFORM
Definition: sfwoff2.h:31
#define WOFF2_DEFAULT_MAX_SIZE
Definition: sfwoff2.h:37
#define FLAG_ARG_1_AND_2_ARE_WORDS
Definition: sfwoff2.h:44
#define GLYF_Y_SHORT
Definition: sfwoff2.h:54
#define FLAG_WE_HAVE_A_TWO_BY_TWO
Definition: sfwoff2.h:48
#define FLAG_WE_HAVE_A_SCALE
Definition: sfwoff2.h:45
#define WOFF2_DEFAULT_GLYPH_BUF
Definition: sfwoff2.h:40
#define GLYF_THIS_X_IS_SAME
Definition: sfwoff2.h:56
#define FLAG_MORE_COMPONENTS
Definition: sfwoff2.h:46
#define CONTOUR_OFFSET_END_POINT
Definition: sfwoff2.h:60
#define GLYF_ON_CURVE
Definition: sfwoff2.h:52
#define FLAG_WE_HAVE_INSTRUCTIONS
Definition: sfwoff2.h:49
#define GLYF_REPEAT
Definition: sfwoff2.h:55
static void Exit(void)
Definition: sock.c:1330
FT_Memory memory
Definition: ftsystem.h:338
FT_Stream_CloseFunc close
Definition: ftsystem.h:336
FT_ULong metaOffset
Definition: wofftypes.h:161
FT_ULong metaOrigLength
Definition: wofftypes.h:163
FT_ULong totalCompressedSize
Definition: wofftypes.h:160
FT_UShort num_fonts
Definition: wofftypes.h:170
FT_ULong actual_sfnt_size
Definition: wofftypes.h:171
FT_ULong totalSfntSize
Definition: wofftypes.h:159
FT_ULong privLength
Definition: wofftypes.h:165
FT_ULong length
Definition: wofftypes.h:157
WOFF2_TtcFont ttc_fonts
Definition: wofftypes.h:173
FT_ULong signature
Definition: wofftypes.h:155
FT_UShort num_tables
Definition: wofftypes.h:158
FT_ULong metaLength
Definition: wofftypes.h:162
FT_ULong flavor
Definition: wofftypes.h:156
FT_ULong header_version
Definition: wofftypes.h:169
FT_ULong privOffset
Definition: wofftypes.h:164
FT_ULong compressed_offset
Definition: wofftypes.h:168
FT_ULong uncompressed_size
Definition: wofftypes.h:167
FT_ULong Tag
Definition: wofftypes.h:194
FT_ULong src_length
Definition: wofftypes.h:200
FT_ULong src_offset
Definition: wofftypes.h:199
FT_UShort * table_indices
Definition: wofftypes.h:129
FT_UShort num_tables
Definition: wofftypes.h:128
FT_ULong flavor
Definition: wofftypes.h:127
LONG y
Definition: windef.h:130
LONG x
Definition: windef.h:129
Definition: inflate.c:139
Definition: parse.h:23
unsigned int size
Definition: parse.h:27
Definition: ecma_167.h:138
SFNT_Service sfnt
Definition: ttdriver.c:208
#define TTAG_hmtx
Definition: tttags.h:70
#define TTAG_hhea
Definition: tttags.h:69
#define TTAG_ttcf
Definition: tttags.h:101
#define TTAG_head
Definition: tttags.h:68
#define TTAG_glyf
Definition: tttags.h:62
#define TTAG_wOF2
Definition: tttags.h:109
#define TTAG_maxp
Definition: tttags.h:79
#define TTAG_loca
Definition: tttags.h:75
Definition: pdh_main.c:96
_Must_inspect_result_ _In_ WDFDEVICE _In_ BOOLEAN _In_opt_ PVOID Tag
Definition: wdfdevice.h:4071
woff2_known_tags(FT_Byte index)
Definition: woff2tags.c:32
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
#define const
Definition: zconf.h:233