~ubuntu-branches/ubuntu/wily/hedgewars/wily

« back to all changes in this revision

Viewing changes to misc/libfreetype/src/gzip/ftgzip.c

  • Committer: Package Import Robot
  • Author(s): Dmitry E. Oboukhov
  • Date: 2011-09-23 10:16:55 UTC
  • mfrom: (1.2.11 upstream)
  • Revision ID: package-import@ubuntu.com-20110923101655-3977th2gc5n0a3pv
Tags: 0.9.16-1
* New upstream version.
 + Downloadable content! Simply click to install any content.
   New voices, hats, maps, themes, translations, music, scripts...
   Hedgewars is now more customisable than ever before! As time goes
   by we will be soliciting community content to feature on this page,
   so remember to check it from time to time. If you decide you want
   to go back to standard Hedgewars, just remove the Data directory
   from your Hedgewars config directory.
 + 3-D rendering! Diorama-like rendering of the game in a variety
   of 3D modes. Let us know which ones work best for you, we didn't
   really have the equipment to test them all.
 + Resizable game window.
 + New utilities! The Time Box will remove one of your hedgehogs
   from the game for a while, protecting from attack until it returns,
   somewhere else on the map. Land spray will allow you to build bridges,
   seal up holes, or just make life unpleasant for your enemies.
 + New single player: Bamboo Thicket, That Sinking Feeling, Newton and
   the Tree and multi-player: The Specialists, Space Invaders,
   Racer - scripts! And a ton more script hooks for scripters
 + New twists on old weapons. Drill strike, seduction and fire have
   been adjusted. Defective mines have been added, rope can attach to
   hogs/crates/barrels again, grenades now have variable bounce (use
   precise key + 1-5). Portal gun is now more usable in flight and
   all game actions are a lot faster.
 + New theme - Golf, dozens of new community hats and a new
   localised Default voice, Ukranian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  ftgzip.c                                                               */
 
4
/*                                                                         */
 
5
/*    FreeType support for .gz compressed files.                           */
 
6
/*                                                                         */
 
7
/*  This optional component relies on zlib.  It should mainly be used to   */
 
8
/*  parse compressed PCF fonts, as found with many X11 server              */
 
9
/*  distributions.                                                         */
 
10
/*                                                                         */
 
11
/*  Copyright 2002-2006, 2009-2011 by                                      */
 
12
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 
13
/*                                                                         */
 
14
/*  This file is part of the FreeType project, and may only be used,       */
 
15
/*  modified, and distributed under the terms of the FreeType project      */
 
16
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
 
17
/*  this file you indicate that you have read the license and              */
 
18
/*  understand and accept it fully.                                        */
 
19
/*                                                                         */
 
20
/***************************************************************************/
 
21
 
 
22
 
 
23
#include <ft2build.h>
 
24
#include FT_INTERNAL_MEMORY_H
 
25
#include FT_INTERNAL_STREAM_H
 
26
#include FT_INTERNAL_DEBUG_H
 
27
#include FT_GZIP_H
 
28
#include FT_CONFIG_STANDARD_LIBRARY_H
 
29
 
 
30
 
 
31
#include FT_MODULE_ERRORS_H
 
32
 
 
33
#undef __FTERRORS_H__
 
34
 
 
35
#define FT_ERR_PREFIX  Gzip_Err_
 
36
#define FT_ERR_BASE    FT_Mod_Err_Gzip
 
37
 
 
38
#include FT_ERRORS_H
 
39
 
 
40
 
 
41
#ifdef FT_CONFIG_OPTION_USE_ZLIB
 
42
 
 
43
#ifdef FT_CONFIG_OPTION_PIC
 
44
#error "gzip code does not support PIC yet"
 
45
#endif 
 
46
 
 
47
#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB
 
48
 
 
49
#include <zlib.h>
 
50
 
 
51
#else /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */
 
52
 
 
53
 /* In this case, we include our own modified sources of the ZLib    */
 
54
 /* within the "ftgzip" component.  The modifications were necessary */
 
55
 /* to #include all files without conflicts, as well as preventing   */
 
56
 /* the definition of "extern" functions that may cause linking      */
 
57
 /* conflicts when a program is linked with both FreeType and the    */
 
58
 /* original ZLib.                                                   */
 
59
 
 
60
#define NO_DUMMY_DECL
 
61
#ifndef USE_ZLIB_ZCALLOC
 
62
#define MY_ZCALLOC /* prevent all zcalloc() & zfree() in zutils.c */
 
63
#endif
 
64
 
 
65
#include "zlib.h"
 
66
 
 
67
#undef  SLOW
 
68
#define SLOW  1  /* we can't use asm-optimized sources here! */
 
69
 
 
70
  /* Urgh.  `inflate_mask' must not be declared twice -- C++ doesn't like
 
71
     this.  We temporarily disable it and load all necessary header files. */
 
72
#define NO_INFLATE_MASK
 
73
#include "zutil.h"
 
74
#include "inftrees.h"
 
75
#include "infblock.h"
 
76
#include "infcodes.h"
 
77
#include "infutil.h"
 
78
#undef  NO_INFLATE_MASK
 
79
 
 
80
  /* infutil.c must be included before infcodes.c */
 
81
#include "zutil.c"
 
82
#include "inftrees.c"
 
83
#include "infutil.c"
 
84
#include "infcodes.c"
 
85
#include "infblock.c"
 
86
#include "inflate.c"
 
87
#include "adler32.c"
 
88
 
 
89
#endif /* !FT_CONFIG_OPTION_SYSTEM_ZLIB */
 
90
 
 
91
 
 
92
/***************************************************************************/
 
93
/***************************************************************************/
 
94
/*****                                                                 *****/
 
95
/*****            Z L I B   M E M O R Y   M A N A G E M E N T          *****/
 
96
/*****                                                                 *****/
 
97
/***************************************************************************/
 
98
/***************************************************************************/
 
99
 
 
100
  /* it is better to use FreeType memory routines instead of raw
 
101
     'malloc/free' */
 
102
 
 
103
  static voidpf
 
104
  ft_gzip_alloc( FT_Memory  memory,
 
105
                 uInt       items,
 
106
                 uInt       size )
 
107
  {
 
108
    FT_ULong    sz = (FT_ULong)size * items;
 
109
    FT_Error    error;
 
110
    FT_Pointer  p  = NULL;
 
111
 
 
112
 
 
113
    (void)FT_ALLOC( p, sz );
 
114
    return p;
 
115
  }
 
116
 
 
117
 
 
118
  static void
 
119
  ft_gzip_free( FT_Memory  memory,
 
120
                voidpf     address )
 
121
  {
 
122
    FT_MEM_FREE( address );
 
123
  }
 
124
 
 
125
 
 
126
#if !defined( FT_CONFIG_OPTION_SYSTEM_ZLIB ) && !defined( USE_ZLIB_ZCALLOC )
 
127
 
 
128
  local voidpf
 
129
  zcalloc ( voidpf    opaque,
 
130
            unsigned  items,
 
131
            unsigned  size )
 
132
  {
 
133
    return ft_gzip_alloc( (FT_Memory)opaque, items, size );
 
134
  }
 
135
 
 
136
  local void
 
137
  zcfree( voidpf  opaque,
 
138
          voidpf  ptr )
 
139
  {
 
140
    ft_gzip_free( (FT_Memory)opaque, ptr );
 
141
  }
 
142
 
 
143
#endif /* !SYSTEM_ZLIB && !USE_ZLIB_ZCALLOC */
 
144
 
 
145
 
 
146
/***************************************************************************/
 
147
/***************************************************************************/
 
148
/*****                                                                 *****/
 
149
/*****               Z L I B   F I L E   D E S C R I P T O R           *****/
 
150
/*****                                                                 *****/
 
151
/***************************************************************************/
 
152
/***************************************************************************/
 
153
 
 
154
#define FT_GZIP_BUFFER_SIZE  4096
 
155
 
 
156
  typedef struct  FT_GZipFileRec_
 
157
  {
 
158
    FT_Stream  source;         /* parent/source stream        */
 
159
    FT_Stream  stream;         /* embedding stream            */
 
160
    FT_Memory  memory;         /* memory allocator            */
 
161
    z_stream   zstream;        /* zlib input stream           */
 
162
 
 
163
    FT_ULong   start;          /* starting position, after .gz header */
 
164
    FT_Byte    input[FT_GZIP_BUFFER_SIZE];   /* input read buffer  */
 
165
 
 
166
    FT_Byte    buffer[FT_GZIP_BUFFER_SIZE];  /* output buffer      */
 
167
    FT_ULong   pos;                          /* position in output */
 
168
    FT_Byte*   cursor;
 
169
    FT_Byte*   limit;
 
170
 
 
171
  } FT_GZipFileRec, *FT_GZipFile;
 
172
 
 
173
 
 
174
  /* gzip flag byte */
 
175
#define FT_GZIP_ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
 
176
#define FT_GZIP_HEAD_CRC     0x02 /* bit 1 set: header CRC present */
 
177
#define FT_GZIP_EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
 
178
#define FT_GZIP_ORIG_NAME    0x08 /* bit 3 set: original file name present */
 
179
#define FT_GZIP_COMMENT      0x10 /* bit 4 set: file comment present */
 
180
#define FT_GZIP_RESERVED     0xE0 /* bits 5..7: reserved */
 
181
 
 
182
 
 
183
  /* check and skip .gz header - we don't support `transparent' compression */
 
184
  static FT_Error
 
185
  ft_gzip_check_header( FT_Stream  stream )
 
186
  {
 
187
    FT_Error  error;
 
188
    FT_Byte   head[4];
 
189
 
 
190
 
 
191
    if ( FT_STREAM_SEEK( 0 )       ||
 
192
         FT_STREAM_READ( head, 4 ) )
 
193
      goto Exit;
 
194
 
 
195
    /* head[0] && head[1] are the magic numbers;    */
 
196
    /* head[2] is the method, and head[3] the flags */
 
197
    if ( head[0] != 0x1f              ||
 
198
         head[1] != 0x8b              ||
 
199
         head[2] != Z_DEFLATED        ||
 
200
        (head[3] & FT_GZIP_RESERVED)  )
 
201
    {
 
202
      error = Gzip_Err_Invalid_File_Format;
 
203
      goto Exit;
 
204
    }
 
205
 
 
206
    /* skip time, xflags and os code */
 
207
    (void)FT_STREAM_SKIP( 6 );
 
208
 
 
209
    /* skip the extra field */
 
210
    if ( head[3] & FT_GZIP_EXTRA_FIELD )
 
211
    {
 
212
      FT_UInt  len;
 
213
 
 
214
 
 
215
      if ( FT_READ_USHORT_LE( len ) ||
 
216
           FT_STREAM_SKIP( len )    )
 
217
        goto Exit;
 
218
    }
 
219
 
 
220
    /* skip original file name */
 
221
    if ( head[3] & FT_GZIP_ORIG_NAME )
 
222
      for (;;)
 
223
      {
 
224
        FT_UInt  c;
 
225
 
 
226
 
 
227
        if ( FT_READ_BYTE( c ) )
 
228
          goto Exit;
 
229
 
 
230
        if ( c == 0 )
 
231
          break;
 
232
      }
 
233
 
 
234
    /* skip .gz comment */
 
235
    if ( head[3] & FT_GZIP_COMMENT )
 
236
      for (;;)
 
237
      {
 
238
        FT_UInt  c;
 
239
 
 
240
 
 
241
        if ( FT_READ_BYTE( c ) )
 
242
          goto Exit;
 
243
 
 
244
        if ( c == 0 )
 
245
          break;
 
246
      }
 
247
 
 
248
    /* skip CRC */
 
249
    if ( head[3] & FT_GZIP_HEAD_CRC )
 
250
      if ( FT_STREAM_SKIP( 2 ) )
 
251
        goto Exit;
 
252
 
 
253
  Exit:
 
254
    return error;
 
255
  }
 
256
 
 
257
 
 
258
  static FT_Error
 
259
  ft_gzip_file_init( FT_GZipFile  zip,
 
260
                     FT_Stream    stream,
 
261
                     FT_Stream    source )
 
262
  {
 
263
    z_stream*  zstream = &zip->zstream;
 
264
    FT_Error   error   = Gzip_Err_Ok;
 
265
 
 
266
 
 
267
    zip->stream = stream;
 
268
    zip->source = source;
 
269
    zip->memory = stream->memory;
 
270
 
 
271
    zip->limit  = zip->buffer + FT_GZIP_BUFFER_SIZE;
 
272
    zip->cursor = zip->limit;
 
273
    zip->pos    = 0;
 
274
 
 
275
    /* check and skip .gz header */
 
276
    {
 
277
      stream = source;
 
278
 
 
279
      error = ft_gzip_check_header( stream );
 
280
      if ( error )
 
281
        goto Exit;
 
282
 
 
283
      zip->start = FT_STREAM_POS();
 
284
    }
 
285
 
 
286
    /* initialize zlib -- there is no zlib header in the compressed stream */
 
287
    zstream->zalloc = (alloc_func)ft_gzip_alloc;
 
288
    zstream->zfree  = (free_func) ft_gzip_free;
 
289
    zstream->opaque = stream->memory;
 
290
 
 
291
    zstream->avail_in = 0;
 
292
    zstream->next_in  = zip->buffer;
 
293
 
 
294
    if ( inflateInit2( zstream, -MAX_WBITS ) != Z_OK ||
 
295
         zstream->next_in == NULL                     )
 
296
      error = Gzip_Err_Invalid_File_Format;
 
297
 
 
298
  Exit:
 
299
    return error;
 
300
  }
 
301
 
 
302
 
 
303
  static void
 
304
  ft_gzip_file_done( FT_GZipFile  zip )
 
305
  {
 
306
    z_stream*  zstream = &zip->zstream;
 
307
 
 
308
 
 
309
    inflateEnd( zstream );
 
310
 
 
311
    /* clear the rest */
 
312
    zstream->zalloc    = NULL;
 
313
    zstream->zfree     = NULL;
 
314
    zstream->opaque    = NULL;
 
315
    zstream->next_in   = NULL;
 
316
    zstream->next_out  = NULL;
 
317
    zstream->avail_in  = 0;
 
318
    zstream->avail_out = 0;
 
319
 
 
320
    zip->memory = NULL;
 
321
    zip->source = NULL;
 
322
    zip->stream = NULL;
 
323
  }
 
324
 
 
325
 
 
326
  static FT_Error
 
327
  ft_gzip_file_reset( FT_GZipFile  zip )
 
328
  {
 
329
    FT_Stream  stream = zip->source;
 
330
    FT_Error   error;
 
331
 
 
332
 
 
333
    if ( !FT_STREAM_SEEK( zip->start ) )
 
334
    {
 
335
      z_stream*  zstream = &zip->zstream;
 
336
 
 
337
 
 
338
      inflateReset( zstream );
 
339
 
 
340
      zstream->avail_in  = 0;
 
341
      zstream->next_in   = zip->input;
 
342
      zstream->avail_out = 0;
 
343
      zstream->next_out  = zip->buffer;
 
344
 
 
345
      zip->limit  = zip->buffer + FT_GZIP_BUFFER_SIZE;
 
346
      zip->cursor = zip->limit;
 
347
      zip->pos    = 0;
 
348
    }
 
349
 
 
350
    return error;
 
351
  }
 
352
 
 
353
 
 
354
  static FT_Error
 
355
  ft_gzip_file_fill_input( FT_GZipFile  zip )
 
356
  {
 
357
    z_stream*  zstream = &zip->zstream;
 
358
    FT_Stream  stream  = zip->source;
 
359
    FT_ULong   size;
 
360
 
 
361
 
 
362
    if ( stream->read )
 
363
    {
 
364
      size = stream->read( stream, stream->pos, zip->input,
 
365
                           FT_GZIP_BUFFER_SIZE );
 
366
      if ( size == 0 )
 
367
        return Gzip_Err_Invalid_Stream_Operation;
 
368
    }
 
369
    else
 
370
    {
 
371
      size = stream->size - stream->pos;
 
372
      if ( size > FT_GZIP_BUFFER_SIZE )
 
373
        size = FT_GZIP_BUFFER_SIZE;
 
374
 
 
375
      if ( size == 0 )
 
376
        return Gzip_Err_Invalid_Stream_Operation;
 
377
 
 
378
      FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
 
379
    }
 
380
    stream->pos += size;
 
381
 
 
382
    zstream->next_in  = zip->input;
 
383
    zstream->avail_in = size;
 
384
 
 
385
    return Gzip_Err_Ok;
 
386
  }
 
387
 
 
388
 
 
389
  static FT_Error
 
390
  ft_gzip_file_fill_output( FT_GZipFile  zip )
 
391
  {
 
392
    z_stream*  zstream = &zip->zstream;
 
393
    FT_Error   error   = Gzip_Err_Ok;
 
394
 
 
395
 
 
396
    zip->cursor        = zip->buffer;
 
397
    zstream->next_out  = zip->cursor;
 
398
    zstream->avail_out = FT_GZIP_BUFFER_SIZE;
 
399
 
 
400
    while ( zstream->avail_out > 0 )
 
401
    {
 
402
      int  err;
 
403
 
 
404
 
 
405
      if ( zstream->avail_in == 0 )
 
406
      {
 
407
        error = ft_gzip_file_fill_input( zip );
 
408
        if ( error )
 
409
          break;
 
410
      }
 
411
 
 
412
      err = inflate( zstream, Z_NO_FLUSH );
 
413
 
 
414
      if ( err == Z_STREAM_END )
 
415
      {
 
416
        zip->limit = zstream->next_out;
 
417
        if ( zip->limit == zip->cursor )
 
418
          error = Gzip_Err_Invalid_Stream_Operation;
 
419
        break;
 
420
      }
 
421
      else if ( err != Z_OK )
 
422
      {
 
423
        error = Gzip_Err_Invalid_Stream_Operation;
 
424
        break;
 
425
      }
 
426
    }
 
427
 
 
428
    return error;
 
429
  }
 
430
 
 
431
 
 
432
  /* fill output buffer; `count' must be <= FT_GZIP_BUFFER_SIZE */
 
433
  static FT_Error
 
434
  ft_gzip_file_skip_output( FT_GZipFile  zip,
 
435
                            FT_ULong     count )
 
436
  {
 
437
    FT_Error  error = Gzip_Err_Ok;
 
438
    FT_ULong  delta;
 
439
 
 
440
 
 
441
    for (;;)
 
442
    {
 
443
      delta = (FT_ULong)( zip->limit - zip->cursor );
 
444
      if ( delta >= count )
 
445
        delta = count;
 
446
 
 
447
      zip->cursor += delta;
 
448
      zip->pos    += delta;
 
449
 
 
450
      count -= delta;
 
451
      if ( count == 0 )
 
452
        break;
 
453
 
 
454
      error = ft_gzip_file_fill_output( zip );
 
455
      if ( error )
 
456
        break;
 
457
    }
 
458
 
 
459
    return error;
 
460
  }
 
461
 
 
462
 
 
463
  static FT_ULong
 
464
  ft_gzip_file_io( FT_GZipFile  zip,
 
465
                   FT_ULong     pos,
 
466
                   FT_Byte*     buffer,
 
467
                   FT_ULong     count )
 
468
  {
 
469
    FT_ULong  result = 0;
 
470
    FT_Error  error;
 
471
 
 
472
 
 
473
    /* Reset inflate stream if we're seeking backwards.        */
 
474
    /* Yes, that is not too efficient, but it saves memory :-) */
 
475
    if ( pos < zip->pos )
 
476
    {
 
477
      error = ft_gzip_file_reset( zip );
 
478
      if ( error )
 
479
        goto Exit;
 
480
    }
 
481
 
 
482
    /* skip unwanted bytes */
 
483
    if ( pos > zip->pos )
 
484
    {
 
485
      error = ft_gzip_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
 
486
      if ( error )
 
487
        goto Exit;
 
488
    }
 
489
 
 
490
    if ( count == 0 )
 
491
      goto Exit;
 
492
 
 
493
    /* now read the data */
 
494
    for (;;)
 
495
    {
 
496
      FT_ULong  delta;
 
497
 
 
498
 
 
499
      delta = (FT_ULong)( zip->limit - zip->cursor );
 
500
      if ( delta >= count )
 
501
        delta = count;
 
502
 
 
503
      FT_MEM_COPY( buffer, zip->cursor, delta );
 
504
      buffer      += delta;
 
505
      result      += delta;
 
506
      zip->cursor += delta;
 
507
      zip->pos    += delta;
 
508
 
 
509
      count -= delta;
 
510
      if ( count == 0 )
 
511
        break;
 
512
 
 
513
      error = ft_gzip_file_fill_output( zip );
 
514
      if ( error )
 
515
        break;
 
516
    }
 
517
 
 
518
  Exit:
 
519
    return result;
 
520
  }
 
521
 
 
522
 
 
523
/***************************************************************************/
 
524
/***************************************************************************/
 
525
/*****                                                                 *****/
 
526
/*****               G Z   E M B E D D I N G   S T R E A M             *****/
 
527
/*****                                                                 *****/
 
528
/***************************************************************************/
 
529
/***************************************************************************/
 
530
 
 
531
  static void
 
532
  ft_gzip_stream_close( FT_Stream  stream )
 
533
  {
 
534
    FT_GZipFile  zip    = (FT_GZipFile)stream->descriptor.pointer;
 
535
    FT_Memory    memory = stream->memory;
 
536
 
 
537
 
 
538
    if ( zip )
 
539
    {
 
540
      /* finalize gzip file descriptor */
 
541
      ft_gzip_file_done( zip );
 
542
 
 
543
      FT_FREE( zip );
 
544
 
 
545
      stream->descriptor.pointer = NULL;
 
546
    }
 
547
  }
 
548
 
 
549
 
 
550
  static FT_ULong
 
551
  ft_gzip_stream_io( FT_Stream  stream,
 
552
                     FT_ULong   pos,
 
553
                     FT_Byte*   buffer,
 
554
                     FT_ULong   count )
 
555
  {
 
556
    FT_GZipFile  zip = (FT_GZipFile)stream->descriptor.pointer;
 
557
 
 
558
 
 
559
    return ft_gzip_file_io( zip, pos, buffer, count );
 
560
  }
 
561
 
 
562
 
 
563
  static FT_ULong
 
564
  ft_gzip_get_uncompressed_size( FT_Stream  stream )
 
565
  {
 
566
    FT_Error  error;
 
567
    FT_ULong  old_pos;
 
568
    FT_ULong  result = 0;
 
569
 
 
570
 
 
571
    old_pos = stream->pos;
 
572
    if ( !FT_Stream_Seek( stream, stream->size - 4 ) )
 
573
    {
 
574
      result = FT_Stream_ReadULong( stream, &error );
 
575
      if ( error )
 
576
        result = 0;
 
577
 
 
578
      (void)FT_Stream_Seek( stream, old_pos );
 
579
    }
 
580
 
 
581
    return result;
 
582
  }
 
583
 
 
584
 
 
585
  FT_EXPORT_DEF( FT_Error )
 
586
  FT_Stream_OpenGzip( FT_Stream  stream,
 
587
                      FT_Stream  source )
 
588
  {
 
589
    FT_Error     error;
 
590
    FT_Memory    memory = source->memory;
 
591
    FT_GZipFile  zip;
 
592
 
 
593
 
 
594
    /*
 
595
     *  check the header right now; this prevents allocating un-necessary
 
596
     *  objects when we don't need them
 
597
     */
 
598
    error = ft_gzip_check_header( source );
 
599
    if ( error )
 
600
      goto Exit;
 
601
 
 
602
    FT_ZERO( stream );
 
603
    stream->memory = memory;
 
604
 
 
605
    if ( !FT_QNEW( zip ) )
 
606
    {
 
607
      error = ft_gzip_file_init( zip, stream, source );
 
608
      if ( error )
 
609
      {
 
610
        FT_FREE( zip );
 
611
        goto Exit;
 
612
      }
 
613
 
 
614
      stream->descriptor.pointer = zip;
 
615
    }
 
616
 
 
617
    /*
 
618
     *  We use the following trick to try to dramatically improve the
 
619
     *  performance while dealing with small files.  If the original stream
 
620
     *  size is less than a certain threshold, we try to load the whole font
 
621
     *  file into memory.  This saves us from using the 32KB buffer needed
 
622
     *  to inflate the file, plus the two 4KB intermediate input/output
 
623
     *  buffers used in the `FT_GZipFile' structure.
 
624
     */
 
625
    {
 
626
      FT_ULong  zip_size = ft_gzip_get_uncompressed_size( source );
 
627
 
 
628
 
 
629
      if ( zip_size != 0 && zip_size < 40 * 1024 )
 
630
      {
 
631
        FT_Byte*  zip_buff;
 
632
 
 
633
 
 
634
        if ( !FT_ALLOC( zip_buff, zip_size ) )
 
635
        {
 
636
          FT_ULong  count;
 
637
 
 
638
 
 
639
          count = ft_gzip_file_io( zip, 0, zip_buff, zip_size );
 
640
          if ( count == zip_size )
 
641
          {
 
642
            ft_gzip_file_done( zip );
 
643
            FT_FREE( zip );
 
644
 
 
645
            stream->descriptor.pointer = NULL;
 
646
 
 
647
            stream->size  = zip_size;
 
648
            stream->pos   = 0;
 
649
            stream->base  = zip_buff;
 
650
            stream->read  = NULL;
 
651
            stream->close = ft_gzip_stream_close;
 
652
 
 
653
            goto Exit;
 
654
          }
 
655
 
 
656
          ft_gzip_file_io( zip, 0, NULL, 0 );
 
657
          FT_FREE( zip_buff );
 
658
        }
 
659
        error = Gzip_Err_Ok;
 
660
      }
 
661
    }
 
662
 
 
663
    stream->size  = 0x7FFFFFFFL;  /* don't know the real size! */
 
664
    stream->pos   = 0;
 
665
    stream->base  = 0;
 
666
    stream->read  = ft_gzip_stream_io;
 
667
    stream->close = ft_gzip_stream_close;
 
668
 
 
669
  Exit:
 
670
    return error;
 
671
  }
 
672
 
 
673
#else  /* !FT_CONFIG_OPTION_USE_ZLIB */
 
674
 
 
675
  FT_EXPORT_DEF( FT_Error )
 
676
  FT_Stream_OpenGzip( FT_Stream  stream,
 
677
                      FT_Stream  source )
 
678
  {
 
679
    FT_UNUSED( stream );
 
680
    FT_UNUSED( source );
 
681
 
 
682
    return Gzip_Err_Unimplemented_Feature;
 
683
  }
 
684
 
 
685
#endif /* !FT_CONFIG_OPTION_USE_ZLIB */
 
686
 
 
687
 
 
688
/* END */