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