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