ftzopen.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ftzopen.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 2005, 2006, 2007, 2009 by David Turner.                      */
00012 /*                                                                         */
00013 /*  This file is part of the FreeType project, and may only be used,       */
00014 /*  modified, and distributed under the terms of the FreeType project      */
00015 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00016 /*  this file you indicate that you have read the license and              */
00017 /*  understand and accept it fully.                                        */
00018 /*                                                                         */
00019 /***************************************************************************/
00020 
00021 #include "ftzopen.h"
00022 #include FT_INTERNAL_MEMORY_H
00023 #include FT_INTERNAL_STREAM_H
00024 #include FT_INTERNAL_DEBUG_H
00025 
00026 
00027   static int
00028   ft_lzwstate_refill( FT_LzwState  state )
00029   {
00030     FT_ULong  count;
00031 
00032 
00033     if ( state->in_eof )
00034       return -1;
00035 
00036     count = FT_Stream_TryRead( state->source,
00037                                state->buf_tab,
00038                                state->num_bits );  /* WHY? */
00039 
00040     state->buf_size   = (FT_UInt)count;
00041     state->buf_total += count;
00042     state->in_eof     = FT_BOOL( count < state->num_bits );
00043     state->buf_offset = 0;
00044     state->buf_size   = ( state->buf_size << 3 ) - ( state->num_bits - 1 );
00045 
00046     if ( count == 0 )  /* end of file */
00047       return -1;
00048 
00049     return 0;
00050   }
00051 
00052 
00053   static FT_Int32
00054   ft_lzwstate_get_code( FT_LzwState  state )
00055   {
00056     FT_UInt   num_bits = state->num_bits;
00057     FT_Int    offset   = state->buf_offset;
00058     FT_Byte*  p;
00059     FT_Int    result;
00060 
00061 
00062     if ( state->buf_clear                    ||
00063          offset >= state->buf_size           ||
00064          state->free_ent >= state->free_bits )
00065     {
00066       if ( state->free_ent >= state->free_bits )
00067       {
00068         state->num_bits  = ++num_bits;
00069         state->free_bits = state->num_bits < state->max_bits
00070                            ? (FT_UInt)( ( 1UL << num_bits ) - 256 )
00071                            : state->max_free + 1;
00072       }
00073 
00074       if ( state->buf_clear )
00075       {
00076         state->num_bits  = num_bits = LZW_INIT_BITS;
00077         state->free_bits = (FT_UInt)( ( 1UL << num_bits ) - 256 );
00078         state->buf_clear = 0;
00079       }
00080 
00081       if ( ft_lzwstate_refill( state ) < 0 )
00082         return -1;
00083 
00084       offset = 0;
00085     }
00086 
00087     state->buf_offset = offset + num_bits;
00088 
00089     p         = &state->buf_tab[offset >> 3];
00090     offset   &= 7;
00091     result    = *p++ >> offset;
00092     offset    = 8 - offset;
00093     num_bits -= offset;
00094 
00095     if ( num_bits >= 8 )
00096     {
00097       result   |= *p++ << offset;
00098       offset   += 8;
00099       num_bits -= 8;
00100     }
00101     if ( num_bits > 0 )
00102       result |= ( *p & LZW_MASK( num_bits ) ) << offset;
00103 
00104     return result;
00105   }
00106 
00107 
00108   /* grow the character stack */
00109   static int
00110   ft_lzwstate_stack_grow( FT_LzwState  state )
00111   {
00112     if ( state->stack_top >= state->stack_size )
00113     {
00114       FT_Memory  memory = state->memory;
00115       FT_Error   error;
00116       FT_Offset  old_size = state->stack_size;
00117       FT_Offset  new_size = old_size;
00118 
00119       new_size = new_size + ( new_size >> 1 ) + 4;
00120 
00121       if ( state->stack == state->stack_0 )
00122       {
00123         state->stack = NULL;
00124         old_size     = 0;
00125       }
00126 
00127       if ( FT_RENEW_ARRAY( state->stack, old_size, new_size ) )
00128         return -1;
00129 
00130       state->stack_size = new_size;
00131     }
00132     return 0;
00133   }
00134 
00135 
00136   /* grow the prefix/suffix arrays */
00137   static int
00138   ft_lzwstate_prefix_grow( FT_LzwState  state )
00139   {
00140     FT_UInt    old_size = state->prefix_size;
00141     FT_UInt    new_size = old_size;
00142     FT_Memory  memory   = state->memory;
00143     FT_Error   error;
00144 
00145 
00146     if ( new_size == 0 )  /* first allocation -> 9 bits */
00147       new_size = 512;
00148     else
00149       new_size += new_size >> 2;  /* don't grow too fast */
00150 
00151     /*
00152      *  Note that the `suffix' array is located in the same memory block
00153      *  pointed to by `prefix'.
00154      *
00155      *  I know that sizeof(FT_Byte) == 1 by definition, but it is clearer
00156      *  to write it literally.
00157      *
00158      */
00159     if ( FT_REALLOC_MULT( state->prefix, old_size, new_size,
00160                           sizeof ( FT_UShort ) + sizeof ( FT_Byte ) ) )
00161       return -1;
00162 
00163     /* now adjust `suffix' and move the data accordingly */
00164     state->suffix = (FT_Byte*)( state->prefix + new_size );
00165 
00166     FT_MEM_MOVE( state->suffix,
00167                  state->prefix + old_size,
00168                  old_size * sizeof ( FT_Byte ) );
00169 
00170     state->prefix_size = new_size;
00171     return 0;
00172   }
00173 
00174 
00175   FT_LOCAL_DEF( void )
00176   ft_lzwstate_reset( FT_LzwState  state )
00177   {
00178     state->in_eof     = 0;
00179     state->buf_offset = 0;
00180     state->buf_size   = 0;
00181     state->buf_clear  = 0;
00182     state->buf_total  = 0;
00183     state->stack_top  = 0;
00184     state->num_bits   = LZW_INIT_BITS;
00185     state->phase      = FT_LZW_PHASE_START;
00186   }
00187 
00188 
00189   FT_LOCAL_DEF( void )
00190   ft_lzwstate_init( FT_LzwState  state,
00191                     FT_Stream    source )
00192   {
00193     FT_ZERO( state );
00194 
00195     state->source = source;
00196     state->memory = source->memory;
00197 
00198     state->prefix      = NULL;
00199     state->suffix      = NULL;
00200     state->prefix_size = 0;
00201 
00202     state->stack      = state->stack_0;
00203     state->stack_size = sizeof ( state->stack_0 );
00204 
00205     ft_lzwstate_reset( state );
00206   }
00207 
00208 
00209   FT_LOCAL_DEF( void )
00210   ft_lzwstate_done( FT_LzwState  state )
00211   {
00212     FT_Memory  memory = state->memory;
00213 
00214 
00215     ft_lzwstate_reset( state );
00216 
00217     if ( state->stack != state->stack_0 )
00218       FT_FREE( state->stack );
00219 
00220     FT_FREE( state->prefix );
00221     state->suffix = NULL;
00222 
00223     FT_ZERO( state );
00224   }
00225 
00226 
00227 #define FTLZW_STACK_PUSH( c )                        \
00228   FT_BEGIN_STMNT                                     \
00229     if ( state->stack_top >= state->stack_size &&    \
00230          ft_lzwstate_stack_grow( state ) < 0   )     \
00231       goto Eof;                                      \
00232                                                      \
00233     state->stack[state->stack_top++] = (FT_Byte)(c); \
00234   FT_END_STMNT
00235 
00236 
00237   FT_LOCAL_DEF( FT_ULong )
00238   ft_lzwstate_io( FT_LzwState  state,
00239                   FT_Byte*     buffer,
00240                   FT_ULong     out_size )
00241   {
00242     FT_ULong  result = 0;
00243 
00244     FT_UInt  old_char = state->old_char;
00245     FT_UInt  old_code = state->old_code;
00246     FT_UInt  in_code  = state->in_code;
00247 
00248 
00249     if ( out_size == 0 )
00250       goto Exit;
00251 
00252     switch ( state->phase )
00253     {
00254     case FT_LZW_PHASE_START:
00255       {
00256         FT_Byte   max_bits;
00257         FT_Int32  c;
00258 
00259 
00260         /* skip magic bytes, and read max_bits + block_flag */
00261         if ( FT_Stream_Seek( state->source, 2 ) != 0               ||
00262              FT_Stream_TryRead( state->source, &max_bits, 1 ) != 1 )
00263           goto Eof;
00264 
00265         state->max_bits   = max_bits & LZW_BIT_MASK;
00266         state->block_mode = max_bits & LZW_BLOCK_MASK;
00267         state->max_free   = (FT_UInt)( ( 1UL << state->max_bits ) - 256 );
00268 
00269         if ( state->max_bits > LZW_MAX_BITS )
00270           goto Eof;
00271 
00272         state->num_bits = LZW_INIT_BITS;
00273         state->free_ent = ( state->block_mode ? LZW_FIRST
00274                                               : LZW_CLEAR ) - 256;
00275         in_code  = 0;
00276 
00277         state->free_bits = state->num_bits < state->max_bits
00278                            ? (FT_UInt)( ( 1UL << state->num_bits ) - 256 )
00279                            : state->max_free + 1;
00280 
00281         c = ft_lzwstate_get_code( state );
00282         if ( c < 0 )
00283           goto Eof;
00284 
00285         old_code = old_char = (FT_UInt)c;
00286 
00287         if ( buffer )
00288           buffer[result] = (FT_Byte)old_char;
00289 
00290         if ( ++result >= out_size )
00291           goto Exit;
00292 
00293         state->phase = FT_LZW_PHASE_CODE;
00294       }
00295       /* fall-through */
00296 
00297     case FT_LZW_PHASE_CODE:
00298       {
00299         FT_Int32  c;
00300         FT_UInt   code;
00301 
00302 
00303       NextCode:
00304         c = ft_lzwstate_get_code( state );
00305         if ( c < 0 )
00306           goto Eof;
00307 
00308         code = (FT_UInt)c;
00309 
00310         if ( code == LZW_CLEAR && state->block_mode )
00311         {
00312           /* why not LZW_FIRST-256 ? */
00313           state->free_ent  = ( LZW_FIRST - 1 ) - 256;
00314           state->buf_clear = 1;
00315           c = ft_lzwstate_get_code( state );
00316           if ( c < 0 )
00317             goto Eof;
00318 
00319           code = (FT_UInt)c;
00320         }
00321 
00322         in_code = code; /* save code for later */
00323 
00324         if ( code >= 256U )
00325         {
00326           /* special case for KwKwKwK */
00327           if ( code - 256U >= state->free_ent )
00328           {
00329             FTLZW_STACK_PUSH( old_char );
00330             code = old_code;
00331           }
00332 
00333           while ( code >= 256U )
00334           {
00335             if ( !state->prefix )
00336               goto Eof;
00337 
00338             FTLZW_STACK_PUSH( state->suffix[code - 256] );
00339             code = state->prefix[code - 256];
00340           }
00341         }
00342 
00343         old_char = code;
00344         FTLZW_STACK_PUSH( old_char );
00345 
00346         state->phase = FT_LZW_PHASE_STACK;
00347       }
00348       /* fall-through */
00349 
00350     case FT_LZW_PHASE_STACK:
00351       {
00352         while ( state->stack_top > 0 )
00353         {
00354           --state->stack_top;
00355 
00356           if ( buffer )
00357             buffer[result] = state->stack[state->stack_top];
00358 
00359           if ( ++result == out_size )
00360             goto Exit;
00361         }
00362 
00363         /* now create new entry */
00364         if ( state->free_ent < state->max_free )
00365         {
00366           if ( state->free_ent >= state->prefix_size &&
00367                ft_lzwstate_prefix_grow( state ) < 0  )
00368             goto Eof;
00369 
00370           FT_ASSERT( state->free_ent < state->prefix_size );
00371 
00372           state->prefix[state->free_ent] = (FT_UShort)old_code;
00373           state->suffix[state->free_ent] = (FT_Byte)  old_char;
00374 
00375           state->free_ent += 1;
00376         }
00377 
00378         old_code = in_code;
00379 
00380         state->phase = FT_LZW_PHASE_CODE;
00381         goto NextCode;
00382       }
00383 
00384     default:  /* state == EOF */
00385       ;
00386     }
00387 
00388   Exit:
00389     state->old_code = old_code;
00390     state->old_char = old_char;
00391     state->in_code  = in_code;
00392 
00393     return result;
00394 
00395   Eof:
00396     state->phase = FT_LZW_PHASE_EOF;
00397     goto Exit;
00398   }
00399 
00400 
00401 /* END */

Generated on Tue Jul 5 14:13:47 2011 for ROOT_528-00b_version by  doxygen 1.5.1