ropes
[dosdemo] / libs / imago / libpng / pngpread.c
1 \r
2 /* pngpread.c - read a png file in push mode\r
3  *\r
4  * Last changed in libpng 1.2.32 [September 18, 2008]\r
5  * For conditions of distribution and use, see copyright notice in png.h\r
6  * Copyright (c) 1998-2008 Glenn Randers-Pehrson\r
7  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)\r
8  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)\r
9  */\r
10 \r
11 #define PNG_INTERNAL\r
12 #include "png.h"\r
13 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED\r
14 \r
15 /* push model modes */\r
16 #define PNG_READ_SIG_MODE   0\r
17 #define PNG_READ_CHUNK_MODE 1\r
18 #define PNG_READ_IDAT_MODE  2\r
19 #define PNG_SKIP_MODE       3\r
20 #define PNG_READ_tEXt_MODE  4\r
21 #define PNG_READ_zTXt_MODE  5\r
22 #define PNG_READ_DONE_MODE  6\r
23 #define PNG_READ_iTXt_MODE  7\r
24 #define PNG_ERROR_MODE      8\r
25 \r
26 void PNGAPI\r
27 png_process_data(png_structp png_ptr, png_infop info_ptr,\r
28    png_bytep buffer, png_size_t buffer_size)\r
29 {\r
30    if (png_ptr == NULL || info_ptr == NULL) return;\r
31    png_push_restore_buffer(png_ptr, buffer, buffer_size);\r
32 \r
33    while (png_ptr->buffer_size)\r
34    {\r
35       png_process_some_data(png_ptr, info_ptr);\r
36    }\r
37 }\r
38 \r
39 /* What we do with the incoming data depends on what we were previously\r
40  * doing before we ran out of data...\r
41  */\r
42 void /* PRIVATE */\r
43 png_process_some_data(png_structp png_ptr, png_infop info_ptr)\r
44 {\r
45    if (png_ptr == NULL) return;\r
46    switch (png_ptr->process_mode)\r
47    {\r
48       case PNG_READ_SIG_MODE:\r
49       {\r
50          png_push_read_sig(png_ptr, info_ptr);\r
51          break;\r
52       }\r
53       case PNG_READ_CHUNK_MODE:\r
54       {\r
55          png_push_read_chunk(png_ptr, info_ptr);\r
56          break;\r
57       }\r
58       case PNG_READ_IDAT_MODE:\r
59       {\r
60          png_push_read_IDAT(png_ptr);\r
61          break;\r
62       }\r
63 #if defined(PNG_READ_tEXt_SUPPORTED)\r
64       case PNG_READ_tEXt_MODE:\r
65       {\r
66          png_push_read_tEXt(png_ptr, info_ptr);\r
67          break;\r
68       }\r
69 #endif\r
70 #if defined(PNG_READ_zTXt_SUPPORTED)\r
71       case PNG_READ_zTXt_MODE:\r
72       {\r
73          png_push_read_zTXt(png_ptr, info_ptr);\r
74          break;\r
75       }\r
76 #endif\r
77 #if defined(PNG_READ_iTXt_SUPPORTED)\r
78       case PNG_READ_iTXt_MODE:\r
79       {\r
80          png_push_read_iTXt(png_ptr, info_ptr);\r
81          break;\r
82       }\r
83 #endif\r
84       case PNG_SKIP_MODE:\r
85       {\r
86          png_push_crc_finish(png_ptr);\r
87          break;\r
88       }\r
89       default:\r
90       {\r
91          png_ptr->buffer_size = 0;\r
92          break;\r
93       }\r
94    }\r
95 }\r
96 \r
97 /* Read any remaining signature bytes from the stream and compare them with\r
98  * the correct PNG signature.  It is possible that this routine is called\r
99  * with bytes already read from the signature, either because they have been\r
100  * checked by the calling application, or because of multiple calls to this\r
101  * routine.\r
102  */\r
103 void /* PRIVATE */\r
104 png_push_read_sig(png_structp png_ptr, png_infop info_ptr)\r
105 {\r
106    png_size_t num_checked = png_ptr->sig_bytes,\r
107              num_to_check = 8 - num_checked;\r
108 \r
109    if (png_ptr->buffer_size < num_to_check)\r
110    {\r
111       num_to_check = png_ptr->buffer_size;\r
112    }\r
113 \r
114    png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),\r
115       num_to_check);\r
116    png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);\r
117 \r
118    if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))\r
119    {\r
120       if (num_checked < 4 &&\r
121           png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))\r
122          png_error(png_ptr, "Not a PNG file");\r
123       else\r
124          png_error(png_ptr, "PNG file corrupted by ASCII conversion");\r
125    }\r
126    else\r
127    {\r
128       if (png_ptr->sig_bytes >= 8)\r
129       {\r
130          png_ptr->process_mode = PNG_READ_CHUNK_MODE;\r
131       }\r
132    }\r
133 }\r
134 \r
135 void /* PRIVATE */\r
136 png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)\r
137 {\r
138 #ifdef PNG_USE_LOCAL_ARRAYS\r
139       PNG_CONST PNG_IHDR;\r
140       PNG_CONST PNG_IDAT;\r
141       PNG_CONST PNG_IEND;\r
142       PNG_CONST PNG_PLTE;\r
143 #if defined(PNG_READ_bKGD_SUPPORTED)\r
144       PNG_CONST PNG_bKGD;\r
145 #endif\r
146 #if defined(PNG_READ_cHRM_SUPPORTED)\r
147       PNG_CONST PNG_cHRM;\r
148 #endif\r
149 #if defined(PNG_READ_gAMA_SUPPORTED)\r
150       PNG_CONST PNG_gAMA;\r
151 #endif\r
152 #if defined(PNG_READ_hIST_SUPPORTED)\r
153       PNG_CONST PNG_hIST;\r
154 #endif\r
155 #if defined(PNG_READ_iCCP_SUPPORTED)\r
156       PNG_CONST PNG_iCCP;\r
157 #endif\r
158 #if defined(PNG_READ_iTXt_SUPPORTED)\r
159       PNG_CONST PNG_iTXt;\r
160 #endif\r
161 #if defined(PNG_READ_oFFs_SUPPORTED)\r
162       PNG_CONST PNG_oFFs;\r
163 #endif\r
164 #if defined(PNG_READ_pCAL_SUPPORTED)\r
165       PNG_CONST PNG_pCAL;\r
166 #endif\r
167 #if defined(PNG_READ_pHYs_SUPPORTED)\r
168       PNG_CONST PNG_pHYs;\r
169 #endif\r
170 #if defined(PNG_READ_sBIT_SUPPORTED)\r
171       PNG_CONST PNG_sBIT;\r
172 #endif\r
173 #if defined(PNG_READ_sCAL_SUPPORTED)\r
174       PNG_CONST PNG_sCAL;\r
175 #endif\r
176 #if defined(PNG_READ_sRGB_SUPPORTED)\r
177       PNG_CONST PNG_sRGB;\r
178 #endif\r
179 #if defined(PNG_READ_sPLT_SUPPORTED)\r
180       PNG_CONST PNG_sPLT;\r
181 #endif\r
182 #if defined(PNG_READ_tEXt_SUPPORTED)\r
183       PNG_CONST PNG_tEXt;\r
184 #endif\r
185 #if defined(PNG_READ_tIME_SUPPORTED)\r
186       PNG_CONST PNG_tIME;\r
187 #endif\r
188 #if defined(PNG_READ_tRNS_SUPPORTED)\r
189       PNG_CONST PNG_tRNS;\r
190 #endif\r
191 #if defined(PNG_READ_zTXt_SUPPORTED)\r
192       PNG_CONST PNG_zTXt;\r
193 #endif\r
194 #endif /* PNG_USE_LOCAL_ARRAYS */\r
195    /* First we make sure we have enough data for the 4 byte chunk name\r
196     * and the 4 byte chunk length before proceeding with decoding the\r
197     * chunk data.  To fully decode each of these chunks, we also make\r
198     * sure we have enough data in the buffer for the 4 byte CRC at the\r
199     * end of every chunk (except IDAT, which is handled separately).\r
200     */\r
201    if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))\r
202    {\r
203       png_byte chunk_length[4];\r
204 \r
205       if (png_ptr->buffer_size < 8)\r
206       {\r
207          png_push_save_buffer(png_ptr);\r
208          return;\r
209       }\r
210 \r
211       png_push_fill_buffer(png_ptr, chunk_length, 4);\r
212       png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);\r
213       png_reset_crc(png_ptr);\r
214       png_crc_read(png_ptr, png_ptr->chunk_name, 4);\r
215       png_check_chunk_name(png_ptr, png_ptr->chunk_name);\r
216       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;\r
217    }\r
218 \r
219    if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))\r
220      if (png_ptr->mode & PNG_AFTER_IDAT)\r
221         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;\r
222 \r
223    if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))\r
224    {\r
225       if (png_ptr->push_length != 13)\r
226          png_error(png_ptr, "Invalid IHDR length");\r
227       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
228       {\r
229          png_push_save_buffer(png_ptr);\r
230          return;\r
231       }\r
232       png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);\r
233    }\r
234    else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))\r
235    {\r
236       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
237       {\r
238          png_push_save_buffer(png_ptr);\r
239          return;\r
240       }\r
241       png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);\r
242 \r
243       png_ptr->process_mode = PNG_READ_DONE_MODE;\r
244       png_push_have_end(png_ptr, info_ptr);\r
245    }\r
246 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED\r
247    else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))\r
248    {\r
249       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
250       {\r
251          png_push_save_buffer(png_ptr);\r
252          return;\r
253       }\r
254       if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))\r
255          png_ptr->mode |= PNG_HAVE_IDAT;\r
256       png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);\r
257       if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))\r
258          png_ptr->mode |= PNG_HAVE_PLTE;\r
259       else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))\r
260       {\r
261          if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
262             png_error(png_ptr, "Missing IHDR before IDAT");\r
263          else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&\r
264                   !(png_ptr->mode & PNG_HAVE_PLTE))\r
265             png_error(png_ptr, "Missing PLTE before IDAT");\r
266       }\r
267    }\r
268 #endif\r
269    else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))\r
270    {\r
271       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
272       {\r
273          png_push_save_buffer(png_ptr);\r
274          return;\r
275       }\r
276       png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);\r
277    }\r
278    else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))\r
279    {\r
280       /* If we reach an IDAT chunk, this means we have read all of the\r
281        * header chunks, and we can start reading the image (or if this\r
282        * is called after the image has been read - we have an error).\r
283        */\r
284      if (!(png_ptr->mode & PNG_HAVE_IHDR))\r
285        png_error(png_ptr, "Missing IHDR before IDAT");\r
286      else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&\r
287          !(png_ptr->mode & PNG_HAVE_PLTE))\r
288        png_error(png_ptr, "Missing PLTE before IDAT");\r
289 \r
290       if (png_ptr->mode & PNG_HAVE_IDAT)\r
291       {\r
292          if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))\r
293            if (png_ptr->push_length == 0)\r
294               return;\r
295 \r
296          if (png_ptr->mode & PNG_AFTER_IDAT)\r
297             png_error(png_ptr, "Too many IDAT's found");\r
298       }\r
299 \r
300       png_ptr->idat_size = png_ptr->push_length;\r
301       png_ptr->mode |= PNG_HAVE_IDAT;\r
302       png_ptr->process_mode = PNG_READ_IDAT_MODE;\r
303       png_push_have_info(png_ptr, info_ptr);\r
304       png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;\r
305       png_ptr->zstream.next_out = png_ptr->row_buf;\r
306       return;\r
307    }\r
308 #if defined(PNG_READ_gAMA_SUPPORTED)\r
309    else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))\r
310    {\r
311       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
312       {\r
313          png_push_save_buffer(png_ptr);\r
314          return;\r
315       }\r
316       png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);\r
317    }\r
318 #endif\r
319 #if defined(PNG_READ_sBIT_SUPPORTED)\r
320    else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))\r
321    {\r
322       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
323       {\r
324          png_push_save_buffer(png_ptr);\r
325          return;\r
326       }\r
327       png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);\r
328    }\r
329 #endif\r
330 #if defined(PNG_READ_cHRM_SUPPORTED)\r
331    else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))\r
332    {\r
333       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
334       {\r
335          png_push_save_buffer(png_ptr);\r
336          return;\r
337       }\r
338       png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);\r
339    }\r
340 #endif\r
341 #if defined(PNG_READ_sRGB_SUPPORTED)\r
342    else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))\r
343    {\r
344       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
345       {\r
346          png_push_save_buffer(png_ptr);\r
347          return;\r
348       }\r
349       png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);\r
350    }\r
351 #endif\r
352 #if defined(PNG_READ_iCCP_SUPPORTED)\r
353    else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))\r
354    {\r
355       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
356       {\r
357          png_push_save_buffer(png_ptr);\r
358          return;\r
359       }\r
360       png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);\r
361    }\r
362 #endif\r
363 #if defined(PNG_READ_sPLT_SUPPORTED)\r
364    else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))\r
365    {\r
366       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
367       {\r
368          png_push_save_buffer(png_ptr);\r
369          return;\r
370       }\r
371       png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);\r
372    }\r
373 #endif\r
374 #if defined(PNG_READ_tRNS_SUPPORTED)\r
375    else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))\r
376    {\r
377       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
378       {\r
379          png_push_save_buffer(png_ptr);\r
380          return;\r
381       }\r
382       png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);\r
383    }\r
384 #endif\r
385 #if defined(PNG_READ_bKGD_SUPPORTED)\r
386    else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))\r
387    {\r
388       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
389       {\r
390          png_push_save_buffer(png_ptr);\r
391          return;\r
392       }\r
393       png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);\r
394    }\r
395 #endif\r
396 #if defined(PNG_READ_hIST_SUPPORTED)\r
397    else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))\r
398    {\r
399       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
400       {\r
401          png_push_save_buffer(png_ptr);\r
402          return;\r
403       }\r
404       png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);\r
405    }\r
406 #endif\r
407 #if defined(PNG_READ_pHYs_SUPPORTED)\r
408    else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))\r
409    {\r
410       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
411       {\r
412          png_push_save_buffer(png_ptr);\r
413          return;\r
414       }\r
415       png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);\r
416    }\r
417 #endif\r
418 #if defined(PNG_READ_oFFs_SUPPORTED)\r
419    else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))\r
420    {\r
421       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
422       {\r
423          png_push_save_buffer(png_ptr);\r
424          return;\r
425       }\r
426       png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);\r
427    }\r
428 #endif\r
429 #if defined(PNG_READ_pCAL_SUPPORTED)\r
430    else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))\r
431    {\r
432       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
433       {\r
434          png_push_save_buffer(png_ptr);\r
435          return;\r
436       }\r
437       png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);\r
438    }\r
439 #endif\r
440 #if defined(PNG_READ_sCAL_SUPPORTED)\r
441    else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))\r
442    {\r
443       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
444       {\r
445          png_push_save_buffer(png_ptr);\r
446          return;\r
447       }\r
448       png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);\r
449    }\r
450 #endif\r
451 #if defined(PNG_READ_tIME_SUPPORTED)\r
452    else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))\r
453    {\r
454       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
455       {\r
456          png_push_save_buffer(png_ptr);\r
457          return;\r
458       }\r
459       png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);\r
460    }\r
461 #endif\r
462 #if defined(PNG_READ_tEXt_SUPPORTED)\r
463    else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))\r
464    {\r
465       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
466       {\r
467          png_push_save_buffer(png_ptr);\r
468          return;\r
469       }\r
470       png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);\r
471    }\r
472 #endif\r
473 #if defined(PNG_READ_zTXt_SUPPORTED)\r
474    else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))\r
475    {\r
476       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
477       {\r
478          png_push_save_buffer(png_ptr);\r
479          return;\r
480       }\r
481       png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);\r
482    }\r
483 #endif\r
484 #if defined(PNG_READ_iTXt_SUPPORTED)\r
485    else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))\r
486    {\r
487       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
488       {\r
489          png_push_save_buffer(png_ptr);\r
490          return;\r
491       }\r
492       png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);\r
493    }\r
494 #endif\r
495    else\r
496    {\r
497       if (png_ptr->push_length + 4 > png_ptr->buffer_size)\r
498       {\r
499          png_push_save_buffer(png_ptr);\r
500          return;\r
501       }\r
502       png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);\r
503    }\r
504 \r
505    png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;\r
506 }\r
507 \r
508 void /* PRIVATE */\r
509 png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)\r
510 {\r
511    png_ptr->process_mode = PNG_SKIP_MODE;\r
512    png_ptr->skip_length = skip;\r
513 }\r
514 \r
515 void /* PRIVATE */\r
516 png_push_crc_finish(png_structp png_ptr)\r
517 {\r
518    if (png_ptr->skip_length && png_ptr->save_buffer_size)\r
519    {\r
520       png_size_t save_size;\r
521 \r
522       if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size)\r
523          save_size = (png_size_t)png_ptr->skip_length;\r
524       else\r
525          save_size = png_ptr->save_buffer_size;\r
526 \r
527       png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);\r
528 \r
529       png_ptr->skip_length -= save_size;\r
530       png_ptr->buffer_size -= save_size;\r
531       png_ptr->save_buffer_size -= save_size;\r
532       png_ptr->save_buffer_ptr += save_size;\r
533    }\r
534    if (png_ptr->skip_length && png_ptr->current_buffer_size)\r
535    {\r
536       png_size_t save_size;\r
537 \r
538       if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size)\r
539          save_size = (png_size_t)png_ptr->skip_length;\r
540       else\r
541          save_size = png_ptr->current_buffer_size;\r
542 \r
543       png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);\r
544 \r
545       png_ptr->skip_length -= save_size;\r
546       png_ptr->buffer_size -= save_size;\r
547       png_ptr->current_buffer_size -= save_size;\r
548       png_ptr->current_buffer_ptr += save_size;\r
549    }\r
550    if (!png_ptr->skip_length)\r
551    {\r
552       if (png_ptr->buffer_size < 4)\r
553       {\r
554          png_push_save_buffer(png_ptr);\r
555          return;\r
556       }\r
557 \r
558       png_crc_finish(png_ptr, 0);\r
559       png_ptr->process_mode = PNG_READ_CHUNK_MODE;\r
560    }\r
561 }\r
562 \r
563 void PNGAPI\r
564 png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)\r
565 {\r
566    png_bytep ptr;\r
567 \r
568    if (png_ptr == NULL) return;\r
569    ptr = buffer;\r
570    if (png_ptr->save_buffer_size)\r
571    {\r
572       png_size_t save_size;\r
573 \r
574       if (length < png_ptr->save_buffer_size)\r
575          save_size = length;\r
576       else\r
577          save_size = png_ptr->save_buffer_size;\r
578 \r
579       png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);\r
580       length -= save_size;\r
581       ptr += save_size;\r
582       png_ptr->buffer_size -= save_size;\r
583       png_ptr->save_buffer_size -= save_size;\r
584       png_ptr->save_buffer_ptr += save_size;\r
585    }\r
586    if (length && png_ptr->current_buffer_size)\r
587    {\r
588       png_size_t save_size;\r
589 \r
590       if (length < png_ptr->current_buffer_size)\r
591          save_size = length;\r
592       else\r
593          save_size = png_ptr->current_buffer_size;\r
594 \r
595       png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);\r
596       png_ptr->buffer_size -= save_size;\r
597       png_ptr->current_buffer_size -= save_size;\r
598       png_ptr->current_buffer_ptr += save_size;\r
599    }\r
600 }\r
601 \r
602 void /* PRIVATE */\r
603 png_push_save_buffer(png_structp png_ptr)\r
604 {\r
605    if (png_ptr->save_buffer_size)\r
606    {\r
607       if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)\r
608       {\r
609          png_size_t i, istop;\r
610          png_bytep sp;\r
611          png_bytep dp;\r
612 \r
613          istop = png_ptr->save_buffer_size;\r
614          for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;\r
615             i < istop; i++, sp++, dp++)\r
616          {\r
617             *dp = *sp;\r
618          }\r
619       }\r
620    }\r
621    if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >\r
622       png_ptr->save_buffer_max)\r
623    {\r
624       png_size_t new_max;\r
625       png_bytep old_buffer;\r
626 \r
627       if (png_ptr->save_buffer_size > PNG_SIZE_MAX -\r
628          (png_ptr->current_buffer_size + 256))\r
629       {\r
630         png_error(png_ptr, "Potential overflow of save_buffer");\r
631       }\r
632       new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;\r
633       old_buffer = png_ptr->save_buffer;\r
634       png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr,\r
635          (png_uint_32)new_max);\r
636       png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);\r
637       png_free(png_ptr, old_buffer);\r
638       png_ptr->save_buffer_max = new_max;\r
639    }\r
640    if (png_ptr->current_buffer_size)\r
641    {\r
642       png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,\r
643          png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);\r
644       png_ptr->save_buffer_size += png_ptr->current_buffer_size;\r
645       png_ptr->current_buffer_size = 0;\r
646    }\r
647    png_ptr->save_buffer_ptr = png_ptr->save_buffer;\r
648    png_ptr->buffer_size = 0;\r
649 }\r
650 \r
651 void /* PRIVATE */\r
652 png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,\r
653    png_size_t buffer_length)\r
654 {\r
655    png_ptr->current_buffer = buffer;\r
656    png_ptr->current_buffer_size = buffer_length;\r
657    png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;\r
658    png_ptr->current_buffer_ptr = png_ptr->current_buffer;\r
659 }\r
660 \r
661 void /* PRIVATE */\r
662 png_push_read_IDAT(png_structp png_ptr)\r
663 {\r
664 #ifdef PNG_USE_LOCAL_ARRAYS\r
665    PNG_CONST PNG_IDAT;\r
666 #endif\r
667    if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))\r
668    {\r
669       png_byte chunk_length[4];\r
670 \r
671       if (png_ptr->buffer_size < 8)\r
672       {\r
673          png_push_save_buffer(png_ptr);\r
674          return;\r
675       }\r
676 \r
677       png_push_fill_buffer(png_ptr, chunk_length, 4);\r
678       png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);\r
679       png_reset_crc(png_ptr);\r
680       png_crc_read(png_ptr, png_ptr->chunk_name, 4);\r
681       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;\r
682 \r
683       if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))\r
684       {\r
685          png_ptr->process_mode = PNG_READ_CHUNK_MODE;\r
686          if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))\r
687             png_error(png_ptr, "Not enough compressed data");\r
688          return;\r
689       }\r
690 \r
691       png_ptr->idat_size = png_ptr->push_length;\r
692    }\r
693    if (png_ptr->idat_size && png_ptr->save_buffer_size)\r
694    {\r
695       png_size_t save_size;\r
696 \r
697       if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)\r
698       {\r
699          save_size = (png_size_t)png_ptr->idat_size;\r
700          /* check for overflow */\r
701          if ((png_uint_32)save_size != png_ptr->idat_size)\r
702             png_error(png_ptr, "save_size overflowed in pngpread");\r
703       }\r
704       else\r
705          save_size = png_ptr->save_buffer_size;\r
706 \r
707       png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);\r
708       if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))\r
709          png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);\r
710       png_ptr->idat_size -= save_size;\r
711       png_ptr->buffer_size -= save_size;\r
712       png_ptr->save_buffer_size -= save_size;\r
713       png_ptr->save_buffer_ptr += save_size;\r
714    }\r
715    if (png_ptr->idat_size && png_ptr->current_buffer_size)\r
716    {\r
717       png_size_t save_size;\r
718 \r
719       if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)\r
720       {\r
721          save_size = (png_size_t)png_ptr->idat_size;\r
722          /* check for overflow */\r
723          if ((png_uint_32)save_size != png_ptr->idat_size)\r
724             png_error(png_ptr, "save_size overflowed in pngpread");\r
725       }\r
726       else\r
727          save_size = png_ptr->current_buffer_size;\r
728 \r
729       png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);\r
730       if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))\r
731         png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);\r
732 \r
733       png_ptr->idat_size -= save_size;\r
734       png_ptr->buffer_size -= save_size;\r
735       png_ptr->current_buffer_size -= save_size;\r
736       png_ptr->current_buffer_ptr += save_size;\r
737    }\r
738    if (!png_ptr->idat_size)\r
739    {\r
740       if (png_ptr->buffer_size < 4)\r
741       {\r
742          png_push_save_buffer(png_ptr);\r
743          return;\r
744       }\r
745 \r
746       png_crc_finish(png_ptr, 0);\r
747       png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;\r
748       png_ptr->mode |= PNG_AFTER_IDAT;\r
749    }\r
750 }\r
751 \r
752 void /* PRIVATE */\r
753 png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,\r
754    png_size_t buffer_length)\r
755 {\r
756    int ret;\r
757 \r
758    if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)\r
759       png_error(png_ptr, "Extra compression data");\r
760 \r
761    png_ptr->zstream.next_in = buffer;\r
762    png_ptr->zstream.avail_in = (uInt)buffer_length;\r
763    for (;;)\r
764    {\r
765       ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);\r
766       if (ret != Z_OK)\r
767       {\r
768          if (ret == Z_STREAM_END)\r
769          {\r
770             if (png_ptr->zstream.avail_in)\r
771                png_error(png_ptr, "Extra compressed data");\r
772             if (!(png_ptr->zstream.avail_out))\r
773             {\r
774                png_push_process_row(png_ptr);\r
775             }\r
776 \r
777             png_ptr->mode |= PNG_AFTER_IDAT;\r
778             png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;\r
779             break;\r
780          }\r
781          else if (ret == Z_BUF_ERROR)\r
782             break;\r
783          else\r
784             png_error(png_ptr, "Decompression Error");\r
785       }\r
786       if (!(png_ptr->zstream.avail_out))\r
787       {\r
788          if ((\r
789 #if defined(PNG_READ_INTERLACING_SUPPORTED)\r
790              png_ptr->interlaced && png_ptr->pass > 6) ||\r
791              (!png_ptr->interlaced &&\r
792 #endif\r
793              png_ptr->row_number == png_ptr->num_rows))\r
794          {\r
795            if (png_ptr->zstream.avail_in)\r
796              png_warning(png_ptr, "Too much data in IDAT chunks");\r
797            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;\r
798            break;\r
799          }\r
800          png_push_process_row(png_ptr);\r
801          png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;\r
802          png_ptr->zstream.next_out = png_ptr->row_buf;\r
803       }\r
804       else\r
805          break;\r
806    }\r
807 }\r
808 \r
809 void /* PRIVATE */\r
810 png_push_process_row(png_structp png_ptr)\r
811 {\r
812    png_ptr->row_info.color_type = png_ptr->color_type;\r
813    png_ptr->row_info.width = png_ptr->iwidth;\r
814    png_ptr->row_info.channels = png_ptr->channels;\r
815    png_ptr->row_info.bit_depth = png_ptr->bit_depth;\r
816    png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;\r
817 \r
818    png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,\r
819        png_ptr->row_info.width);\r
820 \r
821    png_read_filter_row(png_ptr, &(png_ptr->row_info),\r
822       png_ptr->row_buf + 1, png_ptr->prev_row + 1,\r
823       (int)(png_ptr->row_buf[0]));\r
824 \r
825    png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,\r
826       png_ptr->rowbytes + 1);\r
827 \r
828    if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))\r
829       png_do_read_transformations(png_ptr);\r
830 \r
831 #if defined(PNG_READ_INTERLACING_SUPPORTED)\r
832    /* blow up interlaced rows to full size */\r
833    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))\r
834    {\r
835       if (png_ptr->pass < 6)\r
836 /*       old interface (pre-1.0.9):\r
837          png_do_read_interlace(&(png_ptr->row_info),\r
838             png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);\r
839  */\r
840          png_do_read_interlace(png_ptr);\r
841 \r
842     switch (png_ptr->pass)\r
843     {\r
844          case 0:\r
845          {\r
846             int i;\r
847             for (i = 0; i < 8 && png_ptr->pass == 0; i++)\r
848             {\r
849                png_push_have_row(png_ptr, png_ptr->row_buf + 1);\r
850                png_read_push_finish_row(png_ptr); /* updates png_ptr->pass */\r
851             }\r
852             if (png_ptr->pass == 2) /* pass 1 might be empty */\r
853             {\r
854                for (i = 0; i < 4 && png_ptr->pass == 2; i++)\r
855                {\r
856                   png_push_have_row(png_ptr, png_bytep_NULL);\r
857                   png_read_push_finish_row(png_ptr);\r
858                }\r
859             }\r
860             if (png_ptr->pass == 4 && png_ptr->height <= 4)\r
861             {\r
862                for (i = 0; i < 2 && png_ptr->pass == 4; i++)\r
863                {\r
864                   png_push_have_row(png_ptr, png_bytep_NULL);\r
865                   png_read_push_finish_row(png_ptr);\r
866                }\r
867             }\r
868             if (png_ptr->pass == 6 && png_ptr->height <= 4)\r
869             {\r
870                 png_push_have_row(png_ptr, png_bytep_NULL);\r
871                 png_read_push_finish_row(png_ptr);\r
872             }\r
873             break;\r
874          }\r
875          case 1:\r
876          {\r
877             int i;\r
878             for (i = 0; i < 8 && png_ptr->pass == 1; i++)\r
879             {\r
880                png_push_have_row(png_ptr, png_ptr->row_buf + 1);\r
881                png_read_push_finish_row(png_ptr);\r
882             }\r
883             if (png_ptr->pass == 2) /* skip top 4 generated rows */\r
884             {\r
885                for (i = 0; i < 4 && png_ptr->pass == 2; i++)\r
886                {\r
887                   png_push_have_row(png_ptr, png_bytep_NULL);\r
888                   png_read_push_finish_row(png_ptr);\r
889                }\r
890             }\r
891             break;\r
892          }\r
893          case 2:\r
894          {\r
895             int i;\r
896             for (i = 0; i < 4 && png_ptr->pass == 2; i++)\r
897             {\r
898                png_push_have_row(png_ptr, png_ptr->row_buf + 1);\r
899                png_read_push_finish_row(png_ptr);\r
900             }\r
901             for (i = 0; i < 4 && png_ptr->pass == 2; i++)\r
902             {\r
903                png_push_have_row(png_ptr, png_bytep_NULL);\r
904                png_read_push_finish_row(png_ptr);\r
905             }\r
906             if (png_ptr->pass == 4) /* pass 3 might be empty */\r
907             {\r
908                for (i = 0; i < 2 && png_ptr->pass == 4; i++)\r
909                {\r
910                   png_push_have_row(png_ptr, png_bytep_NULL);\r
911                   png_read_push_finish_row(png_ptr);\r
912                }\r
913             }\r
914             break;\r
915          }\r
916          case 3:\r
917          {\r
918             int i;\r
919             for (i = 0; i < 4 && png_ptr->pass == 3; i++)\r
920             {\r
921                png_push_have_row(png_ptr, png_ptr->row_buf + 1);\r
922                png_read_push_finish_row(png_ptr);\r
923             }\r
924             if (png_ptr->pass == 4) /* skip top two generated rows */\r
925             {\r
926                for (i = 0; i < 2 && png_ptr->pass == 4; i++)\r
927                {\r
928                   png_push_have_row(png_ptr, png_bytep_NULL);\r
929                   png_read_push_finish_row(png_ptr);\r
930                }\r
931             }\r
932             break;\r
933          }\r
934          case 4:\r
935          {\r
936             int i;\r
937             for (i = 0; i < 2 && png_ptr->pass == 4; i++)\r
938             {\r
939                png_push_have_row(png_ptr, png_ptr->row_buf + 1);\r
940                png_read_push_finish_row(png_ptr);\r
941             }\r
942             for (i = 0; i < 2 && png_ptr->pass == 4; i++)\r
943             {\r
944                png_push_have_row(png_ptr, png_bytep_NULL);\r
945                png_read_push_finish_row(png_ptr);\r
946             }\r
947             if (png_ptr->pass == 6) /* pass 5 might be empty */\r
948             {\r
949                png_push_have_row(png_ptr, png_bytep_NULL);\r
950                png_read_push_finish_row(png_ptr);\r
951             }\r
952             break;\r
953          }\r
954          case 5:\r
955          {\r
956             int i;\r
957             for (i = 0; i < 2 && png_ptr->pass == 5; i++)\r
958             {\r
959                png_push_have_row(png_ptr, png_ptr->row_buf + 1);\r
960                png_read_push_finish_row(png_ptr);\r
961             }\r
962             if (png_ptr->pass == 6) /* skip top generated row */\r
963             {\r
964                png_push_have_row(png_ptr, png_bytep_NULL);\r
965                png_read_push_finish_row(png_ptr);\r
966             }\r
967             break;\r
968          }\r
969          case 6:\r
970          {\r
971             png_push_have_row(png_ptr, png_ptr->row_buf + 1);\r
972             png_read_push_finish_row(png_ptr);\r
973             if (png_ptr->pass != 6)\r
974                break;\r
975             png_push_have_row(png_ptr, png_bytep_NULL);\r
976             png_read_push_finish_row(png_ptr);\r
977          }\r
978       }\r
979    }\r
980    else\r
981 #endif\r
982    {\r
983       png_push_have_row(png_ptr, png_ptr->row_buf + 1);\r
984       png_read_push_finish_row(png_ptr);\r
985    }\r
986 }\r
987 \r
988 void /* PRIVATE */\r
989 png_read_push_finish_row(png_structp png_ptr)\r
990 {\r
991 #ifdef PNG_USE_LOCAL_ARRAYS\r
992    /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */\r
993 \r
994    /* start of interlace block */\r
995    PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};\r
996 \r
997    /* offset to next interlace block */\r
998    PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};\r
999 \r
1000    /* start of interlace block in the y direction */\r
1001    PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};\r
1002 \r
1003    /* offset to next interlace block in the y direction */\r
1004    PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};\r
1005 \r
1006    /* Height of interlace block.  This is not currently used - if you need\r
1007     * it, uncomment it here and in png.h\r
1008    PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};\r
1009    */\r
1010 #endif\r
1011 \r
1012    png_ptr->row_number++;\r
1013    if (png_ptr->row_number < png_ptr->num_rows)\r
1014       return;\r
1015 \r
1016    if (png_ptr->interlaced)\r
1017    {\r
1018       png_ptr->row_number = 0;\r
1019       png_memset_check(png_ptr, png_ptr->prev_row, 0,\r
1020          png_ptr->rowbytes + 1);\r
1021       do\r
1022       {\r
1023          png_ptr->pass++;\r
1024          if ((png_ptr->pass == 1 && png_ptr->width < 5) ||\r
1025              (png_ptr->pass == 3 && png_ptr->width < 3) ||\r
1026              (png_ptr->pass == 5 && png_ptr->width < 2))\r
1027            png_ptr->pass++;\r
1028 \r
1029          if (png_ptr->pass > 7)\r
1030             png_ptr->pass--;\r
1031          if (png_ptr->pass >= 7)\r
1032             break;\r
1033 \r
1034          png_ptr->iwidth = (png_ptr->width +\r
1035             png_pass_inc[png_ptr->pass] - 1 -\r
1036             png_pass_start[png_ptr->pass]) /\r
1037             png_pass_inc[png_ptr->pass];\r
1038 \r
1039          png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,\r
1040             png_ptr->iwidth) + 1;\r
1041 \r
1042          if (png_ptr->transformations & PNG_INTERLACE)\r
1043             break;\r
1044 \r
1045          png_ptr->num_rows = (png_ptr->height +\r
1046             png_pass_yinc[png_ptr->pass] - 1 -\r
1047             png_pass_ystart[png_ptr->pass]) /\r
1048             png_pass_yinc[png_ptr->pass];\r
1049 \r
1050       } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);\r
1051    }\r
1052 }\r
1053 \r
1054 #if defined(PNG_READ_tEXt_SUPPORTED)\r
1055 void /* PRIVATE */\r
1056 png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32\r
1057    length)\r
1058 {\r
1059    if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))\r
1060       {\r
1061          png_error(png_ptr, "Out of place tEXt");\r
1062          info_ptr = info_ptr; /* to quiet some compiler warnings */\r
1063       }\r
1064 \r
1065 #ifdef PNG_MAX_MALLOC_64K\r
1066    png_ptr->skip_length = 0;  /* This may not be necessary */\r
1067 \r
1068    if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */\r
1069    {\r
1070       png_warning(png_ptr, "tEXt chunk too large to fit in memory");\r
1071       png_ptr->skip_length = length - (png_uint_32)65535L;\r
1072       length = (png_uint_32)65535L;\r
1073    }\r
1074 #endif\r
1075 \r
1076    png_ptr->current_text = (png_charp)png_malloc(png_ptr,\r
1077       (png_uint_32)(length + 1));\r
1078    png_ptr->current_text[length] = '\0';\r
1079    png_ptr->current_text_ptr = png_ptr->current_text;\r
1080    png_ptr->current_text_size = (png_size_t)length;\r
1081    png_ptr->current_text_left = (png_size_t)length;\r
1082    png_ptr->process_mode = PNG_READ_tEXt_MODE;\r
1083 }\r
1084 \r
1085 void /* PRIVATE */\r
1086 png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)\r
1087 {\r
1088    if (png_ptr->buffer_size && png_ptr->current_text_left)\r
1089    {\r
1090       png_size_t text_size;\r
1091 \r
1092       if (png_ptr->buffer_size < png_ptr->current_text_left)\r
1093          text_size = png_ptr->buffer_size;\r
1094       else\r
1095          text_size = png_ptr->current_text_left;\r
1096       png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);\r
1097       png_ptr->current_text_left -= text_size;\r
1098       png_ptr->current_text_ptr += text_size;\r
1099    }\r
1100    if (!(png_ptr->current_text_left))\r
1101    {\r
1102       png_textp text_ptr;\r
1103       png_charp text;\r
1104       png_charp key;\r
1105       int ret;\r
1106 \r
1107       if (png_ptr->buffer_size < 4)\r
1108       {\r
1109          png_push_save_buffer(png_ptr);\r
1110          return;\r
1111       }\r
1112 \r
1113       png_push_crc_finish(png_ptr);\r
1114 \r
1115 #if defined(PNG_MAX_MALLOC_64K)\r
1116       if (png_ptr->skip_length)\r
1117          return;\r
1118 #endif\r
1119 \r
1120       key = png_ptr->current_text;\r
1121 \r
1122       for (text = key; *text; text++)\r
1123          /* empty loop */ ;\r
1124 \r
1125       if (text < key + png_ptr->current_text_size)\r
1126          text++;\r
1127 \r
1128       text_ptr = (png_textp)png_malloc(png_ptr,\r
1129          (png_uint_32)png_sizeof(png_text));\r
1130       text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;\r
1131       text_ptr->key = key;\r
1132 #ifdef PNG_iTXt_SUPPORTED\r
1133       text_ptr->lang = NULL;\r
1134       text_ptr->lang_key = NULL;\r
1135 #endif\r
1136       text_ptr->text = text;\r
1137 \r
1138       ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);\r
1139 \r
1140       png_free(png_ptr, key);\r
1141       png_free(png_ptr, text_ptr);\r
1142       png_ptr->current_text = NULL;\r
1143 \r
1144       if (ret)\r
1145         png_warning(png_ptr, "Insufficient memory to store text chunk.");\r
1146    }\r
1147 }\r
1148 #endif\r
1149 \r
1150 #if defined(PNG_READ_zTXt_SUPPORTED)\r
1151 void /* PRIVATE */\r
1152 png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32\r
1153    length)\r
1154 {\r
1155    if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))\r
1156       {\r
1157          png_error(png_ptr, "Out of place zTXt");\r
1158          info_ptr = info_ptr; /* to quiet some compiler warnings */\r
1159       }\r
1160 \r
1161 #ifdef PNG_MAX_MALLOC_64K\r
1162    /* We can't handle zTXt chunks > 64K, since we don't have enough space\r
1163     * to be able to store the uncompressed data.  Actually, the threshold\r
1164     * is probably around 32K, but it isn't as definite as 64K is.\r
1165     */\r
1166    if (length > (png_uint_32)65535L)\r
1167    {\r
1168       png_warning(png_ptr, "zTXt chunk too large to fit in memory");\r
1169       png_push_crc_skip(png_ptr, length);\r
1170       return;\r
1171    }\r
1172 #endif\r
1173 \r
1174    png_ptr->current_text = (png_charp)png_malloc(png_ptr,\r
1175       (png_uint_32)(length + 1));\r
1176    png_ptr->current_text[length] = '\0';\r
1177    png_ptr->current_text_ptr = png_ptr->current_text;\r
1178    png_ptr->current_text_size = (png_size_t)length;\r
1179    png_ptr->current_text_left = (png_size_t)length;\r
1180    png_ptr->process_mode = PNG_READ_zTXt_MODE;\r
1181 }\r
1182 \r
1183 void /* PRIVATE */\r
1184 png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)\r
1185 {\r
1186    if (png_ptr->buffer_size && png_ptr->current_text_left)\r
1187    {\r
1188       png_size_t text_size;\r
1189 \r
1190       if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)\r
1191          text_size = png_ptr->buffer_size;\r
1192       else\r
1193          text_size = png_ptr->current_text_left;\r
1194       png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);\r
1195       png_ptr->current_text_left -= text_size;\r
1196       png_ptr->current_text_ptr += text_size;\r
1197    }\r
1198    if (!(png_ptr->current_text_left))\r
1199    {\r
1200       png_textp text_ptr;\r
1201       png_charp text;\r
1202       png_charp key;\r
1203       int ret;\r
1204       png_size_t text_size, key_size;\r
1205 \r
1206       if (png_ptr->buffer_size < 4)\r
1207       {\r
1208          png_push_save_buffer(png_ptr);\r
1209          return;\r
1210       }\r
1211 \r
1212       png_push_crc_finish(png_ptr);\r
1213 \r
1214       key = png_ptr->current_text;\r
1215 \r
1216       for (text = key; *text; text++)\r
1217          /* empty loop */ ;\r
1218 \r
1219       /* zTXt can't have zero text */\r
1220       if (text >= key + png_ptr->current_text_size)\r
1221       {\r
1222          png_ptr->current_text = NULL;\r
1223          png_free(png_ptr, key);\r
1224          return;\r
1225       }\r
1226 \r
1227       text++;\r
1228 \r
1229       if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */\r
1230       {\r
1231          png_ptr->current_text = NULL;\r
1232          png_free(png_ptr, key);\r
1233          return;\r
1234       }\r
1235 \r
1236       text++;\r
1237 \r
1238       png_ptr->zstream.next_in = (png_bytep )text;\r
1239       png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -\r
1240          (text - key));\r
1241       png_ptr->zstream.next_out = png_ptr->zbuf;\r
1242       png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;\r
1243 \r
1244       key_size = text - key;\r
1245       text_size = 0;\r
1246       text = NULL;\r
1247       ret = Z_STREAM_END;\r
1248 \r
1249       while (png_ptr->zstream.avail_in)\r
1250       {\r
1251          ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);\r
1252          if (ret != Z_OK && ret != Z_STREAM_END)\r
1253          {\r
1254             inflateReset(&png_ptr->zstream);\r
1255             png_ptr->zstream.avail_in = 0;\r
1256             png_ptr->current_text = NULL;\r
1257             png_free(png_ptr, key);\r
1258             png_free(png_ptr, text);\r
1259             return;\r
1260          }\r
1261          if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)\r
1262          {\r
1263             if (text == NULL)\r
1264             {\r
1265                text = (png_charp)png_malloc(png_ptr,\r
1266                      (png_uint_32)(png_ptr->zbuf_size\r
1267                      - png_ptr->zstream.avail_out + key_size + 1));\r
1268                png_memcpy(text + key_size, png_ptr->zbuf,\r
1269                   png_ptr->zbuf_size - png_ptr->zstream.avail_out);\r
1270                png_memcpy(text, key, key_size);\r
1271                text_size = key_size + png_ptr->zbuf_size -\r
1272                   png_ptr->zstream.avail_out;\r
1273                *(text + text_size) = '\0';\r
1274             }\r
1275             else\r
1276             {\r
1277                png_charp tmp;\r
1278 \r
1279                tmp = text;\r
1280                text = (png_charp)png_malloc(png_ptr, text_size +\r
1281                   (png_uint_32)(png_ptr->zbuf_size \r
1282                   - png_ptr->zstream.avail_out + 1));\r
1283                png_memcpy(text, tmp, text_size);\r
1284                png_free(png_ptr, tmp);\r
1285                png_memcpy(text + text_size, png_ptr->zbuf,\r
1286                   png_ptr->zbuf_size - png_ptr->zstream.avail_out);\r
1287                text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;\r
1288                *(text + text_size) = '\0';\r
1289             }\r
1290             if (ret != Z_STREAM_END)\r
1291             {\r
1292                png_ptr->zstream.next_out = png_ptr->zbuf;\r
1293                png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;\r
1294             }\r
1295          }\r
1296          else\r
1297          {\r
1298             break;\r
1299          }\r
1300 \r
1301          if (ret == Z_STREAM_END)\r
1302             break;\r
1303       }\r
1304 \r
1305       inflateReset(&png_ptr->zstream);\r
1306       png_ptr->zstream.avail_in = 0;\r
1307 \r
1308       if (ret != Z_STREAM_END)\r
1309       {\r
1310          png_ptr->current_text = NULL;\r
1311          png_free(png_ptr, key);\r
1312          png_free(png_ptr, text);\r
1313          return;\r
1314       }\r
1315 \r
1316       png_ptr->current_text = NULL;\r
1317       png_free(png_ptr, key);\r
1318       key = text;\r
1319       text += key_size;\r
1320 \r
1321       text_ptr = (png_textp)png_malloc(png_ptr,\r
1322           (png_uint_32)png_sizeof(png_text));\r
1323       text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;\r
1324       text_ptr->key = key;\r
1325 #ifdef PNG_iTXt_SUPPORTED\r
1326       text_ptr->lang = NULL;\r
1327       text_ptr->lang_key = NULL;\r
1328 #endif\r
1329       text_ptr->text = text;\r
1330 \r
1331       ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);\r
1332 \r
1333       png_free(png_ptr, key);\r
1334       png_free(png_ptr, text_ptr);\r
1335 \r
1336       if (ret)\r
1337         png_warning(png_ptr, "Insufficient memory to store text chunk.");\r
1338    }\r
1339 }\r
1340 #endif\r
1341 \r
1342 #if defined(PNG_READ_iTXt_SUPPORTED)\r
1343 void /* PRIVATE */\r
1344 png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32\r
1345    length)\r
1346 {\r
1347    if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))\r
1348       {\r
1349          png_error(png_ptr, "Out of place iTXt");\r
1350          info_ptr = info_ptr; /* to quiet some compiler warnings */\r
1351       }\r
1352 \r
1353 #ifdef PNG_MAX_MALLOC_64K\r
1354    png_ptr->skip_length = 0;  /* This may not be necessary */\r
1355 \r
1356    if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */\r
1357    {\r
1358       png_warning(png_ptr, "iTXt chunk too large to fit in memory");\r
1359       png_ptr->skip_length = length - (png_uint_32)65535L;\r
1360       length = (png_uint_32)65535L;\r
1361    }\r
1362 #endif\r
1363 \r
1364    png_ptr->current_text = (png_charp)png_malloc(png_ptr,\r
1365       (png_uint_32)(length + 1));\r
1366    png_ptr->current_text[length] = '\0';\r
1367    png_ptr->current_text_ptr = png_ptr->current_text;\r
1368    png_ptr->current_text_size = (png_size_t)length;\r
1369    png_ptr->current_text_left = (png_size_t)length;\r
1370    png_ptr->process_mode = PNG_READ_iTXt_MODE;\r
1371 }\r
1372 \r
1373 void /* PRIVATE */\r
1374 png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr)\r
1375 {\r
1376 \r
1377    if (png_ptr->buffer_size && png_ptr->current_text_left)\r
1378    {\r
1379       png_size_t text_size;\r
1380 \r
1381       if (png_ptr->buffer_size < png_ptr->current_text_left)\r
1382          text_size = png_ptr->buffer_size;\r
1383       else\r
1384          text_size = png_ptr->current_text_left;\r
1385       png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);\r
1386       png_ptr->current_text_left -= text_size;\r
1387       png_ptr->current_text_ptr += text_size;\r
1388    }\r
1389    if (!(png_ptr->current_text_left))\r
1390    {\r
1391       png_textp text_ptr;\r
1392       png_charp key;\r
1393       int comp_flag;\r
1394       png_charp lang;\r
1395       png_charp lang_key;\r
1396       png_charp text;\r
1397       int ret;\r
1398 \r
1399       if (png_ptr->buffer_size < 4)\r
1400       {\r
1401          png_push_save_buffer(png_ptr);\r
1402          return;\r
1403       }\r
1404 \r
1405       png_push_crc_finish(png_ptr);\r
1406 \r
1407 #if defined(PNG_MAX_MALLOC_64K)\r
1408       if (png_ptr->skip_length)\r
1409          return;\r
1410 #endif\r
1411 \r
1412       key = png_ptr->current_text;\r
1413 \r
1414       for (lang = key; *lang; lang++)\r
1415          /* empty loop */ ;\r
1416 \r
1417       if (lang < key + png_ptr->current_text_size - 3)\r
1418          lang++;\r
1419 \r
1420       comp_flag = *lang++;\r
1421       lang++;     /* skip comp_type, always zero */\r
1422 \r
1423       for (lang_key = lang; *lang_key; lang_key++)\r
1424          /* empty loop */ ;\r
1425       lang_key++;        /* skip NUL separator */\r
1426 \r
1427       text=lang_key;\r
1428       if (lang_key < key + png_ptr->current_text_size - 1)\r
1429       {\r
1430         for (; *text; text++)\r
1431            /* empty loop */ ;\r
1432       }\r
1433 \r
1434       if (text < key + png_ptr->current_text_size)\r
1435          text++;\r
1436 \r
1437       text_ptr = (png_textp)png_malloc(png_ptr,\r
1438          (png_uint_32)png_sizeof(png_text));\r
1439       text_ptr->compression = comp_flag + 2;\r
1440       text_ptr->key = key;\r
1441       text_ptr->lang = lang;\r
1442       text_ptr->lang_key = lang_key;\r
1443       text_ptr->text = text;\r
1444       text_ptr->text_length = 0;\r
1445       text_ptr->itxt_length = png_strlen(text);\r
1446 \r
1447       ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);\r
1448 \r
1449       png_ptr->current_text = NULL;\r
1450 \r
1451       png_free(png_ptr, text_ptr);\r
1452       if (ret)\r
1453         png_warning(png_ptr, "Insufficient memory to store iTXt chunk.");\r
1454    }\r
1455 }\r
1456 #endif\r
1457 \r
1458 /* This function is called when we haven't found a handler for this\r
1459  * chunk.  If there isn't a problem with the chunk itself (ie a bad chunk\r
1460  * name or a critical chunk), the chunk is (currently) silently ignored.\r
1461  */\r
1462 void /* PRIVATE */\r
1463 png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32\r
1464    length)\r
1465 {\r
1466    png_uint_32 skip = 0;\r
1467 \r
1468    if (!(png_ptr->chunk_name[0] & 0x20))\r
1469    {\r
1470 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)\r
1471       if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=\r
1472          PNG_HANDLE_CHUNK_ALWAYS\r
1473 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)\r
1474          && png_ptr->read_user_chunk_fn == NULL\r
1475 #endif\r
1476          )\r
1477 #endif\r
1478          png_chunk_error(png_ptr, "unknown critical chunk");\r
1479 \r
1480       info_ptr = info_ptr; /* to quiet some compiler warnings */\r
1481    }\r
1482 \r
1483 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)\r
1484    if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)\r
1485    {\r
1486 #ifdef PNG_MAX_MALLOC_64K\r
1487       if (length > (png_uint_32)65535L)\r
1488       {\r
1489           png_warning(png_ptr, "unknown chunk too large to fit in memory");\r
1490           skip = length - (png_uint_32)65535L;\r
1491           length = (png_uint_32)65535L;\r
1492       }\r
1493 #endif\r
1494       png_memcpy((png_charp)png_ptr->unknown_chunk.name,\r
1495                  (png_charp)png_ptr->chunk_name, \r
1496                  png_sizeof(png_ptr->unknown_chunk.name));\r
1497       png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1]\r
1498         = '\0';\r
1499 \r
1500       png_ptr->unknown_chunk.size = (png_size_t)length;\r
1501       if (length == 0)\r
1502          png_ptr->unknown_chunk.data = NULL;\r
1503       else\r
1504       {\r
1505          png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr,\r
1506        (png_uint_32)length);\r
1507          png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);\r
1508       }\r
1509 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)\r
1510       if (png_ptr->read_user_chunk_fn != NULL)\r
1511       {\r
1512          /* callback to user unknown chunk handler */\r
1513          int ret;\r
1514          ret = (*(png_ptr->read_user_chunk_fn))\r
1515            (png_ptr, &png_ptr->unknown_chunk);\r
1516          if (ret < 0)\r
1517             png_chunk_error(png_ptr, "error in user chunk");\r
1518          if (ret == 0)\r
1519          {\r
1520             if (!(png_ptr->chunk_name[0] & 0x20))\r
1521                if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=\r
1522                     PNG_HANDLE_CHUNK_ALWAYS)\r
1523                   png_chunk_error(png_ptr, "unknown critical chunk");\r
1524             png_set_unknown_chunks(png_ptr, info_ptr,\r
1525                &png_ptr->unknown_chunk, 1);\r
1526          }\r
1527       }\r
1528       else\r
1529 #endif\r
1530         png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);\r
1531       png_free(png_ptr, png_ptr->unknown_chunk.data);\r
1532       png_ptr->unknown_chunk.data = NULL;\r
1533    }\r
1534    else\r
1535 #endif\r
1536       skip=length;\r
1537    png_push_crc_skip(png_ptr, skip);\r
1538 }\r
1539 \r
1540 void /* PRIVATE */\r
1541 png_push_have_info(png_structp png_ptr, png_infop info_ptr)\r
1542 {\r
1543    if (png_ptr->info_fn != NULL)\r
1544       (*(png_ptr->info_fn))(png_ptr, info_ptr);\r
1545 }\r
1546 \r
1547 void /* PRIVATE */\r
1548 png_push_have_end(png_structp png_ptr, png_infop info_ptr)\r
1549 {\r
1550    if (png_ptr->end_fn != NULL)\r
1551       (*(png_ptr->end_fn))(png_ptr, info_ptr);\r
1552 }\r
1553 \r
1554 void /* PRIVATE */\r
1555 png_push_have_row(png_structp png_ptr, png_bytep row)\r
1556 {\r
1557    if (png_ptr->row_fn != NULL)\r
1558       (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,\r
1559          (int)png_ptr->pass);\r
1560 }\r
1561 \r
1562 void PNGAPI\r
1563 png_progressive_combine_row (png_structp png_ptr,\r
1564    png_bytep old_row, png_bytep new_row)\r
1565 {\r
1566 #ifdef PNG_USE_LOCAL_ARRAYS\r
1567    PNG_CONST int FARDATA png_pass_dsp_mask[7] =\r
1568       {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};\r
1569 #endif\r
1570    if (png_ptr == NULL) return;\r
1571    if (new_row != NULL)    /* new_row must == png_ptr->row_buf here. */\r
1572       png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);\r
1573 }\r
1574 \r
1575 void PNGAPI\r
1576 png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,\r
1577    png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,\r
1578    png_progressive_end_ptr end_fn)\r
1579 {\r
1580    if (png_ptr == NULL) return;\r
1581    png_ptr->info_fn = info_fn;\r
1582    png_ptr->row_fn = row_fn;\r
1583    png_ptr->end_fn = end_fn;\r
1584 \r
1585    png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);\r
1586 }\r
1587 \r
1588 png_voidp PNGAPI\r
1589 png_get_progressive_ptr(png_structp png_ptr)\r
1590 {\r
1591    if (png_ptr == NULL) return (NULL);\r
1592    return png_ptr->io_ptr;\r
1593 }\r
1594 #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */\r