shithub: freetype+ttf2subf

ref: c1b6d08291087287bceb4dc2ec2c82a295adc575
dir: /src/lzw/ftzopen.h/

View raw version
#ifndef __FT_ZOPEN_H__
#define __FT_ZOPEN_H__

#include <ft2build.h>
#include FT_FREETYPE_H

/* this is a complete re-implementation of the LZW file reader,
 * since the old one was incredibly badly written, and used
 * 400 Kb of heap memory before decompressing anything.
 */

#define  FT_LZW_IN_BUFF_SIZE        64
#define  FT_LZW_DEFAULT_STACK_SIZE  64

#define  LZW_INIT_BITS     9
#define  LZW_MAX_BITS      16

#define  LZW_CLEAR         256
#define  LZW_FIRST         257

#define  LZW_BIT_MASK      0x1f
#define  LZW_BLOCK_MASK    0x80
#define  LZW_MASK(n)       ((1U << (n)) - 1U)

typedef enum
{
  FT_LZW_PHASE_START = 0,
  FT_LZW_PHASE_CODE,
  FT_LZW_PHASE_STACK,
  FT_LZW_PHASE_EOF

} FT_LzwPhase;


/* state of LZW decompressor
 *
 * small technical note:
 *
 * we use a few tricks in this implementation that are explained here to
 * ease debugging and maintenance.
 *
 * - first of all, the "prefix" and "suffix" arrays contain the
 *   suffix and prefix for codes over 256, this means that:
 *
 *     prefix_of(code) == state->prefix[ code-256 ]
 *     suffix_of(code) == state->suffix[ code-256 ]
 *
 *   each prefix is a 16-bit code, and each suffix an 8-bit byte
 *
 *   both arrays are stored in a single memory block, pointed to by
 *   'state->prefix', this means that the following equality is always
 *   true:
 *
 *     state->suffix == (FT_Byte*)(state->prefix + state->prefix_size)
 *
 *   of course, state->prefix_size is the number of prefix/suffix slots
 *   in the arrays, corresponding to codes 256..255+prefix_size
 *
 * - 'free_ent' is the index of the next free entry in the "prefix"
 *   and "suffix" arrays. This means that the corresponding "next free
 *   code" is really '256+free_ent'
 *
 *   moreover, 'max_free' is the maximum value that 'free_ent' can reach.
 *
 *   'max_free' corresponds to "(1 << max_bits) - 256". Note that this value
 *   is always <= 0xFF00, which means that both 'free_ent' and 'max_free' can
 *   be stored in FT_UInt variable, even on 16-bit machines.
 *
 *   if 'free_ent == max_free', you cannot add new codes to the prefix/suffix
 *   table.
 *
 * - 'num_bits' is the current number of code bits, starting at 9 and
 *   growing each time 'free_ent' reaches the value of 'free_bits'. the
 *   latter is computed as follows:
 *
 *     if num_bits < max_bits:
 *        free_bits = (1 << num_bits)-256
 *     else:
 *        free_bits = max_free + 1
 *
 *     since the value of 'max_free + 1' can never be reached by 'free_ent',
 *     'num_bits' cannot grow larger than 'max_bits'
 */
typedef struct
{
  FT_LzwPhase  phase;

  FT_Int       in_eof;
  FT_Byte*     in_cursor;                        /* current buffer pos */
  FT_Byte*     in_limit;                         /* current buffer limit */

  FT_UInt32    pad;          /* a pad value where incoming bits were read */
  FT_Int       pad_bits;     /* number of meaningful bits in pad value    */

  FT_UInt      max_bits;     /* max code bits, from file header   */
  FT_Int       block_mode;   /* block mode flag, from file header */
  FT_UInt      max_free;     /* (1 << max_bits) - 256             */

  FT_UInt      num_bits;     /* current code bit number */
  FT_UInt      free_ent;     /* index of next free entry */
  FT_UInt      free_bits;    /* if free_ent reaches this, increment num_bits */
  FT_UInt      old_code;
  FT_UInt      old_char;
  FT_UInt      in_code;

  FT_UShort*   prefix;       /* always dynamically allocated / reallocated */
  FT_Byte*     suffix;       /* suffix = (FT_Byte*)(prefix + prefix_size)  */
  FT_UInt      prefix_size;  /* number of slots in 'prefix' or 'suffix'    */

  FT_Byte*     stack;        /* character stack */
  FT_UInt      stack_top;
  FT_UInt      stack_size;

  FT_Byte      in_buff[ FT_LZW_IN_BUFF_SIZE ];   /* small buffer to read data */
  FT_Byte      stack_0[ FT_LZW_DEFAULT_STACK_SIZE ];  /* minimize heap alloc */

  FT_Stream    source;   /* source stream */
  FT_Memory    memory;

} FT_LzwStateRec, *FT_LzwState;


FT_LOCAL( void )
ft_lzwstate_init( FT_LzwState  state,
                  FT_Stream    source );

FT_LOCAL( void )
ft_lzwstate_done( FT_LzwState  state );


FT_LOCAL( void )
ft_lzwstate_reset( FT_LzwState  state );


FT_LOCAL( FT_ULong )
ft_lzwstate_io( FT_LzwState  state,
                FT_Byte*     buffer,
                FT_ULong     out_size );

/* */

#endif /* __FT_ZOPEN_H__ */