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