xref: /inferno-os/libfreetype/ftgzip.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  ftgzip.c                                                               */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    FreeType support for .gz compressed fileds                           */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  this optional component relies on zlib. It should mainly be used to    */
8*37da2899SCharles.Forsyth /*  parse compressed PCF fonts, as found with many X11 server              */
9*37da2899SCharles.Forsyth /*  distributions.                                                         */
10*37da2899SCharles.Forsyth /*                                                                         */
11*37da2899SCharles.Forsyth /*  Copyright 2002 by                                                      */
12*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
13*37da2899SCharles.Forsyth /*                                                                         */
14*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
15*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
16*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
17*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
18*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
19*37da2899SCharles.Forsyth /*                                                                         */
20*37da2899SCharles.Forsyth /***************************************************************************/
21*37da2899SCharles.Forsyth 
22*37da2899SCharles.Forsyth #include <ft2build.h>
23*37da2899SCharles.Forsyth #include FT_INTERNAL_MEMORY_H
24*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H
25*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
26*37da2899SCharles.Forsyth #include <string.h>
27*37da2899SCharles.Forsyth 
28*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_USE_ZLIB
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB
31*37da2899SCharles.Forsyth 
32*37da2899SCharles.Forsyth #  include "zlib.h"
33*37da2899SCharles.Forsyth 
34*37da2899SCharles.Forsyth #else /* !SYSTEM_ZLIB */
35*37da2899SCharles.Forsyth 
36*37da2899SCharles.Forsyth  /* in this case, we include our own modified sources of the ZLib   */
37*37da2899SCharles.Forsyth  /* within the "ftgzip" component. The modifications were necessary */
38*37da2899SCharles.Forsyth  /* to #include all files without conflicts, as well as preventing  */
39*37da2899SCharles.Forsyth  /* the definition of "extern" functions that may cause linking     */
40*37da2899SCharles.Forsyth  /* conflicts when a program is linked with both FreeType and the   */
41*37da2899SCharles.Forsyth  /* original ZLib                                                   */
42*37da2899SCharles.Forsyth 
43*37da2899SCharles.Forsyth #  define  NO_DUMMY_DECL
44*37da2899SCharles.Forsyth #  define  BUILDFIXED    /* save code size */
45*37da2899SCharles.Forsyth #  define  MY_ZCALLOC
46*37da2899SCharles.Forsyth 
47*37da2899SCharles.Forsyth #  include "zlib.h"
48*37da2899SCharles.Forsyth 
49*37da2899SCharles.Forsyth #    undef   SLOW
50*37da2899SCharles.Forsyth #    define  SLOW  1  /* we can't use asm-optimized sources here !! */
51*37da2899SCharles.Forsyth 
52*37da2899SCharles.Forsyth #    include "zutil.c"
53*37da2899SCharles.Forsyth #    include "inftrees.c"
54*37da2899SCharles.Forsyth #    include "infcodes.c"
55*37da2899SCharles.Forsyth #    include "infutil.c"
56*37da2899SCharles.Forsyth #    include "infblock.c"
57*37da2899SCharles.Forsyth #    include "inflate.c"
58*37da2899SCharles.Forsyth #    include "adler32.c"
59*37da2899SCharles.Forsyth 
60*37da2899SCharles.Forsyth #endif /* !SYSTEM_ZLIB */
61*37da2899SCharles.Forsyth 
62*37da2899SCharles.Forsyth 
63*37da2899SCharles.Forsyth /***************************************************************************/
64*37da2899SCharles.Forsyth /***************************************************************************/
65*37da2899SCharles.Forsyth /*****                                                                 *****/
66*37da2899SCharles.Forsyth /*****            Z L I B   M E M O R Y   M A N A G E M E N T          *****/
67*37da2899SCharles.Forsyth /*****                                                                 *****/
68*37da2899SCharles.Forsyth /***************************************************************************/
69*37da2899SCharles.Forsyth /***************************************************************************/
70*37da2899SCharles.Forsyth 
71*37da2899SCharles.Forsyth  /* it's better to use FreeType memory routines instead of raw 'malloc/free' */
72*37da2899SCharles.Forsyth 
73*37da2899SCharles.Forsyth 
74*37da2899SCharles.Forsyth  static voidpf
ft_gzip_alloc(FT_Memory memory,uInt items,uInt size)75*37da2899SCharles.Forsyth  ft_gzip_alloc( FT_Memory  memory,
76*37da2899SCharles.Forsyth                 uInt       items,
77*37da2899SCharles.Forsyth                 uInt       size )
78*37da2899SCharles.Forsyth  {
79*37da2899SCharles.Forsyth    FT_ULong    sz = (FT_ULong)size * items;
80*37da2899SCharles.Forsyth    FT_Pointer  p;
81*37da2899SCharles.Forsyth 
82*37da2899SCharles.Forsyth    FT_MEM_ALLOC( p, sz );
83*37da2899SCharles.Forsyth 
84*37da2899SCharles.Forsyth    return (voidpf) p;
85*37da2899SCharles.Forsyth  }
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth 
88*37da2899SCharles.Forsyth  static void
ft_gzip_free(FT_Memory memory,voidpf address)89*37da2899SCharles.Forsyth  ft_gzip_free( FT_Memory  memory,
90*37da2899SCharles.Forsyth                voidpf     address )
91*37da2899SCharles.Forsyth  {
92*37da2899SCharles.Forsyth    FT_MEM_FREE( address );
93*37da2899SCharles.Forsyth  }
94*37da2899SCharles.Forsyth 
95*37da2899SCharles.Forsyth 
96*37da2899SCharles.Forsyth #ifndef FT_CONFIG_OPTION_SYSTEM_ZLIB
97*37da2899SCharles.Forsyth 
98*37da2899SCharles.Forsyth  local voidpf
zcalloc(opaque,items,size)99*37da2899SCharles.Forsyth  zcalloc (opaque, items, size)
100*37da2899SCharles.Forsyth     voidpf opaque;
101*37da2899SCharles.Forsyth     unsigned items;
102*37da2899SCharles.Forsyth     unsigned size;
103*37da2899SCharles.Forsyth  {
104*37da2899SCharles.Forsyth    return ft_gzip_alloc( opaque, items, size );
105*37da2899SCharles.Forsyth  }
106*37da2899SCharles.Forsyth 
107*37da2899SCharles.Forsyth  local void
zcfree(voidpf opaque,voidpf ptr)108*37da2899SCharles.Forsyth  zcfree( voidpf  opaque,
109*37da2899SCharles.Forsyth          voidpf  ptr )
110*37da2899SCharles.Forsyth  {
111*37da2899SCharles.Forsyth    ft_gzip_free( opaque, ptr );
112*37da2899SCharles.Forsyth  }
113*37da2899SCharles.Forsyth 
114*37da2899SCharles.Forsyth #endif /* !SYSTEM_ZLIB */
115*37da2899SCharles.Forsyth 
116*37da2899SCharles.Forsyth 
117*37da2899SCharles.Forsyth /***************************************************************************/
118*37da2899SCharles.Forsyth /***************************************************************************/
119*37da2899SCharles.Forsyth /*****                                                                 *****/
120*37da2899SCharles.Forsyth /*****               Z L I B   F I L E   D E S C R I P T O R           *****/
121*37da2899SCharles.Forsyth /*****                                                                 *****/
122*37da2899SCharles.Forsyth /***************************************************************************/
123*37da2899SCharles.Forsyth /***************************************************************************/
124*37da2899SCharles.Forsyth 
125*37da2899SCharles.Forsyth #define  FT_GZIP_BUFFER_SIZE          4096
126*37da2899SCharles.Forsyth 
127*37da2899SCharles.Forsyth   typedef struct FT_GZipFileRec_
128*37da2899SCharles.Forsyth   {
129*37da2899SCharles.Forsyth     FT_Stream    source;         /* parent/source stream        */
130*37da2899SCharles.Forsyth     FT_Stream    stream;         /* embedding stream            */
131*37da2899SCharles.Forsyth     FT_Memory    memory;         /* memory allocator            */
132*37da2899SCharles.Forsyth     z_stream     zstream;        /* zlib input stream           */
133*37da2899SCharles.Forsyth 
134*37da2899SCharles.Forsyth     FT_ULong     start;          /* starting position, after .gz header */
135*37da2899SCharles.Forsyth     FT_Byte      input[ FT_GZIP_BUFFER_SIZE ];  /* input read buffer */
136*37da2899SCharles.Forsyth 
137*37da2899SCharles.Forsyth     FT_Byte      buffer[ FT_GZIP_BUFFER_SIZE ];  /* output buffer      */
138*37da2899SCharles.Forsyth     FT_ULong     pos;                            /* position in output */
139*37da2899SCharles.Forsyth     FT_Byte*     cursor;
140*37da2899SCharles.Forsyth     FT_Byte*     limit;
141*37da2899SCharles.Forsyth 
142*37da2899SCharles.Forsyth   } FT_GZipFileRec, *FT_GZipFile;
143*37da2899SCharles.Forsyth 
144*37da2899SCharles.Forsyth 
145*37da2899SCharles.Forsyth /* gzip flag byte */
146*37da2899SCharles.Forsyth #define FT_GZIP_ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
147*37da2899SCharles.Forsyth #define FT_GZIP_HEAD_CRC     0x02 /* bit 1 set: header CRC present */
148*37da2899SCharles.Forsyth #define FT_GZIP_EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
149*37da2899SCharles.Forsyth #define FT_GZIP_ORIG_NAME    0x08 /* bit 3 set: original file name present */
150*37da2899SCharles.Forsyth #define FT_GZIP_COMMENT      0x10 /* bit 4 set: file comment present */
151*37da2899SCharles.Forsyth #define FT_GZIP_RESERVED     0xE0 /* bits 5..7: reserved */
152*37da2899SCharles.Forsyth 
153*37da2899SCharles.Forsyth 
154*37da2899SCharles.Forsyth  /* check and skip .gz header - we don't support "transparent" compression */
155*37da2899SCharles.Forsyth   static FT_Error
ft_gzip_check_header(FT_Stream stream)156*37da2899SCharles.Forsyth   ft_gzip_check_header( FT_Stream  stream )
157*37da2899SCharles.Forsyth   {
158*37da2899SCharles.Forsyth     FT_Error  error;
159*37da2899SCharles.Forsyth     FT_Byte   head[4];
160*37da2899SCharles.Forsyth 
161*37da2899SCharles.Forsyth     if ( FT_STREAM_SEEK( 0 )       ||
162*37da2899SCharles.Forsyth          FT_STREAM_READ( head, 4 ) )
163*37da2899SCharles.Forsyth       goto Exit;
164*37da2899SCharles.Forsyth 
165*37da2899SCharles.Forsyth     /* head[0] && head[1] are the magic numbers     */
166*37da2899SCharles.Forsyth     /* head[2] is the method, and head[3] the flags */
167*37da2899SCharles.Forsyth     if ( head[0] != 0x1f              ||
168*37da2899SCharles.Forsyth          head[1] != 0x8b              ||
169*37da2899SCharles.Forsyth          head[2] != Z_DEFLATED        ||
170*37da2899SCharles.Forsyth         (head[3] & FT_GZIP_RESERVED)  )
171*37da2899SCharles.Forsyth     {
172*37da2899SCharles.Forsyth       error = FT_Err_Invalid_File_Format;
173*37da2899SCharles.Forsyth       goto Exit;
174*37da2899SCharles.Forsyth     }
175*37da2899SCharles.Forsyth 
176*37da2899SCharles.Forsyth     /* skip time, xflags and os code */
177*37da2899SCharles.Forsyth     (void)FT_STREAM_SKIP( 6 );
178*37da2899SCharles.Forsyth 
179*37da2899SCharles.Forsyth     /* skip the extra field */
180*37da2899SCharles.Forsyth     if ( head[3] && FT_GZIP_EXTRA_FIELD )
181*37da2899SCharles.Forsyth     {
182*37da2899SCharles.Forsyth       FT_UInt  len;
183*37da2899SCharles.Forsyth 
184*37da2899SCharles.Forsyth       if ( FT_READ_USHORT_LE( len ) ||
185*37da2899SCharles.Forsyth            FT_STREAM_SKIP( len )    )
186*37da2899SCharles.Forsyth         goto Exit;
187*37da2899SCharles.Forsyth     }
188*37da2899SCharles.Forsyth 
189*37da2899SCharles.Forsyth     /* skip original file name */
190*37da2899SCharles.Forsyth     if ( head[3] && FT_GZIP_ORIG_NAME )
191*37da2899SCharles.Forsyth       for (;;)
192*37da2899SCharles.Forsyth       {
193*37da2899SCharles.Forsyth         FT_UInt  c;
194*37da2899SCharles.Forsyth 
195*37da2899SCharles.Forsyth         if ( FT_READ_BYTE( c) )
196*37da2899SCharles.Forsyth           goto Exit;
197*37da2899SCharles.Forsyth 
198*37da2899SCharles.Forsyth         if ( c == 0 )
199*37da2899SCharles.Forsyth           break;
200*37da2899SCharles.Forsyth       }
201*37da2899SCharles.Forsyth 
202*37da2899SCharles.Forsyth     /* skip .gz comment */
203*37da2899SCharles.Forsyth     if ( head[3] & FT_GZIP_COMMENT )
204*37da2899SCharles.Forsyth       for (;;)
205*37da2899SCharles.Forsyth       {
206*37da2899SCharles.Forsyth         FT_UInt  c;
207*37da2899SCharles.Forsyth 
208*37da2899SCharles.Forsyth         if ( FT_READ_BYTE( c) )
209*37da2899SCharles.Forsyth           goto Exit;
210*37da2899SCharles.Forsyth 
211*37da2899SCharles.Forsyth         if ( c == 0 )
212*37da2899SCharles.Forsyth           break;
213*37da2899SCharles.Forsyth       }
214*37da2899SCharles.Forsyth 
215*37da2899SCharles.Forsyth     /* skip CRC */
216*37da2899SCharles.Forsyth     if ( head[3] & FT_GZIP_HEAD_CRC )
217*37da2899SCharles.Forsyth       if ( FT_STREAM_SKIP( 2 ) )
218*37da2899SCharles.Forsyth         goto Exit;
219*37da2899SCharles.Forsyth 
220*37da2899SCharles.Forsyth   Exit:
221*37da2899SCharles.Forsyth     return error;
222*37da2899SCharles.Forsyth   }
223*37da2899SCharles.Forsyth 
224*37da2899SCharles.Forsyth 
225*37da2899SCharles.Forsyth 
226*37da2899SCharles.Forsyth   static FT_Error
ft_gzip_file_init(FT_GZipFile zip,FT_Stream stream,FT_Stream source)227*37da2899SCharles.Forsyth   ft_gzip_file_init( FT_GZipFile   zip,
228*37da2899SCharles.Forsyth                      FT_Stream     stream,
229*37da2899SCharles.Forsyth                      FT_Stream     source )
230*37da2899SCharles.Forsyth   {
231*37da2899SCharles.Forsyth     z_stream*  zstream = &zip->zstream;
232*37da2899SCharles.Forsyth     FT_Error   error   = 0;
233*37da2899SCharles.Forsyth 
234*37da2899SCharles.Forsyth     zip->stream = stream;
235*37da2899SCharles.Forsyth     zip->source = source;
236*37da2899SCharles.Forsyth     zip->memory = stream->memory;
237*37da2899SCharles.Forsyth 
238*37da2899SCharles.Forsyth     zip->limit  = zip->buffer + FT_GZIP_BUFFER_SIZE;
239*37da2899SCharles.Forsyth     zip->cursor = zip->limit;
240*37da2899SCharles.Forsyth     zip->pos    = 0;
241*37da2899SCharles.Forsyth 
242*37da2899SCharles.Forsyth     /* check and skip .gz header */
243*37da2899SCharles.Forsyth     {
244*37da2899SCharles.Forsyth       stream = source;
245*37da2899SCharles.Forsyth 
246*37da2899SCharles.Forsyth       error = ft_gzip_check_header( stream );
247*37da2899SCharles.Forsyth       if (error)
248*37da2899SCharles.Forsyth         goto Exit;
249*37da2899SCharles.Forsyth 
250*37da2899SCharles.Forsyth       zip->start = FT_STREAM_POS();
251*37da2899SCharles.Forsyth     }
252*37da2899SCharles.Forsyth 
253*37da2899SCharles.Forsyth     /* initialize zlib - there is no zlib header in the compressed stream */
254*37da2899SCharles.Forsyth     zstream->zalloc = (alloc_func) ft_gzip_alloc;
255*37da2899SCharles.Forsyth     zstream->zfree  = (free_func)  ft_gzip_free;
256*37da2899SCharles.Forsyth     zstream->opaque = stream->memory;
257*37da2899SCharles.Forsyth 
258*37da2899SCharles.Forsyth     zstream->avail_in = 0;
259*37da2899SCharles.Forsyth     zstream->next_in  = zip->buffer;
260*37da2899SCharles.Forsyth 
261*37da2899SCharles.Forsyth     if ( inflateInit2( zstream, -MAX_WBITS ) != Z_OK ||
262*37da2899SCharles.Forsyth          zstream->next_in == NULL                     )
263*37da2899SCharles.Forsyth     {
264*37da2899SCharles.Forsyth       error = FT_Err_Invalid_File_Format;
265*37da2899SCharles.Forsyth       goto Exit;
266*37da2899SCharles.Forsyth     }
267*37da2899SCharles.Forsyth 
268*37da2899SCharles.Forsyth   Exit:
269*37da2899SCharles.Forsyth     return error;
270*37da2899SCharles.Forsyth   }
271*37da2899SCharles.Forsyth 
272*37da2899SCharles.Forsyth 
273*37da2899SCharles.Forsyth 
274*37da2899SCharles.Forsyth   static void
ft_gzip_file_done(FT_GZipFile zip)275*37da2899SCharles.Forsyth   ft_gzip_file_done( FT_GZipFile  zip )
276*37da2899SCharles.Forsyth   {
277*37da2899SCharles.Forsyth     z_stream*  zstream = &zip->zstream;
278*37da2899SCharles.Forsyth 
279*37da2899SCharles.Forsyth     /* clear the rest */
280*37da2899SCharles.Forsyth     zstream->zalloc    = NULL;
281*37da2899SCharles.Forsyth     zstream->zfree     = NULL;
282*37da2899SCharles.Forsyth     zstream->opaque    = NULL;
283*37da2899SCharles.Forsyth     zstream->next_in   = NULL;
284*37da2899SCharles.Forsyth     zstream->next_out  = NULL;
285*37da2899SCharles.Forsyth     zstream->avail_in  = 0;
286*37da2899SCharles.Forsyth     zstream->avail_out = 0;
287*37da2899SCharles.Forsyth 
288*37da2899SCharles.Forsyth     zip->memory = NULL;
289*37da2899SCharles.Forsyth     zip->source = NULL;
290*37da2899SCharles.Forsyth     zip->stream = NULL;
291*37da2899SCharles.Forsyth   }
292*37da2899SCharles.Forsyth 
293*37da2899SCharles.Forsyth 
294*37da2899SCharles.Forsyth   static FT_Error
ft_gzip_file_reset(FT_GZipFile zip)295*37da2899SCharles.Forsyth   ft_gzip_file_reset( FT_GZipFile  zip )
296*37da2899SCharles.Forsyth   {
297*37da2899SCharles.Forsyth     FT_Stream  stream = zip->source;
298*37da2899SCharles.Forsyth     FT_Error   error;
299*37da2899SCharles.Forsyth 
300*37da2899SCharles.Forsyth     if ( !FT_STREAM_SEEK( zip->start ) )
301*37da2899SCharles.Forsyth     {
302*37da2899SCharles.Forsyth       z_stream*  zstream = &zip->zstream;
303*37da2899SCharles.Forsyth 
304*37da2899SCharles.Forsyth       inflateReset( zstream );
305*37da2899SCharles.Forsyth 
306*37da2899SCharles.Forsyth       zstream->avail_in  = 0;
307*37da2899SCharles.Forsyth       zstream->next_in   = zip->input;
308*37da2899SCharles.Forsyth       zstream->avail_out = 0;
309*37da2899SCharles.Forsyth       zstream->next_out  = zip->buffer;
310*37da2899SCharles.Forsyth 
311*37da2899SCharles.Forsyth       zip->limit  = zip->buffer + FT_GZIP_BUFFER_SIZE;
312*37da2899SCharles.Forsyth       zip->cursor = zip->limit;
313*37da2899SCharles.Forsyth       zip->pos    = 0;
314*37da2899SCharles.Forsyth     }
315*37da2899SCharles.Forsyth     return  error;
316*37da2899SCharles.Forsyth   }
317*37da2899SCharles.Forsyth 
318*37da2899SCharles.Forsyth 
319*37da2899SCharles.Forsyth   static FT_Error
ft_gzip_file_fill_input(FT_GZipFile zip)320*37da2899SCharles.Forsyth   ft_gzip_file_fill_input( FT_GZipFile  zip )
321*37da2899SCharles.Forsyth   {
322*37da2899SCharles.Forsyth     z_stream*  zstream = &zip->zstream;
323*37da2899SCharles.Forsyth     FT_Stream  stream  = zip->source;
324*37da2899SCharles.Forsyth     FT_ULong   size;
325*37da2899SCharles.Forsyth 
326*37da2899SCharles.Forsyth     if ( stream->read )
327*37da2899SCharles.Forsyth     {
328*37da2899SCharles.Forsyth       size = stream->read( stream, stream->pos, zip->input, FT_GZIP_BUFFER_SIZE );
329*37da2899SCharles.Forsyth       if ( size == 0 )
330*37da2899SCharles.Forsyth         return FT_Err_Invalid_Stream_Operation;
331*37da2899SCharles.Forsyth     }
332*37da2899SCharles.Forsyth     else
333*37da2899SCharles.Forsyth     {
334*37da2899SCharles.Forsyth       size = stream->size - stream->pos;
335*37da2899SCharles.Forsyth       if ( size > FT_GZIP_BUFFER_SIZE )
336*37da2899SCharles.Forsyth         size = FT_GZIP_BUFFER_SIZE;
337*37da2899SCharles.Forsyth 
338*37da2899SCharles.Forsyth       if ( size == 0 )
339*37da2899SCharles.Forsyth        return FT_Err_Invalid_Stream_Operation;
340*37da2899SCharles.Forsyth 
341*37da2899SCharles.Forsyth       FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
342*37da2899SCharles.Forsyth     }
343*37da2899SCharles.Forsyth     stream->pos += size;
344*37da2899SCharles.Forsyth 
345*37da2899SCharles.Forsyth     zstream->next_in  = zip->input;
346*37da2899SCharles.Forsyth     zstream->avail_in = size;
347*37da2899SCharles.Forsyth 
348*37da2899SCharles.Forsyth     return 0;
349*37da2899SCharles.Forsyth   }
350*37da2899SCharles.Forsyth 
351*37da2899SCharles.Forsyth 
352*37da2899SCharles.Forsyth 
353*37da2899SCharles.Forsyth   static FT_Error
ft_gzip_file_fill_output(FT_GZipFile zip)354*37da2899SCharles.Forsyth   ft_gzip_file_fill_output( FT_GZipFile  zip )
355*37da2899SCharles.Forsyth   {
356*37da2899SCharles.Forsyth     z_stream*  zstream = &zip->zstream;
357*37da2899SCharles.Forsyth     FT_Error   error   = 0;
358*37da2899SCharles.Forsyth 
359*37da2899SCharles.Forsyth     zip->cursor        = zip->buffer;
360*37da2899SCharles.Forsyth     zstream->next_out  = zip->cursor;
361*37da2899SCharles.Forsyth     zstream->avail_out = FT_GZIP_BUFFER_SIZE;
362*37da2899SCharles.Forsyth 
363*37da2899SCharles.Forsyth     while ( zstream->avail_out > 0 )
364*37da2899SCharles.Forsyth     {
365*37da2899SCharles.Forsyth       int  err;
366*37da2899SCharles.Forsyth 
367*37da2899SCharles.Forsyth       if ( zstream->avail_in == 0 )
368*37da2899SCharles.Forsyth       {
369*37da2899SCharles.Forsyth         error = ft_gzip_file_fill_input( zip );
370*37da2899SCharles.Forsyth         if ( error )
371*37da2899SCharles.Forsyth           break;
372*37da2899SCharles.Forsyth       }
373*37da2899SCharles.Forsyth 
374*37da2899SCharles.Forsyth       err = inflate( zstream, Z_NO_FLUSH );
375*37da2899SCharles.Forsyth 
376*37da2899SCharles.Forsyth       if ( err == Z_STREAM_END )
377*37da2899SCharles.Forsyth       {
378*37da2899SCharles.Forsyth         zip->limit = zstream->next_out;
379*37da2899SCharles.Forsyth         break;
380*37da2899SCharles.Forsyth       }
381*37da2899SCharles.Forsyth       else if ( err != Z_OK )
382*37da2899SCharles.Forsyth       {
383*37da2899SCharles.Forsyth         error = FT_Err_Invalid_Stream_Operation;
384*37da2899SCharles.Forsyth         break;
385*37da2899SCharles.Forsyth       }
386*37da2899SCharles.Forsyth     }
387*37da2899SCharles.Forsyth     return error;
388*37da2899SCharles.Forsyth   }
389*37da2899SCharles.Forsyth 
390*37da2899SCharles.Forsyth 
391*37da2899SCharles.Forsyth  /* fill output buffer, 'count' must be <= FT_GZIP_BUFFER_SIZE */
392*37da2899SCharles.Forsyth   static FT_Error
ft_gzip_file_skip_output(FT_GZipFile zip,FT_ULong count)393*37da2899SCharles.Forsyth   ft_gzip_file_skip_output( FT_GZipFile  zip,
394*37da2899SCharles.Forsyth                             FT_ULong     count )
395*37da2899SCharles.Forsyth   {
396*37da2899SCharles.Forsyth     FT_Error   error   = 0;
397*37da2899SCharles.Forsyth     FT_ULong   delta;
398*37da2899SCharles.Forsyth 
399*37da2899SCharles.Forsyth     for (;;)
400*37da2899SCharles.Forsyth     {
401*37da2899SCharles.Forsyth       delta = (FT_ULong)( zip->limit - zip->cursor );
402*37da2899SCharles.Forsyth       if ( delta >= count )
403*37da2899SCharles.Forsyth         delta = count;
404*37da2899SCharles.Forsyth 
405*37da2899SCharles.Forsyth       zip->cursor += delta;
406*37da2899SCharles.Forsyth       zip->pos    += delta;
407*37da2899SCharles.Forsyth 
408*37da2899SCharles.Forsyth       count -= delta;
409*37da2899SCharles.Forsyth       if ( count == 0 )
410*37da2899SCharles.Forsyth         break;
411*37da2899SCharles.Forsyth 
412*37da2899SCharles.Forsyth       error = ft_gzip_file_fill_output( zip );
413*37da2899SCharles.Forsyth       if ( error )
414*37da2899SCharles.Forsyth         break;
415*37da2899SCharles.Forsyth     }
416*37da2899SCharles.Forsyth 
417*37da2899SCharles.Forsyth     return error;
418*37da2899SCharles.Forsyth   }
419*37da2899SCharles.Forsyth 
420*37da2899SCharles.Forsyth 
421*37da2899SCharles.Forsyth   static FT_ULong
ft_gzip_file_io(FT_GZipFile zip,FT_ULong pos,FT_Byte * buffer,FT_ULong count)422*37da2899SCharles.Forsyth   ft_gzip_file_io( FT_GZipFile   zip,
423*37da2899SCharles.Forsyth                    FT_ULong      pos,
424*37da2899SCharles.Forsyth                    FT_Byte*      buffer,
425*37da2899SCharles.Forsyth                    FT_ULong      count )
426*37da2899SCharles.Forsyth   {
427*37da2899SCharles.Forsyth     FT_ULong   result = 0;
428*37da2899SCharles.Forsyth     FT_Error   error;
429*37da2899SCharles.Forsyth 
430*37da2899SCharles.Forsyth     /* reset inflate stream if we're seeking backwards        */
431*37da2899SCharles.Forsyth     /* yes, that's not too efficient, but it saves memory :-) */
432*37da2899SCharles.Forsyth     if ( pos < zip->pos )
433*37da2899SCharles.Forsyth     {
434*37da2899SCharles.Forsyth       error = ft_gzip_file_reset( zip );
435*37da2899SCharles.Forsyth       if ( error ) goto Exit;
436*37da2899SCharles.Forsyth     }
437*37da2899SCharles.Forsyth 
438*37da2899SCharles.Forsyth     /* skip unwanted bytes */
439*37da2899SCharles.Forsyth     if ( pos > zip->pos )
440*37da2899SCharles.Forsyth     {
441*37da2899SCharles.Forsyth       error = ft_gzip_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
442*37da2899SCharles.Forsyth       if (error)
443*37da2899SCharles.Forsyth         goto Exit;
444*37da2899SCharles.Forsyth     }
445*37da2899SCharles.Forsyth 
446*37da2899SCharles.Forsyth     if ( count == 0 )
447*37da2899SCharles.Forsyth       goto Exit;
448*37da2899SCharles.Forsyth 
449*37da2899SCharles.Forsyth     /* now read the data */
450*37da2899SCharles.Forsyth     for (;;)
451*37da2899SCharles.Forsyth     {
452*37da2899SCharles.Forsyth       FT_ULong   delta;
453*37da2899SCharles.Forsyth 
454*37da2899SCharles.Forsyth       delta = (FT_ULong)( zip->limit - zip->cursor );
455*37da2899SCharles.Forsyth       if ( delta >= count )
456*37da2899SCharles.Forsyth         delta = count;
457*37da2899SCharles.Forsyth 
458*37da2899SCharles.Forsyth       FT_MEM_COPY( buffer, zip->cursor, delta );
459*37da2899SCharles.Forsyth       buffer      += delta;
460*37da2899SCharles.Forsyth       result      += delta;
461*37da2899SCharles.Forsyth       zip->cursor += delta;
462*37da2899SCharles.Forsyth       zip->pos    += delta;
463*37da2899SCharles.Forsyth 
464*37da2899SCharles.Forsyth       count -= delta;
465*37da2899SCharles.Forsyth       if ( count == 0 )
466*37da2899SCharles.Forsyth         break;
467*37da2899SCharles.Forsyth 
468*37da2899SCharles.Forsyth       error = ft_gzip_file_fill_output( zip );
469*37da2899SCharles.Forsyth       if (error)
470*37da2899SCharles.Forsyth         break;
471*37da2899SCharles.Forsyth     }
472*37da2899SCharles.Forsyth 
473*37da2899SCharles.Forsyth   Exit:
474*37da2899SCharles.Forsyth     return result;
475*37da2899SCharles.Forsyth   }
476*37da2899SCharles.Forsyth 
477*37da2899SCharles.Forsyth 
478*37da2899SCharles.Forsyth /***************************************************************************/
479*37da2899SCharles.Forsyth /***************************************************************************/
480*37da2899SCharles.Forsyth /*****                                                                 *****/
481*37da2899SCharles.Forsyth /*****               G Z   E M B E D D I N G   S T R E A M             *****/
482*37da2899SCharles.Forsyth /*****                                                                 *****/
483*37da2899SCharles.Forsyth /***************************************************************************/
484*37da2899SCharles.Forsyth /***************************************************************************/
485*37da2899SCharles.Forsyth 
486*37da2899SCharles.Forsyth   static void
ft_gzip_stream_close(FT_Stream stream)487*37da2899SCharles.Forsyth   ft_gzip_stream_close( FT_Stream  stream )
488*37da2899SCharles.Forsyth   {
489*37da2899SCharles.Forsyth     FT_GZipFile  zip    = stream->descriptor.pointer;
490*37da2899SCharles.Forsyth     FT_Memory    memory = stream->memory;
491*37da2899SCharles.Forsyth 
492*37da2899SCharles.Forsyth     if ( zip )
493*37da2899SCharles.Forsyth     {
494*37da2899SCharles.Forsyth       /* finalize gzip file descriptor */
495*37da2899SCharles.Forsyth       ft_gzip_file_done( zip );
496*37da2899SCharles.Forsyth 
497*37da2899SCharles.Forsyth       FT_FREE( zip );
498*37da2899SCharles.Forsyth 
499*37da2899SCharles.Forsyth       stream->descriptor.pointer = NULL;
500*37da2899SCharles.Forsyth     }
501*37da2899SCharles.Forsyth   }
502*37da2899SCharles.Forsyth 
503*37da2899SCharles.Forsyth 
504*37da2899SCharles.Forsyth   static FT_ULong
ft_gzip_stream_io(FT_Stream stream,FT_ULong pos,FT_Byte * buffer,FT_ULong count)505*37da2899SCharles.Forsyth   ft_gzip_stream_io( FT_Stream   stream,
506*37da2899SCharles.Forsyth                      FT_ULong    pos,
507*37da2899SCharles.Forsyth                      FT_Byte*    buffer,
508*37da2899SCharles.Forsyth                      FT_ULong    count )
509*37da2899SCharles.Forsyth   {
510*37da2899SCharles.Forsyth     FT_GZipFile  zip = stream->descriptor.pointer;
511*37da2899SCharles.Forsyth 
512*37da2899SCharles.Forsyth     return ft_gzip_file_io( zip, pos, buffer, count );
513*37da2899SCharles.Forsyth   }
514*37da2899SCharles.Forsyth 
515*37da2899SCharles.Forsyth 
516*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Stream_OpenGzip(FT_Stream stream,FT_Stream source)517*37da2899SCharles.Forsyth   FT_Stream_OpenGzip( FT_Stream    stream,
518*37da2899SCharles.Forsyth                       FT_Stream    source )
519*37da2899SCharles.Forsyth   {
520*37da2899SCharles.Forsyth     FT_Error     error;
521*37da2899SCharles.Forsyth     FT_Memory    memory = source->memory;
522*37da2899SCharles.Forsyth     FT_GZipFile  zip;
523*37da2899SCharles.Forsyth 
524*37da2899SCharles.Forsyth     FT_ZERO( stream );
525*37da2899SCharles.Forsyth     stream->memory = memory;
526*37da2899SCharles.Forsyth 
527*37da2899SCharles.Forsyth     if ( !FT_NEW( zip ) )
528*37da2899SCharles.Forsyth     {
529*37da2899SCharles.Forsyth       error = ft_gzip_file_init( zip, stream, source );
530*37da2899SCharles.Forsyth       if ( error )
531*37da2899SCharles.Forsyth       {
532*37da2899SCharles.Forsyth         FT_FREE( zip );
533*37da2899SCharles.Forsyth         goto Exit;
534*37da2899SCharles.Forsyth       }
535*37da2899SCharles.Forsyth 
536*37da2899SCharles.Forsyth       stream->descriptor.pointer = zip;
537*37da2899SCharles.Forsyth     }
538*37da2899SCharles.Forsyth 
539*37da2899SCharles.Forsyth      stream->size = 0x7FFFFFFF;  /* don't know the real size !! */
540*37da2899SCharles.Forsyth     stream->pos   = 0;
541*37da2899SCharles.Forsyth     stream->base  = 0;
542*37da2899SCharles.Forsyth     stream->read  = ft_gzip_stream_io;
543*37da2899SCharles.Forsyth     stream->close = ft_gzip_stream_close;
544*37da2899SCharles.Forsyth 
545*37da2899SCharles.Forsyth   Exit:
546*37da2899SCharles.Forsyth     return error;
547*37da2899SCharles.Forsyth   }
548*37da2899SCharles.Forsyth 
549*37da2899SCharles.Forsyth #else  /* !FT_CONFIG_OPTION_USE_ZLIB */
550*37da2899SCharles.Forsyth 
551*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Stream_OpenGzip(FT_Stream stream,FT_Stream source)552*37da2899SCharles.Forsyth   FT_Stream_OpenGzip( FT_Stream    stream,
553*37da2899SCharles.Forsyth                       FT_Stream    source )
554*37da2899SCharles.Forsyth   {
555*37da2899SCharles.Forsyth     FT_UNUSED( stream );
556*37da2899SCharles.Forsyth     FT_UNUSED( source );
557*37da2899SCharles.Forsyth 
558*37da2899SCharles.Forsyth     return FT_Err_Unimplemented_Feature;
559*37da2899SCharles.Forsyth   }
560*37da2899SCharles.Forsyth 
561*37da2899SCharles.Forsyth #endif /* !FT_CONFIG_OPTION_USE_ZLIB */
562