00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <ft2build.h>
00026 #include FT_INTERNAL_MEMORY_H
00027 #include FT_INTERNAL_STREAM_H
00028 #include FT_INTERNAL_DEBUG_H
00029 #include FT_LZW_H
00030 #include FT_CONFIG_STANDARD_LIBRARY_H
00031
00032
00033 #include FT_MODULE_ERRORS_H
00034
00035 #undef __FTERRORS_H__
00036
00037 #define FT_ERR_PREFIX LZW_Err_
00038 #define FT_ERR_BASE FT_Mod_Err_LZW
00039
00040 #include FT_ERRORS_H
00041
00042
00043 #ifdef FT_CONFIG_OPTION_USE_LZW
00044
00045 #ifdef FT_CONFIG_OPTION_PIC
00046 #error "lzw code does not support PIC yet"
00047 #endif
00048
00049 #include "ftzopen.h"
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #define FT_LZW_BUFFER_SIZE 4096
00069
00070 typedef struct FT_LZWFileRec_
00071 {
00072 FT_Stream source;
00073 FT_Stream stream;
00074 FT_Memory memory;
00075 FT_LzwStateRec lzw;
00076
00077 FT_Byte buffer[FT_LZW_BUFFER_SIZE];
00078 FT_ULong pos;
00079 FT_Byte* cursor;
00080 FT_Byte* limit;
00081
00082 } FT_LZWFileRec, *FT_LZWFile;
00083
00084
00085
00086 static FT_Error
00087 ft_lzw_check_header( FT_Stream stream )
00088 {
00089 FT_Error error;
00090 FT_Byte head[2];
00091
00092
00093 if ( FT_STREAM_SEEK( 0 ) ||
00094 FT_STREAM_READ( head, 2 ) )
00095 goto Exit;
00096
00097
00098 if ( head[0] != 0x1f ||
00099 head[1] != 0x9d )
00100 error = LZW_Err_Invalid_File_Format;
00101
00102 Exit:
00103 return error;
00104 }
00105
00106
00107 static FT_Error
00108 ft_lzw_file_init( FT_LZWFile zip,
00109 FT_Stream stream,
00110 FT_Stream source )
00111 {
00112 FT_LzwState lzw = &zip->lzw;
00113 FT_Error error = LZW_Err_Ok;
00114
00115
00116 zip->stream = stream;
00117 zip->source = source;
00118 zip->memory = stream->memory;
00119
00120 zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE;
00121 zip->cursor = zip->limit;
00122 zip->pos = 0;
00123
00124
00125 error = ft_lzw_check_header( source );
00126 if ( error )
00127 goto Exit;
00128
00129
00130 ft_lzwstate_init( lzw, source );
00131
00132 Exit:
00133 return error;
00134 }
00135
00136
00137 static void
00138 ft_lzw_file_done( FT_LZWFile zip )
00139 {
00140
00141 ft_lzwstate_done( &zip->lzw );
00142
00143 zip->memory = NULL;
00144 zip->source = NULL;
00145 zip->stream = NULL;
00146 }
00147
00148
00149 static FT_Error
00150 ft_lzw_file_reset( FT_LZWFile zip )
00151 {
00152 FT_Stream stream = zip->source;
00153 FT_Error error;
00154
00155
00156 if ( !FT_STREAM_SEEK( 0 ) )
00157 {
00158 ft_lzwstate_reset( &zip->lzw );
00159
00160 zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE;
00161 zip->cursor = zip->limit;
00162 zip->pos = 0;
00163 }
00164
00165 return error;
00166 }
00167
00168
00169 static FT_Error
00170 ft_lzw_file_fill_output( FT_LZWFile zip )
00171 {
00172 FT_LzwState lzw = &zip->lzw;
00173 FT_ULong count;
00174 FT_Error error = 0;
00175
00176
00177 zip->cursor = zip->buffer;
00178
00179 count = ft_lzwstate_io( lzw, zip->buffer, FT_LZW_BUFFER_SIZE );
00180
00181 zip->limit = zip->cursor + count;
00182
00183 if ( count == 0 )
00184 error = LZW_Err_Invalid_Stream_Operation;
00185
00186 return error;
00187 }
00188
00189
00190
00191 static FT_Error
00192 ft_lzw_file_skip_output( FT_LZWFile zip,
00193 FT_ULong count )
00194 {
00195 FT_Error error = LZW_Err_Ok;
00196
00197
00198
00199 {
00200 FT_ULong delta = (FT_ULong)( zip->limit - zip->cursor );
00201
00202
00203 if ( delta >= count )
00204 delta = count;
00205
00206 zip->cursor += delta;
00207 zip->pos += delta;
00208
00209 count -= delta;
00210 }
00211
00212
00213 while ( count > 0 )
00214 {
00215 FT_ULong delta = FT_LZW_BUFFER_SIZE;
00216 FT_ULong numread;
00217
00218
00219 if ( delta > count )
00220 delta = count;
00221
00222 numread = ft_lzwstate_io( &zip->lzw, NULL, delta );
00223 if ( numread < delta )
00224 {
00225
00226 error = LZW_Err_Invalid_Stream_Operation;
00227 break;
00228 }
00229
00230 zip->pos += delta;
00231 count -= delta;
00232 }
00233
00234 return error;
00235 }
00236
00237
00238 static FT_ULong
00239 ft_lzw_file_io( FT_LZWFile zip,
00240 FT_ULong pos,
00241 FT_Byte* buffer,
00242 FT_ULong count )
00243 {
00244 FT_ULong result = 0;
00245 FT_Error error;
00246
00247
00248
00249 if ( pos < zip->pos )
00250 {
00251
00252
00253 if ( ( zip->pos - pos ) <= (FT_ULong)( zip->cursor - zip->buffer ) )
00254 {
00255 zip->cursor -= zip->pos - pos;
00256 zip->pos = pos;
00257 }
00258 else
00259 {
00260 error = ft_lzw_file_reset( zip );
00261 if ( error )
00262 goto Exit;
00263 }
00264 }
00265
00266
00267 if ( pos > zip->pos )
00268 {
00269 error = ft_lzw_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
00270 if ( error )
00271 goto Exit;
00272 }
00273
00274 if ( count == 0 )
00275 goto Exit;
00276
00277
00278 for (;;)
00279 {
00280 FT_ULong delta;
00281
00282
00283 delta = (FT_ULong)( zip->limit - zip->cursor );
00284 if ( delta >= count )
00285 delta = count;
00286
00287 FT_MEM_COPY( buffer + result, zip->cursor, delta );
00288 result += delta;
00289 zip->cursor += delta;
00290 zip->pos += delta;
00291
00292 count -= delta;
00293 if ( count == 0 )
00294 break;
00295
00296 error = ft_lzw_file_fill_output( zip );
00297 if ( error )
00298 break;
00299 }
00300
00301 Exit:
00302 return result;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 static void
00315 ft_lzw_stream_close( FT_Stream stream )
00316 {
00317 FT_LZWFile zip = (FT_LZWFile)stream->descriptor.pointer;
00318 FT_Memory memory = stream->memory;
00319
00320
00321 if ( zip )
00322 {
00323
00324 ft_lzw_file_done( zip );
00325
00326 FT_FREE( zip );
00327
00328 stream->descriptor.pointer = NULL;
00329 }
00330 }
00331
00332
00333 static FT_ULong
00334 ft_lzw_stream_io( FT_Stream stream,
00335 FT_ULong pos,
00336 FT_Byte* buffer,
00337 FT_ULong count )
00338 {
00339 FT_LZWFile zip = (FT_LZWFile)stream->descriptor.pointer;
00340
00341
00342 return ft_lzw_file_io( zip, pos, buffer, count );
00343 }
00344
00345
00346 FT_EXPORT_DEF( FT_Error )
00347 FT_Stream_OpenLZW( FT_Stream stream,
00348 FT_Stream source )
00349 {
00350 FT_Error error;
00351 FT_Memory memory = source->memory;
00352 FT_LZWFile zip;
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 error = ft_lzw_check_header( source );
00363 if ( error )
00364 goto Exit;
00365
00366 FT_ZERO( stream );
00367 stream->memory = memory;
00368
00369 if ( !FT_NEW( zip ) )
00370 {
00371 error = ft_lzw_file_init( zip, stream, source );
00372 if ( error )
00373 {
00374 FT_FREE( zip );
00375 goto Exit;
00376 }
00377
00378 stream->descriptor.pointer = zip;
00379 }
00380
00381 stream->size = 0x7FFFFFFFL;
00382 stream->pos = 0;
00383 stream->base = 0;
00384 stream->read = ft_lzw_stream_io;
00385 stream->close = ft_lzw_stream_close;
00386
00387 Exit:
00388 return error;
00389 }
00390
00391
00392 #include "ftzopen.c"
00393
00394
00395 #else
00396
00397
00398 FT_EXPORT_DEF( FT_Error )
00399 FT_Stream_OpenLZW( FT_Stream stream,
00400 FT_Stream source )
00401 {
00402 FT_UNUSED( stream );
00403 FT_UNUSED( source );
00404
00405 return LZW_Err_Unimplemented_Feature;
00406 }
00407
00408
00409 #endif
00410
00411
00412