Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenftlzw.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* ftlzw.c */ 00004 /* */ 00005 /* FreeType support for .Z compressed files. */ 00006 /* */ 00007 /* This optional component relies on NetBSD's zopen(). It should mainly */ 00008 /* be used to parse compressed PCF fonts, as found with many X11 server */ 00009 /* distributions. */ 00010 /* */ 00011 /* Copyright 2004, 2005, 2006, 2009, 2010 by */ 00012 /* Albert Chin-A-Young. */ 00013 /* */ 00014 /* Based on code in src/gzip/ftgzip.c, Copyright 2004 by */ 00015 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00016 /* */ 00017 /* This file is part of the FreeType project, and may only be used, */ 00018 /* modified, and distributed under the terms of the FreeType project */ 00019 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00020 /* this file you indicate that you have read the license and */ 00021 /* understand and accept it fully. */ 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 /***** M E M O R Y M A N A G E M E N T *****/ 00056 /***** *****/ 00057 /***************************************************************************/ 00058 /***************************************************************************/ 00059 00060 /***************************************************************************/ 00061 /***************************************************************************/ 00062 /***** *****/ 00063 /***** F I L E D E S C R I P T O R *****/ 00064 /***** *****/ 00065 /***************************************************************************/ 00066 /***************************************************************************/ 00067 00068 #define FT_LZW_BUFFER_SIZE 4096 00069 00070 typedef struct FT_LZWFileRec_ 00071 { 00072 FT_Stream source; /* parent/source stream */ 00073 FT_Stream stream; /* embedding stream */ 00074 FT_Memory memory; /* memory allocator */ 00075 FT_LzwStateRec lzw; /* lzw decompressor state */ 00076 00077 FT_Byte buffer[FT_LZW_BUFFER_SIZE]; /* output buffer */ 00078 FT_ULong pos; /* position in output */ 00079 FT_Byte* cursor; 00080 FT_Byte* limit; 00081 00082 } FT_LZWFileRec, *FT_LZWFile; 00083 00084 00085 /* check and skip .Z header */ 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 /* head[0] && head[1] are the magic numbers */ 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 /* check and skip .Z header */ 00125 error = ft_lzw_check_header( source ); 00126 if ( error ) 00127 goto Exit; 00128 00129 /* initialize internal lzw variable */ 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 /* clear the rest */ 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 = LZW_Err_Ok; 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 /* fill output buffer; `count' must be <= FT_LZW_BUFFER_SIZE */ 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 /* first, we skip what we can from the output buffer */ 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 /* next, we skip as many bytes remaining as possible */ 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 /* not enough bytes */ 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 /* seeking backwards. */ 00249 if ( pos < zip->pos ) 00250 { 00251 /* If the new position is within the output buffer, simply */ 00252 /* decrement pointers, otherwise we reset the stream completely! */ 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 /* skip unwanted bytes */ 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 /* now read the data */ 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 /***** L Z W E M B E D D I N G S T R E A M *****/ 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 /* finalize lzw file descriptor */ 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 * Check the header right now; this prevents allocation of a huge 00357 * LZWFile object (400 KByte of heap memory) if not necessary. 00358 * 00359 * Did I mention that you should never use .Z compressed font 00360 * files? 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; /* don't know the real size! */ 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 /* !FT_CONFIG_OPTION_USE_LZW */ 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 /* !FT_CONFIG_OPTION_USE_LZW */ 00410 00411 00412 /* END */ Generated on Sun May 27 2012 04:33:52 for ReactOS by
1.7.6.1
|