ReactOS 0.4.16-dev-2357-g35d0dfe
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 (C) 2010-2020 by
12 * Joel Klinghed.
13 *
14 * based on `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
28#include <freetype/ftbzip2.h>
29#include FT_CONFIG_STANDARD_LIBRARY_H
30
31
32#include <freetype/ftmoderr.h>
33
34#undef FTERRORS_H_
35
36#undef FT_ERR_PREFIX
37#define FT_ERR_PREFIX Bzip2_Err_
38#define FT_ERR_BASE FT_Mod_Err_Bzip2
39
40#include <freetype/fterrors.h>
41
42
43#ifdef FT_CONFIG_OPTION_USE_BZIP2
44
45#define BZ_NO_STDIO /* Do not need FILE */
46#include <bzlib.h>
47
48
49/***************************************************************************/
50/***************************************************************************/
51/***** *****/
52/***** B Z I P 2 M E M O R Y M A N A G E M E N T *****/
53/***** *****/
54/***************************************************************************/
55/***************************************************************************/
56
57 /* it is better to use FreeType memory routines instead of raw
58 'malloc/free' */
59
60 typedef void *(* alloc_func)(void*, int, int);
61 typedef void (* free_func)(void*, void*);
62
63 static void*
64 ft_bzip2_alloc( FT_Memory memory,
65 int items,
66 int size )
67 {
71
72
73 (void)FT_ALLOC( p, sz );
74 return p;
75 }
76
77
78 static void
79 ft_bzip2_free( FT_Memory memory,
80 void* address )
81 {
83 }
84
85
86/***************************************************************************/
87/***************************************************************************/
88/***** *****/
89/***** B Z I P 2 F I L E D E S C R I P T O R *****/
90/***** *****/
91/***************************************************************************/
92/***************************************************************************/
93
94#define FT_BZIP2_BUFFER_SIZE 4096
95
96 typedef struct FT_BZip2FileRec_
97 {
98 FT_Stream source; /* parent/source stream */
99 FT_Stream stream; /* embedding stream */
100 FT_Memory memory; /* memory allocator */
101 bz_stream bzstream; /* bzlib input stream */
102
103 FT_Byte input[FT_BZIP2_BUFFER_SIZE]; /* input read buffer */
104
105 FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */
106 FT_ULong pos; /* position in output */
108 FT_Byte* limit;
109
110 } FT_BZip2FileRec, *FT_BZip2File;
111
112
113 /* check and skip .bz2 header - we don't support `transparent' compression */
114 static FT_Error
115 ft_bzip2_check_header( FT_Stream stream )
116 {
118 FT_Byte head[4];
119
120
121 if ( FT_STREAM_SEEK( 0 ) ||
122 FT_STREAM_READ( head, 4 ) )
123 goto Exit;
124
125 /* head[0] && head[1] are the magic numbers; */
126 /* head[2] is the version, and head[3] the blocksize */
127 if ( head[0] != 0x42 ||
128 head[1] != 0x5A ||
129 head[2] != 0x68 ) /* only support bzip2 (huffman) */
130 {
131 error = FT_THROW( Invalid_File_Format );
132 goto Exit;
133 }
134
135 Exit:
136 return error;
137 }
138
139
140 static FT_Error
141 ft_bzip2_file_init( FT_BZip2File zip,
144 {
145 bz_stream* bzstream = &zip->bzstream;
147
148
149 zip->stream = stream;
150 zip->source = source;
151 zip->memory = stream->memory;
152
153 zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
154 zip->cursor = zip->limit;
155 zip->pos = 0;
156
157 /* check .bz2 header */
158 {
159 stream = source;
160
161 error = ft_bzip2_check_header( stream );
162 if ( error )
163 goto Exit;
164
165 if ( FT_STREAM_SEEK( 0 ) )
166 goto Exit;
167 }
168
169 /* initialize bzlib */
170 bzstream->bzalloc = (alloc_func)ft_bzip2_alloc;
171 bzstream->bzfree = (free_func) ft_bzip2_free;
172 bzstream->opaque = zip->memory;
173
174 bzstream->avail_in = 0;
175 bzstream->next_in = (char*)zip->buffer;
176
177 if ( BZ2_bzDecompressInit( bzstream, 0, 0 ) != BZ_OK ||
178 !bzstream->next_in )
179 error = FT_THROW( Invalid_File_Format );
180
181 Exit:
182 return error;
183 }
184
185
186 static void
187 ft_bzip2_file_done( FT_BZip2File zip )
188 {
189 bz_stream* bzstream = &zip->bzstream;
190
191
192 BZ2_bzDecompressEnd( bzstream );
193
194 /* clear the rest */
195 bzstream->bzalloc = NULL;
196 bzstream->bzfree = NULL;
197 bzstream->opaque = NULL;
198 bzstream->next_in = NULL;
199 bzstream->next_out = NULL;
200 bzstream->avail_in = 0;
201 bzstream->avail_out = 0;
202
203 zip->memory = NULL;
204 zip->source = NULL;
205 zip->stream = NULL;
206 }
207
208
209 static FT_Error
210 ft_bzip2_file_reset( FT_BZip2File zip )
211 {
212 FT_Stream stream = zip->source;
214
215
216 if ( !FT_STREAM_SEEK( 0 ) )
217 {
218 bz_stream* bzstream = &zip->bzstream;
219
220
221 BZ2_bzDecompressEnd( bzstream );
222
223 bzstream->avail_in = 0;
224 bzstream->next_in = (char*)zip->input;
225 bzstream->avail_out = 0;
226 bzstream->next_out = (char*)zip->buffer;
227
228 zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
229 zip->cursor = zip->limit;
230 zip->pos = 0;
231
232 BZ2_bzDecompressInit( bzstream, 0, 0 );
233 }
234
235 return error;
236 }
237
238
239 static FT_Error
240 ft_bzip2_file_fill_input( FT_BZip2File zip )
241 {
242 bz_stream* bzstream = &zip->bzstream;
243 FT_Stream stream = zip->source;
245
246
247 if ( stream->read )
248 {
249 size = stream->read( stream, stream->pos, zip->input,
250 FT_BZIP2_BUFFER_SIZE );
251 if ( size == 0 )
252 {
253 zip->limit = zip->cursor;
254 return FT_THROW( Invalid_Stream_Operation );
255 }
256 }
257 else
258 {
259 size = stream->size - stream->pos;
260 if ( size > FT_BZIP2_BUFFER_SIZE )
261 size = FT_BZIP2_BUFFER_SIZE;
262
263 if ( size == 0 )
264 {
265 zip->limit = zip->cursor;
266 return FT_THROW( Invalid_Stream_Operation );
267 }
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 zip->limit = zip->cursor;
315 error = FT_THROW( Invalid_Stream_Operation );
316 break;
317 }
318 }
319
320 return error;
321 }
322
323
324 /* fill output buffer; `count' must be <= FT_BZIP2_BUFFER_SIZE */
325 static FT_Error
326 ft_bzip2_file_skip_output( FT_BZip2File zip,
328 {
330 FT_ULong delta;
331
332
333 for (;;)
334 {
335 delta = (FT_ULong)( zip->limit - zip->cursor );
336 if ( delta >= count )
337 delta = count;
338
339 zip->cursor += delta;
340 zip->pos += delta;
341
342 count -= delta;
343 if ( count == 0 )
344 break;
345
346 error = ft_bzip2_file_fill_output( zip );
347 if ( error )
348 break;
349 }
350
351 return error;
352 }
353
354
355 static FT_ULong
356 ft_bzip2_file_io( FT_BZip2File zip,
360 {
361 FT_ULong result = 0;
363
364
365 /* Reset inflate stream if we're seeking backwards. */
366 /* Yes, that is not too efficient, but it saves memory :-) */
367 if ( pos < zip->pos )
368 {
369 error = ft_bzip2_file_reset( zip );
370 if ( error )
371 goto Exit;
372 }
373
374 /* skip unwanted bytes */
375 if ( pos > zip->pos )
376 {
377 error = ft_bzip2_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
378 if ( error )
379 goto Exit;
380 }
381
382 if ( count == 0 )
383 goto Exit;
384
385 /* now read the data */
386 for (;;)
387 {
388 FT_ULong delta;
389
390
391 delta = (FT_ULong)( zip->limit - zip->cursor );
392 if ( delta >= count )
393 delta = count;
394
395 FT_MEM_COPY( buffer, zip->cursor, delta );
396 buffer += delta;
397 result += delta;
398 zip->cursor += delta;
399 zip->pos += delta;
400
401 count -= delta;
402 if ( count == 0 )
403 break;
404
405 error = ft_bzip2_file_fill_output( zip );
406 if ( error )
407 break;
408 }
409
410 Exit:
411 return result;
412 }
413
414
415/***************************************************************************/
416/***************************************************************************/
417/***** *****/
418/***** B Z E M B E D D I N G S T R E A M *****/
419/***** *****/
420/***************************************************************************/
421/***************************************************************************/
422
423 static void
424 ft_bzip2_stream_close( FT_Stream stream )
425 {
426 FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
427 FT_Memory memory = stream->memory;
428
429
430 if ( zip )
431 {
432 /* finalize bzip file descriptor */
433 ft_bzip2_file_done( zip );
434
435 FT_FREE( zip );
436
437 stream->descriptor.pointer = NULL;
438 }
439 }
440
441
442 static unsigned long
443 ft_bzip2_stream_io( FT_Stream stream,
444 unsigned long offset,
445 unsigned char* buffer,
446 unsigned long count )
447 {
448 FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
449
450
451 return ft_bzip2_file_io( zip, offset, buffer, count );
452 }
453
454
458 {
461 FT_BZip2File zip = NULL;
462
463
464 if ( !stream || !source )
465 {
466 error = FT_THROW( Invalid_Stream_Handle );
467 goto Exit;
468 }
469
470 memory = source->memory;
471
472 /*
473 * check the header right now; this prevents allocating unnecessary
474 * objects when we don't need them
475 */
476 error = ft_bzip2_check_header( source );
477 if ( error )
478 goto Exit;
479
480 FT_ZERO( stream );
481 stream->memory = memory;
482
483 if ( !FT_QNEW( zip ) )
484 {
485 error = ft_bzip2_file_init( zip, stream, source );
486 if ( error )
487 {
488 FT_FREE( zip );
489 goto Exit;
490 }
491
492 stream->descriptor.pointer = zip;
493 }
494
495 stream->size = 0x7FFFFFFFL; /* don't know the real size! */
496 stream->pos = 0;
497 stream->base = 0;
498 stream->read = ft_bzip2_stream_io;
499 stream->close = ft_bzip2_stream_close;
500
501 Exit:
502 return error;
503 }
504
505#else /* !FT_CONFIG_OPTION_USE_BZIP2 */
506
510 {
511 FT_UNUSED( stream );
512 FT_UNUSED( source );
513
514 return FT_THROW( Unimplemented_Feature );
515 }
516
517#endif /* !FT_CONFIG_OPTION_USE_BZIP2 */
518
519
520/* END */
struct outqueuenode * head
Definition: adnsresfilter.c:66
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define FT_EXPORT_DEF(x)
#define NULL
Definition: types.h:112
void(* free_func)(voidpf opaque, voidpf address)
Definition: zlib.h:54
voidpf(* alloc_func)(voidpf opaque, uInt items, uInt size)
Definition: zlib.h:53
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return FT_Err_Ok
Definition: ftbbox.c:526
FT_Stream_OpenBzip2(FT_Stream stream, FT_Stream source)
Definition: ftbzip2.c:508
#define FT_THROW(e)
Definition: ftdebug.h:243
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:311
#define FT_FREE(ptr)
Definition: ftmemory.h:337
#define FT_MEM_FREE(ptr)
Definition: ftmemory.h:165
#define FT_ZERO(p)
Definition: ftmemory.h:246
#define FT_MEM_COPY(dest, source, count)
Definition: ftmemory.h:237
#define FT_QNEW(ptr)
Definition: ftmemory.h:347
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:525
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:533
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:64
unsigned long FT_ULong
Definition: fttypes.h:253
unsigned char FT_Byte
Definition: fttypes.h:154
int FT_Error
Definition: fttypes.h:299
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint address
Definition: glext.h:9393
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLint limit
Definition: glext.h:10326
GLuint64EXT * result
Definition: glext.h:11304
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLenum GLenum input
Definition: glext.h:9031
const char cursor[]
Definition: icontest.c:13
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
static char memory[1024 *256]
Definition: process.c:122
static TCHAR * items[]
Definition: page1.c:45
#define FT_UNUSED(arg)
#define err(...)
static void Exit(void)
Definition: sock.c:1330
Definition: parse.h:23
ULARGE_INTEGER pos
Definition: request.c:4380
unsigned int size
Definition: parse.h:27