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
mng_process_eof(mng_datap pData)142 mng_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
mng_release_pushdata(mng_datap pData)161 mng_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
mng_release_pushchunk(mng_datap pData)191 mng_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
read_data(mng_datap pData,mng_uint8p pBuf,mng_uint32 iSize,mng_uint32 * iRead)221 MNG_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
read_databuffer(mng_datap pData,mng_uint8p pBuf,mng_uint8p * pBufnext,mng_uint32 iSize,mng_uint32 * iRead)292 MNG_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
process_raw_chunk(mng_datap pData,mng_uint8p pBuf,mng_uint32 iBuflen)447 MNG_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
check_chunk_crc(mng_datap pData,mng_uint8p pBuf,mng_uint32 iBuflen)892 MNG_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
read_chunk(mng_datap pData)961 MNG_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
process_pushedchunk(mng_datap pData)1182 MNG_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
mng_read_graphic(mng_datap pData)1279 mng_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
1370