source: trunk/src/3rdparty/libmng/libmng_read.c@ 122

Last change on this file since 122 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 58.7 KB
Line 
1/* ************************************************************************** */
2/* * For conditions of distribution and use, * */
3/* * see copyright notice in libmng.h * */
4/* ************************************************************************** */
5/* * * */
6/* * project : libmng * */
7/* * file : libmng_read.c copyright (c) 2000-2007 G.Juyn * */
8/* * version : 1.0.10 * */
9/* * * */
10/* * purpose : Read logic (implementation) * */
11/* * * */
12/* * author : G.Juyn * */
13/* * * */
14/* * comment : implementation of the high-level read logic * */
15/* * * */
16/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
17/* * - changed strict-ANSI stuff * */
18/* * 0.5.1 - 05/11/2000 - G.Juyn * */
19/* * - added callback error-reporting support * */
20/* * 0.5.1 - 05/12/2000 - G.Juyn * */
21/* * - changed trace to macro for callback error-reporting * */
22/* * * */
23/* * 0.5.2 - 05/19/2000 - G.Juyn * */
24/* * - cleaned up some code regarding mixed support * */
25/* * 0.5.2 - 05/20/2000 - G.Juyn * */
26/* * - added support for JNG * */
27/* * 0.5.2 - 05/31/2000 - G.Juyn * */
28/* * - fixed up punctuation (contribution by Tim Rowley) * */
29/* * * */
30/* * 0.5.3 - 06/16/2000 - G.Juyn * */
31/* * - changed progressive-display processing * */
32/* * * */
33/* * 0.9.1 - 07/08/2000 - G.Juyn * */
34/* * - changed read-processing for improved I/O-suspension * */
35/* * 0.9.1 - 07/14/2000 - G.Juyn * */
36/* * - changed EOF processing behavior * */
37/* * 0.9.1 - 07/14/2000 - G.Juyn * */
38/* * - changed default readbuffer size from 1024 to 4200 * */
39/* * * */
40/* * 0.9.2 - 07/27/2000 - G.Juyn * */
41/* * - B110320 - fixed GCC warning about mix-sized pointer math * */
42/* * 0.9.2 - 07/31/2000 - G.Juyn * */
43/* * - B110546 - fixed for improperly returning UNEXPECTEDEOF * */
44/* * 0.9.2 - 08/04/2000 - G.Juyn * */
45/* * - B111096 - fixed large-buffer read-suspension * */
46/* * 0.9.2 - 08/05/2000 - G.Juyn * */
47/* * - changed file-prefixes * */
48/* * * */
49/* * 0.9.3 - 08/26/2000 - G.Juyn * */
50/* * - added MAGN chunk * */
51/* * 0.9.3 - 10/11/2000 - G.Juyn * */
52/* * - removed test-MaGN * */
53/* * 0.9.3 - 10/16/2000 - G.Juyn * */
54/* * - added support for JDAA * */
55/* * * */
56/* * 0.9.5 - 01/23/2001 - G.Juyn * */
57/* * - fixed timing-problem with switching framing_modes * */
58/* * * */
59/* * 1.0.4 - 06/22/2002 - G.Juyn * */
60/* * - B495443 - incorrect suspend check in read_databuffer * */
61/* * * */
62/* * 1.0.5 - 07/04/2002 - G.Juyn * */
63/* * - added errorcode for extreme chunk-sizes * */
64/* * 1.0.5 - 07/08/2002 - G.Juyn * */
65/* * - B578572 - removed eMNGma hack (thanks Dimitri!) * */
66/* * 1.0.5 - 07/16/2002 - G.Juyn * */
67/* * - B581625 - large chunks fail with suspension reads * */
68/* * 1.0.5 - 08/19/2002 - G.Juyn * */
69/* * - B597134 - libmng pollutes the linker namespace * */
70/* * - added HLAPI function to copy chunks * */
71/* * 1.0.5 - 09/16/2002 - G.Juyn * */
72/* * - added event handling for dynamic MNG * */
73/* * * */
74/* * 1.0.6 - 05/25/2003 - G.R-P * */
75/* * - added MNG_SKIPCHUNK_cHNK footprint optimizations * */
76/* * 1.0.6 - 07/07/2003 - G.R-P * */
77/* * - added MNG_NO_DELTA_PNG reduction * */
78/* * - skip additional code when MNG_INCLUDE_JNG is not enabled * */
79/* * 1.0.6 - 07/29/2003 - G.R-P * */
80/* * - added conditionals around PAST chunk support * */
81/* * 1.0.6 - 08/17/2003 - G.R-P * */
82/* * - added conditionals around non-VLC chunk support * */
83/* * * */
84/* * 1.0.7 - 03/10/2004 - G.R-P * */
85/* * - added conditionals around openstream/closestream * */
86/* * * */
87/* * 1.0.8 - 04/08/2004 - G.Juyn * */
88/* * - added CRC existence & checking flags * */
89/* * 1.0.8 - 04/11/2004 - G.Juyn * */
90/* * - added data-push mechanisms for specialized decoders * */
91/* * 1.0.8 - 07/06/2004 - G.R-P * */
92/* * - defend against using undefined closestream function * */
93/* * 1.0.8 - 07/28/2004 - G.R-P * */
94/* * - added check for extreme chunk-lengths * */
95/* * * */
96/* * 1.0.9 - 09/16/2004 - G.Juyn * */
97/* * - fixed chunk pushing mechanism * */
98/* * 1.0.9 - 12/05/2004 - G.Juyn * */
99/* * - added conditional MNG_OPTIMIZE_CHUNKINITFREE * */
100/* * 1.0.9 - 12/06/2004 - G.Juyn * */
101/* * - added conditional MNG_OPTIMIZE_CHUNKASSIGN * */
102/* * - added conditional MNG_OPTIMIZE_CHUNKREADER * */
103/* * 1.0.9 - 12/20/2004 - G.Juyn * */
104/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
105/* * 1.0.9 - 12/31/2004 - G.R-P * */
106/* * - removed stray characters from #ifdef directive * */
107/* * * */
108/* * 1.0.10 - 04/08/2007 - G.Juyn * */
109/* * - added support for mPNG proposal * */
110/* * * */
111/* ************************************************************************** */
112
113#include "libmng.h"
114#include "libmng_data.h"
115#include "libmng_error.h"
116#include "libmng_trace.h"
117#ifdef __BORLANDC__
118#pragma hdrstop
119#endif
120#include "libmng_memory.h"
121#include "libmng_objects.h"
122#include "libmng_object_prc.h"
123#include "libmng_chunks.h"
124#ifdef MNG_OPTIMIZE_CHUNKREADER
125#include "libmng_chunk_descr.h"
126#endif
127#include "libmng_chunk_prc.h"
128#include "libmng_chunk_io.h"
129#include "libmng_display.h"
130#include "libmng_read.h"
131
132#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
133#pragma option -A /* force ANSI-C */
134#endif
135
136/* ************************************************************************** */
137
138#ifdef MNG_INCLUDE_READ_PROCS
139
140/* ************************************************************************** */
141
142mng_retcode mng_process_eof (mng_datap pData)
143{
144 if (!pData->bEOF) /* haven't closed the stream yet ? */
145 {
146 pData->bEOF = MNG_TRUE; /* now we do! */
147
148#ifndef MNG_NO_OPEN_CLOSE_STREAM
149 if (pData->fClosestream && !pData->fClosestream ((mng_handle)pData))
150 {
151 MNG_ERROR (pData, MNG_APPIOERROR);
152 }
153#endif
154 }
155
156 return MNG_NOERROR;
157}
158
159/* ************************************************************************** */
160
161mng_retcode mng_release_pushdata (mng_datap pData)
162{
163 mng_pushdatap pFirst = pData->pFirstpushdata;
164 mng_pushdatap pNext = pFirst->pNext;
165
166#ifdef MNG_SUPPORT_TRACE
167 MNG_TRACE (pData, MNG_FN_RELEASE_PUSHDATA, MNG_LC_START);
168#endif
169
170 pData->pFirstpushdata = pNext; /* next becomes the first */
171
172 if (!pNext) /* no next? => no last! */
173 pData->pLastpushdata = MNG_NULL;
174 /* buffer owned and release callback defined? */
175 if ((pFirst->bOwned) && (pData->fReleasedata))
176 pData->fReleasedata ((mng_handle)pData, pFirst->pData, pFirst->iLength);
177 else /* otherwise use internal free mechanism */
178 MNG_FREEX (pData, pFirst->pData, pFirst->iLength);
179 /* and free it */
180 MNG_FREEX (pData, pFirst, sizeof(mng_pushdata));
181
182#ifdef MNG_SUPPORT_TRACE
183 MNG_TRACE (pData, MNG_FN_RELEASE_PUSHDATA, MNG_LC_END);
184#endif
185
186 return MNG_NOERROR;
187}
188
189/* ************************************************************************** */
190
191mng_retcode mng_release_pushchunk (mng_datap pData)
192{
193 mng_pushdatap pFirst = pData->pFirstpushchunk;
194 mng_pushdatap pNext = pFirst->pNext;
195
196#ifdef MNG_SUPPORT_TRACE
197 MNG_TRACE (pData, MNG_FN_RELEASE_PUSHCHUNK, MNG_LC_START);
198#endif
199
200 pData->pFirstpushchunk = pNext; /* next becomes the first */
201
202 if (!pNext) /* no next? => no last! */
203 pData->pLastpushchunk = MNG_NULL;
204 /* buffer owned and release callback defined? */
205 if ((pFirst->bOwned) && (pData->fReleasedata))
206 pData->fReleasedata ((mng_handle)pData, pFirst->pData, pFirst->iLength);
207 else /* otherwise use internal free mechanism */
208 MNG_FREEX (pData, pFirst->pData, pFirst->iLength);
209 /* and free it */
210 MNG_FREEX (pData, pFirst, sizeof(mng_pushdata));
211
212#ifdef MNG_SUPPORT_TRACE
213 MNG_TRACE (pData, MNG_FN_RELEASE_PUSHCHUNK, MNG_LC_END);
214#endif
215
216 return MNG_NOERROR;
217}
218
219/* ************************************************************************** */
220
221MNG_LOCAL mng_retcode read_data (mng_datap pData,
222 mng_uint8p pBuf,
223 mng_uint32 iSize,
224 mng_uint32 * iRead)
225{
226 mng_retcode iRetcode;
227 mng_uint32 iTempsize = iSize;
228 mng_uint8p pTempbuf = pBuf;
229 mng_pushdatap pPush = pData->pFirstpushdata;
230 mng_uint32 iPushsize = 0;
231 *iRead = 0; /* nothing yet */
232
233#ifdef MNG_SUPPORT_TRACE
234 MNG_TRACE (pData, MNG_FN_READ_DATA, MNG_LC_START);
235#endif
236
237 while (pPush) /* calculate size of pushed data */
238 {
239 iPushsize += pPush->iRemaining;
240 pPush = pPush->pNext;
241 }
242
243 if (iTempsize <= iPushsize) /* got enough push data? */
244 {
245 while (iTempsize)
246 {
247 pPush = pData->pFirstpushdata;
248 /* enough data remaining in this buffer? */
249 if (pPush->iRemaining <= iTempsize)
250 { /* no: then copy what we've got */
251 MNG_COPY (pTempbuf, pPush->pDatanext, pPush->iRemaining);
252 /* move pointers & lengths */
253 pTempbuf += pPush->iRemaining;
254 *iRead += pPush->iRemaining;
255 iTempsize -= pPush->iRemaining;
256 /* release the depleted buffer */
257 iRetcode = mng_release_pushdata (pData);
258 if (iRetcode)
259 return iRetcode;
260 }
261 else
262 { /* copy the needed bytes */
263 MNG_COPY (pTempbuf, pPush->pDatanext, iTempsize);
264 /* move pointers & lengths */
265 pPush->iRemaining -= iTempsize;
266 pPush->pDatanext += iTempsize;
267 pTempbuf += iTempsize;
268 *iRead += iTempsize;
269 iTempsize = 0; /* all done!!! */
270 }
271 }
272 }
273 else
274 {
275 mng_uint32 iTempread = 0;
276 /* get it from the app then */
277 if (!pData->fReaddata (((mng_handle)pData), pTempbuf, iTempsize, &iTempread))
278 MNG_ERROR (pData, MNG_APPIOERROR);
279
280 *iRead += iTempread;
281 }
282
283#ifdef MNG_SUPPORT_TRACE
284 MNG_TRACE (pData, MNG_FN_READ_DATA, MNG_LC_END);
285#endif
286
287 return MNG_NOERROR;
288}
289
290/* ************************************************************************** */
291
292MNG_LOCAL mng_retcode read_databuffer (mng_datap pData,
293 mng_uint8p pBuf,
294 mng_uint8p * pBufnext,
295 mng_uint32 iSize,
296 mng_uint32 * iRead)
297{
298 mng_retcode iRetcode;
299
300#ifdef MNG_SUPPORT_TRACE
301 MNG_TRACE (pData, MNG_FN_READ_DATABUFFER, MNG_LC_START);
302#endif
303
304 if (pData->bSuspensionmode)
305 {
306 mng_uint8p pTemp;
307 mng_uint32 iTemp;
308
309 *iRead = 0; /* let's be negative about the outcome */
310
311 if (!pData->pSuspendbuf) /* need to create a suspension buffer ? */
312 {
313 pData->iSuspendbufsize = MNG_SUSPENDBUFFERSIZE;
314 /* so, create it */
315 MNG_ALLOC (pData, pData->pSuspendbuf, pData->iSuspendbufsize);
316
317 pData->iSuspendbufleft = 0; /* make sure to fill it first time */
318 pData->pSuspendbufnext = pData->pSuspendbuf;
319 }
320 /* more than our buffer can hold ? */
321 if (iSize > pData->iSuspendbufsize)
322 {
323 mng_uint32 iRemain;
324
325 if (!*pBufnext) /* first time ? */
326 {
327 if (pData->iSuspendbufleft) /* do we have some data left ? */
328 { /* then copy it */
329 MNG_COPY (pBuf, pData->pSuspendbufnext, pData->iSuspendbufleft);
330 /* fixup variables */
331 *pBufnext = pBuf + pData->iSuspendbufleft;
332 pData->pSuspendbufnext = pData->pSuspendbuf;
333 pData->iSuspendbufleft = 0;
334 }
335 else
336 {
337 *pBufnext = pBuf;
338 }
339 }
340 /* calculate how much to get */
341 iRemain = iSize - (mng_uint32)(*pBufnext - pBuf);
342 /* let's go get it */
343 iRetcode = read_data (pData, *pBufnext, iRemain, &iTemp);
344 if (iRetcode)
345 return iRetcode;
346 /* first read after suspension return 0 means EOF */
347 if ((pData->iSuspendpoint) && (iTemp == 0))
348 { /* that makes it final */
349 mng_retcode iRetcode = mng_process_eof (pData);
350 if (iRetcode) /* on error bail out */
351 return iRetcode;
352 /* indicate the source is depleted */
353 *iRead = iSize - iRemain + iTemp;
354 }
355 else
356 {
357 if (iTemp < iRemain) /* suspension required ? */
358 {
359 *pBufnext = *pBufnext + iTemp;
360 pData->bSuspended = MNG_TRUE;
361 }
362 else
363 {
364 *iRead = iSize; /* got it all now ! */
365 }
366 }
367 }
368 else
369 { /* need to read some more ? */
370 while ((!pData->bSuspended) && (!pData->bEOF) && (iSize > pData->iSuspendbufleft))
371 { /* not enough space left in buffer ? */
372 if (pData->iSuspendbufsize - pData->iSuspendbufleft -
373 (mng_uint32)(pData->pSuspendbufnext - pData->pSuspendbuf) <
374 MNG_SUSPENDREQUESTSIZE)
375 {
376 if (pData->iSuspendbufleft) /* then lets shift (if there's anything left) */
377 MNG_COPY (pData->pSuspendbuf, pData->pSuspendbufnext, pData->iSuspendbufleft);
378 /* adjust running pointer */
379 pData->pSuspendbufnext = pData->pSuspendbuf;
380 }
381 /* still not enough room ? */
382 if (pData->iSuspendbufsize - pData->iSuspendbufleft < MNG_SUSPENDREQUESTSIZE)
383 MNG_ERROR (pData, MNG_INTERNALERROR);
384 /* now read some more data */
385 pTemp = pData->pSuspendbufnext + pData->iSuspendbufleft;
386
387 iRetcode = read_data (pData, pTemp, MNG_SUSPENDREQUESTSIZE, &iTemp);
388 if (iRetcode)
389 return iRetcode;
390 /* adjust fill-counter */
391 pData->iSuspendbufleft += iTemp;
392 /* first read after suspension returning 0 means EOF */
393 if ((pData->iSuspendpoint) && (iTemp == 0))
394 { /* that makes it final */
395 mng_retcode iRetcode = mng_process_eof (pData);
396 if (iRetcode) /* on error bail out */
397 return iRetcode;
398
399 if (pData->iSuspendbufleft) /* return the leftover scraps */
400 MNG_COPY (pBuf, pData->pSuspendbufnext, pData->iSuspendbufleft);
401 /* and indicate so */
402 *iRead = pData->iSuspendbufleft;
403 pData->pSuspendbufnext = pData->pSuspendbuf;
404 pData->iSuspendbufleft = 0;
405 }
406 else
407 { /* suspension required ? */
408 if ((iSize > pData->iSuspendbufleft) && (iTemp < MNG_SUSPENDREQUESTSIZE))
409 pData->bSuspended = MNG_TRUE;
410
411 }
412
413 pData->iSuspendpoint = 0; /* reset it here in case we loop back */
414 }
415
416 if ((!pData->bSuspended) && (!pData->bEOF))
417 { /* return the data ! */
418 MNG_COPY (pBuf, pData->pSuspendbufnext, iSize);
419
420 *iRead = iSize; /* returned it all */
421 /* adjust suspension-buffer variables */
422 pData->pSuspendbufnext += iSize;
423 pData->iSuspendbufleft -= iSize;
424 }
425 }
426 }
427 else
428 {
429 iRetcode = read_data (pData, (mng_ptr)pBuf, iSize, iRead);
430 if (iRetcode)
431 return iRetcode;
432 if (*iRead == 0) /* suspension required ? */
433 pData->bSuspended = MNG_TRUE;
434 }
435
436 pData->iSuspendpoint = 0; /* safely reset it here ! */
437
438#ifdef MNG_SUPPORT_TRACE
439 MNG_TRACE (pData, MNG_FN_READ_DATABUFFER, MNG_LC_END);
440#endif
441
442 return MNG_NOERROR;
443}
444
445/* ************************************************************************** */
446
447MNG_LOCAL mng_retcode process_raw_chunk (mng_datap pData,
448 mng_uint8p pBuf,
449 mng_uint32 iBuflen)
450{
451
452#ifndef MNG_OPTIMIZE_CHUNKREADER
453 /* the table-idea & binary search code was adapted from
454 libpng 1.1.0 (pngread.c) */
455 /* NOTE1: the table must remain sorted by chunkname, otherwise the binary
456 search will break !!! (ps. watch upper-/lower-case chunknames !!) */
457 /* NOTE2: the layout must remain equal to the header part of all the
458 chunk-structures (yes, that means even the pNext and pPrev fields;
459 it's wasting a bit of space, but hey, the code is a lot easier) */
460
461#ifdef MNG_OPTIMIZE_CHUNKINITFREE
462 mng_chunk_header mng_chunk_unknown = {MNG_UINT_HUH, mng_init_general, mng_free_unknown,
463 mng_read_unknown, mng_write_unknown, mng_assign_unknown, 0, 0, sizeof(mng_unknown_chunk)};
464#else
465 mng_chunk_header mng_chunk_unknown = {MNG_UINT_HUH, mng_init_unknown, mng_free_unknown,
466 mng_read_unknown, mng_write_unknown, mng_assign_unknown, 0, 0};
467#endif
468
469#ifdef MNG_OPTIMIZE_CHUNKINITFREE
470
471 mng_chunk_header mng_chunk_table [] =
472 {
473#ifndef MNG_SKIPCHUNK_BACK
474 {MNG_UINT_BACK, mng_init_general, mng_free_general, mng_read_back, mng_write_back, mng_assign_general, 0, 0, sizeof(mng_back)},
475#endif
476#ifndef MNG_SKIPCHUNK_BASI
477 {MNG_UINT_BASI, mng_init_general, mng_free_general, mng_read_basi, mng_write_basi, mng_assign_general, 0, 0, sizeof(mng_basi)},
478#endif
479#ifndef MNG_SKIPCHUNK_CLIP
480 {MNG_UINT_CLIP, mng_init_general, mng_free_general, mng_read_clip, mng_write_clip, mng_assign_general, 0, 0, sizeof(mng_clip)},
481#endif
482#ifndef MNG_SKIPCHUNK_CLON
483 {MNG_UINT_CLON, mng_init_general, mng_free_general, mng_read_clon, mng_write_clon, mng_assign_general, 0, 0, sizeof(mng_clon)},
484#endif
485#ifndef MNG_NO_DELTA_PNG
486#ifndef MNG_SKIPCHUNK_DBYK
487 {MNG_UINT_DBYK, mng_init_general, mng_free_dbyk, mng_read_dbyk, mng_write_dbyk, mng_assign_dbyk, 0, 0, sizeof(mng_dbyk)},
488#endif
489#endif
490#ifndef MNG_SKIPCHUNK_DEFI
491 {MNG_UINT_DEFI, mng_init_general, mng_free_general, mng_read_defi, mng_write_defi, mng_assign_general, 0, 0, sizeof(mng_defi)},
492#endif
493#ifndef MNG_NO_DELTA_PNG
494 {MNG_UINT_DHDR, mng_init_general, mng_free_general, mng_read_dhdr, mng_write_dhdr, mng_assign_general, 0, 0, sizeof(mng_dhdr)},
495#endif
496#ifndef MNG_SKIPCHUNK_DISC
497 {MNG_UINT_DISC, mng_init_general, mng_free_disc, mng_read_disc, mng_write_disc, mng_assign_disc, 0, 0, sizeof(mng_disc)},
498#endif
499#ifndef MNG_NO_DELTA_PNG
500#ifndef MNG_SKIPCHUNK_DROP
501 {MNG_UINT_DROP, mng_init_general, mng_free_drop, mng_read_drop, mng_write_drop, mng_assign_drop, 0, 0, sizeof(mng_drop)},
502#endif
503#endif
504#ifndef MNG_SKIPCHUNK_LOOP
505 {MNG_UINT_ENDL, mng_init_general, mng_free_general, mng_read_endl, mng_write_endl, mng_assign_general, 0, 0, sizeof(mng_endl)},
506#endif
507#ifndef MNG_SKIPCHUNK_FRAM
508 {MNG_UINT_FRAM, mng_init_general, mng_free_fram, mng_read_fram, mng_write_fram, mng_assign_fram, 0, 0, sizeof(mng_fram)},
509#endif
510 {MNG_UINT_IDAT, mng_init_general, mng_free_idat, mng_read_idat, mng_write_idat, mng_assign_idat, 0, 0, sizeof(mng_idat)}, /* 12-th element! */
511 {MNG_UINT_IEND, mng_init_general, mng_free_general, mng_read_iend, mng_write_iend, mng_assign_general, 0, 0, sizeof(mng_iend)},
512 {MNG_UINT_IHDR, mng_init_general, mng_free_general, mng_read_ihdr, mng_write_ihdr, mng_assign_general, 0, 0, sizeof(mng_ihdr)},
513#ifndef MNG_NO_DELTA_PNG
514#ifdef MNG_INCLUDE_JNG
515 {MNG_UINT_IJNG, mng_init_general, mng_free_general, mng_read_ijng, mng_write_ijng, mng_assign_general, 0, 0, sizeof(mng_ijng)},
516#endif
517 {MNG_UINT_IPNG, mng_init_general, mng_free_general, mng_read_ipng, mng_write_ipng, mng_assign_general, 0, 0, sizeof(mng_ipng)},
518#endif
519#ifdef MNG_INCLUDE_JNG
520 {MNG_UINT_JDAA, mng_init_general, mng_free_jdaa, mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa, 0, 0, sizeof(mng_jdaa)},
521 {MNG_UINT_JDAT, mng_init_general, mng_free_jdat, mng_read_jdat, mng_write_jdat, mng_assign_jdat, 0, 0, sizeof(mng_jdat)},
522 {MNG_UINT_JHDR, mng_init_general, mng_free_general, mng_read_jhdr, mng_write_jhdr, mng_assign_general, 0, 0, sizeof(mng_jhdr)},
523 {MNG_UINT_JSEP, mng_init_general, mng_free_general, mng_read_jsep, mng_write_jsep, mng_assign_general, 0, 0, sizeof(mng_jsep)},
524 {MNG_UINT_JdAA, mng_init_general, mng_free_jdaa, mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa, 0, 0, sizeof(mng_jdaa)},
525#endif
526#ifndef MNG_SKIPCHUNK_LOOP
527 {MNG_UINT_LOOP, mng_init_general, mng_free_loop, mng_read_loop, mng_write_loop, mng_assign_loop, 0, 0, sizeof(mng_loop)},
528#endif
529#ifndef MNG_SKIPCHUNK_MAGN
530 {MNG_UINT_MAGN, mng_init_general, mng_free_general, mng_read_magn, mng_write_magn, mng_assign_general, 0, 0, sizeof(mng_magn)},
531#endif
532 {MNG_UINT_MEND, mng_init_general, mng_free_general, mng_read_mend, mng_write_mend, mng_assign_general, 0, 0, sizeof(mng_mend)},
533 {MNG_UINT_MHDR, mng_init_general, mng_free_general, mng_read_mhdr, mng_write_mhdr, mng_assign_general, 0, 0, sizeof(mng_mhdr)},
534#ifndef MNG_SKIPCHUNK_MOVE
535 {MNG_UINT_MOVE, mng_init_general, mng_free_general, mng_read_move, mng_write_move, mng_assign_general, 0, 0, sizeof(mng_move)},
536#endif
537#ifndef MNG_NO_DELTA_PNG
538#ifndef MNG_SKIPCHUNK_ORDR
539 {MNG_UINT_ORDR, mng_init_general, mng_free_ordr, mng_read_ordr, mng_write_ordr, mng_assign_ordr, 0, 0, sizeof(mng_ordr)},
540#endif
541#endif
542#ifndef MNG_SKIPCHUNK_PAST
543 {MNG_UINT_PAST, mng_init_general, mng_free_past, mng_read_past, mng_write_past, mng_assign_past, 0, 0, sizeof(mng_past)},
544#endif
545 {MNG_UINT_PLTE, mng_init_general, mng_free_general, mng_read_plte, mng_write_plte, mng_assign_general, 0, 0, sizeof(mng_plte)},
546#ifndef MNG_NO_DELTA_PNG
547 {MNG_UINT_PPLT, mng_init_general, mng_free_general, mng_read_pplt, mng_write_pplt, mng_assign_general, 0, 0, sizeof(mng_pplt)},
548 {MNG_UINT_PROM, mng_init_general, mng_free_general, mng_read_prom, mng_write_prom, mng_assign_general, 0, 0, sizeof(mng_prom)},
549#endif
550#ifndef MNG_SKIPCHUNK_SAVE
551 {MNG_UINT_SAVE, mng_init_general, mng_free_save, mng_read_save, mng_write_save, mng_assign_save, 0, 0, sizeof(mng_save)},
552#endif
553#ifndef MNG_SKIPCHUNK_SEEK
554 {MNG_UINT_SEEK, mng_init_general, mng_free_seek, mng_read_seek, mng_write_seek, mng_assign_seek, 0, 0, sizeof(mng_seek)},
555#endif
556#ifndef MNG_SKIPCHUNK_SHOW
557 {MNG_UINT_SHOW, mng_init_general, mng_free_general, mng_read_show, mng_write_show, mng_assign_general, 0, 0, sizeof(mng_show)},
558#endif
559#ifndef MNG_SKIPCHUNK_TERM
560 {MNG_UINT_TERM, mng_init_general, mng_free_general, mng_read_term, mng_write_term, mng_assign_general, 0, 0, sizeof(mng_term)},
561#endif
562#ifndef MNG_SKIPCHUNK_bKGD
563 {MNG_UINT_bKGD, mng_init_general, mng_free_general, mng_read_bkgd, mng_write_bkgd, mng_assign_general, 0, 0, sizeof(mng_bkgd)},
564#endif
565#ifndef MNG_SKIPCHUNK_cHRM
566 {MNG_UINT_cHRM, mng_init_general, mng_free_general, mng_read_chrm, mng_write_chrm, mng_assign_general, 0, 0, sizeof(mng_chrm)},
567#endif
568#ifndef MNG_SKIPCHUNK_eXPI
569 {MNG_UINT_eXPI, mng_init_general, mng_free_expi, mng_read_expi, mng_write_expi, mng_assign_expi, 0, 0, sizeof(mng_expi)},
570#endif
571#ifndef MNG_SKIPCHUNK_evNT
572 {MNG_UINT_evNT, mng_init_general, mng_free_evnt, mng_read_evnt, mng_write_evnt, mng_assign_evnt, 0, 0, sizeof(mng_evnt)},
573#endif
574#ifndef MNG_SKIPCHUNK_fPRI
575 {MNG_UINT_fPRI, mng_init_general, mng_free_general, mng_read_fpri, mng_write_fpri, mng_assign_general, 0, 0, sizeof(mng_fpri)},
576#endif
577#ifndef MNG_SKIPCHUNK_gAMA
578 {MNG_UINT_gAMA, mng_init_general, mng_free_general, mng_read_gama, mng_write_gama, mng_assign_general, 0, 0, sizeof(mng_gama)},
579#endif
580#ifndef MNG_SKIPCHUNK_hIST
581 {MNG_UINT_hIST, mng_init_general, mng_free_general, mng_read_hist, mng_write_hist, mng_assign_general, 0, 0, sizeof(mng_hist)},
582#endif
583#ifndef MNG_SKIPCHUNK_iCCP
584 {MNG_UINT_iCCP, mng_init_general, mng_free_iccp, mng_read_iccp, mng_write_iccp, mng_assign_iccp, 0, 0, sizeof(mng_iccp)},
585#endif
586#ifndef MNG_SKIPCHUNK_iTXt
587 {MNG_UINT_iTXt, mng_init_general, mng_free_itxt, mng_read_itxt, mng_write_itxt, mng_assign_itxt, 0, 0, sizeof(mng_itxt)},
588#endif
589#ifdef MNG_INCLUDE_MPNG_PROPOSAL
590 {MNG_UINT_mpNG, mng_init_general, mng_free_mpng, mng_read_mpng, mng_write_mpng, mng_assign_mpng, 0, 0, sizeof(mng_mpng)},
591#endif
592#ifndef MNG_SKIPCHUNK_nEED
593 {MNG_UINT_nEED, mng_init_general, mng_free_need, mng_read_need, mng_write_need, mng_assign_need, 0, 0, sizeof(mng_need)},
594#endif
595/* TODO: {MNG_UINT_oFFs, 0, 0, 0, 0, 0, 0}, */
596/* TODO: {MNG_UINT_pCAL, 0, 0, 0, 0, 0, 0}, */
597#ifndef MNG_SKIPCHUNK_pHYg
598 {MNG_UINT_pHYg, mng_init_general, mng_free_general, mng_read_phyg, mng_write_phyg, mng_assign_general, 0, 0, sizeof(mng_phyg)},
599#endif
600#ifndef MNG_SKIPCHUNK_pHYs
601 {MNG_UINT_pHYs, mng_init_general, mng_free_general, mng_read_phys, mng_write_phys, mng_assign_general, 0, 0, sizeof(mng_phys)},
602#endif
603#ifndef MNG_SKIPCHUNK_sBIT
604 {MNG_UINT_sBIT, mng_init_general, mng_free_general, mng_read_sbit, mng_write_sbit, mng_assign_general, 0, 0, sizeof(mng_sbit)},
605#endif
606/* TODO: {MNG_UINT_sCAL, 0, 0, 0, 0, 0, 0}, */
607#ifndef MNG_SKIPCHUNK_sPLT
608 {MNG_UINT_sPLT, mng_init_general, mng_free_splt, mng_read_splt, mng_write_splt, mng_assign_splt, 0, 0, sizeof(mng_splt)},
609#endif
610 {MNG_UINT_sRGB, mng_init_general, mng_free_general, mng_read_srgb, mng_write_srgb, mng_assign_general, 0, 0, sizeof(mng_srgb)},
611#ifndef MNG_SKIPCHUNK_tEXt
612 {MNG_UINT_tEXt, mng_init_general, mng_free_text, mng_read_text, mng_write_text, mng_assign_text, 0, 0, sizeof(mng_text)},
613#endif
614#ifndef MNG_SKIPCHUNK_tIME
615 {MNG_UINT_tIME, mng_init_general, mng_free_general, mng_read_time, mng_write_time, mng_assign_general, 0, 0, sizeof(mng_time)},
616#endif
617 {MNG_UINT_tRNS, mng_init_general, mng_free_general, mng_read_trns, mng_write_trns, mng_assign_general, 0, 0, sizeof(mng_trns)},
618#ifndef MNG_SKIPCHUNK_zTXt
619 {MNG_UINT_zTXt, mng_init_general, mng_free_ztxt, mng_read_ztxt, mng_write_ztxt, mng_assign_ztxt, 0, 0, sizeof(mng_ztxt)},
620#endif
621 };
622
623#else /* MNG_OPTIMIZE_CHUNKINITFREE */
624
625 mng_chunk_header mng_chunk_table [] =
626 {
627#ifndef MNG_SKIPCHUNK_BACK
628 {MNG_UINT_BACK, mng_init_back, mng_free_back, mng_read_back, mng_write_back, mng_assign_back, 0, 0},
629#endif
630#ifndef MNG_SKIPCHUNK_BASI
631 {MNG_UINT_BASI, mng_init_basi, mng_free_basi, mng_read_basi, mng_write_basi, mng_assign_basi, 0, 0},
632#endif
633#ifndef MNG_SKIPCHUNK_CLIP
634 {MNG_UINT_CLIP, mng_init_clip, mng_free_clip, mng_read_clip, mng_write_clip, mng_assign_clip, 0, 0},
635#endif
636#ifndef MNG_SKIPCHUNK_CLON
637 {MNG_UINT_CLON, mng_init_clon, mng_free_clon, mng_read_clon, mng_write_clon, mng_assign_clon, 0, 0},
638#endif
639#ifndef MNG_NO_DELTA_PNG
640#ifndef MNG_SKIPCHUNK_DBYK
641 {MNG_UINT_DBYK, mng_init_dbyk, mng_free_dbyk, mng_read_dbyk, mng_write_dbyk, mng_assign_dbyk, 0, 0},
642#endif
643#endif
644#ifndef MNG_SKIPCHUNK_DEFI
645 {MNG_UINT_DEFI, mng_init_defi, mng_free_defi, mng_read_defi, mng_write_defi, mng_assign_defi, 0, 0},
646#endif
647#ifndef MNG_NO_DELTA_PNG
648 {MNG_UINT_DHDR, mng_init_dhdr, mng_free_dhdr, mng_read_dhdr, mng_write_dhdr, mng_assign_dhdr, 0, 0},
649#endif
650#ifndef MNG_SKIPCHUNK_DISC
651 {MNG_UINT_DISC, mng_init_disc, mng_free_disc, mng_read_disc, mng_write_disc, mng_assign_disc, 0, 0},
652#endif
653#ifndef MNG_NO_DELTA_PNG
654#ifndef MNG_SKIPCHUNK_DROP
655 {MNG_UINT_DROP, mng_init_drop, mng_free_drop, mng_read_drop, mng_write_drop, mng_assign_drop, 0, 0},
656#endif
657#endif
658#ifndef MNG_SKIPCHUNK_LOOP
659 {MNG_UINT_ENDL, mng_init_endl, mng_free_endl, mng_read_endl, mng_write_endl, mng_assign_endl, 0, 0},
660#endif
661#ifndef MNG_SKIPCHUNK_FRAM
662 {MNG_UINT_FRAM, mng_init_fram, mng_free_fram, mng_read_fram, mng_write_fram, mng_assign_fram, 0, 0},
663#endif
664 {MNG_UINT_IDAT, mng_init_idat, mng_free_idat, mng_read_idat, mng_write_idat, mng_assign_idat, 0, 0}, /* 12-th element! */
665 {MNG_UINT_IEND, mng_init_iend, mng_free_iend, mng_read_iend, mng_write_iend, mng_assign_iend, 0, 0},
666 {MNG_UINT_IHDR, mng_init_ihdr, mng_free_ihdr, mng_read_ihdr, mng_write_ihdr, mng_assign_ihdr, 0, 0},
667#ifndef MNG_NO_DELTA_PNG
668#ifdef MNG_INCLUDE_JNG
669 {MNG_UINT_IJNG, mng_init_ijng, mng_free_ijng, mng_read_ijng, mng_write_ijng, mng_assign_ijng, 0, 0},
670#endif
671 {MNG_UINT_IPNG, mng_init_ipng, mng_free_ipng, mng_read_ipng, mng_write_ipng, mng_assign_ipng, 0, 0},
672#endif
673#ifdef MNG_INCLUDE_JNG
674 {MNG_UINT_JDAA, mng_init_jdaa, mng_free_jdaa, mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa, 0, 0},
675 {MNG_UINT_JDAT, mng_init_jdat, mng_free_jdat, mng_read_jdat, mng_write_jdat, mng_assign_jdat, 0, 0},
676 {MNG_UINT_JHDR, mng_init_jhdr, mng_free_jhdr, mng_read_jhdr, mng_write_jhdr, mng_assign_jhdr, 0, 0},
677 {MNG_UINT_JSEP, mng_init_jsep, mng_free_jsep, mng_read_jsep, mng_write_jsep, mng_assign_jsep, 0, 0},
678 {MNG_UINT_JdAA, mng_init_jdaa, mng_free_jdaa, mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa, 0, 0},
679#endif
680#ifndef MNG_SKIPCHUNK_LOOP
681 {MNG_UINT_LOOP, mng_init_loop, mng_free_loop, mng_read_loop, mng_write_loop, mng_assign_loop, 0, 0},
682#endif
683#ifndef MNG_SKIPCHUNK_MAGN
684 {MNG_UINT_MAGN, mng_init_magn, mng_free_magn, mng_read_magn, mng_write_magn, mng_assign_magn, 0, 0},
685#endif
686 {MNG_UINT_MEND, mng_init_mend, mng_free_mend, mng_read_mend, mng_write_mend, mng_assign_mend, 0, 0},
687 {MNG_UINT_MHDR, mng_init_mhdr, mng_free_mhdr, mng_read_mhdr, mng_write_mhdr, mng_assign_mhdr, 0, 0},
688#ifndef MNG_SKIPCHUNK_MOVE
689 {MNG_UINT_MOVE, mng_init_move, mng_free_move, mng_read_move, mng_write_move, mng_assign_move, 0, 0},
690#endif
691#ifndef MNG_NO_DELTA_PNG
692#ifndef MNG_SKIPCHUNK_ORDR
693 {MNG_UINT_ORDR, mng_init_ordr, mng_free_ordr, mng_read_ordr, mng_write_ordr, mng_assign_ordr, 0, 0},
694#endif
695#endif
696#ifndef MNG_SKIPCHUNK_PAST
697 {MNG_UINT_PAST, mng_init_past, mng_free_past, mng_read_past, mng_write_past, mng_assign_past, 0, 0},
698#endif
699 {MNG_UINT_PLTE, mng_init_plte, mng_free_plte, mng_read_plte, mng_write_plte, mng_assign_plte, 0, 0},
700#ifndef MNG_NO_DELTA_PNG
701 {MNG_UINT_PPLT, mng_init_pplt, mng_free_pplt, mng_read_pplt, mng_write_pplt, mng_assign_pplt, 0, 0},
702 {MNG_UINT_PROM, mng_init_prom, mng_free_prom, mng_read_prom, mng_write_prom, mng_assign_prom, 0, 0},
703#endif
704#ifndef MNG_SKIPCHUNK_SAVE
705 {MNG_UINT_SAVE, mng_init_save, mng_free_save, mng_read_save, mng_write_save, mng_assign_save, 0, 0},
706#endif
707#ifndef MNG_SKIPCHUNK_SEEK
708 {MNG_UINT_SEEK, mng_init_seek, mng_free_seek, mng_read_seek, mng_write_seek, mng_assign_seek, 0, 0},
709#endif
710#ifndef MNG_SKIPCHUNK_SHOW
711 {MNG_UINT_SHOW, mng_init_show, mng_free_show, mng_read_show, mng_write_show, mng_assign_show, 0, 0},
712#endif
713#ifndef MNG_SKIPCHUNK_TERM
714 {MNG_UINT_TERM, mng_init_term, mng_free_term, mng_read_term, mng_write_term, mng_assign_term, 0, 0},
715#endif
716#ifndef MNG_SKIPCHUNK_bKGD
717 {MNG_UINT_bKGD, mng_init_bkgd, mng_free_bkgd, mng_read_bkgd, mng_write_bkgd, mng_assign_bkgd, 0, 0},
718#endif
719#ifndef MNG_SKIPCHUNK_cHRM
720 {MNG_UINT_cHRM, mng_init_chrm, mng_free_chrm, mng_read_chrm, mng_write_chrm, mng_assign_chrm, 0, 0},
721#endif
722#ifndef MNG_SKIPCHUNK_eXPI
723 {MNG_UINT_eXPI, mng_init_expi, mng_free_expi, mng_read_expi, mng_write_expi, mng_assign_expi, 0, 0},
724#endif
725#ifndef MNG_SKIPCHUNK_evNT
726 {MNG_UINT_evNT, mng_init_evnt, mng_free_evnt, mng_read_evnt, mng_write_evnt, mng_assign_evnt, 0, 0},
727#endif
728#ifndef MNG_SKIPCHUNK_fPRI
729 {MNG_UINT_fPRI, mng_init_fpri, mng_free_fpri, mng_read_fpri, mng_write_fpri, mng_assign_fpri, 0, 0},
730#endif
731#ifndef MNG_SKIPCHUNK_gAMA
732 {MNG_UINT_gAMA, mng_init_gama, mng_free_gama, mng_read_gama, mng_write_gama, mng_assign_gama, 0, 0},
733#endif
734#ifndef MNG_SKIPCHUNK_hIST
735 {MNG_UINT_hIST, mng_init_hist, mng_free_hist, mng_read_hist, mng_write_hist, mng_assign_hist, 0, 0},
736#endif
737#ifndef MNG_SKIPCHUNK_iCCP
738 {MNG_UINT_iCCP, mng_init_iccp, mng_free_iccp, mng_read_iccp, mng_write_iccp, mng_assign_iccp, 0, 0},
739#endif
740#ifndef MNG_SKIPCHUNK_iTXt
741 {MNG_UINT_iTXt, mng_init_itxt, mng_free_itxt, mng_read_itxt, mng_write_itxt, mng_assign_itxt, 0, 0},
742#endif
743#ifndef MNG_SKIPCHUNK_nEED
744 {MNG_UINT_nEED, mng_init_need, mng_free_need, mng_read_need, mng_write_need, mng_assign_need, 0, 0},
745#endif
746/* TODO: {MNG_UINT_oFFs, 0, 0, 0, 0, 0, 0}, */
747/* TODO: {MNG_UINT_pCAL, 0, 0, 0, 0, 0, 0}, */
748#ifndef MNG_SKIPCHUNK_pHYg
749 {MNG_UINT_pHYg, mng_init_phyg, mng_free_phyg, mng_read_phyg, mng_write_phyg, mng_assign_phyg, 0, 0},
750#endif
751#ifndef MNG_SKIPCHUNK_pHYs
752 {MNG_UINT_pHYs, mng_init_phys, mng_free_phys, mng_read_phys, mng_write_phys, mng_assign_phys, 0, 0},
753#endif
754#ifndef MNG_SKIPCHUNK_sBIT
755 {MNG_UINT_sBIT, mng_init_sbit, mng_free_sbit, mng_read_sbit, mng_write_sbit, mng_assign_sbit, 0, 0},
756#endif
757/* TODO: {MNG_UINT_sCAL, 0, 0, 0, 0, 0, 0}, */
758#ifndef MNG_SKIPCHUNK_sPLT
759 {MNG_UINT_sPLT, mng_init_splt, mng_free_splt, mng_read_splt, mng_write_splt, mng_assign_splt, 0, 0},
760#endif
761 {MNG_UINT_sRGB, mng_init_srgb, mng_free_srgb, mng_read_srgb, mng_write_srgb, mng_assign_srgb, 0, 0},
762#ifndef MNG_SKIPCHUNK_tEXt
763 {MNG_UINT_tEXt, mng_init_text, mng_free_text, mng_read_text, mng_write_text, mng_assign_text, 0, 0},
764#endif
765#ifndef MNG_SKIPCHUNK_tIME
766 {MNG_UINT_tIME, mng_init_time, mng_free_time, mng_read_time, mng_write_time, mng_assign_time, 0, 0},
767#endif
768 {MNG_UINT_tRNS, mng_init_trns, mng_free_trns, mng_read_trns, mng_write_trns, mng_assign_trns, 0, 0},
769#ifndef MNG_SKIPCHUNK_zTXt
770 {MNG_UINT_zTXt, mng_init_ztxt, mng_free_ztxt, mng_read_ztxt, mng_write_ztxt, mng_assign_ztxt, 0, 0},
771#endif
772 };
773
774#endif /* MNG_OPTIMIZE_CHUNKINITFREE */
775
776 /* binary search variables */
777 mng_int32 iTop, iLower, iUpper, iMiddle;
778 mng_chunk_headerp pEntry; /* pointer to found entry */
779#else
780 mng_chunk_header sEntry; /* temp chunk-header */
781#endif /* MNG_OPTIMIZE_CHUNKREADER */
782
783 mng_chunkid iChunkname; /* the chunk's tag */
784 mng_chunkp pChunk; /* chunk structure (if #define MNG_STORE_CHUNKS) */
785 mng_retcode iRetcode; /* temporary error-code */
786
787#ifdef MNG_SUPPORT_TRACE
788 MNG_TRACE (pData, MNG_FN_PROCESS_RAW_CHUNK, MNG_LC_START);
789#endif
790 /* reset timer indicator on read-cycle */
791 if ((pData->bReading) && (!pData->bDisplaying))
792 pData->bTimerset = MNG_FALSE;
793 /* get the chunkname */
794 iChunkname = (mng_chunkid)(mng_get_uint32 (pBuf));
795
796 pBuf += sizeof (mng_chunkid); /* adjust the buffer */
797 iBuflen -= sizeof (mng_chunkid);
798 pChunk = 0;
799
800#ifndef MNG_OPTIMIZE_CHUNKREADER
801 /* determine max index of table */
802 iTop = (sizeof (mng_chunk_table) / sizeof (mng_chunk_table [0])) - 1;
803
804 /* binary search; with 54 chunks, worst-case is 7 comparisons */
805 iLower = 0;
806#ifndef MNG_NO_DELTA_PNG
807 iMiddle = 11; /* start with the IDAT entry */
808#else
809 iMiddle = 8;
810#endif
811 iUpper = iTop;
812 pEntry = 0; /* no goods yet! */
813
814 do /* the binary search itself */
815 {
816 if (mng_chunk_table [iMiddle].iChunkname < iChunkname)
817 iLower = iMiddle + 1;
818 else if (mng_chunk_table [iMiddle].iChunkname > iChunkname)
819 iUpper = iMiddle - 1;
820 else
821 {
822 pEntry = &mng_chunk_table [iMiddle];
823 break;
824 }
825
826 iMiddle = (iLower + iUpper) >> 1;
827 }
828 while (iLower <= iUpper);
829
830 if (!pEntry) /* unknown chunk ? */
831 pEntry = &mng_chunk_unknown; /* make it so! */
832
833#else /* MNG_OPTIMIZE_CHUNKREADER */
834
835 mng_get_chunkheader (iChunkname, &sEntry);
836
837#endif /* MNG_OPTIMIZE_CHUNKREADER */
838
839 pData->iChunkname = iChunkname; /* keep track of where we are */
840 pData->iChunkseq++;
841
842#ifndef MNG_OPTIMIZE_CHUNKREADER
843 if (pEntry->fRead) /* read-callback available ? */
844 {
845 iRetcode = pEntry->fRead (pData, pEntry, iBuflen, (mng_ptr)pBuf, &pChunk);
846
847 if (!iRetcode) /* everything oke ? */
848 { /* remember unknown chunk's id */
849 if ((pChunk) && (pEntry->iChunkname == MNG_UINT_HUH))
850 ((mng_chunk_headerp)pChunk)->iChunkname = iChunkname;
851 }
852 }
853#else /* MNG_OPTIMIZE_CHUNKREADER */
854 if (sEntry.fRead) /* read-callback available ? */
855 {
856 iRetcode = sEntry.fRead (pData, &sEntry, iBuflen, (mng_ptr)pBuf, &pChunk);
857
858#ifndef MNG_OPTIMIZE_CHUNKREADER
859 if (!iRetcode) /* everything oke ? */
860 { /* remember unknown chunk's id */
861 if ((pChunk) && (sEntry.iChunkname == MNG_UINT_HUH))
862 ((mng_chunk_headerp)pChunk)->iChunkname = iChunkname;
863 }
864#endif
865 }
866#endif /* MNG_OPTIMIZE_CHUNKREADER */
867 else
868 iRetcode = MNG_NOERROR;
869
870 if (pChunk) /* store this chunk ? */
871 mng_add_chunk (pData, pChunk); /* do it */
872
873#ifdef MNG_INCLUDE_JNG /* implicit EOF ? */
874 if ((!pData->bHasMHDR) && (!pData->bHasIHDR) && (!pData->bHasJHDR))
875#else
876 if ((!pData->bHasMHDR) && (!pData->bHasIHDR))
877#endif
878 iRetcode = mng_process_eof (pData);/* then do some EOF processing */
879
880 if (iRetcode) /* on error bail out */
881 return iRetcode;
882
883#ifdef MNG_SUPPORT_TRACE
884 MNG_TRACE (pData, MNG_FN_PROCESS_RAW_CHUNK, MNG_LC_END);
885#endif
886
887 return MNG_NOERROR;
888}
889
890/* ************************************************************************** */
891
892MNG_LOCAL mng_retcode check_chunk_crc (mng_datap pData,
893 mng_uint8p pBuf,
894 mng_uint32 iBuflen)
895{
896 mng_uint32 iCrc; /* calculated CRC */
897 mng_bool bDiscard = MNG_FALSE;
898 mng_retcode iRetcode = MNG_NOERROR;
899
900#ifdef MNG_SUPPORT_TRACE
901 MNG_TRACE (pData, MNG_FN_READ_CHUNK_CRC, MNG_LC_START);
902#endif
903
904 if (pData->iCrcmode & MNG_CRC_INPUT) /* crc included ? */
905 {
906 mng_bool bCritical = (mng_bool)((*pBuf & 0x20) == 0);
907 mng_uint32 iL = iBuflen - (mng_uint32)(sizeof (iCrc));
908
909 if (((bCritical ) && (pData->iCrcmode & MNG_CRC_CRITICAL )) ||
910 ((!bCritical) && (pData->iCrcmode & MNG_CRC_ANCILLARY)))
911 { /* calculate the crc */
912 iCrc = mng_crc (pData, pBuf, iL);
913 /* and check it */
914 if (!(iCrc == mng_get_uint32 (pBuf + iL)))
915 {
916 mng_bool bWarning = MNG_FALSE;
917 mng_bool bError = MNG_FALSE;
918
919 if (bCritical)
920 {
921 switch (pData->iCrcmode & MNG_CRC_CRITICAL)
922 {
923 case MNG_CRC_CRITICAL_WARNING : { bWarning = MNG_TRUE; break; }
924 case MNG_CRC_CRITICAL_ERROR : { bError = MNG_TRUE; break; }
925 }
926 }
927 else
928 {
929 switch (pData->iCrcmode & MNG_CRC_ANCILLARY)
930 {
931 case MNG_CRC_ANCILLARY_DISCARD : { bDiscard = MNG_TRUE; break; }
932 case MNG_CRC_ANCILLARY_WARNING : { bWarning = MNG_TRUE; break; }
933 case MNG_CRC_ANCILLARY_ERROR : { bError = MNG_TRUE; break; }
934 }
935 }
936
937 if (bWarning)
938 MNG_WARNING (pData, MNG_INVALIDCRC);
939 if (bError)
940 MNG_ERROR (pData, MNG_INVALIDCRC);
941 }
942 }
943
944 if (!bDiscard) /* still processing ? */
945 iRetcode = process_raw_chunk (pData, pBuf, iL);
946 }
947 else
948 { /* no crc => straight onto processing */
949 iRetcode = process_raw_chunk (pData, pBuf, iBuflen);
950 }
951
952#ifdef MNG_SUPPORT_TRACE
953 MNG_TRACE (pData, MNG_FN_READ_CHUNK_CRC, MNG_LC_END);
954#endif
955
956 return iRetcode;
957}
958
959/* ************************************************************************** */
960
961MNG_LOCAL mng_retcode read_chunk (mng_datap pData)
962{
963 mng_uint32 iBufmax = pData->iReadbufsize;
964 mng_uint8p pBuf = pData->pReadbuf;
965 mng_uint32 iBuflen = 0; /* number of bytes requested */
966 mng_uint32 iRead = 0; /* number of bytes read */
967 mng_retcode iRetcode = MNG_NOERROR;
968
969#ifdef MNG_SUPPORT_TRACE
970 MNG_TRACE (pData, MNG_FN_READ_CHUNK, MNG_LC_START);
971#endif
972
973#ifdef MNG_SUPPORT_DISPLAY
974 if (pData->pCurraniobj) /* processing an animation object ? */
975 {
976 do /* process it then */
977 {
978 iRetcode = ((mng_object_headerp)pData->pCurraniobj)->fProcess (pData, pData->pCurraniobj);
979 /* refresh needed ? */
980/* if ((!iRetcode) && (!pData->bTimerset) && (pData->bNeedrefresh))
981 iRetcode = display_progressive_refresh (pData, 1); */
982 /* can we advance to next object ? */
983 if ((!iRetcode) && (pData->pCurraniobj) &&
984 (!pData->bTimerset) && (!pData->bSectionwait))
985 { /* reset timer indicator on read-cycle */
986 if ((pData->bReading) && (!pData->bDisplaying))
987 pData->bTimerset = MNG_FALSE;
988
989 pData->pCurraniobj = ((mng_object_headerp)pData->pCurraniobj)->pNext;
990 /* TERM processing to be done ? */
991 if ((!pData->pCurraniobj) && (pData->bHasTERM) && (!pData->bHasMHDR))
992 iRetcode = mng_process_display_mend (pData);
993 }
994 } /* until error or a break or no more objects */
995 while ((!iRetcode) && (pData->pCurraniobj) &&
996 (!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bFreezing));
997 }
998 else
999 {
1000 if (pData->iBreakpoint) /* do we need to finish something first ? */
1001 {
1002 switch (pData->iBreakpoint) /* return to broken display routine */
1003 {
1004#ifndef MNG_SKIPCHUNK_FRAM
1005 case 1 : { iRetcode = mng_process_display_fram2 (pData); break; }
1006#endif
1007 case 2 : { iRetcode = mng_process_display_ihdr (pData); break; }
1008#ifndef MNG_SKIPCHUNK_SHOW
1009 case 3 : ; /* same as 4 !!! */
1010 case 4 : { iRetcode = mng_process_display_show (pData); break; }
1011#endif
1012#ifndef MNG_SKIPCHUNK_CLON
1013 case 5 : { iRetcode = mng_process_display_clon2 (pData); break; }
1014#endif
1015#ifdef MNG_INCLUDE_JNG
1016 case 7 : { iRetcode = mng_process_display_jhdr (pData); break; }
1017#endif
1018 case 6 : ; /* same as 8 !!! */
1019 case 8 : { iRetcode = mng_process_display_iend (pData); break; }
1020#ifndef MNG_SKIPCHUNK_MAGN
1021 case 9 : { iRetcode = mng_process_display_magn2 (pData); break; }
1022#endif
1023 case 10 : { iRetcode = mng_process_display_mend2 (pData); break; }
1024#ifndef MNG_SKIPCHUNK_PAST
1025 case 11 : { iRetcode = mng_process_display_past2 (pData); break; }
1026#endif
1027 }
1028 }
1029 }
1030
1031 if (iRetcode) /* on error bail out */
1032 return iRetcode;
1033
1034#endif /* MNG_SUPPORT_DISPLAY */
1035 /* can we continue processing now, or do we */
1036 /* need to wait for the timer to finish (again) ? */
1037#ifdef MNG_SUPPORT_DISPLAY
1038 if ((!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bEOF))
1039#else
1040 if (!pData->bEOF)
1041#endif
1042 {
1043#ifdef MNG_SUPPORT_DISPLAY
1044 /* freezing in progress ? */
1045 if ((pData->bFreezing) && (pData->iSuspendpoint == 0))
1046 pData->bRunning = MNG_FALSE; /* then this is the right moment to do it */
1047#endif
1048
1049 if (pData->iSuspendpoint <= 2)
1050 {
1051 iBuflen = sizeof (mng_uint32); /* read length */
1052 iRetcode = read_databuffer (pData, pBuf, &pData->pReadbufnext, iBuflen, &iRead);
1053
1054 if (iRetcode) /* bail on errors */
1055 return iRetcode;
1056
1057 if (pData->bSuspended) /* suspended ? */
1058 pData->iSuspendpoint = 2;
1059 else /* save the length */
1060 {
1061 pData->iChunklen = mng_get_uint32 (pBuf);
1062 if (pData->iChunklen > 0x7ffffff)
1063 return MNG_INVALIDLENGTH;
1064 }
1065
1066 }
1067
1068 if (!pData->bSuspended) /* still going ? */
1069 { /* previously suspended or not eof ? */
1070 if ((pData->iSuspendpoint > 2) || (iRead == iBuflen))
1071 { /* determine length chunkname + data (+ crc) */
1072 if (pData->iCrcmode & MNG_CRC_INPUT)
1073 iBuflen = pData->iChunklen + (mng_uint32)(sizeof (mng_chunkid) + sizeof (mng_uint32));
1074 else
1075 iBuflen = pData->iChunklen + (mng_uint32)(sizeof (mng_chunkid));
1076
1077 /* do we have enough data in the current push buffer ? */
1078 if ((pData->pFirstpushdata) && (iBuflen <= pData->pFirstpushdata->iRemaining))
1079 {
1080 mng_pushdatap pPush = pData->pFirstpushdata;
1081 pBuf = pPush->pDatanext;
1082 pPush->pDatanext += iBuflen;
1083 pPush->iRemaining -= iBuflen;
1084 pData->iSuspendpoint = 0; /* safely reset this here ! */
1085
1086 iRetcode = check_chunk_crc (pData, pBuf, iBuflen);
1087 if (iRetcode)
1088 return iRetcode;
1089
1090 if (!pPush->iRemaining) /* buffer depleted? then release it */
1091 iRetcode = mng_release_pushdata (pData);
1092 }
1093 else
1094 {
1095 if (iBuflen < iBufmax) /* does it fit in default buffer ? */
1096 { /* note that we don't use the full size
1097 so there's always a zero-byte at the
1098 very end !!! */
1099 iRetcode = read_databuffer (pData, pBuf, &pData->pReadbufnext, iBuflen, &iRead);
1100 if (iRetcode) /* bail on errors */
1101 return iRetcode;
1102
1103 if (pData->bSuspended) /* suspended ? */
1104 pData->iSuspendpoint = 3;
1105 else
1106 {
1107 if (iRead != iBuflen) /* did we get all the data ? */
1108 MNG_ERROR (pData, MNG_UNEXPECTEDEOF);
1109 iRetcode = check_chunk_crc (pData, pBuf, iBuflen);
1110 }
1111 }
1112 else
1113 {
1114 if (iBuflen > 16777216) /* is the length incredible? */
1115 MNG_ERROR (pData, MNG_IMPROBABLELENGTH);
1116
1117 if (!pData->iSuspendpoint) /* create additional large buffer ? */
1118 { /* again reserve space for the last zero-byte */
1119 pData->iLargebufsize = iBuflen + 1;
1120 pData->pLargebufnext = MNG_NULL;
1121 MNG_ALLOC (pData, pData->pLargebuf, pData->iLargebufsize);
1122 }
1123
1124 iRetcode = read_databuffer (pData, pData->pLargebuf, &pData->pLargebufnext, iBuflen, &iRead);
1125 if (iRetcode)
1126 return iRetcode;
1127
1128 if (pData->bSuspended) /* suspended ? */
1129 pData->iSuspendpoint = 4;
1130 else
1131 {
1132 if (iRead != iBuflen) /* did we get all the data ? */
1133 MNG_ERROR (pData, MNG_UNEXPECTEDEOF);
1134 iRetcode = check_chunk_crc (pData, pData->pLargebuf, iBuflen);
1135 /* cleanup additional large buffer */
1136 MNG_FREE (pData, pData->pLargebuf, pData->iLargebufsize);
1137 }
1138 }
1139 }
1140
1141 if (iRetcode) /* on error bail out */
1142 return iRetcode;
1143
1144 }
1145 else
1146 { /* that's final */
1147 iRetcode = mng_process_eof (pData);
1148
1149 if (iRetcode) /* on error bail out */
1150 return iRetcode;
1151
1152 if ((iRead != 0) || /* did we get an unexpected eof ? */
1153#ifdef MNG_INCLUDE_JNG
1154 (pData->bHasIHDR || pData->bHasMHDR || pData->bHasJHDR))
1155#else
1156 (pData->bHasIHDR || pData->bHasMHDR))
1157#endif
1158 MNG_ERROR (pData, MNG_UNEXPECTEDEOF);
1159 }
1160 }
1161 }
1162
1163#ifdef MNG_SUPPORT_DISPLAY /* refresh needed ? */
1164 if ((!pData->bTimerset) && (!pData->bSuspended) && (pData->bNeedrefresh))
1165 {
1166 iRetcode = mng_display_progressive_refresh (pData, 1);
1167
1168 if (iRetcode) /* on error bail out */
1169 return iRetcode;
1170 }
1171#endif
1172
1173#ifdef MNG_SUPPORT_TRACE
1174 MNG_TRACE (pData, MNG_FN_READ_CHUNK, MNG_LC_END);
1175#endif
1176
1177 return MNG_NOERROR;
1178}
1179
1180/* ************************************************************************** */
1181
1182MNG_LOCAL mng_retcode process_pushedchunk (mng_datap pData)
1183{
1184 mng_pushdatap pPush;
1185 mng_retcode iRetcode = MNG_NOERROR;
1186
1187#ifdef MNG_SUPPORT_DISPLAY
1188 if (pData->pCurraniobj) /* processing an animation object ? */
1189 {
1190 do /* process it then */
1191 {
1192 iRetcode = ((mng_object_headerp)pData->pCurraniobj)->fProcess (pData, pData->pCurraniobj);
1193 /* refresh needed ? */
1194/* if ((!iRetcode) && (!pData->bTimerset) && (pData->bNeedrefresh))
1195 iRetcode = display_progressive_refresh (pData, 1); */
1196 /* can we advance to next object ? */
1197 if ((!iRetcode) && (pData->pCurraniobj) &&
1198 (!pData->bTimerset) && (!pData->bSectionwait))
1199 { /* reset timer indicator on read-cycle */
1200 if ((pData->bReading) && (!pData->bDisplaying))
1201 pData->bTimerset = MNG_FALSE;
1202
1203 pData->pCurraniobj = ((mng_object_headerp)pData->pCurraniobj)->pNext;
1204 /* TERM processing to be done ? */
1205 if ((!pData->pCurraniobj) && (pData->bHasTERM) && (!pData->bHasMHDR))
1206 iRetcode = mng_process_display_mend (pData);
1207 }
1208 } /* until error or a break or no more objects */
1209 while ((!iRetcode) && (pData->pCurraniobj) &&
1210 (!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bFreezing));
1211 }
1212 else
1213 {
1214 if (pData->iBreakpoint) /* do we need to finish something first ? */
1215 {
1216 switch (pData->iBreakpoint) /* return to broken display routine */
1217 {
1218#ifndef MNG_SKIPCHUNK_FRAM
1219 case 1 : { iRetcode = mng_process_display_fram2 (pData); break; }
1220#endif
1221 case 2 : { iRetcode = mng_process_display_ihdr (pData); break; }
1222#ifndef MNG_SKIPCHUNK_SHOW
1223 case 3 : ; /* same as 4 !!! */
1224 case 4 : { iRetcode = mng_process_display_show (pData); break; }
1225#endif
1226#ifndef MNG_SKIPCHUNK_CLON
1227 case 5 : { iRetcode = mng_process_display_clon2 (pData); break; }
1228#endif
1229#ifdef MNG_INCLUDE_JNG
1230 case 7 : { iRetcode = mng_process_display_jhdr (pData); break; }
1231#endif
1232 case 6 : ; /* same as 8 !!! */
1233 case 8 : { iRetcode = mng_process_display_iend (pData); break; }
1234#ifndef MNG_SKIPCHUNK_MAGN
1235 case 9 : { iRetcode = mng_process_display_magn2 (pData); break; }
1236#endif
1237 case 10 : { iRetcode = mng_process_display_mend2 (pData); break; }
1238#ifndef MNG_SKIPCHUNK_PAST
1239 case 11 : { iRetcode = mng_process_display_past2 (pData); break; }
1240#endif
1241 }
1242 }
1243 }
1244
1245 if (iRetcode) /* on error bail out */
1246 return iRetcode;
1247
1248#endif /* MNG_SUPPORT_DISPLAY */
1249 /* can we continue processing now, or do we */
1250 /* need to wait for the timer to finish (again) ? */
1251#ifdef MNG_SUPPORT_DISPLAY
1252 if ((!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bEOF))
1253#else
1254 if (!pData->bEOF)
1255#endif
1256 {
1257 pData->iSuspendpoint = 0; /* safely reset it here ! */
1258 pPush = pData->pFirstpushchunk;
1259
1260 iRetcode = process_raw_chunk (pData, pPush->pData, pPush->iLength);
1261 if (iRetcode)
1262 return iRetcode;
1263
1264#ifdef MNG_SUPPORT_DISPLAY /* refresh needed ? */
1265 if ((!pData->bTimerset) && (!pData->bSuspended) && (pData->bNeedrefresh))
1266 {
1267 iRetcode = mng_display_progressive_refresh (pData, 1);
1268 if (iRetcode) /* on error bail out */
1269 return iRetcode;
1270 }
1271#endif
1272 }
1273
1274 return mng_release_pushchunk (pData);
1275}
1276
1277/* ************************************************************************** */
1278
1279mng_retcode mng_read_graphic (mng_datap pData)
1280{
1281 mng_uint32 iBuflen; /* number of bytes requested */
1282 mng_uint32 iRead; /* number of bytes read */
1283 mng_retcode iRetcode; /* temporary error-code */
1284
1285#ifdef MNG_SUPPORT_TRACE
1286 MNG_TRACE (pData, MNG_FN_READ_GRAPHIC, MNG_LC_START);
1287#endif
1288
1289 if (!pData->pReadbuf) /* buffer allocated ? */
1290 {
1291 pData->iReadbufsize = 4200; /* allocate a default read buffer */
1292 MNG_ALLOC (pData, pData->pReadbuf, pData->iReadbufsize);
1293 }
1294 /* haven't processed the signature ? */
1295 if ((!pData->bHavesig) || (pData->iSuspendpoint == 1))
1296 {
1297 iBuflen = 2 * sizeof (mng_uint32); /* read signature */
1298
1299 iRetcode = read_databuffer (pData, pData->pReadbuf, &pData->pReadbufnext, iBuflen, &iRead);
1300
1301 if (iRetcode)
1302 return iRetcode;
1303
1304 if (pData->bSuspended) /* input suspension ? */
1305 pData->iSuspendpoint = 1;
1306 else
1307 {
1308 if (iRead != iBuflen) /* full signature received ? */
1309 MNG_ERROR (pData, MNG_UNEXPECTEDEOF);
1310 /* is it a valid signature ? */
1311 if (mng_get_uint32 (pData->pReadbuf) == PNG_SIG)
1312 pData->eSigtype = mng_it_png;
1313 else
1314#ifdef MNG_INCLUDE_JNG
1315 if (mng_get_uint32 (pData->pReadbuf) == JNG_SIG)
1316 pData->eSigtype = mng_it_jng;
1317 else
1318#endif
1319 if (mng_get_uint32 (pData->pReadbuf) == MNG_SIG)
1320 pData->eSigtype = mng_it_mng;
1321 else
1322 MNG_ERROR (pData, MNG_INVALIDSIG);
1323 /* all of it ? */
1324 if (mng_get_uint32 (pData->pReadbuf+4) != POST_SIG)
1325 MNG_ERROR (pData, MNG_INVALIDSIG);
1326
1327 pData->bHavesig = MNG_TRUE;
1328 }
1329 }
1330
1331 if (!pData->bSuspended) /* still going ? */
1332 {
1333 do
1334 { /* reset timer during mng_read() ? */
1335 if ((pData->bReading) && (!pData->bDisplaying))
1336 pData->bTimerset = MNG_FALSE;
1337
1338 if (pData->pFirstpushchunk) /* chunks pushed ? */
1339 iRetcode = process_pushedchunk (pData); /* process the pushed chunk */
1340 else
1341 iRetcode = read_chunk (pData); /* read & process a chunk */
1342
1343 if (iRetcode) /* on error bail out */
1344 return iRetcode;
1345 }
1346#ifdef MNG_SUPPORT_DISPLAY /* until EOF or a break-request */
1347 while (((!pData->bEOF) || (pData->pCurraniobj)) &&
1348 (!pData->bSuspended) && (!pData->bSectionwait) &&
1349 ((!pData->bTimerset) || ((pData->bReading) && (!pData->bDisplaying))));
1350#else
1351 while ((!pData->bEOF) && (!pData->bSuspended));
1352#endif
1353 }
1354
1355#ifdef MNG_SUPPORT_TRACE
1356 MNG_TRACE (pData, MNG_FN_READ_GRAPHIC, MNG_LC_END);
1357#endif
1358
1359 return MNG_NOERROR;
1360}
1361
1362/* ************************************************************************** */
1363
1364#endif /* MNG_INCLUDE_READ_PROCS */
1365
1366/* ************************************************************************** */
1367/* * end of file * */
1368/* ************************************************************************** */
1369
Note: See TracBrowser for help on using the repository browser.