Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
ftbzip2.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* ftbzip2.c */
4 /* */
5 /* FreeType support for .bz2 compressed files. */
6 /* */
7 /* This optional component relies on libbz2. It should mainly be used to */
8 /* parse compressed PCF fonts, as found with many X11 server */
9 /* distributions. */
10 /* */
11 /* Copyright 2010, 2012, 2013 by */
12 /* Joel Klinghed. */
13 /* */
14 /* Based on src/gzip/ftgzip.c, Copyright 2002 - 2010 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 
26 #include <ft2build.h>
27 #include FT_INTERNAL_MEMORY_H
28 #include FT_INTERNAL_STREAM_H
29 #include FT_INTERNAL_DEBUG_H
30 #include FT_BZIP2_H
31 #include FT_CONFIG_STANDARD_LIBRARY_H
32 
33 
34 #include FT_MODULE_ERRORS_H
35 
36 #undef __FTERRORS_H__
37 
38 #undef FT_ERR_PREFIX
39 #define FT_ERR_PREFIX Bzip2_Err_
40 #define FT_ERR_BASE FT_Mod_Err_Bzip2
41 
42 #include FT_ERRORS_H
43 
44 
45 #ifdef FT_CONFIG_OPTION_USE_BZIP2
46 
47 #ifdef FT_CONFIG_OPTION_PIC
48 #error "bzip2 code does not support PIC yet"
49 #endif
50 
51 #define BZ_NO_STDIO /* Do not need FILE */
52 #include <bzlib.h>
53 
54 
55 /***************************************************************************/
56 /***************************************************************************/
57 /***** *****/
58 /***** B Z I P 2 M E M O R Y M A N A G E M E N T *****/
59 /***** *****/
60 /***************************************************************************/
61 /***************************************************************************/
62 
63  /* it is better to use FreeType memory routines instead of raw
64  'malloc/free' */
65 
66  typedef void *(* alloc_func)(void*, int, int);
67  typedef void (* free_func)(void*, void*);
68 
69  static void*
70  ft_bzip2_alloc( FT_Memory memory,
71  int items,
72  int size )
73  {
74  FT_ULong sz = (FT_ULong)size * items;
76  FT_Pointer p = NULL;
77 
78 
79  (void)FT_ALLOC( p, sz );
80  return p;
81  }
82 
83 
84  static void
85  ft_bzip2_free( FT_Memory memory,
86  void* address )
87  {
88  FT_MEM_FREE( address );
89  }
90 
91 
92 /***************************************************************************/
93 /***************************************************************************/
94 /***** *****/
95 /***** B Z I P 2 F I L E D E S C R I P T O R *****/
96 /***** *****/
97 /***************************************************************************/
98 /***************************************************************************/
99 
100 #define FT_BZIP2_BUFFER_SIZE 4096
101 
102  typedef struct FT_BZip2FileRec_
103  {
104  FT_Stream source; /* parent/source stream */
105  FT_Stream stream; /* embedding stream */
106  FT_Memory memory; /* memory allocator */
107  bz_stream bzstream; /* bzlib input stream */
108 
109  FT_Byte input[FT_BZIP2_BUFFER_SIZE]; /* input read buffer */
110 
111  FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */
112  FT_ULong pos; /* position in output */
113  FT_Byte* cursor;
114  FT_Byte* limit;
115 
116  } FT_BZip2FileRec, *FT_BZip2File;
117 
118 
119  /* check and skip .bz2 header - we don't support `transparent' compression */
120  static FT_Error
121  ft_bzip2_check_header( FT_Stream stream )
122  {
124  FT_Byte head[4];
125 
126 
127  if ( FT_STREAM_SEEK( 0 ) ||
128  FT_STREAM_READ( head, 4 ) )
129  goto Exit;
130 
131  /* head[0] && head[1] are the magic numbers; */
132  /* head[2] is the version, and head[3] the blocksize */
133  if ( head[0] != 0x42 ||
134  head[1] != 0x5a ||
135  head[2] != 0x68 ) /* only support bzip2 (huffman) */
136  {
137  error = FT_THROW( Invalid_File_Format );
138  goto Exit;
139  }
140 
141  Exit:
142  return error;
143  }
144 
145 
146  static FT_Error
147  ft_bzip2_file_init( FT_BZip2File zip,
148  FT_Stream stream,
149  FT_Stream source )
150  {
151  bz_stream* bzstream = &zip->bzstream;
153 
154 
155  zip->stream = stream;
156  zip->source = source;
157  zip->memory = stream->memory;
158 
159  zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
160  zip->cursor = zip->limit;
161  zip->pos = 0;
162 
163  /* check .bz2 header */
164  {
165  stream = source;
166 
167  error = ft_bzip2_check_header( stream );
168  if ( error )
169  goto Exit;
170 
171  if ( FT_STREAM_SEEK( 0 ) )
172  goto Exit;
173  }
174 
175  /* initialize bzlib */
176  bzstream->bzalloc = (alloc_func)ft_bzip2_alloc;
177  bzstream->bzfree = (free_func) ft_bzip2_free;
178  bzstream->opaque = zip->memory;
179 
180  bzstream->avail_in = 0;
181  bzstream->next_in = (char*)zip->buffer;
182 
183  if ( BZ2_bzDecompressInit( bzstream, 0, 0 ) != BZ_OK ||
184  bzstream->next_in == NULL )
185  error = FT_THROW( Invalid_File_Format );
186 
187  Exit:
188  return error;
189  }
190 
191 
192  static void
193  ft_bzip2_file_done( FT_BZip2File zip )
194  {
195  bz_stream* bzstream = &zip->bzstream;
196 
197 
198  BZ2_bzDecompressEnd( bzstream );
199 
200  /* clear the rest */
201  bzstream->bzalloc = NULL;
202  bzstream->bzfree = NULL;
203  bzstream->opaque = NULL;
204  bzstream->next_in = NULL;
205  bzstream->next_out = NULL;
206  bzstream->avail_in = 0;
207  bzstream->avail_out = 0;
208 
209  zip->memory = NULL;
210  zip->source = NULL;
211  zip->stream = NULL;
212  }
213 
214 
215  static FT_Error
216  ft_bzip2_file_reset( FT_BZip2File zip )
217  {
218  FT_Stream stream = zip->source;
219  FT_Error error;
220 
221 
222  if ( !FT_STREAM_SEEK( 0 ) )
223  {
224  bz_stream* bzstream = &zip->bzstream;
225 
226 
227  BZ2_bzDecompressEnd( bzstream );
228 
229  bzstream->avail_in = 0;
230  bzstream->next_in = (char*)zip->input;
231  bzstream->avail_out = 0;
232  bzstream->next_out = (char*)zip->buffer;
233 
234  zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
235  zip->cursor = zip->limit;
236  zip->pos = 0;
237 
238  BZ2_bzDecompressInit( bzstream, 0, 0 );
239  }
240 
241  return error;
242  }
243 
244 
245  static FT_Error
246  ft_bzip2_file_fill_input( FT_BZip2File zip )
247  {
248  bz_stream* bzstream = &zip->bzstream;
249  FT_Stream stream = zip->source;
250  FT_ULong size;
251 
252 
253  if ( stream->read )
254  {
255  size = stream->read( stream, stream->pos, zip->input,
256  FT_BZIP2_BUFFER_SIZE );
257  if ( size == 0 )
258  return FT_THROW( Invalid_Stream_Operation );
259  }
260  else
261  {
262  size = stream->size - stream->pos;
263  if ( size > FT_BZIP2_BUFFER_SIZE )
264  size = FT_BZIP2_BUFFER_SIZE;
265 
266  if ( size == 0 )
267  return FT_THROW( Invalid_Stream_Operation );
268 
269  FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
270  }
271  stream->pos += size;
272 
273  bzstream->next_in = (char*)zip->input;
274  bzstream->avail_in = size;
275 
276  return FT_Err_Ok;
277  }
278 
279 
280  static FT_Error
281  ft_bzip2_file_fill_output( FT_BZip2File zip )
282  {
283  bz_stream* bzstream = &zip->bzstream;
285 
286 
287  zip->cursor = zip->buffer;
288  bzstream->next_out = (char*)zip->cursor;
289  bzstream->avail_out = FT_BZIP2_BUFFER_SIZE;
290 
291  while ( bzstream->avail_out > 0 )
292  {
293  int err;
294 
295 
296  if ( bzstream->avail_in == 0 )
297  {
298  error = ft_bzip2_file_fill_input( zip );
299  if ( error )
300  break;
301  }
302 
303  err = BZ2_bzDecompress( bzstream );
304 
305  if ( err == BZ_STREAM_END )
306  {
307  zip->limit = (FT_Byte*)bzstream->next_out;
308  if ( zip->limit == zip->cursor )
309  error = FT_THROW( Invalid_Stream_Operation );
310  break;
311  }
312  else if ( err != BZ_OK )
313  {
314  error = FT_THROW( Invalid_Stream_Operation );
315  break;
316  }
317  }
318 
319  return error;
320  }
321 
322 
323  /* fill output buffer; `count' must be <= FT_BZIP2_BUFFER_SIZE */
324  static FT_Error
325  ft_bzip2_file_skip_output( FT_BZip2File zip,
326  FT_ULong count )
327  {
329  FT_ULong delta;
330 
331 
332  for (;;)
333  {
334  delta = (FT_ULong)( zip->limit - zip->cursor );
335  if ( delta >= count )
336  delta = count;
337 
338  zip->cursor += delta;
339  zip->pos += delta;
340 
341  count -= delta;
342  if ( count == 0 )
343  break;
344 
345  error = ft_bzip2_file_fill_output( zip );
346  if ( error )
347  break;
348  }
349 
350  return error;
351  }
352 
353 
354  static FT_ULong
355  ft_bzip2_file_io( FT_BZip2File zip,
356  FT_ULong pos,
357  FT_Byte* buffer,
358  FT_ULong count )
359  {
360  FT_ULong result = 0;
361  FT_Error error;
362 
363 
364  /* Reset inflate stream if we're seeking backwards. */
365  /* Yes, that is not too efficient, but it saves memory :-) */
366  if ( pos < zip->pos )
367  {
368  error = ft_bzip2_file_reset( zip );
369  if ( error )
370  goto Exit;
371  }
372 
373  /* skip unwanted bytes */
374  if ( pos > zip->pos )
375  {
376  error = ft_bzip2_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
377  if ( error )
378  goto Exit;
379  }
380 
381  if ( count == 0 )
382  goto Exit;
383 
384  /* now read the data */
385  for (;;)
386  {
387  FT_ULong delta;
388 
389 
390  delta = (FT_ULong)( zip->limit - zip->cursor );
391  if ( delta >= count )
392  delta = count;
393 
394  FT_MEM_COPY( buffer, zip->cursor, delta );
395  buffer += delta;
396  result += delta;
397  zip->cursor += delta;
398  zip->pos += delta;
399 
400  count -= delta;
401  if ( count == 0 )
402  break;
403 
404  error = ft_bzip2_file_fill_output( zip );
405  if ( error )
406  break;
407  }
408 
409  Exit:
410  return result;
411  }
412 
413 
414 /***************************************************************************/
415 /***************************************************************************/
416 /***** *****/
417 /***** B Z E M B E D D I N G S T R E A M *****/
418 /***** *****/
419 /***************************************************************************/
420 /***************************************************************************/
421 
422  static void
423  ft_bzip2_stream_close( FT_Stream stream )
424  {
425  FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
426  FT_Memory memory = stream->memory;
427 
428 
429  if ( zip )
430  {
431  /* finalize bzip file descriptor */
432  ft_bzip2_file_done( zip );
433 
434  FT_FREE( zip );
435 
436  stream->descriptor.pointer = NULL;
437  }
438  }
439 
440 
441  static FT_ULong
442  ft_bzip2_stream_io( FT_Stream stream,
443  FT_ULong pos,
444  FT_Byte* buffer,
445  FT_ULong count )
446  {
447  FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
448 
449 
450  return ft_bzip2_file_io( zip, pos, buffer, count );
451  }
452 
453 
456  FT_Stream source )
457  {
458  FT_Error error;
459  FT_Memory memory = source->memory;
460  FT_BZip2File zip = NULL;
461 
462 
463  /*
464  * check the header right now; this prevents allocating unnecessary
465  * objects when we don't need them
466  */
467  error = ft_bzip2_check_header( source );
468  if ( error )
469  goto Exit;
470 
471  FT_ZERO( stream );
472  stream->memory = memory;
473 
474  if ( !FT_QNEW( zip ) )
475  {
476  error = ft_bzip2_file_init( zip, stream, source );
477  if ( error )
478  {
479  FT_FREE( zip );
480  goto Exit;
481  }
482 
483  stream->descriptor.pointer = zip;
484  }
485 
486  stream->size = 0x7FFFFFFFL; /* don't know the real size! */
487  stream->pos = 0;
488  stream->base = 0;
489  stream->read = ft_bzip2_stream_io;
490  stream->close = ft_bzip2_stream_close;
491 
492  Exit:
493  return error;
494  }
495 
496 #else /* !FT_CONFIG_OPTION_USE_BZIP2 */
497 
500  FT_Stream source )
501  {
502  FT_UNUSED( stream );
503  FT_UNUSED( source );
504 
505  return FT_THROW( Unimplemented_Feature );
506  }
507 
508 #endif /* !FT_CONFIG_OPTION_USE_BZIP2 */
509 
510 
511 /* END */
unsigned char * base
Definition: ftsystem.h:323
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:260
int FT_Error
Definition: fttypes.h:296
GLuint GLuint stream
unsigned long FT_ULong
Definition: fttypes.h:249
unsigned long size
Definition: ftsystem.h:324
GLfloat GLfloat p
#define NULL
Definition: ftobjs.h:61
return FT_THROW(Missing_Property)
#define FT_UNUSED(arg)
Definition: ftconfig.h:76
GLsizei GLsizei GLchar * source
return FT_Err_Ok
Definition: ftbbox.c:645
typedef void(APIENTRY *GLDEBUGPROCARB)(GLenum source
#define FT_QNEW(ptr)
Definition: ftmemory.h:296
FT_Stream_IoFunc read
Definition: ftsystem.h:329
unsigned char FT_Byte
Definition: fttypes.h:150
FT_StreamDesc descriptor
Definition: ftsystem.h:327
FT_Memory memory
Definition: ftsystem.h:332
#define FT_FREE(ptr)
Definition: ftmemory.h:286
GLenum GLenum GLenum input
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:32
FT_Stream_OpenBzip2(FT_Stream stream, FT_Stream source)
Definition: ftbzip2.c:499
FT_Error error
Definition: cffdrivr.c:411
void * FT_Pointer
Definition: fttypes.h:307
#define FT_ZERO(p)
Definition: ftmemory.h:210
#define FT_MEM_FREE(ptr)
Definition: ftmemory.h:147
GLuint buffer
FT_Stream_CloseFunc close
Definition: ftsystem.h:330
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:489
if(!abbox) return FT_THROW(Invalid_Argument)
typedef int
Definition: png.h:978
void * pointer
Definition: ftsystem.h:212
GLuint64EXT * result
GLuint GLuint GLsizei count
#define FT_MEM_COPY(dest, source, count)
Definition: ftmemory.h:203
unsigned long pos
Definition: ftsystem.h:325
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:495
GLsizeiptr size
GLint limit
GLuint address