ReactOS 0.4.16-dev-1078-g21d3e29
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 (C) 2004-2019 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#include "ftzopen.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 FT_LzwStateRec lzw; /* lzw decompressor state */
72
73 FT_Byte buffer[FT_LZW_BUFFER_SIZE]; /* output buffer */
74 FT_ULong pos; /* position in output */
77
78 } FT_LZWFileRec, *FT_LZWFile;
79
80
81 /* check and skip .Z header */
82 static FT_Error
83 ft_lzw_check_header( FT_Stream stream )
84 {
86 FT_Byte head[2];
87
88
89 if ( FT_STREAM_SEEK( 0 ) ||
90 FT_STREAM_READ( head, 2 ) )
91 goto Exit;
92
93 /* head[0] && head[1] are the magic numbers */
94 if ( head[0] != 0x1F ||
95 head[1] != 0x9D )
96 error = FT_THROW( Invalid_File_Format );
97
98 Exit:
99 return error;
100 }
101
102
103 static FT_Error
104 ft_lzw_file_init( FT_LZWFile zip,
107 {
108 FT_LzwState lzw = &zip->lzw;
110
111
112 zip->stream = stream;
113 zip->source = source;
114 zip->memory = stream->memory;
115
116 zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE;
117 zip->cursor = zip->limit;
118 zip->pos = 0;
119
120 /* check and skip .Z header */
121 error = ft_lzw_check_header( source );
122 if ( error )
123 goto Exit;
124
125 /* initialize internal lzw variable */
126 ft_lzwstate_init( lzw, source );
127
128 Exit:
129 return error;
130 }
131
132
133 static void
134 ft_lzw_file_done( FT_LZWFile zip )
135 {
136 /* clear the rest */
137 ft_lzwstate_done( &zip->lzw );
138
139 zip->memory = NULL;
140 zip->source = NULL;
141 zip->stream = NULL;
142 }
143
144
145 static FT_Error
146 ft_lzw_file_reset( FT_LZWFile zip )
147 {
148 FT_Stream stream = zip->source;
150
151
152 if ( !FT_STREAM_SEEK( 0 ) )
153 {
154 ft_lzwstate_reset( &zip->lzw );
155
156 zip->limit = zip->buffer + FT_LZW_BUFFER_SIZE;
157 zip->cursor = zip->limit;
158 zip->pos = 0;
159 }
160
161 return error;
162 }
163
164
165 static FT_Error
166 ft_lzw_file_fill_output( FT_LZWFile zip )
167 {
168 FT_LzwState lzw = &zip->lzw;
171
172
173 zip->cursor = zip->buffer;
174
175 count = ft_lzwstate_io( lzw, zip->buffer, FT_LZW_BUFFER_SIZE );
176
177 zip->limit = zip->cursor + count;
178
179 if ( count == 0 )
180 error = FT_THROW( Invalid_Stream_Operation );
181
182 return error;
183 }
184
185
186 /* fill output buffer; `count' must be <= FT_LZW_BUFFER_SIZE */
187 static FT_Error
188 ft_lzw_file_skip_output( FT_LZWFile zip,
190 {
192
193
194 /* first, we skip what we can from the output buffer */
195 {
196 FT_ULong delta = (FT_ULong)( zip->limit - zip->cursor );
197
198
199 if ( delta >= count )
200 delta = count;
201
202 zip->cursor += delta;
203 zip->pos += delta;
204
205 count -= delta;
206 }
207
208 /* next, we skip as many bytes remaining as possible */
209 while ( count > 0 )
210 {
211 FT_ULong delta = FT_LZW_BUFFER_SIZE;
212 FT_ULong numread;
213
214
215 if ( delta > count )
216 delta = count;
217
218 numread = ft_lzwstate_io( &zip->lzw, NULL, delta );
219 if ( numread < delta )
220 {
221 /* not enough bytes */
222 error = FT_THROW( Invalid_Stream_Operation );
223 break;
224 }
225
226 zip->pos += delta;
227 count -= delta;
228 }
229
230 return error;
231 }
232
233
234 static FT_ULong
235 ft_lzw_file_io( FT_LZWFile zip,
239 {
240 FT_ULong result = 0;
242
243
244 /* seeking backwards. */
245 if ( pos < zip->pos )
246 {
247 /* If the new position is within the output buffer, simply */
248 /* decrement pointers, otherwise we reset the stream completely! */
249 if ( ( zip->pos - pos ) <= (FT_ULong)( zip->cursor - zip->buffer ) )
250 {
251 zip->cursor -= zip->pos - pos;
252 zip->pos = pos;
253 }
254 else
255 {
256 error = ft_lzw_file_reset( zip );
257 if ( error )
258 goto Exit;
259 }
260 }
261
262 /* skip unwanted bytes */
263 if ( pos > zip->pos )
264 {
265 error = ft_lzw_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
266 if ( error )
267 goto Exit;
268 }
269
270 if ( count == 0 )
271 goto Exit;
272
273 /* now read the data */
274 for (;;)
275 {
276 FT_ULong delta;
277
278
279 delta = (FT_ULong)( zip->limit - zip->cursor );
280 if ( delta >= count )
281 delta = count;
282
283 FT_MEM_COPY( buffer + result, zip->cursor, delta );
284 result += delta;
285 zip->cursor += delta;
286 zip->pos += delta;
287
288 count -= delta;
289 if ( count == 0 )
290 break;
291
292 error = ft_lzw_file_fill_output( zip );
293 if ( error )
294 break;
295 }
296
297 Exit:
298 return result;
299 }
300
301
302/***************************************************************************/
303/***************************************************************************/
304/***** *****/
305/***** L Z W E M B E D D I N G S T R E A M *****/
306/***** *****/
307/***************************************************************************/
308/***************************************************************************/
309
310 static void
311 ft_lzw_stream_close( FT_Stream stream )
312 {
313 FT_LZWFile zip = (FT_LZWFile)stream->descriptor.pointer;
314 FT_Memory memory = stream->memory;
315
316
317 if ( zip )
318 {
319 /* finalize lzw file descriptor */
320 ft_lzw_file_done( zip );
321
322 FT_FREE( zip );
323
324 stream->descriptor.pointer = NULL;
325 }
326 }
327
328
329 static unsigned long
330 ft_lzw_stream_io( FT_Stream stream,
331 unsigned long offset,
332 unsigned char* buffer,
333 unsigned long count )
334 {
335 FT_LZWFile zip = (FT_LZWFile)stream->descriptor.pointer;
336
337
338 return ft_lzw_file_io( zip, offset, buffer, count );
339 }
340
341
345 {
348 FT_LZWFile zip = NULL;
349
350
351 if ( !stream || !source )
352 {
353 error = FT_THROW( Invalid_Stream_Handle );
354 goto Exit;
355 }
356
357 memory = source->memory;
358
359 /*
360 * Check the header right now; this prevents allocation of a huge
361 * LZWFile object (400 KByte of heap memory) if not necessary.
362 *
363 * Did I mention that you should never use .Z compressed font
364 * files?
365 */
366 error = ft_lzw_check_header( source );
367 if ( error )
368 goto Exit;
369
370 FT_ZERO( stream );
371 stream->memory = memory;
372
373 if ( !FT_NEW( zip ) )
374 {
375 error = ft_lzw_file_init( zip, stream, source );
376 if ( error )
377 {
378 FT_FREE( zip );
379 goto Exit;
380 }
381
382 stream->descriptor.pointer = zip;
383 }
384
385 stream->size = 0x7FFFFFFFL; /* don't know the real size! */
386 stream->pos = 0;
387 stream->base = 0;
388 stream->read = ft_lzw_stream_io;
389 stream->close = ft_lzw_stream_close;
390
391 Exit:
392 return error;
393 }
394
395
396#include "ftzopen.c"
397
398
399#else /* !FT_CONFIG_OPTION_USE_LZW */
400
401
405 {
406 FT_UNUSED( stream );
407 FT_UNUSED( source );
408
409 return FT_THROW( Unimplemented_Feature );
410 }
411
412
413#endif /* !FT_CONFIG_OPTION_USE_LZW */
414
415
416/* END */
struct outqueuenode * head
Definition: adnsresfilter.c:66
#define NULL
Definition: types.h:112
return FT_Err_Ok
Definition: ftbbox.c:527
#define FT_UNUSED(arg)
Definition: ftconfig.h:100
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:494
#define FT_THROW(e)
Definition: ftdebug.h:241
FT_Stream_OpenLZW(FT_Stream stream, FT_Stream source)
Definition: ftlzw.c:403
#define FT_NEW(ptr)
Definition: ftmemory.h:330
#define FT_FREE(ptr)
Definition: ftmemory.h:328
#define FT_ZERO(p)
Definition: ftmemory.h:237
#define FT_MEM_COPY(dest, source, count)
Definition: ftmemory.h:228
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:514
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:522
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:65
unsigned long FT_ULong
Definition: fttypes.h:253
unsigned char FT_Byte
Definition: fttypes.h:154
int FT_Error
Definition: fttypes.h:299
ft_lzwstate_init(FT_LzwState state, FT_Stream source)
Definition: ftzopen.c:208
ft_lzwstate_io(FT_LzwState state, FT_Byte *buffer, FT_ULong out_size)
Definition: ftzopen.c:256
ft_lzwstate_reset(FT_LzwState state)
Definition: ftzopen.c:194
ft_lzwstate_done(FT_LzwState state)
Definition: ftzopen.c:228
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint buffer
Definition: glext.h:5915
GLintptr offset
Definition: glext.h:5920
GLint limit
Definition: glext.h:10326
GLuint64EXT * result
Definition: glext.h:11304
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:116
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