fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

pngpread.c

Go to the documentation of this file.
00001 
00002 /* pngpread.c - read a png file in push mode
00003  *
00004  * Last changed in libpng 1.2.38 [July 16, 2009]
00005  * Copyright (c) 1998-2009 Glenn Randers-Pehrson
00006  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
00007  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
00008  *
00009  * This code is released under the libpng license.
00010  * For conditions of distribution and use, see the disclaimer
00011  * and license in png.h
00012  */
00013 
00014 #define PNG_INTERNAL
00015 #include "png.h"
00016 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
00017 
00018 /* Push model modes */
00019 #define PNG_READ_SIG_MODE   0
00020 #define PNG_READ_CHUNK_MODE 1
00021 #define PNG_READ_IDAT_MODE  2
00022 #define PNG_SKIP_MODE       3
00023 #define PNG_READ_tEXt_MODE  4
00024 #define PNG_READ_zTXt_MODE  5
00025 #define PNG_READ_DONE_MODE  6
00026 #define PNG_READ_iTXt_MODE  7
00027 #define PNG_ERROR_MODE      8
00028 
00029 void PNGAPI
00030 png_process_data(png_structp png_ptr, png_infop info_ptr,
00031    png_bytep buffer, png_size_t buffer_size)
00032 {
00033    if (png_ptr == NULL || info_ptr == NULL)
00034       return;
00035 
00036    png_push_restore_buffer(png_ptr, buffer, buffer_size);
00037 
00038    while (png_ptr->buffer_size)
00039    {
00040       png_process_some_data(png_ptr, info_ptr);
00041    }
00042 }
00043 
00044 /* What we do with the incoming data depends on what we were previously
00045  * doing before we ran out of data...
00046  */
00047 void /* PRIVATE */
00048 png_process_some_data(png_structp png_ptr, png_infop info_ptr)
00049 {
00050    if (png_ptr == NULL)
00051       return;
00052 
00053    switch (png_ptr->process_mode)
00054    {
00055       case PNG_READ_SIG_MODE:
00056       {
00057          png_push_read_sig(png_ptr, info_ptr);
00058          break;
00059       }
00060 
00061       case PNG_READ_CHUNK_MODE:
00062       {
00063          png_push_read_chunk(png_ptr, info_ptr);
00064          break;
00065       }
00066 
00067       case PNG_READ_IDAT_MODE:
00068       {
00069          png_push_read_IDAT(png_ptr);
00070          break;
00071       }
00072 
00073 #if defined(PNG_READ_tEXt_SUPPORTED)
00074       case PNG_READ_tEXt_MODE:
00075       {
00076          png_push_read_tEXt(png_ptr, info_ptr);
00077          break;
00078       }
00079 
00080 #endif
00081 #if defined(PNG_READ_zTXt_SUPPORTED)
00082       case PNG_READ_zTXt_MODE:
00083       {
00084          png_push_read_zTXt(png_ptr, info_ptr);
00085          break;
00086       }
00087 
00088 #endif
00089 #if defined(PNG_READ_iTXt_SUPPORTED)
00090       case PNG_READ_iTXt_MODE:
00091       {
00092          png_push_read_iTXt(png_ptr, info_ptr);
00093          break;
00094       }
00095 
00096 #endif
00097       case PNG_SKIP_MODE:
00098       {
00099          png_push_crc_finish(png_ptr);
00100          break;
00101       }
00102 
00103       default:
00104       {
00105          png_ptr->buffer_size = 0;
00106          break;
00107       }
00108    }
00109 }
00110 
00111 /* Read any remaining signature bytes from the stream and compare them with
00112  * the correct PNG signature.  It is possible that this routine is called
00113  * with bytes already read from the signature, either because they have been
00114  * checked by the calling application, or because of multiple calls to this
00115  * routine.
00116  */
00117 void /* PRIVATE */
00118 png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
00119 {
00120    png_size_t num_checked = png_ptr->sig_bytes,
00121              num_to_check = 8 - num_checked;
00122 
00123    if (png_ptr->buffer_size < num_to_check)
00124    {
00125       num_to_check = png_ptr->buffer_size;
00126    }
00127 
00128    png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
00129       num_to_check);
00130    png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
00131 
00132    if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
00133    {
00134       if (num_checked < 4 &&
00135           png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
00136          png_error(png_ptr, "Not a PNG file");
00137       else
00138          png_error(png_ptr, "PNG file corrupted by ASCII conversion");
00139    }
00140    else
00141    {
00142       if (png_ptr->sig_bytes >= 8)
00143       {
00144          png_ptr->process_mode = PNG_READ_CHUNK_MODE;
00145       }
00146    }
00147 }
00148 
00149 void /* PRIVATE */
00150 png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
00151 {
00152 #ifdef PNG_USE_LOCAL_ARRAYS
00153       PNG_CONST PNG_IHDR;
00154       PNG_CONST PNG_IDAT;
00155       PNG_CONST PNG_IEND;
00156       PNG_CONST PNG_PLTE;
00157 #if defined(PNG_READ_bKGD_SUPPORTED)
00158       PNG_CONST PNG_bKGD;
00159 #endif
00160 #if defined(PNG_READ_cHRM_SUPPORTED)
00161       PNG_CONST PNG_cHRM;
00162 #endif
00163 #if defined(PNG_READ_gAMA_SUPPORTED)
00164       PNG_CONST PNG_gAMA;
00165 #endif
00166 #if defined(PNG_READ_hIST_SUPPORTED)
00167       PNG_CONST PNG_hIST;
00168 #endif
00169 #if defined(PNG_READ_iCCP_SUPPORTED)
00170       PNG_CONST PNG_iCCP;
00171 #endif
00172 #if defined(PNG_READ_iTXt_SUPPORTED)
00173       PNG_CONST PNG_iTXt;
00174 #endif
00175 #if defined(PNG_READ_oFFs_SUPPORTED)
00176       PNG_CONST PNG_oFFs;
00177 #endif
00178 #if defined(PNG_READ_pCAL_SUPPORTED)
00179       PNG_CONST PNG_pCAL;
00180 #endif
00181 #if defined(PNG_READ_pHYs_SUPPORTED)
00182       PNG_CONST PNG_pHYs;
00183 #endif
00184 #if defined(PNG_READ_sBIT_SUPPORTED)
00185       PNG_CONST PNG_sBIT;
00186 #endif
00187 #if defined(PNG_READ_sCAL_SUPPORTED)
00188       PNG_CONST PNG_sCAL;
00189 #endif
00190 #if defined(PNG_READ_sRGB_SUPPORTED)
00191       PNG_CONST PNG_sRGB;
00192 #endif
00193 #if defined(PNG_READ_sPLT_SUPPORTED)
00194       PNG_CONST PNG_sPLT;
00195 #endif
00196 #if defined(PNG_READ_tEXt_SUPPORTED)
00197       PNG_CONST PNG_tEXt;
00198 #endif
00199 #if defined(PNG_READ_tIME_SUPPORTED)
00200       PNG_CONST PNG_tIME;
00201 #endif
00202 #if defined(PNG_READ_tRNS_SUPPORTED)
00203       PNG_CONST PNG_tRNS;
00204 #endif
00205 #if defined(PNG_READ_zTXt_SUPPORTED)
00206       PNG_CONST PNG_zTXt;
00207 #endif
00208 #endif /* PNG_USE_LOCAL_ARRAYS */
00209    /* First we make sure we have enough data for the 4 byte chunk name
00210     * and the 4 byte chunk length before proceeding with decoding the
00211     * chunk data.  To fully decode each of these chunks, we also make
00212     * sure we have enough data in the buffer for the 4 byte CRC at the
00213     * end of every chunk (except IDAT, which is handled separately).
00214     */
00215    if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
00216    {
00217       png_byte chunk_length[4];
00218 
00219       if (png_ptr->buffer_size < 8)
00220       {
00221          png_push_save_buffer(png_ptr);
00222          return;
00223       }
00224 
00225       png_push_fill_buffer(png_ptr, chunk_length, 4);
00226       png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
00227       png_reset_crc(png_ptr);
00228       png_crc_read(png_ptr, png_ptr->chunk_name, 4);
00229       png_check_chunk_name(png_ptr, png_ptr->chunk_name);
00230       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
00231    }
00232 
00233    if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
00234      if (png_ptr->mode & PNG_AFTER_IDAT)
00235         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
00236 
00237    if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
00238    {
00239       if (png_ptr->push_length != 13)
00240          png_error(png_ptr, "Invalid IHDR length");
00241 
00242       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00243       {
00244          png_push_save_buffer(png_ptr);
00245          return;
00246       }
00247 
00248       png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
00249    }
00250 
00251    else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
00252    {
00253       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00254       {
00255          png_push_save_buffer(png_ptr);
00256          return;
00257       }
00258 
00259       png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
00260 
00261       png_ptr->process_mode = PNG_READ_DONE_MODE;
00262       png_push_have_end(png_ptr, info_ptr);
00263    }
00264 
00265 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
00266    else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
00267    {
00268       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00269       {
00270          png_push_save_buffer(png_ptr);
00271          return;
00272       }
00273 
00274       if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
00275          png_ptr->mode |= PNG_HAVE_IDAT;
00276 
00277       png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
00278 
00279       if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
00280          png_ptr->mode |= PNG_HAVE_PLTE;
00281 
00282       else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
00283       {
00284          if (!(png_ptr->mode & PNG_HAVE_IHDR))
00285             png_error(png_ptr, "Missing IHDR before IDAT");
00286 
00287          else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
00288                   !(png_ptr->mode & PNG_HAVE_PLTE))
00289             png_error(png_ptr, "Missing PLTE before IDAT");
00290       }
00291    }
00292 
00293 #endif
00294    else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
00295    {
00296       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00297       {
00298          png_push_save_buffer(png_ptr);
00299          return;
00300       }
00301       png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
00302    }
00303 
00304    else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
00305    {
00306       /* If we reach an IDAT chunk, this means we have read all of the
00307        * header chunks, and we can start reading the image (or if this
00308        * is called after the image has been read - we have an error).
00309        */
00310 
00311       if (!(png_ptr->mode & PNG_HAVE_IHDR))
00312          png_error(png_ptr, "Missing IHDR before IDAT");
00313 
00314       else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
00315           !(png_ptr->mode & PNG_HAVE_PLTE))
00316          png_error(png_ptr, "Missing PLTE before IDAT");
00317 
00318       if (png_ptr->mode & PNG_HAVE_IDAT)
00319       {
00320          if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
00321             if (png_ptr->push_length == 0)
00322                return;
00323 
00324          if (png_ptr->mode & PNG_AFTER_IDAT)
00325             png_error(png_ptr, "Too many IDAT's found");
00326       }
00327 
00328       png_ptr->idat_size = png_ptr->push_length;
00329       png_ptr->mode |= PNG_HAVE_IDAT;
00330       png_ptr->process_mode = PNG_READ_IDAT_MODE;
00331       png_push_have_info(png_ptr, info_ptr);
00332       png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
00333       png_ptr->zstream.next_out = png_ptr->row_buf;
00334       return;
00335    }
00336 
00337 #if defined(PNG_READ_gAMA_SUPPORTED)
00338    else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
00339    {
00340       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00341       {
00342          png_push_save_buffer(png_ptr);
00343          return;
00344       }
00345 
00346       png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
00347    }
00348 
00349 #endif
00350 #if defined(PNG_READ_sBIT_SUPPORTED)
00351    else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
00352    {
00353       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00354       {
00355          png_push_save_buffer(png_ptr);
00356          return;
00357       }
00358 
00359       png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
00360    }
00361 
00362 #endif
00363 #if defined(PNG_READ_cHRM_SUPPORTED)
00364    else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
00365    {
00366       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00367       {
00368          png_push_save_buffer(png_ptr);
00369          return;
00370       }
00371 
00372       png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
00373    }
00374 
00375 #endif
00376 #if defined(PNG_READ_sRGB_SUPPORTED)
00377    else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
00378    {
00379       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00380       {
00381          png_push_save_buffer(png_ptr);
00382          return;
00383       }
00384 
00385       png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
00386    }
00387 
00388 #endif
00389 #if defined(PNG_READ_iCCP_SUPPORTED)
00390    else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
00391    {
00392       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00393       {
00394          png_push_save_buffer(png_ptr);
00395          return;
00396       }
00397 
00398       png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
00399    }
00400 
00401 #endif
00402 #if defined(PNG_READ_sPLT_SUPPORTED)
00403    else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
00404    {
00405       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00406       {
00407          png_push_save_buffer(png_ptr);
00408          return;
00409       }
00410 
00411       png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
00412    }
00413 
00414 #endif
00415 #if defined(PNG_READ_tRNS_SUPPORTED)
00416    else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
00417    {
00418       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00419       {
00420          png_push_save_buffer(png_ptr);
00421          return;
00422       }
00423 
00424       png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
00425    }
00426 
00427 #endif
00428 #if defined(PNG_READ_bKGD_SUPPORTED)
00429    else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
00430    {
00431       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00432       {
00433          png_push_save_buffer(png_ptr);
00434          return;
00435       }
00436 
00437       png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
00438    }
00439 
00440 #endif
00441 #if defined(PNG_READ_hIST_SUPPORTED)
00442    else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
00443    {
00444       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00445       {
00446          png_push_save_buffer(png_ptr);
00447          return;
00448       }
00449 
00450       png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
00451    }
00452 
00453 #endif
00454 #if defined(PNG_READ_pHYs_SUPPORTED)
00455    else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
00456    {
00457       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00458       {
00459          png_push_save_buffer(png_ptr);
00460          return;
00461       }
00462 
00463       png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
00464    }
00465 
00466 #endif
00467 #if defined(PNG_READ_oFFs_SUPPORTED)
00468    else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
00469    {
00470       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00471       {
00472          png_push_save_buffer(png_ptr);
00473          return;
00474       }
00475 
00476       png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
00477    }
00478 #endif
00479 
00480 #if defined(PNG_READ_pCAL_SUPPORTED)
00481    else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
00482    {
00483       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00484       {
00485          png_push_save_buffer(png_ptr);
00486          return;
00487       }
00488 
00489       png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
00490    }
00491 
00492 #endif
00493 #if defined(PNG_READ_sCAL_SUPPORTED)
00494    else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
00495    {
00496       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00497       {
00498          png_push_save_buffer(png_ptr);
00499          return;
00500       }
00501 
00502       png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
00503    }
00504 
00505 #endif
00506 #if defined(PNG_READ_tIME_SUPPORTED)
00507    else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
00508    {
00509       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00510       {
00511          png_push_save_buffer(png_ptr);
00512          return;
00513       }
00514 
00515       png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
00516    }
00517 
00518 #endif
00519 #if defined(PNG_READ_tEXt_SUPPORTED)
00520    else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
00521    {
00522       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00523       {
00524          png_push_save_buffer(png_ptr);
00525          return;
00526       }
00527 
00528       png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
00529    }
00530 
00531 #endif
00532 #if defined(PNG_READ_zTXt_SUPPORTED)
00533    else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
00534    {
00535       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00536       {
00537          png_push_save_buffer(png_ptr);
00538          return;
00539       }
00540 
00541       png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
00542    }
00543 
00544 #endif
00545 #if defined(PNG_READ_iTXt_SUPPORTED)
00546    else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
00547    {
00548       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00549       {
00550          png_push_save_buffer(png_ptr);
00551          return;
00552       }
00553 
00554       png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
00555    }
00556 
00557 #endif
00558    else
00559    {
00560       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00561       {
00562          png_push_save_buffer(png_ptr);
00563          return;
00564       }
00565       png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
00566    }
00567 
00568    png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
00569 }
00570 
00571 void /* PRIVATE */
00572 png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
00573 {
00574    png_ptr->process_mode = PNG_SKIP_MODE;
00575    png_ptr->skip_length = skip;
00576 }
00577 
00578 void /* PRIVATE */
00579 png_push_crc_finish(png_structp png_ptr)
00580 {
00581    if (png_ptr->skip_length && png_ptr->save_buffer_size)
00582    {
00583       png_size_t save_size;
00584 
00585       if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size)
00586          save_size = (png_size_t)png_ptr->skip_length;
00587       else
00588          save_size = png_ptr->save_buffer_size;
00589 
00590       png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
00591 
00592       png_ptr->skip_length -= save_size;
00593       png_ptr->buffer_size -= save_size;
00594       png_ptr->save_buffer_size -= save_size;
00595       png_ptr->save_buffer_ptr += save_size;
00596    }
00597    if (png_ptr->skip_length && png_ptr->current_buffer_size)
00598    {
00599       png_size_t save_size;
00600 
00601       if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size)
00602          save_size = (png_size_t)png_ptr->skip_length;
00603       else
00604          save_size = png_ptr->current_buffer_size;
00605 
00606       png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
00607 
00608       png_ptr->skip_length -= save_size;
00609       png_ptr->buffer_size -= save_size;
00610       png_ptr->current_buffer_size -= save_size;
00611       png_ptr->current_buffer_ptr += save_size;
00612    }
00613    if (!png_ptr->skip_length)
00614    {
00615       if (png_ptr->buffer_size < 4)
00616       {
00617          png_push_save_buffer(png_ptr);
00618          return;
00619       }
00620 
00621       png_crc_finish(png_ptr, 0);
00622       png_ptr->process_mode = PNG_READ_CHUNK_MODE;
00623    }
00624 }
00625 
00626 void PNGAPI
00627 png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
00628 {
00629    png_bytep ptr;
00630 
00631    if (png_ptr == NULL)
00632       return;
00633 
00634    ptr = buffer;
00635    if (png_ptr->save_buffer_size)
00636    {
00637       png_size_t save_size;
00638 
00639       if (length < png_ptr->save_buffer_size)
00640          save_size = length;
00641       else
00642          save_size = png_ptr->save_buffer_size;
00643 
00644       png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
00645       length -= save_size;
00646       ptr += save_size;
00647       png_ptr->buffer_size -= save_size;
00648       png_ptr->save_buffer_size -= save_size;
00649       png_ptr->save_buffer_ptr += save_size;
00650    }
00651    if (length && png_ptr->current_buffer_size)
00652    {
00653       png_size_t save_size;
00654 
00655       if (length < png_ptr->current_buffer_size)
00656          save_size = length;
00657 
00658       else
00659          save_size = png_ptr->current_buffer_size;
00660 
00661       png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
00662       png_ptr->buffer_size -= save_size;
00663       png_ptr->current_buffer_size -= save_size;
00664       png_ptr->current_buffer_ptr += save_size;
00665    }
00666 }
00667 
00668 void /* PRIVATE */
00669 png_push_save_buffer(png_structp png_ptr)
00670 {
00671    if (png_ptr->save_buffer_size)
00672    {
00673       if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
00674       {
00675          png_size_t i, istop;
00676          png_bytep sp;
00677          png_bytep dp;
00678 
00679          istop = png_ptr->save_buffer_size;
00680          for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
00681             i < istop; i++, sp++, dp++)
00682          {
00683             *dp = *sp;
00684          }
00685       }
00686    }
00687    if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
00688       png_ptr->save_buffer_max)
00689    {
00690       png_size_t new_max;
00691       png_bytep old_buffer;
00692 
00693       if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
00694          (png_ptr->current_buffer_size + 256))
00695       {
00696         png_error(png_ptr, "Potential overflow of save_buffer");
00697       }
00698 
00699       new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
00700       old_buffer = png_ptr->save_buffer;
00701       png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr,
00702          (png_uint_32)new_max);
00703       png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
00704       png_free(png_ptr, old_buffer);
00705       png_ptr->save_buffer_max = new_max;
00706    }
00707    if (png_ptr->current_buffer_size)
00708    {
00709       png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
00710          png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
00711       png_ptr->save_buffer_size += png_ptr->current_buffer_size;
00712       png_ptr->current_buffer_size = 0;
00713    }
00714    png_ptr->save_buffer_ptr = png_ptr->save_buffer;
00715    png_ptr->buffer_size = 0;
00716 }
00717 
00718 void /* PRIVATE */
00719 png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
00720    png_size_t buffer_length)
00721 {
00722    png_ptr->current_buffer = buffer;
00723    png_ptr->current_buffer_size = buffer_length;
00724    png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
00725    png_ptr->current_buffer_ptr = png_ptr->current_buffer;
00726 }
00727 
00728 void /* PRIVATE */
00729 png_push_read_IDAT(png_structp png_ptr)
00730 {
00731 #ifdef PNG_USE_LOCAL_ARRAYS
00732    PNG_CONST PNG_IDAT;
00733 #endif
00734    if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
00735    {
00736       png_byte chunk_length[4];
00737 
00738       if (png_ptr->buffer_size < 8)
00739       {
00740          png_push_save_buffer(png_ptr);
00741          return;
00742       }
00743 
00744       png_push_fill_buffer(png_ptr, chunk_length, 4);
00745       png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
00746       png_reset_crc(png_ptr);
00747       png_crc_read(png_ptr, png_ptr->chunk_name, 4);
00748       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
00749 
00750       if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
00751       {
00752          png_ptr->process_mode = PNG_READ_CHUNK_MODE;
00753          if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
00754             png_error(png_ptr, "Not enough compressed data");
00755          return;
00756       }
00757 
00758       png_ptr->idat_size = png_ptr->push_length;
00759    }
00760    if (png_ptr->idat_size && png_ptr->save_buffer_size)
00761    {
00762       png_size_t save_size;
00763 
00764       if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
00765       {
00766          save_size = (png_size_t)png_ptr->idat_size;
00767 
00768          /* Check for overflow */
00769          if ((png_uint_32)save_size != png_ptr->idat_size)
00770             png_error(png_ptr, "save_size overflowed in pngpread");
00771       }
00772       else
00773          save_size = png_ptr->save_buffer_size;
00774 
00775       png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
00776 
00777       if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
00778          png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
00779 
00780       png_ptr->idat_size -= save_size;
00781       png_ptr->buffer_size -= save_size;
00782       png_ptr->save_buffer_size -= save_size;
00783       png_ptr->save_buffer_ptr += save_size;
00784    }
00785    if (png_ptr->idat_size && png_ptr->current_buffer_size)
00786    {
00787       png_size_t save_size;
00788 
00789       if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
00790       {
00791          save_size = (png_size_t)png_ptr->idat_size;
00792 
00793          /* Check for overflow */
00794          if ((png_uint_32)save_size != png_ptr->idat_size)
00795             png_error(png_ptr, "save_size overflowed in pngpread");
00796       }
00797       else
00798          save_size = png_ptr->current_buffer_size;
00799 
00800       png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
00801       if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
00802         png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
00803 
00804       png_ptr->idat_size -= save_size;
00805       png_ptr->buffer_size -= save_size;
00806       png_ptr->current_buffer_size -= save_size;
00807       png_ptr->current_buffer_ptr += save_size;
00808    }
00809    if (!png_ptr->idat_size)
00810    {
00811       if (png_ptr->buffer_size < 4)
00812       {
00813          png_push_save_buffer(png_ptr);
00814          return;
00815       }
00816 
00817       png_crc_finish(png_ptr, 0);
00818       png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
00819       png_ptr->mode |= PNG_AFTER_IDAT;
00820    }
00821 }
00822 
00823 void /* PRIVATE */
00824 png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
00825    png_size_t buffer_length)
00826 {
00827    int ret;
00828 
00829    if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
00830       png_error(png_ptr, "Extra compression data");
00831 
00832    png_ptr->zstream.next_in = buffer;
00833    png_ptr->zstream.avail_in = (uInt)buffer_length;
00834    for (;;)
00835    {
00836       ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
00837       if (ret != Z_OK)
00838       {
00839          if (ret == Z_STREAM_END)
00840          {
00841             if (png_ptr->zstream.avail_in)
00842                png_error(png_ptr, "Extra compressed data");
00843 
00844             if (!(png_ptr->zstream.avail_out))
00845             {
00846                png_push_process_row(png_ptr);
00847             }
00848 
00849             png_ptr->mode |= PNG_AFTER_IDAT;
00850             png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
00851             break;
00852          }
00853          else if (ret == Z_BUF_ERROR)
00854             break;
00855 
00856          else
00857             png_error(png_ptr, "Decompression Error");
00858       }
00859       if (!(png_ptr->zstream.avail_out))
00860       {
00861          if ((
00862 #if defined(PNG_READ_INTERLACING_SUPPORTED)
00863              png_ptr->interlaced && png_ptr->pass > 6) ||
00864              (!png_ptr->interlaced &&
00865 #endif
00866              png_ptr->row_number == png_ptr->num_rows))
00867          {
00868            if (png_ptr->zstream.avail_in)
00869              png_warning(png_ptr, "Too much data in IDAT chunks");
00870            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
00871            break;
00872          }
00873          png_push_process_row(png_ptr);
00874          png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
00875          png_ptr->zstream.next_out = png_ptr->row_buf;
00876       }
00877 
00878       else
00879          break;
00880    }
00881 }
00882 
00883 void /* PRIVATE */
00884 png_push_process_row(png_structp png_ptr)
00885 {
00886    png_ptr->row_info.color_type = png_ptr->color_type;
00887    png_ptr->row_info.width = png_ptr->iwidth;
00888    png_ptr->row_info.channels = png_ptr->channels;
00889    png_ptr->row_info.bit_depth = png_ptr->bit_depth;
00890    png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
00891 
00892    png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
00893        png_ptr->row_info.width);
00894 
00895    png_read_filter_row(png_ptr, &(png_ptr->row_info),
00896       png_ptr->row_buf + 1, png_ptr->prev_row + 1,
00897       (int)(png_ptr->row_buf[0]));
00898 
00899    png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
00900       png_ptr->rowbytes + 1);
00901 
00902    if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
00903       png_do_read_transformations(png_ptr);
00904 
00905 #if defined(PNG_READ_INTERLACING_SUPPORTED)
00906    /* Blow up interlaced rows to full size */
00907    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
00908    {
00909       if (png_ptr->pass < 6)
00910 /*       old interface (pre-1.0.9):
00911          png_do_read_interlace(&(png_ptr->row_info),
00912             png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
00913  */
00914          png_do_read_interlace(png_ptr);
00915 
00916     switch (png_ptr->pass)
00917     {
00918          case 0:
00919          {
00920             int i;
00921             for (i = 0; i < 8 && png_ptr->pass == 0; i++)
00922             {
00923                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
00924                png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
00925             }
00926 
00927             if (png_ptr->pass == 2) /* Pass 1 might be empty */
00928             {
00929                for (i = 0; i < 4 && png_ptr->pass == 2; i++)
00930                {
00931                   png_push_have_row(png_ptr, png_bytep_NULL);
00932                   png_read_push_finish_row(png_ptr);
00933                }
00934             }
00935 
00936             if (png_ptr->pass == 4 && png_ptr->height <= 4)
00937             {
00938                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
00939                {
00940                   png_push_have_row(png_ptr, png_bytep_NULL);
00941                   png_read_push_finish_row(png_ptr);
00942                }
00943             }
00944 
00945             if (png_ptr->pass == 6 && png_ptr->height <= 4)
00946             {
00947                 png_push_have_row(png_ptr, png_bytep_NULL);
00948                 png_read_push_finish_row(png_ptr);
00949             }
00950 
00951             break;
00952          }
00953 
00954          case 1:
00955          {
00956             int i;
00957             for (i = 0; i < 8 && png_ptr->pass == 1; i++)
00958             {
00959                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
00960                png_read_push_finish_row(png_ptr);
00961             }
00962 
00963             if (png_ptr->pass == 2) /* Skip top 4 generated rows */
00964             {
00965                for (i = 0; i < 4 && png_ptr->pass == 2; i++)
00966                {
00967                   png_push_have_row(png_ptr, png_bytep_NULL);
00968                   png_read_push_finish_row(png_ptr);
00969                }
00970             }
00971 
00972             break;
00973          }
00974 
00975          case 2:
00976          {
00977             int i;
00978 
00979             for (i = 0; i < 4 && png_ptr->pass == 2; i++)
00980             {
00981                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
00982                png_read_push_finish_row(png_ptr);
00983             }
00984 
00985             for (i = 0; i < 4 && png_ptr->pass == 2; i++)
00986             {
00987                png_push_have_row(png_ptr, png_bytep_NULL);
00988                png_read_push_finish_row(png_ptr);
00989             }
00990 
00991             if (png_ptr->pass == 4) /* Pass 3 might be empty */
00992             {
00993                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
00994                {
00995                   png_push_have_row(png_ptr, png_bytep_NULL);
00996                   png_read_push_finish_row(png_ptr);
00997                }
00998             }
00999 
01000             break;
01001          }
01002 
01003          case 3:
01004          {
01005             int i;
01006 
01007             for (i = 0; i < 4 && png_ptr->pass == 3; i++)
01008             {
01009                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
01010                png_read_push_finish_row(png_ptr);
01011             }
01012 
01013             if (png_ptr->pass == 4) /* Skip top two generated rows */
01014             {
01015                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
01016                {
01017                   png_push_have_row(png_ptr, png_bytep_NULL);
01018                   png_read_push_finish_row(png_ptr);
01019                }
01020             }
01021 
01022             break;
01023          }
01024 
01025          case 4:
01026          {
01027             int i;
01028 
01029             for (i = 0; i < 2 && png_ptr->pass == 4; i++)
01030             {
01031                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
01032                png_read_push_finish_row(png_ptr);
01033             }
01034 
01035             for (i = 0; i < 2 && png_ptr->pass == 4; i++)
01036             {
01037                png_push_have_row(png_ptr, png_bytep_NULL);
01038                png_read_push_finish_row(png_ptr);
01039             }
01040 
01041             if (png_ptr->pass == 6) /* Pass 5 might be empty */
01042             {
01043                png_push_have_row(png_ptr, png_bytep_NULL);
01044                png_read_push_finish_row(png_ptr);
01045             }
01046 
01047             break;
01048          }
01049 
01050          case 5:
01051          {
01052             int i;
01053 
01054             for (i = 0; i < 2 && png_ptr->pass == 5; i++)
01055             {
01056                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
01057                png_read_push_finish_row(png_ptr);
01058             }
01059 
01060             if (png_ptr->pass == 6) /* Skip top generated row */
01061             {
01062                png_push_have_row(png_ptr, png_bytep_NULL);
01063                png_read_push_finish_row(png_ptr);
01064             }
01065 
01066             break;
01067          }
01068          case 6:
01069          {
01070             png_push_have_row(png_ptr, png_ptr->row_buf + 1);
01071             png_read_push_finish_row(png_ptr);
01072 
01073             if (png_ptr->pass != 6)
01074                break;
01075 
01076             png_push_have_row(png_ptr, png_bytep_NULL);
01077             png_read_push_finish_row(png_ptr);
01078          }
01079       }
01080    }
01081    else
01082 #endif
01083    {
01084       png_push_have_row(png_ptr, png_ptr->row_buf + 1);
01085       png_read_push_finish_row(png_ptr);
01086    }
01087 }
01088 
01089 void /* PRIVATE */
01090 png_read_push_finish_row(png_structp png_ptr)
01091 {
01092 #ifdef PNG_USE_LOCAL_ARRAYS
01093    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
01094 
01095    /* Start of interlace block */
01096    PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
01097 
01098    /* Offset to next interlace block */
01099    PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
01100 
01101    /* Start of interlace block in the y direction */
01102    PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
01103 
01104    /* Offset to next interlace block in the y direction */
01105    PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
01106 
01107    /* Height of interlace block.  This is not currently used - if you need
01108     * it, uncomment it here and in png.h
01109    PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
01110    */
01111 #endif
01112 
01113    png_ptr->row_number++;
01114    if (png_ptr->row_number < png_ptr->num_rows)
01115       return;
01116 
01117 #if defined(PNG_READ_INTERLACING_SUPPORTED)
01118    if (png_ptr->interlaced)
01119    {
01120       png_ptr->row_number = 0;
01121       png_memset_check(png_ptr, png_ptr->prev_row, 0,
01122          png_ptr->rowbytes + 1);
01123       do
01124       {
01125          png_ptr->pass++;
01126          if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
01127              (png_ptr->pass == 3 && png_ptr->width < 3) ||
01128              (png_ptr->pass == 5 && png_ptr->width < 2))
01129            png_ptr->pass++;
01130 
01131          if (png_ptr->pass > 7)
01132             png_ptr->pass--;
01133 
01134          if (png_ptr->pass >= 7)
01135             break;
01136 
01137          png_ptr->iwidth = (png_ptr->width +
01138             png_pass_inc[png_ptr->pass] - 1 -
01139             png_pass_start[png_ptr->pass]) /
01140             png_pass_inc[png_ptr->pass];
01141 
01142          png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
01143             png_ptr->iwidth) + 1;
01144 
01145          if (png_ptr->transformations & PNG_INTERLACE)
01146             break;
01147 
01148          png_ptr->num_rows = (png_ptr->height +
01149             png_pass_yinc[png_ptr->pass] - 1 -
01150             png_pass_ystart[png_ptr->pass]) /
01151             png_pass_yinc[png_ptr->pass];
01152 
01153       } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
01154    }
01155 #endif /* PNG_READ_INTERLACING_SUPPORTED */
01156 }
01157 
01158 #if defined(PNG_READ_tEXt_SUPPORTED)
01159 void /* PRIVATE */
01160 png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
01161    length)
01162 {
01163    if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
01164       {
01165          png_error(png_ptr, "Out of place tEXt");
01166          info_ptr = info_ptr; /* To quiet some compiler warnings */
01167       }
01168 
01169 #ifdef PNG_MAX_MALLOC_64K
01170    png_ptr->skip_length = 0;  /* This may not be necessary */
01171 
01172    if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
01173    {
01174       png_warning(png_ptr, "tEXt chunk too large to fit in memory");
01175       png_ptr->skip_length = length - (png_uint_32)65535L;
01176       length = (png_uint_32)65535L;
01177    }
01178 #endif
01179 
01180    png_ptr->current_text = (png_charp)png_malloc(png_ptr,
01181       (png_uint_32)(length + 1));
01182    png_ptr->current_text[length] = '\0';
01183    png_ptr->current_text_ptr = png_ptr->current_text;
01184    png_ptr->current_text_size = (png_size_t)length;
01185    png_ptr->current_text_left = (png_size_t)length;
01186    png_ptr->process_mode = PNG_READ_tEXt_MODE;
01187 }
01188 
01189 void /* PRIVATE */
01190 png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
01191 {
01192    if (png_ptr->buffer_size && png_ptr->current_text_left)
01193    {
01194       png_size_t text_size;
01195 
01196       if (png_ptr->buffer_size < png_ptr->current_text_left)
01197          text_size = png_ptr->buffer_size;
01198 
01199       else
01200          text_size = png_ptr->current_text_left;
01201 
01202       png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
01203       png_ptr->current_text_left -= text_size;
01204       png_ptr->current_text_ptr += text_size;
01205    }
01206    if (!(png_ptr->current_text_left))
01207    {
01208       png_textp text_ptr;
01209       png_charp text;
01210       png_charp key;
01211       int ret;
01212 
01213       if (png_ptr->buffer_size < 4)
01214       {
01215          png_push_save_buffer(png_ptr);
01216          return;
01217       }
01218 
01219       png_push_crc_finish(png_ptr);
01220 
01221 #if defined(PNG_MAX_MALLOC_64K)
01222       if (png_ptr->skip_length)
01223          return;
01224 #endif
01225 
01226       key = png_ptr->current_text;
01227 
01228       for (text = key; *text; text++)
01229          /* Empty loop */ ;
01230 
01231       if (text < key + png_ptr->current_text_size)
01232          text++;
01233 
01234       text_ptr = (png_textp)png_malloc(png_ptr,
01235          (png_uint_32)png_sizeof(png_text));
01236       text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
01237       text_ptr->key = key;
01238 #ifdef PNG_iTXt_SUPPORTED
01239       text_ptr->lang = NULL;
01240       text_ptr->lang_key = NULL;
01241 #endif
01242       text_ptr->text = text;
01243 
01244       ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
01245 
01246       png_free(png_ptr, key);
01247       png_free(png_ptr, text_ptr);
01248       png_ptr->current_text = NULL;
01249 
01250       if (ret)
01251         png_warning(png_ptr, "Insufficient memory to store text chunk.");
01252    }
01253 }
01254 #endif
01255 
01256 #if defined(PNG_READ_zTXt_SUPPORTED)
01257 void /* PRIVATE */
01258 png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
01259    length)
01260 {
01261    if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
01262       {
01263          png_error(png_ptr, "Out of place zTXt");
01264          info_ptr = info_ptr; /* To quiet some compiler warnings */
01265       }
01266 
01267 #ifdef PNG_MAX_MALLOC_64K
01268    /* We can't handle zTXt chunks > 64K, since we don't have enough space
01269     * to be able to store the uncompressed data.  Actually, the threshold
01270     * is probably around 32K, but it isn't as definite as 64K is.
01271     */
01272    if (length > (png_uint_32)65535L)
01273    {
01274       png_warning(png_ptr, "zTXt chunk too large to fit in memory");
01275       png_push_crc_skip(png_ptr, length);
01276       return;
01277    }
01278 #endif
01279 
01280    png_ptr->current_text = (png_charp)png_malloc(png_ptr,
01281       (png_uint_32)(length + 1));
01282    png_ptr->current_text[length] = '\0';
01283    png_ptr->current_text_ptr = png_ptr->current_text;
01284    png_ptr->current_text_size = (png_size_t)length;
01285    png_ptr->current_text_left = (png_size_t)length;
01286    png_ptr->process_mode = PNG_READ_zTXt_MODE;
01287 }
01288 
01289 void /* PRIVATE */
01290 png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
01291 {
01292    if (png_ptr->buffer_size && png_ptr->current_text_left)
01293    {
01294       png_size_t text_size;
01295 
01296       if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
01297          text_size = png_ptr->buffer_size;
01298 
01299       else
01300          text_size = png_ptr->current_text_left;
01301 
01302       png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
01303       png_ptr->current_text_left -= text_size;
01304       png_ptr->current_text_ptr += text_size;
01305    }
01306    if (!(png_ptr->current_text_left))
01307    {
01308       png_textp text_ptr;
01309       png_charp text;
01310       png_charp key;
01311       int ret;
01312       png_size_t text_size, key_size;
01313 
01314       if (png_ptr->buffer_size < 4)
01315       {
01316          png_push_save_buffer(png_ptr);
01317          return;
01318       }
01319 
01320       png_push_crc_finish(png_ptr);
01321 
01322       key = png_ptr->current_text;
01323 
01324       for (text = key; *text; text++)
01325          /* Empty loop */ ;
01326 
01327       /* zTXt can't have zero text */
01328       if (text >= key + png_ptr->current_text_size)
01329       {
01330          png_ptr->current_text = NULL;
01331          png_free(png_ptr, key);
01332          return;
01333       }
01334 
01335       text++;
01336 
01337       if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */
01338       {
01339          png_ptr->current_text = NULL;
01340          png_free(png_ptr, key);
01341          return;
01342       }
01343 
01344       text++;
01345 
01346       png_ptr->zstream.next_in = (png_bytep )text;
01347       png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
01348          (text - key));
01349       png_ptr->zstream.next_out = png_ptr->zbuf;
01350       png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
01351 
01352       key_size = text - key;
01353       text_size = 0;
01354       text = NULL;
01355       ret = Z_STREAM_END;
01356 
01357       while (png_ptr->zstream.avail_in)
01358       {
01359          ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
01360          if (ret != Z_OK && ret != Z_STREAM_END)
01361          {
01362             inflateReset(&png_ptr->zstream);
01363             png_ptr->zstream.avail_in = 0;
01364             png_ptr->current_text = NULL;
01365             png_free(png_ptr, key);
01366             png_free(png_ptr, text);
01367             return;
01368          }
01369          if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)
01370          {
01371             if (text == NULL)
01372             {
01373                text = (png_charp)png_malloc(png_ptr,
01374                      (png_uint_32)(png_ptr->zbuf_size
01375                      - png_ptr->zstream.avail_out + key_size + 1));
01376 
01377                png_memcpy(text + key_size, png_ptr->zbuf,
01378                   png_ptr->zbuf_size - png_ptr->zstream.avail_out);
01379 
01380                png_memcpy(text, key, key_size);
01381 
01382                text_size = key_size + png_ptr->zbuf_size -
01383                   png_ptr->zstream.avail_out;
01384 
01385                *(text + text_size) = '\0';
01386             }
01387             else
01388             {
01389                png_charp tmp;
01390 
01391                tmp = text;
01392                text = (png_charp)png_malloc(png_ptr, text_size +
01393                   (png_uint_32)(png_ptr->zbuf_size 
01394                   - png_ptr->zstream.avail_out + 1));
01395 
01396                png_memcpy(text, tmp, text_size);
01397                png_free(png_ptr, tmp);
01398 
01399                png_memcpy(text + text_size, png_ptr->zbuf,
01400                   png_ptr->zbuf_size - png_ptr->zstream.avail_out);
01401 
01402                text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
01403                *(text + text_size) = '\0';
01404             }
01405             if (ret != Z_STREAM_END)
01406             {
01407                png_ptr->zstream.next_out = png_ptr->zbuf;
01408                png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
01409             }
01410          }
01411          else
01412          {
01413             break;
01414          }
01415 
01416          if (ret == Z_STREAM_END)
01417             break;
01418       }
01419 
01420       inflateReset(&png_ptr->zstream);
01421       png_ptr->zstream.avail_in = 0;
01422 
01423       if (ret != Z_STREAM_END)
01424       {
01425          png_ptr->current_text = NULL;
01426          png_free(png_ptr, key);
01427          png_free(png_ptr, text);
01428          return;
01429       }
01430 
01431       png_ptr->current_text = NULL;
01432       png_free(png_ptr, key);
01433       key = text;
01434       text += key_size;
01435 
01436       text_ptr = (png_textp)png_malloc(png_ptr,
01437           (png_uint_32)png_sizeof(png_text));
01438       text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
01439       text_ptr->key = key;
01440 #ifdef PNG_iTXt_SUPPORTED
01441       text_ptr->lang = NULL;
01442       text_ptr->lang_key = NULL;
01443 #endif
01444       text_ptr->text = text;
01445 
01446       ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
01447 
01448       png_free(png_ptr, key);
01449       png_free(png_ptr, text_ptr);
01450 
01451       if (ret)
01452         png_warning(png_ptr, "Insufficient memory to store text chunk.");
01453    }
01454 }
01455 #endif
01456 
01457 #if defined(PNG_READ_iTXt_SUPPORTED)
01458 void /* PRIVATE */
01459 png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32
01460    length)
01461 {
01462    if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND))
01463       {
01464          png_error(png_ptr, "Out of place iTXt");
01465          info_ptr = info_ptr; /* To quiet some compiler warnings */
01466       }
01467 
01468 #ifdef PNG_MAX_MALLOC_64K
01469    png_ptr->skip_length = 0;  /* This may not be necessary */
01470 
01471    if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */
01472    {
01473       png_warning(png_ptr, "iTXt chunk too large to fit in memory");
01474       png_ptr->skip_length = length - (png_uint_32)65535L;
01475       length = (png_uint_32)65535L;
01476    }
01477 #endif
01478 
01479    png_ptr->current_text = (png_charp)png_malloc(png_ptr,
01480       (png_uint_32)(length + 1));
01481    png_ptr->current_text[length] = '\0';
01482    png_ptr->current_text_ptr = png_ptr->current_text;
01483    png_ptr->current_text_size = (png_size_t)length;
01484    png_ptr->current_text_left = (png_size_t)length;
01485    png_ptr->process_mode = PNG_READ_iTXt_MODE;
01486 }
01487 
01488 void /* PRIVATE */
01489 png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr)
01490 {
01491 
01492    if (png_ptr->buffer_size && png_ptr->current_text_left)
01493    {
01494       png_size_t text_size;
01495 
01496       if (png_ptr->buffer_size < png_ptr->current_text_left)
01497          text_size = png_ptr->buffer_size;
01498 
01499       else
01500          text_size = png_ptr->current_text_left;
01501 
01502       png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
01503       png_ptr->current_text_left -= text_size;
01504       png_ptr->current_text_ptr += text_size;
01505    }
01506    if (!(png_ptr->current_text_left))
01507    {
01508       png_textp text_ptr;
01509       png_charp key;
01510       int comp_flag;
01511       png_charp lang;
01512       png_charp lang_key;
01513       png_charp text;
01514       int ret;
01515 
01516       if (png_ptr->buffer_size < 4)
01517       {
01518          png_push_save_buffer(png_ptr);
01519          return;
01520       }
01521 
01522       png_push_crc_finish(png_ptr);
01523 
01524 #if defined(PNG_MAX_MALLOC_64K)
01525       if (png_ptr->skip_length)
01526          return;
01527 #endif
01528 
01529       key = png_ptr->current_text;
01530 
01531       for (lang = key; *lang; lang++)
01532          /* Empty loop */ ;
01533 
01534       if (lang < key + png_ptr->current_text_size - 3)
01535          lang++;
01536 
01537       comp_flag = *lang++;
01538       lang++;     /* Skip comp_type, always zero */
01539 
01540       for (lang_key = lang; *lang_key; lang_key++)
01541          /* Empty loop */ ;
01542 
01543       lang_key++;        /* Skip NUL separator */
01544 
01545       text=lang_key;
01546 
01547       if (lang_key < key + png_ptr->current_text_size - 1)
01548       {
01549         for (; *text; text++)
01550            /* Empty loop */ ;
01551       }
01552 
01553       if (text < key + png_ptr->current_text_size)
01554          text++;
01555 
01556       text_ptr = (png_textp)png_malloc(png_ptr,
01557          (png_uint_32)png_sizeof(png_text));
01558 
01559       text_ptr->compression = comp_flag + 2;
01560       text_ptr->key = key;
01561       text_ptr->lang = lang;
01562       text_ptr->lang_key = lang_key;
01563       text_ptr->text = text;
01564       text_ptr->text_length = 0;
01565       text_ptr->itxt_length = png_strlen(text);
01566 
01567       ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
01568 
01569       png_ptr->current_text = NULL;
01570 
01571       png_free(png_ptr, text_ptr);
01572       if (ret)
01573         png_warning(png_ptr, "Insufficient memory to store iTXt chunk.");
01574    }
01575 }
01576 #endif
01577 
01578 /* This function is called when we haven't found a handler for this
01579  * chunk.  If there isn't a problem with the chunk itself (ie a bad chunk
01580  * name or a critical chunk), the chunk is (currently) silently ignored.
01581  */
01582 void /* PRIVATE */
01583 png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32
01584    length)
01585 {
01586    png_uint_32 skip = 0;
01587 
01588    if (!(png_ptr->chunk_name[0] & 0x20))
01589    {
01590 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
01591       if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
01592          PNG_HANDLE_CHUNK_ALWAYS
01593 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
01594          && png_ptr->read_user_chunk_fn == NULL
01595 #endif
01596          )
01597 #endif
01598          png_chunk_error(png_ptr, "unknown critical chunk");
01599 
01600       info_ptr = info_ptr; /* To quiet some compiler warnings */
01601    }
01602 
01603 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
01604    if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
01605    {
01606 #ifdef PNG_MAX_MALLOC_64K
01607       if (length > (png_uint_32)65535L)
01608       {
01609           png_warning(png_ptr, "unknown chunk too large to fit in memory");
01610           skip = length - (png_uint_32)65535L;
01611           length = (png_uint_32)65535L;
01612       }
01613 #endif
01614       png_memcpy((png_charp)png_ptr->unknown_chunk.name,
01615                  (png_charp)png_ptr->chunk_name, 
01616                  png_sizeof(png_ptr->unknown_chunk.name));
01617       png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1]
01618         = '\0';
01619 
01620       png_ptr->unknown_chunk.size = (png_size_t)length;
01621 
01622       if (length == 0)
01623          png_ptr->unknown_chunk.data = NULL;
01624 
01625       else
01626       {
01627          png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr,
01628        (png_uint_32)length);
01629          png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
01630       }
01631 
01632 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
01633       if (png_ptr->read_user_chunk_fn != NULL)
01634       {
01635          /* Callback to user unknown chunk handler */
01636          int ret;
01637          ret = (*(png_ptr->read_user_chunk_fn))
01638            (png_ptr, &png_ptr->unknown_chunk);
01639 
01640          if (ret < 0)
01641             png_chunk_error(png_ptr, "error in user chunk");
01642 
01643          if (ret == 0)
01644          {
01645             if (!(png_ptr->chunk_name[0] & 0x20))
01646                if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
01647                     PNG_HANDLE_CHUNK_ALWAYS)
01648                   png_chunk_error(png_ptr, "unknown critical chunk");
01649             png_set_unknown_chunks(png_ptr, info_ptr,
01650                &png_ptr->unknown_chunk, 1);
01651          }
01652       }
01653 
01654       else
01655 #endif
01656         png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
01657       png_free(png_ptr, png_ptr->unknown_chunk.data);
01658       png_ptr->unknown_chunk.data = NULL;
01659    }
01660 
01661    else
01662 #endif
01663       skip=length;
01664    png_push_crc_skip(png_ptr, skip);
01665 }
01666 
01667 void /* PRIVATE */
01668 png_push_have_info(png_structp png_ptr, png_infop info_ptr)
01669 {
01670    if (png_ptr->info_fn != NULL)
01671       (*(png_ptr->info_fn))(png_ptr, info_ptr);
01672 }
01673 
01674 void /* PRIVATE */
01675 png_push_have_end(png_structp png_ptr, png_infop info_ptr)
01676 {
01677    if (png_ptr->end_fn != NULL)
01678       (*(png_ptr->end_fn))(png_ptr, info_ptr);
01679 }
01680 
01681 void /* PRIVATE */
01682 png_push_have_row(png_structp png_ptr, png_bytep row)
01683 {
01684    if (png_ptr->row_fn != NULL)
01685       (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
01686          (int)png_ptr->pass);
01687 }
01688 
01689 void PNGAPI
01690 png_progressive_combine_row (png_structp png_ptr,
01691    png_bytep old_row, png_bytep new_row)
01692 {
01693 #ifdef PNG_USE_LOCAL_ARRAYS
01694    PNG_CONST int FARDATA png_pass_dsp_mask[7] =
01695       {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
01696 #endif
01697    if (png_ptr == NULL)
01698       return;
01699 
01700    if (new_row != NULL)    /* new_row must == png_ptr->row_buf here. */
01701       png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
01702 }
01703 
01704 void PNGAPI
01705 png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
01706    png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
01707    png_progressive_end_ptr end_fn)
01708 {
01709    if (png_ptr == NULL)
01710       return;
01711 
01712    png_ptr->info_fn = info_fn;
01713    png_ptr->row_fn = row_fn;
01714    png_ptr->end_fn = end_fn;
01715 
01716    png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
01717 }
01718 
01719 png_voidp PNGAPI
01720 png_get_progressive_ptr(png_structp png_ptr)
01721 {
01722    if (png_ptr == NULL)
01723       return (NULL);
01724 
01725    return png_ptr->io_ptr;
01726 }
01727 #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */