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