zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ftlzw.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* ftlzw.c */
4 /* */
5 /* FreeType support for .Z compressed files. */
6 /* */
7 /* This optional component relies on NetBSD's zopen(). It should mainly */
8 /* be used to parse compressed PCF fonts, as found with many X11 server */
9 /* distributions. */
10 /* */
11 /* Copyright 2004-2006, 2009, 2010, 2012 by */
12 /* Albert Chin-A-Young. */
13 /* */
14 /* Based on code in src/gzip/ftgzip.c, Copyright 2004 by */
15 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
16 /* */
17 /* This file is part of the FreeType project, and may only be used, */
18 /* modified, and distributed under the terms of the FreeType project */
19 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
20 /* this file you indicate that you have read the license and */
21 /* understand and accept it fully. */
22 /* */
23 /***************************************************************************/
24 
25 #include <ft2build.h>
26 #include FT_INTERNAL_MEMORY_H
27 #include FT_INTERNAL_STREAM_H
28 #include FT_INTERNAL_DEBUG_H
29 #include FT_LZW_H
30 #include FT_CONFIG_STANDARD_LIBRARY_H
31 
32 
33 #include FT_MODULE_ERRORS_H
34 
35 #undef __FTERRORS_H__
36 
37 #undef FT_ERR_PREFIX
38 #define FT_ERR_PREFIX LZW_Err_
39 #define FT_ERR_BASE FT_Mod_Err_LZW
40 
41 #include FT_ERRORS_H
42 
43 
44 #ifdef FT_CONFIG_OPTION_USE_LZW
45 
46 #ifdef FT_CONFIG_OPTION_PIC
47 #error "lzw code does not support PIC yet"
48 #endif
49 
50 #include "ftzopen.h"
51 
52 
53 /***************************************************************************/
54 /***************************************************************************/
55 /***** *****/
56 /***** M E M O R Y M A N A G E M E N T *****/
57 /***** *****/
58 /***************************************************************************/
59 /***************************************************************************/
60 
61 /***************************************************************************/
62 /***************************************************************************/
63 /***** *****/
64 /***** F I L E D E S C R I P T O R *****/
65 /***** *****/
66 /***************************************************************************/
67 /***************************************************************************/
68 
69 #define FT_LZW_BUFFER_SIZE 4096
70 
71  typedef struct FT_LZWFileRec_
72  {
73  FT_Stream source; /* parent/source stream */
74  FT_Stream stream; /* embedding stream */
75  FT_Memory memory; /* memory allocator */
76  FT_LzwStateRec lzw; /* lzw decompressor state */
77 
78  FT_Byte buffer[FT_LZW_BUFFER_SIZE]; /* output buffer */
79  FT_ULong pos; /* position in output */
80  FT_Byte* cursor;
81  FT_Byte* limit;
82 
83  } FT_LZWFileRec, *FT_LZWFile;
84 
85 
86  /* check and skip .Z header */
87  static FT_Error
88  ft_lzw_check_header( FT_Stream stream )
89  {
91  FT_Byte head[2];
92 
93 
94  if ( FT_STREAM_SEEK( 0 ) ||
95  FT_STREAM_READ( head, 2 ) )
96  goto Exit;
97 
98  /* head[0] && head[1] are the magic numbers */
99  if ( head[0] != 0x1f ||
100  head[1] != 0x9d )
101  error = LZW_Err_Invalid_File_Format;
102 
103  Exit:
104  return error;
105  }
106 
107 
108  static FT_Error
109  ft_lzw_file_init( FT_LZWFile zip,
110  FT_Stream stream,
111  FT_Stream source )
112  {
113  FT_LzwState lzw = &zip->lzw;
114  FT_Error error = LZW_Err_Ok;
115 
116 
117  zip->stream = stream;
118  zip->source = source;
119  zip->memory = stream->memory;
120 
121  zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE;
122  zip->cursor = zip->limit;
123  zip->pos = 0;
124 
125  /* check and skip .Z header */
126  error = ft_lzw_check_header( source );
127  if ( error )
128  goto Exit;
129 
130  /* initialize internal lzw variable */
131  ft_lzwstate_init( lzw, source );
132 
133  Exit:
134  return error;
135  }
136 
137 
138  static void
139  ft_lzw_file_done( FT_LZWFile zip )
140  {
141  /* clear the rest */
142  ft_lzwstate_done( &zip->lzw );
143 
144  zip->memory = NULL;
145  zip->source = NULL;
146  zip->stream = NULL;
147  }
148 
149 
150  static FT_Error
151  ft_lzw_file_reset( FT_LZWFile zip )
152  {
153  FT_Stream stream = zip->source;
154  FT_Error error;
155 
156 
157  if ( !FT_STREAM_SEEK( 0 ) )
158  {
159  ft_lzwstate_reset( &zip->lzw );
160 
161  zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE;
162  zip->cursor = zip->limit;
163  zip->pos = 0;
164  }
165 
166  return error;
167  }
168 
169 
170  static FT_Error
171  ft_lzw_file_fill_output( FT_LZWFile zip )
172  {
173  FT_LzwState lzw = &zip->lzw;
174  FT_ULong count;
175  FT_Error error = LZW_Err_Ok;
176 
177 
178  zip->cursor = zip->buffer;
179 
180  count = ft_lzwstate_io( lzw, zip->buffer, FT_LZW_BUFFER_SIZE );
181 
182  zip->limit = zip->cursor + count;
183 
184  if ( count == 0 )
185  error = LZW_Err_Invalid_Stream_Operation;
186 
187  return error;
188  }
189 
190 
191  /* fill output buffer; `count' must be <= FT_LZW_BUFFER_SIZE */
192  static FT_Error
193  ft_lzw_file_skip_output( FT_LZWFile zip,
194  FT_ULong count )
195  {
196  FT_Error error = LZW_Err_Ok;
197 
198 
199  /* first, we skip what we can from the output buffer */
200  {
201  FT_ULong delta = (FT_ULong)( zip->limit - zip->cursor );
202 
203 
204  if ( delta >= count )
205  delta = count;
206 
207  zip->cursor += delta;
208  zip->pos += delta;
209 
210  count -= delta;
211  }
212 
213  /* next, we skip as many bytes remaining as possible */
214  while ( count > 0 )
215  {
216  FT_ULong delta = FT_LZW_BUFFER_SIZE;
217  FT_ULong numread;
218 
219 
220  if ( delta > count )
221  delta = count;
222 
223  numread = ft_lzwstate_io( &zip->lzw, NULL, delta );
224  if ( numread < delta )
225  {
226  /* not enough bytes */
227  error = LZW_Err_Invalid_Stream_Operation;
228  break;
229  }
230 
231  zip->pos += delta;
232  count -= delta;
233  }
234 
235  return error;
236  }
237 
238 
239  static FT_ULong
240  ft_lzw_file_io( FT_LZWFile zip,
241  FT_ULong pos,
242  FT_Byte* buffer,
243  FT_ULong count )
244  {
245  FT_ULong result = 0;
246  FT_Error error;
247 
248 
249  /* seeking backwards. */
250  if ( pos < zip->pos )
251  {
252  /* If the new position is within the output buffer, simply */
253  /* decrement pointers, otherwise we reset the stream completely! */
254  if ( ( zip->pos - pos ) <= (FT_ULong)( zip->cursor - zip->buffer ) )
255  {
256  zip->cursor -= zip->pos - pos;
257  zip->pos = pos;
258  }
259  else
260  {
261  error = ft_lzw_file_reset( zip );
262  if ( error )
263  goto Exit;
264  }
265  }
266 
267  /* skip unwanted bytes */
268  if ( pos > zip->pos )
269  {
270  error = ft_lzw_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
271  if ( error )
272  goto Exit;
273  }
274 
275  if ( count == 0 )
276  goto Exit;
277 
278  /* now read the data */
279  for (;;)
280  {
281  FT_ULong delta;
282 
283 
284  delta = (FT_ULong)( zip->limit - zip->cursor );
285  if ( delta >= count )
286  delta = count;
287 
288  FT_MEM_COPY( buffer + result, zip->cursor, delta );
289  result += delta;
290  zip->cursor += delta;
291  zip->pos += delta;
292 
293  count -= delta;
294  if ( count == 0 )
295  break;
296 
297  error = ft_lzw_file_fill_output( zip );
298  if ( error )
299  break;
300  }
301 
302  Exit:
303  return result;
304  }
305 
306 
307 /***************************************************************************/
308 /***************************************************************************/
309 /***** *****/
310 /***** L Z W E M B E D D I N G S T R E A M *****/
311 /***** *****/
312 /***************************************************************************/
313 /***************************************************************************/
314 
315  static void
316  ft_lzw_stream_close( FT_Stream stream )
317  {
318  FT_LZWFile zip = (FT_LZWFile)stream->descriptor.pointer;
319  FT_Memory memory = stream->memory;
320 
321 
322  if ( zip )
323  {
324  /* finalize lzw file descriptor */
325  ft_lzw_file_done( zip );
326 
327  FT_FREE( zip );
328 
329  stream->descriptor.pointer = NULL;
330  }
331  }
332 
333 
334  static FT_ULong
335  ft_lzw_stream_io( FT_Stream stream,
336  FT_ULong pos,
337  FT_Byte* buffer,
338  FT_ULong count )
339  {
340  FT_LZWFile zip = (FT_LZWFile)stream->descriptor.pointer;
341 
342 
343  return ft_lzw_file_io( zip, pos, buffer, count );
344  }
345 
346 
349  FT_Stream source )
350  {
351  FT_Error error;
352  FT_Memory memory = source->memory;
353  FT_LZWFile zip = NULL;
354 
355 
356  /*
357  * Check the header right now; this prevents allocation of a huge
358  * LZWFile object (400 KByte of heap memory) if not necessary.
359  *
360  * Did I mention that you should never use .Z compressed font
361  * files?
362  */
363  error = ft_lzw_check_header( source );
364  if ( error )
365  goto Exit;
366 
367  FT_ZERO( stream );
368  stream->memory = memory;
369 
370  if ( !FT_NEW( zip ) )
371  {
372  error = ft_lzw_file_init( zip, stream, source );
373  if ( error )
374  {
375  FT_FREE( zip );
376  goto Exit;
377  }
378 
379  stream->descriptor.pointer = zip;
380  }
381 
382  stream->size = 0x7FFFFFFFL; /* don't know the real size! */
383  stream->pos = 0;
384  stream->base = 0;
385  stream->read = ft_lzw_stream_io;
386  stream->close = ft_lzw_stream_close;
387 
388  Exit:
389  return error;
390  }
391 
392 
393 #include "ftzopen.c"
394 
395 
396 #else /* !FT_CONFIG_OPTION_USE_LZW */
397 
398 
401  FT_Stream source )
402  {
403  FT_UNUSED( stream );
404  FT_UNUSED( source );
405 
406  return LZW_Err_Unimplemented_Feature;
407  }
408 
409 
410 #endif /* !FT_CONFIG_OPTION_USE_LZW */
411 
412 
413 /* END */
int FT_Error
Definition: fttypes.h:296
FT_BEGIN_HEADER FT_Stream_OpenLZW(FT_Stream stream, FT_Stream source)
Definition: ftlzw.c:400
unsigned long FT_ULong
Definition: fttypes.h:249
#define NULL
Definition: ftobjs.h:61
GLuint GLuint stream
Definition: glew.h:6573
ft_lzwstate_reset(FT_LzwState state)
Definition: ftzopen.c:185
if(!yyg->yy_init)
unsigned char FT_Byte
Definition: fttypes.h:150
FT_StreamDesc descriptor
Definition: ftsystem.h:327
EGLContext EGLenum EGLClientBuffer buffer
Definition: eglext.h:87
FT_Memory memory
Definition: ftsystem.h:332
#define FT_FREE(ptr)
Definition: ftmemory.h:286
GLuint64EXT * result
Definition: glew.h:12708
FT_Error error
Definition: cffdrivr.c:407
#define FT_ZERO(p)
Definition: ftmemory.h:210
GLint GLsizei count
Definition: gl2ext.h:1011
GLint limit
Definition: glew.h:11829
ft_lzwstate_done(FT_LzwState state)
Definition: ftzopen.c:219
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:496
void * pointer
Definition: ftsystem.h:212
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:511
ft_lzwstate_init(FT_LzwState state, FT_Stream source)
Definition: ftzopen.c:199
#define FT_NEW(ptr)
Definition: ftmemory.h:288
#define FT_MEM_COPY(dest, source, count)
Definition: ftmemory.h:203
SDL_EventEntry * head
Definition: SDL_events.c:78
GLsizei GLsizei GLchar * source
Definition: gl2ext.h:994
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:502
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
ft_lzwstate_io(FT_LzwState state, FT_Byte *buffer, FT_ULong out_size)
Definition: ftzopen.c:247