Coverage Report

Created: 2025-04-04 07:08

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