aboutsummaryrefslogtreecommitdiff
path: root/freetype/src/lzw/ftzopen.h
blob: f7d2936be2f8e5241530480f46b3d943908f38f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/***************************************************************************/
/*                                                                         */
/*  ftzopen.h                                                              */
/*                                                                         */
/*    FreeType support for .Z compressed files.                            */
/*                                                                         */
/*  This optional component relies on NetBSD's zopen().  It should mainly  */
/*  be used to parse compressed PCF fonts, as found with many X11 server   */
/*  distributions.                                                         */
/*                                                                         */
/*  Copyright 2005, 2006, 2007, 2008 by David Turner.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/***************************************************************************/

#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, using
   *  400 KByte 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_LzwPhase_
  {
    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 an 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_LzwStateRec_
  {
    FT_LzwPhase  phase;
    FT_Int       in_eof;

    FT_Byte      buf_tab[16];
    FT_Int       buf_offset;
    FT_Int       buf_size;
    FT_Bool      buf_clear;
    FT_Offset    buf_total;

    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 reached by free_ent, 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_Offset    stack_size;
    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__ */


/* END */