source: trunk/poppler/freetype-2.1.10/src/lzw/ftlzw.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

File size: 12.0 KB
Line 
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, 2005 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 <string.h>
30#include <stdio.h>
31
32
33#include FT_MODULE_ERRORS_H
34
35#undef __FTERRORS_H__
36
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#include "zopen.h"
46
47
48/***************************************************************************/
49/***************************************************************************/
50/*****                                                                 *****/
51/*****                  M E M O R Y   M A N A G E M E N T              *****/
52/*****                                                                 *****/
53/***************************************************************************/
54/***************************************************************************/
55
56/***************************************************************************/
57/***************************************************************************/
58/*****                                                                 *****/
59/*****                   F I L E   D E S C R I P T O R                 *****/
60/*****                                                                 *****/
61/***************************************************************************/
62/***************************************************************************/
63
64#define  FT_LZW_BUFFER_SIZE  4096
65
66  typedef struct FT_LZWFileRec_
67  {
68    FT_Stream   source;         /* parent/source stream        */
69    FT_Stream   stream;         /* embedding stream            */
70    FT_Memory   memory;         /* memory allocator            */
71    s_zstate_t  zstream;        /* lzw input stream            */
72
73    FT_ULong    start;          /* starting position, after .Z header */
74    FT_Byte     input[FT_LZW_BUFFER_SIZE];  /* input buffer */
75
76    FT_Byte     buffer[FT_LZW_BUFFER_SIZE]; /* output buffer */
77    FT_ULong    pos;            /* position in output          */
78    FT_Byte*    cursor;
79    FT_Byte*    limit;
80
81  } FT_LZWFileRec, *FT_LZWFile;
82
83
84  /* check and skip .Z header */
85  static FT_Error
86  ft_lzw_check_header( FT_Stream  stream )
87  {
88    FT_Error  error;
89    FT_Byte   head[2];
90
91
92    if ( FT_STREAM_SEEK( 0 )       ||
93         FT_STREAM_READ( head, 2 ) )
94      goto Exit;
95
96    /* head[0] && head[1] are the magic numbers     */
97    if ( head[0] != 0x1f ||
98         head[1] != 0x9d )
99      error = LZW_Err_Invalid_File_Format;
100
101  Exit:
102    return error;
103  }
104
105
106  static FT_Error
107  ft_lzw_file_init( FT_LZWFile  zip,
108                    FT_Stream   stream,
109                    FT_Stream   source )
110  {
111    s_zstate_t*  zstream = &zip->zstream;
112    FT_Error     error   = LZW_Err_Ok;
113
114
115    zip->stream = stream;
116    zip->source = source;
117    zip->memory = stream->memory;
118
119    zip->limit  = zip->buffer + FT_LZW_BUFFER_SIZE;
120    zip->cursor = zip->limit;
121    zip->pos    = 0;
122
123    /* check and skip .Z header */
124    {
125      stream = source;
126
127      error = ft_lzw_check_header( source );
128      if ( error )
129        goto Exit;
130
131      zip->start = FT_STREAM_POS();
132    }
133
134    /* initialize internal lzw variable */
135    zinit( zstream );
136
137    zstream->avail_in    = 0;
138    zstream->next_in     = zip->buffer;
139    zstream->zs_in_count = source->size - 2;
140
141    if ( zstream->next_in == NULL )
142      error = LZW_Err_Invalid_File_Format;
143
144  Exit:
145    return error;
146  }
147
148
149  static void
150  ft_lzw_file_done( FT_LZWFile  zip )
151  {
152    s_zstate_t*  zstream = &zip->zstream;
153
154
155    /* clear the rest */
156    zstream->next_in   = NULL;
157    zstream->next_out  = NULL;
158    zstream->avail_in  = 0;
159    zstream->avail_out = 0;
160    zstream->total_in  = 0;
161    zstream->total_out = 0;
162
163    zip->memory = NULL;
164    zip->source = NULL;
165    zip->stream = NULL;
166  }
167
168
169  static FT_Error
170  ft_lzw_file_reset( FT_LZWFile  zip )
171  {
172    FT_Stream  stream = zip->source;
173    FT_Error   error;
174
175
176    if ( !FT_STREAM_SEEK( zip->start ) )
177    {
178      s_zstate_t*  zstream = &zip->zstream;
179
180
181      zinit( zstream );
182
183      zstream->avail_in    = 0;
184      zstream->next_in     = zip->input;
185      zstream->total_in    = 0;
186      zstream->avail_out   = 0;
187      zstream->next_out    = zip->buffer;
188      zstream->total_out   = 0;
189      zstream->zs_in_count = zip->source->size - 2;
190
191      zip->limit  = zip->buffer + FT_LZW_BUFFER_SIZE;
192      zip->cursor = zip->limit;
193      zip->pos    = 0;
194    }
195
196    return error;
197  }
198
199
200  static FT_Error
201  ft_lzw_file_fill_input( FT_LZWFile  zip )
202  {
203    s_zstate_t*  zstream = &zip->zstream;
204    FT_Stream    stream  = zip->source;
205    FT_ULong     size;
206
207
208    if ( stream->read )
209    {
210      size = stream->read( stream, stream->pos, zip->input,
211                           FT_LZW_BUFFER_SIZE );
212      if ( size == 0 )
213        return LZW_Err_Invalid_Stream_Operation;
214    }
215    else
216    {
217      size = stream->size - stream->pos;
218      if ( size > FT_LZW_BUFFER_SIZE )
219        size = FT_LZW_BUFFER_SIZE;
220
221      if ( size == 0 )
222        return LZW_Err_Invalid_Stream_Operation;
223
224      FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
225    }
226    stream->pos += size;
227
228    zstream->next_in  = zip->input;
229    zstream->avail_in = size;
230
231    return LZW_Err_Ok;
232  }
233
234
235
236  static FT_Error
237  ft_lzw_file_fill_output( FT_LZWFile  zip )
238  {
239    s_zstate_t*  zstream = &zip->zstream;
240    FT_Error     error   = 0;
241
242
243    zip->cursor        = zip->buffer;
244    zstream->next_out  = zip->cursor;
245    zstream->avail_out = FT_LZW_BUFFER_SIZE;
246
247    while ( zstream->avail_out > 0 )
248    {
249      int  num_read = 0;
250
251
252      if ( zstream->avail_in == 0 )
253      {
254        error = ft_lzw_file_fill_input( zip );
255        if ( error )
256          break;
257      }
258
259      num_read = zread( zstream );
260
261      if ( num_read == -1 && zstream->zs_in_count == 0 )
262      {
263        zip->limit = zstream->next_out;
264        if ( zip->limit == zip->cursor )
265          error = LZW_Err_Invalid_Stream_Operation;
266        break;
267      }
268      else if ( num_read == -1 )
269        break;
270      else
271        zstream->avail_out -= num_read;
272    }
273
274    return error;
275  }
276
277
278  /* fill output buffer; `count' must be <= FT_LZW_BUFFER_SIZE */
279  static FT_Error
280  ft_lzw_file_skip_output( FT_LZWFile  zip,
281                           FT_ULong    count )
282  {
283    FT_Error  error = LZW_Err_Ok;
284    FT_ULong  delta;
285
286
287    for (;;)
288    {
289      delta = (FT_ULong)( zip->limit - zip->cursor );
290      if ( delta >= count )
291        delta = count;
292
293      zip->cursor += delta;
294      zip->pos    += delta;
295
296      count -= delta;
297      if ( count == 0 )
298        break;
299
300      error = ft_lzw_file_fill_output( zip );
301      if ( error )
302        break;
303    }
304
305    return error;
306  }
307
308
309  static FT_ULong
310  ft_lzw_file_io( FT_LZWFile  zip,
311                  FT_ULong    pos,
312                  FT_Byte*    buffer,
313                  FT_ULong    count )
314  {
315    FT_ULong  result = 0;
316    FT_Error  error;
317
318
319    /* Teset inflate stream if we're seeking backwards.        */
320    /* Yes, that is not too efficient, but it saves memory :-) */
321    if ( pos < zip->pos )
322    {
323      error = ft_lzw_file_reset( zip );
324      if ( error )
325        goto Exit;
326    }
327
328    /* skip unwanted bytes */
329    if ( pos > zip->pos )
330    {
331      error = ft_lzw_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
332      if ( error )
333        goto Exit;
334    }
335
336    if ( count == 0 )
337      goto Exit;
338
339    /* now read the data */
340    for (;;)
341    {
342      FT_ULong  delta;
343
344
345      delta = (FT_ULong)( zip->limit - zip->cursor );
346      if ( delta >= count )
347        delta = count;
348
349      FT_MEM_COPY( buffer, zip->cursor, delta );
350      buffer      += delta;
351      result      += delta;
352      zip->cursor += delta;
353      zip->pos    += delta;
354
355      count -= delta;
356      if ( count == 0 )
357        break;
358
359      error = ft_lzw_file_fill_output( zip );
360      if ( error )
361        break;
362    }
363
364  Exit:
365    return result;
366  }
367
368
369/***************************************************************************/
370/***************************************************************************/
371/*****                                                                 *****/
372/*****            L Z W   E M B E D D I N G   S T R E A M              *****/
373/*****                                                                 *****/
374/***************************************************************************/
375/***************************************************************************/
376
377  static void
378  ft_lzw_stream_close( FT_Stream  stream )
379  {
380    FT_LZWFile  zip    = (FT_LZWFile)stream->descriptor.pointer;
381    FT_Memory   memory = stream->memory;
382
383
384    if ( zip )
385    {
386      /* finalize lzw file descriptor */
387      ft_lzw_file_done( zip );
388
389      FT_FREE( zip );
390
391      stream->descriptor.pointer = NULL;
392    }
393  }
394
395
396  static FT_ULong
397  ft_lzw_stream_io( FT_Stream  stream,
398                    FT_ULong   pos,
399                    FT_Byte*   buffer,
400                    FT_ULong   count )
401  {
402    FT_LZWFile  zip = (FT_LZWFile)stream->descriptor.pointer;
403
404
405    return ft_lzw_file_io( zip, pos, buffer, count );
406  }
407
408
409  FT_EXPORT_DEF( FT_Error )
410  FT_Stream_OpenLZW( FT_Stream  stream,
411                     FT_Stream  source )
412  {
413    FT_Error    error;
414    FT_Memory   memory = source->memory;
415    FT_LZWFile  zip;
416
417
418    /*
419     *  Check the header right now; this prevents allocation a huge
420     *  LZWFile object (400 KByte of heap memory) if not necessary.
421     *
422     *  Did I mention that you should never use .Z compressed font
423     *  file?
424     */
425    error = ft_lzw_check_header( source );
426    if ( error )
427      goto Exit;
428
429    FT_ZERO( stream );
430    stream->memory = memory;
431
432    if ( !FT_NEW( zip ) )
433    {
434      error = ft_lzw_file_init( zip, stream, source );
435      if ( error )
436      {
437        FT_FREE( zip );
438        goto Exit;
439      }
440
441      stream->descriptor.pointer = zip;
442    }
443
444    stream->size  = 0x7FFFFFFFL;  /* don't know the real size! */
445    stream->pos   = 0;
446    stream->base  = 0;
447    stream->read  = ft_lzw_stream_io;
448    stream->close = ft_lzw_stream_close;
449
450  Exit:
451    return error;
452  }
453
454#include "zopen.c"
455
456
457#else  /* !FT_CONFIG_OPTION_USE_LZW */
458
459
460  FT_EXPORT_DEF( FT_Error )
461  FT_Stream_OpenLZW( FT_Stream  stream,
462                     FT_Stream  source )
463  {
464    FT_UNUSED( stream );
465    FT_UNUSED( source );
466
467    return LZW_Err_Unimplemented_Feature;
468  }
469
470
471#endif /* !FT_CONFIG_OPTION_USE_LZW */
472
473
474/* END */
Note: See TracBrowser for help on using the repository browser.