13965825b97a5809454f5810f7e603cbd02daa036scroggo
23965825b97a5809454f5810f7e603cbd02daa036scroggo/* pngpread.c - read a png file in push mode
33965825b97a5809454f5810f7e603cbd02daa036scroggo *
43965825b97a5809454f5810f7e603cbd02daa036scroggo * Last changed in libpng 1.6.18 [July 23, 2015]
53965825b97a5809454f5810f7e603cbd02daa036scroggo * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
63965825b97a5809454f5810f7e603cbd02daa036scroggo * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
73965825b97a5809454f5810f7e603cbd02daa036scroggo * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
83965825b97a5809454f5810f7e603cbd02daa036scroggo *
93965825b97a5809454f5810f7e603cbd02daa036scroggo * This code is released under the libpng license.
103965825b97a5809454f5810f7e603cbd02daa036scroggo * For conditions of distribution and use, see the disclaimer
113965825b97a5809454f5810f7e603cbd02daa036scroggo * and license in png.h
123965825b97a5809454f5810f7e603cbd02daa036scroggo */
133965825b97a5809454f5810f7e603cbd02daa036scroggo
143965825b97a5809454f5810f7e603cbd02daa036scroggo#include "pngpriv.h"
153965825b97a5809454f5810f7e603cbd02daa036scroggo
163965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
173965825b97a5809454f5810f7e603cbd02daa036scroggo
183965825b97a5809454f5810f7e603cbd02daa036scroggo/* Push model modes */
193965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_READ_SIG_MODE   0
203965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_READ_CHUNK_MODE 1
213965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_READ_IDAT_MODE  2
223965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_READ_tEXt_MODE  4
233965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_READ_zTXt_MODE  5
243965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_READ_DONE_MODE  6
253965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_READ_iTXt_MODE  7
263965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_ERROR_MODE      8
273965825b97a5809454f5810f7e603cbd02daa036scroggo
283965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_PUSH_SAVE_BUFFER_IF_FULL \
293965825b97a5809454f5810f7e603cbd02daa036scroggoif (png_ptr->push_length + 4 > png_ptr->buffer_size) \
303965825b97a5809454f5810f7e603cbd02daa036scroggo   { png_push_save_buffer(png_ptr); return; }
313965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_PUSH_SAVE_BUFFER_IF_LT(N) \
323965825b97a5809454f5810f7e603cbd02daa036scroggoif (png_ptr->buffer_size < N) \
333965825b97a5809454f5810f7e603cbd02daa036scroggo   { png_push_save_buffer(png_ptr); return; }
343965825b97a5809454f5810f7e603cbd02daa036scroggo
353965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI
363965825b97a5809454f5810f7e603cbd02daa036scroggopng_process_data(png_structrp png_ptr, png_inforp info_ptr,
373965825b97a5809454f5810f7e603cbd02daa036scroggo    png_bytep buffer, png_size_t buffer_size)
383965825b97a5809454f5810f7e603cbd02daa036scroggo{
393965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr == NULL || info_ptr == NULL)
403965825b97a5809454f5810f7e603cbd02daa036scroggo      return;
413965825b97a5809454f5810f7e603cbd02daa036scroggo
423965825b97a5809454f5810f7e603cbd02daa036scroggo   png_push_restore_buffer(png_ptr, buffer, buffer_size);
433965825b97a5809454f5810f7e603cbd02daa036scroggo
443965825b97a5809454f5810f7e603cbd02daa036scroggo   while (png_ptr->buffer_size)
453965825b97a5809454f5810f7e603cbd02daa036scroggo   {
463965825b97a5809454f5810f7e603cbd02daa036scroggo      png_process_some_data(png_ptr, info_ptr);
473965825b97a5809454f5810f7e603cbd02daa036scroggo   }
483965825b97a5809454f5810f7e603cbd02daa036scroggo}
493965825b97a5809454f5810f7e603cbd02daa036scroggo
503965825b97a5809454f5810f7e603cbd02daa036scroggopng_size_t PNGAPI
513965825b97a5809454f5810f7e603cbd02daa036scroggopng_process_data_pause(png_structrp png_ptr, int save)
523965825b97a5809454f5810f7e603cbd02daa036scroggo{
533965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr != NULL)
543965825b97a5809454f5810f7e603cbd02daa036scroggo   {
553965825b97a5809454f5810f7e603cbd02daa036scroggo      /* It's easiest for the caller if we do the save; then the caller doesn't
563965825b97a5809454f5810f7e603cbd02daa036scroggo       * have to supply the same data again:
573965825b97a5809454f5810f7e603cbd02daa036scroggo       */
583965825b97a5809454f5810f7e603cbd02daa036scroggo      if (save != 0)
593965825b97a5809454f5810f7e603cbd02daa036scroggo         png_push_save_buffer(png_ptr);
603965825b97a5809454f5810f7e603cbd02daa036scroggo      else
613965825b97a5809454f5810f7e603cbd02daa036scroggo      {
623965825b97a5809454f5810f7e603cbd02daa036scroggo         /* This includes any pending saved bytes: */
633965825b97a5809454f5810f7e603cbd02daa036scroggo         png_size_t remaining = png_ptr->buffer_size;
643965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->buffer_size = 0;
653965825b97a5809454f5810f7e603cbd02daa036scroggo
663965825b97a5809454f5810f7e603cbd02daa036scroggo         /* So subtract the saved buffer size, unless all the data
673965825b97a5809454f5810f7e603cbd02daa036scroggo          * is actually 'saved', in which case we just return 0
683965825b97a5809454f5810f7e603cbd02daa036scroggo          */
693965825b97a5809454f5810f7e603cbd02daa036scroggo         if (png_ptr->save_buffer_size < remaining)
703965825b97a5809454f5810f7e603cbd02daa036scroggo            return remaining - png_ptr->save_buffer_size;
713965825b97a5809454f5810f7e603cbd02daa036scroggo      }
723965825b97a5809454f5810f7e603cbd02daa036scroggo   }
733965825b97a5809454f5810f7e603cbd02daa036scroggo
743965825b97a5809454f5810f7e603cbd02daa036scroggo   return 0;
753965825b97a5809454f5810f7e603cbd02daa036scroggo}
763965825b97a5809454f5810f7e603cbd02daa036scroggo
773965825b97a5809454f5810f7e603cbd02daa036scroggopng_uint_32 PNGAPI
783965825b97a5809454f5810f7e603cbd02daa036scroggopng_process_data_skip(png_structrp png_ptr)
793965825b97a5809454f5810f7e603cbd02daa036scroggo{
803965825b97a5809454f5810f7e603cbd02daa036scroggo  /* TODO: Deprecate and remove this API.
813965825b97a5809454f5810f7e603cbd02daa036scroggo   * Somewhere the implementation of this seems to have been lost,
823965825b97a5809454f5810f7e603cbd02daa036scroggo   * or abandoned.  It was only to support some internal back-door access
833965825b97a5809454f5810f7e603cbd02daa036scroggo   * to png_struct) in libpng-1.4.x.
843965825b97a5809454f5810f7e603cbd02daa036scroggo   */
853965825b97a5809454f5810f7e603cbd02daa036scroggo   png_app_warning(png_ptr,
863965825b97a5809454f5810f7e603cbd02daa036scroggo"png_process_data_skip is not implemented in any current version of libpng");
873965825b97a5809454f5810f7e603cbd02daa036scroggo   return 0;
883965825b97a5809454f5810f7e603cbd02daa036scroggo}
893965825b97a5809454f5810f7e603cbd02daa036scroggo
903965825b97a5809454f5810f7e603cbd02daa036scroggo/* What we do with the incoming data depends on what we were previously
913965825b97a5809454f5810f7e603cbd02daa036scroggo * doing before we ran out of data...
923965825b97a5809454f5810f7e603cbd02daa036scroggo */
933965825b97a5809454f5810f7e603cbd02daa036scroggovoid /* PRIVATE */
943965825b97a5809454f5810f7e603cbd02daa036scroggopng_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
953965825b97a5809454f5810f7e603cbd02daa036scroggo{
963965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr == NULL)
973965825b97a5809454f5810f7e603cbd02daa036scroggo      return;
983965825b97a5809454f5810f7e603cbd02daa036scroggo
993965825b97a5809454f5810f7e603cbd02daa036scroggo   switch (png_ptr->process_mode)
1003965825b97a5809454f5810f7e603cbd02daa036scroggo   {
1013965825b97a5809454f5810f7e603cbd02daa036scroggo      case PNG_READ_SIG_MODE:
1023965825b97a5809454f5810f7e603cbd02daa036scroggo      {
1033965825b97a5809454f5810f7e603cbd02daa036scroggo         png_push_read_sig(png_ptr, info_ptr);
1043965825b97a5809454f5810f7e603cbd02daa036scroggo         break;
1053965825b97a5809454f5810f7e603cbd02daa036scroggo      }
1063965825b97a5809454f5810f7e603cbd02daa036scroggo
1073965825b97a5809454f5810f7e603cbd02daa036scroggo      case PNG_READ_CHUNK_MODE:
1083965825b97a5809454f5810f7e603cbd02daa036scroggo      {
1093965825b97a5809454f5810f7e603cbd02daa036scroggo         png_push_read_chunk(png_ptr, info_ptr);
1103965825b97a5809454f5810f7e603cbd02daa036scroggo         break;
1113965825b97a5809454f5810f7e603cbd02daa036scroggo      }
1123965825b97a5809454f5810f7e603cbd02daa036scroggo
1133965825b97a5809454f5810f7e603cbd02daa036scroggo      case PNG_READ_IDAT_MODE:
1143965825b97a5809454f5810f7e603cbd02daa036scroggo      {
1153965825b97a5809454f5810f7e603cbd02daa036scroggo         png_push_read_IDAT(png_ptr);
1163965825b97a5809454f5810f7e603cbd02daa036scroggo         break;
1173965825b97a5809454f5810f7e603cbd02daa036scroggo      }
1183965825b97a5809454f5810f7e603cbd02daa036scroggo
1193965825b97a5809454f5810f7e603cbd02daa036scroggo      default:
1203965825b97a5809454f5810f7e603cbd02daa036scroggo      {
1213965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->buffer_size = 0;
1223965825b97a5809454f5810f7e603cbd02daa036scroggo         break;
1233965825b97a5809454f5810f7e603cbd02daa036scroggo      }
1243965825b97a5809454f5810f7e603cbd02daa036scroggo   }
1253965825b97a5809454f5810f7e603cbd02daa036scroggo}
1263965825b97a5809454f5810f7e603cbd02daa036scroggo
1273965825b97a5809454f5810f7e603cbd02daa036scroggo/* Read any remaining signature bytes from the stream and compare them with
1283965825b97a5809454f5810f7e603cbd02daa036scroggo * the correct PNG signature.  It is possible that this routine is called
1293965825b97a5809454f5810f7e603cbd02daa036scroggo * with bytes already read from the signature, either because they have been
1303965825b97a5809454f5810f7e603cbd02daa036scroggo * checked by the calling application, or because of multiple calls to this
1313965825b97a5809454f5810f7e603cbd02daa036scroggo * routine.
1323965825b97a5809454f5810f7e603cbd02daa036scroggo */
1333965825b97a5809454f5810f7e603cbd02daa036scroggovoid /* PRIVATE */
1343965825b97a5809454f5810f7e603cbd02daa036scroggopng_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
1353965825b97a5809454f5810f7e603cbd02daa036scroggo{
1363965825b97a5809454f5810f7e603cbd02daa036scroggo   png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */
1373965825b97a5809454f5810f7e603cbd02daa036scroggo       num_to_check = 8 - num_checked;
1383965825b97a5809454f5810f7e603cbd02daa036scroggo
1393965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->buffer_size < num_to_check)
1403965825b97a5809454f5810f7e603cbd02daa036scroggo   {
1413965825b97a5809454f5810f7e603cbd02daa036scroggo      num_to_check = png_ptr->buffer_size;
1423965825b97a5809454f5810f7e603cbd02daa036scroggo   }
1433965825b97a5809454f5810f7e603cbd02daa036scroggo
1443965825b97a5809454f5810f7e603cbd02daa036scroggo   png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
1453965825b97a5809454f5810f7e603cbd02daa036scroggo       num_to_check);
1463965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
1473965825b97a5809454f5810f7e603cbd02daa036scroggo
1483965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
1493965825b97a5809454f5810f7e603cbd02daa036scroggo   {
1503965825b97a5809454f5810f7e603cbd02daa036scroggo      if (num_checked < 4 &&
1513965825b97a5809454f5810f7e603cbd02daa036scroggo          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
1523965825b97a5809454f5810f7e603cbd02daa036scroggo         png_error(png_ptr, "Not a PNG file");
1533965825b97a5809454f5810f7e603cbd02daa036scroggo
1543965825b97a5809454f5810f7e603cbd02daa036scroggo      else
1553965825b97a5809454f5810f7e603cbd02daa036scroggo         png_error(png_ptr, "PNG file corrupted by ASCII conversion");
1563965825b97a5809454f5810f7e603cbd02daa036scroggo   }
1573965825b97a5809454f5810f7e603cbd02daa036scroggo   else
1583965825b97a5809454f5810f7e603cbd02daa036scroggo   {
1593965825b97a5809454f5810f7e603cbd02daa036scroggo      if (png_ptr->sig_bytes >= 8)
1603965825b97a5809454f5810f7e603cbd02daa036scroggo      {
1613965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
1623965825b97a5809454f5810f7e603cbd02daa036scroggo      }
1633965825b97a5809454f5810f7e603cbd02daa036scroggo   }
1643965825b97a5809454f5810f7e603cbd02daa036scroggo}
1653965825b97a5809454f5810f7e603cbd02daa036scroggo
1663965825b97a5809454f5810f7e603cbd02daa036scroggovoid /* PRIVATE */
1673965825b97a5809454f5810f7e603cbd02daa036scroggopng_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
1683965825b97a5809454f5810f7e603cbd02daa036scroggo{
1693965825b97a5809454f5810f7e603cbd02daa036scroggo   png_uint_32 chunk_name;
1703965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1713965825b97a5809454f5810f7e603cbd02daa036scroggo   int keep; /* unknown handling method */
1723965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
1733965825b97a5809454f5810f7e603cbd02daa036scroggo
1743965825b97a5809454f5810f7e603cbd02daa036scroggo   /* First we make sure we have enough data for the 4-byte chunk name
1753965825b97a5809454f5810f7e603cbd02daa036scroggo    * and the 4-byte chunk length before proceeding with decoding the
1763965825b97a5809454f5810f7e603cbd02daa036scroggo    * chunk data.  To fully decode each of these chunks, we also make
1773965825b97a5809454f5810f7e603cbd02daa036scroggo    * sure we have enough data in the buffer for the 4-byte CRC at the
1783965825b97a5809454f5810f7e603cbd02daa036scroggo    * end of every chunk (except IDAT, which is handled separately).
1793965825b97a5809454f5810f7e603cbd02daa036scroggo    */
1803965825b97a5809454f5810f7e603cbd02daa036scroggo   if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
1813965825b97a5809454f5810f7e603cbd02daa036scroggo   {
1823965825b97a5809454f5810f7e603cbd02daa036scroggo      png_byte chunk_length[4];
1833965825b97a5809454f5810f7e603cbd02daa036scroggo      png_byte chunk_tag[4];
1843965825b97a5809454f5810f7e603cbd02daa036scroggo
1853965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_LT(8)
1863965825b97a5809454f5810f7e603cbd02daa036scroggo      png_push_fill_buffer(png_ptr, chunk_length, 4);
1873965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
1883965825b97a5809454f5810f7e603cbd02daa036scroggo      png_reset_crc(png_ptr);
1893965825b97a5809454f5810f7e603cbd02daa036scroggo      png_crc_read(png_ptr, chunk_tag, 4);
1903965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
1913965825b97a5809454f5810f7e603cbd02daa036scroggo      png_check_chunk_name(png_ptr, png_ptr->chunk_name);
1923965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
1933965825b97a5809454f5810f7e603cbd02daa036scroggo   }
1943965825b97a5809454f5810f7e603cbd02daa036scroggo
1953965825b97a5809454f5810f7e603cbd02daa036scroggo   chunk_name = png_ptr->chunk_name;
1963965825b97a5809454f5810f7e603cbd02daa036scroggo
1973965825b97a5809454f5810f7e603cbd02daa036scroggo   if (chunk_name == png_IDAT)
1983965825b97a5809454f5810f7e603cbd02daa036scroggo   {
1993965825b97a5809454f5810f7e603cbd02daa036scroggo      if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
2003965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
2013965825b97a5809454f5810f7e603cbd02daa036scroggo
2023965825b97a5809454f5810f7e603cbd02daa036scroggo      /* If we reach an IDAT chunk, this means we have read all of the
2033965825b97a5809454f5810f7e603cbd02daa036scroggo       * header chunks, and we can start reading the image (or if this
2043965825b97a5809454f5810f7e603cbd02daa036scroggo       * is called after the image has been read - we have an error).
2053965825b97a5809454f5810f7e603cbd02daa036scroggo       */
2063965825b97a5809454f5810f7e603cbd02daa036scroggo      if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
2073965825b97a5809454f5810f7e603cbd02daa036scroggo         png_error(png_ptr, "Missing IHDR before IDAT");
2083965825b97a5809454f5810f7e603cbd02daa036scroggo
2093965825b97a5809454f5810f7e603cbd02daa036scroggo      else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
2103965825b97a5809454f5810f7e603cbd02daa036scroggo          (png_ptr->mode & PNG_HAVE_PLTE) == 0)
2113965825b97a5809454f5810f7e603cbd02daa036scroggo         png_error(png_ptr, "Missing PLTE before IDAT");
2123965825b97a5809454f5810f7e603cbd02daa036scroggo
2133965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->mode |= PNG_HAVE_IDAT;
2143965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->process_mode = PNG_READ_IDAT_MODE;
2153965825b97a5809454f5810f7e603cbd02daa036scroggo
2163965825b97a5809454f5810f7e603cbd02daa036scroggo      if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
2173965825b97a5809454f5810f7e603cbd02daa036scroggo         if (png_ptr->push_length == 0)
2183965825b97a5809454f5810f7e603cbd02daa036scroggo            return;
2193965825b97a5809454f5810f7e603cbd02daa036scroggo
2203965825b97a5809454f5810f7e603cbd02daa036scroggo      if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
2213965825b97a5809454f5810f7e603cbd02daa036scroggo         png_benign_error(png_ptr, "Too many IDATs found");
2223965825b97a5809454f5810f7e603cbd02daa036scroggo   }
2233965825b97a5809454f5810f7e603cbd02daa036scroggo
2243965825b97a5809454f5810f7e603cbd02daa036scroggo   if (chunk_name == png_IHDR)
2253965825b97a5809454f5810f7e603cbd02daa036scroggo   {
2263965825b97a5809454f5810f7e603cbd02daa036scroggo      if (png_ptr->push_length != 13)
2273965825b97a5809454f5810f7e603cbd02daa036scroggo         png_error(png_ptr, "Invalid IHDR length");
2283965825b97a5809454f5810f7e603cbd02daa036scroggo
2293965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
2303965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
2313965825b97a5809454f5810f7e603cbd02daa036scroggo   }
2323965825b97a5809454f5810f7e603cbd02daa036scroggo
2333965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_IEND)
2343965825b97a5809454f5810f7e603cbd02daa036scroggo   {
2353965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
2363965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
2373965825b97a5809454f5810f7e603cbd02daa036scroggo
2383965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->process_mode = PNG_READ_DONE_MODE;
2393965825b97a5809454f5810f7e603cbd02daa036scroggo      png_push_have_end(png_ptr, info_ptr);
2403965825b97a5809454f5810f7e603cbd02daa036scroggo   }
2413965825b97a5809454f5810f7e603cbd02daa036scroggo
2423965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
2433965825b97a5809454f5810f7e603cbd02daa036scroggo   else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
2443965825b97a5809454f5810f7e603cbd02daa036scroggo   {
2453965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
2463965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
2473965825b97a5809454f5810f7e603cbd02daa036scroggo
2483965825b97a5809454f5810f7e603cbd02daa036scroggo      if (chunk_name == png_PLTE)
2493965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->mode |= PNG_HAVE_PLTE;
2503965825b97a5809454f5810f7e603cbd02daa036scroggo   }
2513965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
2523965825b97a5809454f5810f7e603cbd02daa036scroggo
2533965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_PLTE)
2543965825b97a5809454f5810f7e603cbd02daa036scroggo   {
2553965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
2563965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
2573965825b97a5809454f5810f7e603cbd02daa036scroggo   }
2583965825b97a5809454f5810f7e603cbd02daa036scroggo
2593965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_IDAT)
2603965825b97a5809454f5810f7e603cbd02daa036scroggo   {
2613965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->idat_size = png_ptr->push_length;
2623965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->process_mode = PNG_READ_IDAT_MODE;
2633965825b97a5809454f5810f7e603cbd02daa036scroggo      png_push_have_info(png_ptr, info_ptr);
2643965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->zstream.avail_out =
2653965825b97a5809454f5810f7e603cbd02daa036scroggo          (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
2663965825b97a5809454f5810f7e603cbd02daa036scroggo          png_ptr->iwidth) + 1;
2673965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->zstream.next_out = png_ptr->row_buf;
2683965825b97a5809454f5810f7e603cbd02daa036scroggo      return;
2693965825b97a5809454f5810f7e603cbd02daa036scroggo   }
2703965825b97a5809454f5810f7e603cbd02daa036scroggo
2713965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_gAMA_SUPPORTED
2723965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (png_ptr->chunk_name == png_gAMA)
2733965825b97a5809454f5810f7e603cbd02daa036scroggo   {
2743965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
2753965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
2763965825b97a5809454f5810f7e603cbd02daa036scroggo   }
2773965825b97a5809454f5810f7e603cbd02daa036scroggo
2783965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
2793965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_sBIT_SUPPORTED
2803965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (png_ptr->chunk_name == png_sBIT)
2813965825b97a5809454f5810f7e603cbd02daa036scroggo   {
2823965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
2833965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
2843965825b97a5809454f5810f7e603cbd02daa036scroggo   }
2853965825b97a5809454f5810f7e603cbd02daa036scroggo
2863965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
2873965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_cHRM_SUPPORTED
2883965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (png_ptr->chunk_name == png_cHRM)
2893965825b97a5809454f5810f7e603cbd02daa036scroggo   {
2903965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
2913965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
2923965825b97a5809454f5810f7e603cbd02daa036scroggo   }
2933965825b97a5809454f5810f7e603cbd02daa036scroggo
2943965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
2953965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_sRGB_SUPPORTED
2963965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_sRGB)
2973965825b97a5809454f5810f7e603cbd02daa036scroggo   {
2983965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
2993965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
3003965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3013965825b97a5809454f5810f7e603cbd02daa036scroggo
3023965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3033965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_iCCP_SUPPORTED
3043965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (png_ptr->chunk_name == png_iCCP)
3053965825b97a5809454f5810f7e603cbd02daa036scroggo   {
3063965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
3073965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
3083965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3093965825b97a5809454f5810f7e603cbd02daa036scroggo
3103965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3113965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_sPLT_SUPPORTED
3123965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_sPLT)
3133965825b97a5809454f5810f7e603cbd02daa036scroggo   {
3143965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
3153965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
3163965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3173965825b97a5809454f5810f7e603cbd02daa036scroggo
3183965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3193965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_tRNS_SUPPORTED
3203965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_tRNS)
3213965825b97a5809454f5810f7e603cbd02daa036scroggo   {
3223965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
3233965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
3243965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3253965825b97a5809454f5810f7e603cbd02daa036scroggo
3263965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3273965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_bKGD_SUPPORTED
3283965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_bKGD)
3293965825b97a5809454f5810f7e603cbd02daa036scroggo   {
3303965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
3313965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
3323965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3333965825b97a5809454f5810f7e603cbd02daa036scroggo
3343965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3353965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_hIST_SUPPORTED
3363965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_hIST)
3373965825b97a5809454f5810f7e603cbd02daa036scroggo   {
3383965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
3393965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
3403965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3413965825b97a5809454f5810f7e603cbd02daa036scroggo
3423965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3433965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_pHYs_SUPPORTED
3443965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_pHYs)
3453965825b97a5809454f5810f7e603cbd02daa036scroggo   {
3463965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
3473965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
3483965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3493965825b97a5809454f5810f7e603cbd02daa036scroggo
3503965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3513965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_oFFs_SUPPORTED
3523965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_oFFs)
3533965825b97a5809454f5810f7e603cbd02daa036scroggo   {
3543965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
3553965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
3563965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3573965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3583965825b97a5809454f5810f7e603cbd02daa036scroggo
3593965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_pCAL_SUPPORTED
3603965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_pCAL)
3613965825b97a5809454f5810f7e603cbd02daa036scroggo   {
3623965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
3633965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
3643965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3653965825b97a5809454f5810f7e603cbd02daa036scroggo
3663965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3673965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_sCAL_SUPPORTED
3683965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_sCAL)
3693965825b97a5809454f5810f7e603cbd02daa036scroggo   {
3703965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
3713965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
3723965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3733965825b97a5809454f5810f7e603cbd02daa036scroggo
3743965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3753965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_tIME_SUPPORTED
3763965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_tIME)
3773965825b97a5809454f5810f7e603cbd02daa036scroggo   {
3783965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
3793965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
3803965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3813965825b97a5809454f5810f7e603cbd02daa036scroggo
3823965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3833965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_tEXt_SUPPORTED
3843965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_tEXt)
3853965825b97a5809454f5810f7e603cbd02daa036scroggo   {
3863965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
3873965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
3883965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3893965825b97a5809454f5810f7e603cbd02daa036scroggo
3903965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3913965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_zTXt_SUPPORTED
3923965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_zTXt)
3933965825b97a5809454f5810f7e603cbd02daa036scroggo   {
3943965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
3953965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
3963965825b97a5809454f5810f7e603cbd02daa036scroggo   }
3973965825b97a5809454f5810f7e603cbd02daa036scroggo
3983965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
3993965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_iTXt_SUPPORTED
4003965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (chunk_name == png_iTXt)
4013965825b97a5809454f5810f7e603cbd02daa036scroggo   {
4023965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
4033965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
4043965825b97a5809454f5810f7e603cbd02daa036scroggo   }
4053965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
4063965825b97a5809454f5810f7e603cbd02daa036scroggo
4073965825b97a5809454f5810f7e603cbd02daa036scroggo   else
4083965825b97a5809454f5810f7e603cbd02daa036scroggo   {
4093965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_FULL
4103965825b97a5809454f5810f7e603cbd02daa036scroggo      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
4113965825b97a5809454f5810f7e603cbd02daa036scroggo         PNG_HANDLE_CHUNK_AS_DEFAULT);
4123965825b97a5809454f5810f7e603cbd02daa036scroggo   }
4133965825b97a5809454f5810f7e603cbd02daa036scroggo
4143965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
4153965825b97a5809454f5810f7e603cbd02daa036scroggo}
4163965825b97a5809454f5810f7e603cbd02daa036scroggo
4173965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGCBAPI
4183965825b97a5809454f5810f7e603cbd02daa036scroggopng_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
4193965825b97a5809454f5810f7e603cbd02daa036scroggo{
4203965825b97a5809454f5810f7e603cbd02daa036scroggo   png_bytep ptr;
4213965825b97a5809454f5810f7e603cbd02daa036scroggo
4223965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr == NULL)
4233965825b97a5809454f5810f7e603cbd02daa036scroggo      return;
4243965825b97a5809454f5810f7e603cbd02daa036scroggo
4253965825b97a5809454f5810f7e603cbd02daa036scroggo   ptr = buffer;
4263965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->save_buffer_size != 0)
4273965825b97a5809454f5810f7e603cbd02daa036scroggo   {
4283965825b97a5809454f5810f7e603cbd02daa036scroggo      png_size_t save_size;
4293965825b97a5809454f5810f7e603cbd02daa036scroggo
4303965825b97a5809454f5810f7e603cbd02daa036scroggo      if (length < png_ptr->save_buffer_size)
4313965825b97a5809454f5810f7e603cbd02daa036scroggo         save_size = length;
4323965825b97a5809454f5810f7e603cbd02daa036scroggo
4333965825b97a5809454f5810f7e603cbd02daa036scroggo      else
4343965825b97a5809454f5810f7e603cbd02daa036scroggo         save_size = png_ptr->save_buffer_size;
4353965825b97a5809454f5810f7e603cbd02daa036scroggo
4363965825b97a5809454f5810f7e603cbd02daa036scroggo      memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
4373965825b97a5809454f5810f7e603cbd02daa036scroggo      length -= save_size;
4383965825b97a5809454f5810f7e603cbd02daa036scroggo      ptr += save_size;
4393965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->buffer_size -= save_size;
4403965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->save_buffer_size -= save_size;
4413965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->save_buffer_ptr += save_size;
4423965825b97a5809454f5810f7e603cbd02daa036scroggo   }
4433965825b97a5809454f5810f7e603cbd02daa036scroggo   if (length != 0 && png_ptr->current_buffer_size != 0)
4443965825b97a5809454f5810f7e603cbd02daa036scroggo   {
4453965825b97a5809454f5810f7e603cbd02daa036scroggo      png_size_t save_size;
4463965825b97a5809454f5810f7e603cbd02daa036scroggo
4473965825b97a5809454f5810f7e603cbd02daa036scroggo      if (length < png_ptr->current_buffer_size)
4483965825b97a5809454f5810f7e603cbd02daa036scroggo         save_size = length;
4493965825b97a5809454f5810f7e603cbd02daa036scroggo
4503965825b97a5809454f5810f7e603cbd02daa036scroggo      else
4513965825b97a5809454f5810f7e603cbd02daa036scroggo         save_size = png_ptr->current_buffer_size;
4523965825b97a5809454f5810f7e603cbd02daa036scroggo
4533965825b97a5809454f5810f7e603cbd02daa036scroggo      memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
4543965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->buffer_size -= save_size;
4553965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->current_buffer_size -= save_size;
4563965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->current_buffer_ptr += save_size;
4573965825b97a5809454f5810f7e603cbd02daa036scroggo   }
4583965825b97a5809454f5810f7e603cbd02daa036scroggo}
4593965825b97a5809454f5810f7e603cbd02daa036scroggo
4603965825b97a5809454f5810f7e603cbd02daa036scroggovoid /* PRIVATE */
4613965825b97a5809454f5810f7e603cbd02daa036scroggopng_push_save_buffer(png_structrp png_ptr)
4623965825b97a5809454f5810f7e603cbd02daa036scroggo{
4633965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->save_buffer_size != 0)
4643965825b97a5809454f5810f7e603cbd02daa036scroggo   {
4653965825b97a5809454f5810f7e603cbd02daa036scroggo      if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
4663965825b97a5809454f5810f7e603cbd02daa036scroggo      {
4673965825b97a5809454f5810f7e603cbd02daa036scroggo         png_size_t i, istop;
4683965825b97a5809454f5810f7e603cbd02daa036scroggo         png_bytep sp;
4693965825b97a5809454f5810f7e603cbd02daa036scroggo         png_bytep dp;
4703965825b97a5809454f5810f7e603cbd02daa036scroggo
4713965825b97a5809454f5810f7e603cbd02daa036scroggo         istop = png_ptr->save_buffer_size;
4723965825b97a5809454f5810f7e603cbd02daa036scroggo         for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
4733965825b97a5809454f5810f7e603cbd02daa036scroggo             i < istop; i++, sp++, dp++)
4743965825b97a5809454f5810f7e603cbd02daa036scroggo         {
4753965825b97a5809454f5810f7e603cbd02daa036scroggo            *dp = *sp;
4763965825b97a5809454f5810f7e603cbd02daa036scroggo         }
4773965825b97a5809454f5810f7e603cbd02daa036scroggo      }
4783965825b97a5809454f5810f7e603cbd02daa036scroggo   }
4793965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
4803965825b97a5809454f5810f7e603cbd02daa036scroggo       png_ptr->save_buffer_max)
4813965825b97a5809454f5810f7e603cbd02daa036scroggo   {
4823965825b97a5809454f5810f7e603cbd02daa036scroggo      png_size_t new_max;
4833965825b97a5809454f5810f7e603cbd02daa036scroggo      png_bytep old_buffer;
4843965825b97a5809454f5810f7e603cbd02daa036scroggo
4853965825b97a5809454f5810f7e603cbd02daa036scroggo      if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
4863965825b97a5809454f5810f7e603cbd02daa036scroggo          (png_ptr->current_buffer_size + 256))
4873965825b97a5809454f5810f7e603cbd02daa036scroggo      {
4883965825b97a5809454f5810f7e603cbd02daa036scroggo         png_error(png_ptr, "Potential overflow of save_buffer");
4893965825b97a5809454f5810f7e603cbd02daa036scroggo      }
4903965825b97a5809454f5810f7e603cbd02daa036scroggo
4913965825b97a5809454f5810f7e603cbd02daa036scroggo      new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
4923965825b97a5809454f5810f7e603cbd02daa036scroggo      old_buffer = png_ptr->save_buffer;
4933965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
4943965825b97a5809454f5810f7e603cbd02daa036scroggo          (png_size_t)new_max);
4953965825b97a5809454f5810f7e603cbd02daa036scroggo
4963965825b97a5809454f5810f7e603cbd02daa036scroggo      if (png_ptr->save_buffer == NULL)
4973965825b97a5809454f5810f7e603cbd02daa036scroggo      {
4983965825b97a5809454f5810f7e603cbd02daa036scroggo         png_free(png_ptr, old_buffer);
4993965825b97a5809454f5810f7e603cbd02daa036scroggo         png_error(png_ptr, "Insufficient memory for save_buffer");
5003965825b97a5809454f5810f7e603cbd02daa036scroggo      }
5013965825b97a5809454f5810f7e603cbd02daa036scroggo
5021915b0bab2b48cf8bf85dc49e76994b033f25450scroggo#if 0
5031915b0bab2b48cf8bf85dc49e76994b033f25450scroggo      // This is the code checked into libpng. Calling memcpy with a null
5041915b0bab2b48cf8bf85dc49e76994b033f25450scroggo      // source is undefined, even if count is 0, but libpng does not
5051915b0bab2b48cf8bf85dc49e76994b033f25450scroggo      // currently check for null or 0. The Skia fix is below.
5061915b0bab2b48cf8bf85dc49e76994b033f25450scroggo      // skbug.com/5390
5073965825b97a5809454f5810f7e603cbd02daa036scroggo      memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
5081915b0bab2b48cf8bf85dc49e76994b033f25450scroggo#else
5091915b0bab2b48cf8bf85dc49e76994b033f25450scroggo      if (old_buffer)
5101915b0bab2b48cf8bf85dc49e76994b033f25450scroggo         memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
5111915b0bab2b48cf8bf85dc49e76994b033f25450scroggo      else if (png_ptr->save_buffer_size)
5121915b0bab2b48cf8bf85dc49e76994b033f25450scroggo         png_error(png_ptr, "save_buffer error");
5131915b0bab2b48cf8bf85dc49e76994b033f25450scroggo#endif
5143965825b97a5809454f5810f7e603cbd02daa036scroggo      png_free(png_ptr, old_buffer);
5153965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->save_buffer_max = new_max;
5163965825b97a5809454f5810f7e603cbd02daa036scroggo   }
5173965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->current_buffer_size)
5183965825b97a5809454f5810f7e603cbd02daa036scroggo   {
5193965825b97a5809454f5810f7e603cbd02daa036scroggo      memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
5203965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
5213965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->save_buffer_size += png_ptr->current_buffer_size;
5223965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->current_buffer_size = 0;
5233965825b97a5809454f5810f7e603cbd02daa036scroggo   }
5243965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->save_buffer_ptr = png_ptr->save_buffer;
5253965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->buffer_size = 0;
5263965825b97a5809454f5810f7e603cbd02daa036scroggo}
5273965825b97a5809454f5810f7e603cbd02daa036scroggo
5283965825b97a5809454f5810f7e603cbd02daa036scroggovoid /* PRIVATE */
5293965825b97a5809454f5810f7e603cbd02daa036scroggopng_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
5303965825b97a5809454f5810f7e603cbd02daa036scroggo   png_size_t buffer_length)
5313965825b97a5809454f5810f7e603cbd02daa036scroggo{
5323965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->current_buffer = buffer;
5333965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->current_buffer_size = buffer_length;
5343965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
5353965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->current_buffer_ptr = png_ptr->current_buffer;
5363965825b97a5809454f5810f7e603cbd02daa036scroggo}
5373965825b97a5809454f5810f7e603cbd02daa036scroggo
5383965825b97a5809454f5810f7e603cbd02daa036scroggovoid /* PRIVATE */
5393965825b97a5809454f5810f7e603cbd02daa036scroggopng_push_read_IDAT(png_structrp png_ptr)
5403965825b97a5809454f5810f7e603cbd02daa036scroggo{
5413965825b97a5809454f5810f7e603cbd02daa036scroggo   if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
5423965825b97a5809454f5810f7e603cbd02daa036scroggo   {
5433965825b97a5809454f5810f7e603cbd02daa036scroggo      png_byte chunk_length[4];
5443965825b97a5809454f5810f7e603cbd02daa036scroggo      png_byte chunk_tag[4];
5453965825b97a5809454f5810f7e603cbd02daa036scroggo
5463965825b97a5809454f5810f7e603cbd02daa036scroggo      /* TODO: this code can be commoned up with the same code in push_read */
5473965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_LT(8)
5483965825b97a5809454f5810f7e603cbd02daa036scroggo      png_push_fill_buffer(png_ptr, chunk_length, 4);
5493965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
5503965825b97a5809454f5810f7e603cbd02daa036scroggo      png_reset_crc(png_ptr);
5513965825b97a5809454f5810f7e603cbd02daa036scroggo      png_crc_read(png_ptr, chunk_tag, 4);
5523965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
5533965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
5543965825b97a5809454f5810f7e603cbd02daa036scroggo
5553965825b97a5809454f5810f7e603cbd02daa036scroggo      if (png_ptr->chunk_name != png_IDAT)
5563965825b97a5809454f5810f7e603cbd02daa036scroggo      {
5573965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
5583965825b97a5809454f5810f7e603cbd02daa036scroggo
5593965825b97a5809454f5810f7e603cbd02daa036scroggo         if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
5603965825b97a5809454f5810f7e603cbd02daa036scroggo            png_error(png_ptr, "Not enough compressed data");
5613965825b97a5809454f5810f7e603cbd02daa036scroggo
5623965825b97a5809454f5810f7e603cbd02daa036scroggo         return;
5633965825b97a5809454f5810f7e603cbd02daa036scroggo      }
5643965825b97a5809454f5810f7e603cbd02daa036scroggo
5653965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->idat_size = png_ptr->push_length;
5663965825b97a5809454f5810f7e603cbd02daa036scroggo   }
5673965825b97a5809454f5810f7e603cbd02daa036scroggo
5683965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
5693965825b97a5809454f5810f7e603cbd02daa036scroggo   {
5703965825b97a5809454f5810f7e603cbd02daa036scroggo      png_size_t save_size = png_ptr->save_buffer_size;
5713965825b97a5809454f5810f7e603cbd02daa036scroggo      png_uint_32 idat_size = png_ptr->idat_size;
5723965825b97a5809454f5810f7e603cbd02daa036scroggo
5733965825b97a5809454f5810f7e603cbd02daa036scroggo      /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
5743965825b97a5809454f5810f7e603cbd02daa036scroggo       * are of different types and we don't know which variable has the fewest
5753965825b97a5809454f5810f7e603cbd02daa036scroggo       * bits.  Carefully select the smaller and cast it to the type of the
5763965825b97a5809454f5810f7e603cbd02daa036scroggo       * larger - this cannot overflow.  Do not cast in the following test - it
5773965825b97a5809454f5810f7e603cbd02daa036scroggo       * will break on either 16-bit or 64-bit platforms.
5783965825b97a5809454f5810f7e603cbd02daa036scroggo       */
5793965825b97a5809454f5810f7e603cbd02daa036scroggo      if (idat_size < save_size)
5803965825b97a5809454f5810f7e603cbd02daa036scroggo         save_size = (png_size_t)idat_size;
5813965825b97a5809454f5810f7e603cbd02daa036scroggo
5823965825b97a5809454f5810f7e603cbd02daa036scroggo      else
5833965825b97a5809454f5810f7e603cbd02daa036scroggo         idat_size = (png_uint_32)save_size;
5843965825b97a5809454f5810f7e603cbd02daa036scroggo
5853965825b97a5809454f5810f7e603cbd02daa036scroggo      png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
5863965825b97a5809454f5810f7e603cbd02daa036scroggo
5873965825b97a5809454f5810f7e603cbd02daa036scroggo      png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
5883965825b97a5809454f5810f7e603cbd02daa036scroggo
5893965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->idat_size -= idat_size;
5903965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->buffer_size -= save_size;
5913965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->save_buffer_size -= save_size;
5923965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->save_buffer_ptr += save_size;
5933965825b97a5809454f5810f7e603cbd02daa036scroggo   }
5943965825b97a5809454f5810f7e603cbd02daa036scroggo
5953965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0)
5963965825b97a5809454f5810f7e603cbd02daa036scroggo   {
5973965825b97a5809454f5810f7e603cbd02daa036scroggo      png_size_t save_size = png_ptr->current_buffer_size;
5983965825b97a5809454f5810f7e603cbd02daa036scroggo      png_uint_32 idat_size = png_ptr->idat_size;
5993965825b97a5809454f5810f7e603cbd02daa036scroggo
6003965825b97a5809454f5810f7e603cbd02daa036scroggo      /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
6013965825b97a5809454f5810f7e603cbd02daa036scroggo       * are of different types and we don't know which variable has the fewest
6023965825b97a5809454f5810f7e603cbd02daa036scroggo       * bits.  Carefully select the smaller and cast it to the type of the
6033965825b97a5809454f5810f7e603cbd02daa036scroggo       * larger - this cannot overflow.
6043965825b97a5809454f5810f7e603cbd02daa036scroggo       */
6053965825b97a5809454f5810f7e603cbd02daa036scroggo      if (idat_size < save_size)
6063965825b97a5809454f5810f7e603cbd02daa036scroggo         save_size = (png_size_t)idat_size;
6073965825b97a5809454f5810f7e603cbd02daa036scroggo
6083965825b97a5809454f5810f7e603cbd02daa036scroggo      else
6093965825b97a5809454f5810f7e603cbd02daa036scroggo         idat_size = (png_uint_32)save_size;
6103965825b97a5809454f5810f7e603cbd02daa036scroggo
6113965825b97a5809454f5810f7e603cbd02daa036scroggo      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
6123965825b97a5809454f5810f7e603cbd02daa036scroggo
6133965825b97a5809454f5810f7e603cbd02daa036scroggo      png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
6143965825b97a5809454f5810f7e603cbd02daa036scroggo
6153965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->idat_size -= idat_size;
6163965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->buffer_size -= save_size;
6173965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->current_buffer_size -= save_size;
6183965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->current_buffer_ptr += save_size;
6193965825b97a5809454f5810f7e603cbd02daa036scroggo   }
6203965825b97a5809454f5810f7e603cbd02daa036scroggo
6213965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->idat_size == 0)
6223965825b97a5809454f5810f7e603cbd02daa036scroggo   {
6233965825b97a5809454f5810f7e603cbd02daa036scroggo      PNG_PUSH_SAVE_BUFFER_IF_LT(4)
6243965825b97a5809454f5810f7e603cbd02daa036scroggo      png_crc_finish(png_ptr, 0);
6253965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
6263965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->mode |= PNG_AFTER_IDAT;
6273965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->zowner = 0;
6283965825b97a5809454f5810f7e603cbd02daa036scroggo   }
6293965825b97a5809454f5810f7e603cbd02daa036scroggo}
6303965825b97a5809454f5810f7e603cbd02daa036scroggo
6313965825b97a5809454f5810f7e603cbd02daa036scroggovoid /* PRIVATE */
6323965825b97a5809454f5810f7e603cbd02daa036scroggopng_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
6333965825b97a5809454f5810f7e603cbd02daa036scroggo   png_size_t buffer_length)
6343965825b97a5809454f5810f7e603cbd02daa036scroggo{
6353965825b97a5809454f5810f7e603cbd02daa036scroggo   /* The caller checks for a non-zero buffer length. */
6363965825b97a5809454f5810f7e603cbd02daa036scroggo   if (!(buffer_length > 0) || buffer == NULL)
6373965825b97a5809454f5810f7e603cbd02daa036scroggo      png_error(png_ptr, "No IDAT data (internal error)");
6383965825b97a5809454f5810f7e603cbd02daa036scroggo
6393965825b97a5809454f5810f7e603cbd02daa036scroggo   /* This routine must process all the data it has been given
6403965825b97a5809454f5810f7e603cbd02daa036scroggo    * before returning, calling the row callback as required to
6413965825b97a5809454f5810f7e603cbd02daa036scroggo    * handle the uncompressed results.
6423965825b97a5809454f5810f7e603cbd02daa036scroggo    */
6433965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->zstream.next_in = buffer;
6443965825b97a5809454f5810f7e603cbd02daa036scroggo   /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
6453965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->zstream.avail_in = (uInt)buffer_length;
6463965825b97a5809454f5810f7e603cbd02daa036scroggo
6473965825b97a5809454f5810f7e603cbd02daa036scroggo   /* Keep going until the decompressed data is all processed
6483965825b97a5809454f5810f7e603cbd02daa036scroggo    * or the stream marked as finished.
6493965825b97a5809454f5810f7e603cbd02daa036scroggo    */
6503965825b97a5809454f5810f7e603cbd02daa036scroggo   while (png_ptr->zstream.avail_in > 0 &&
6513965825b97a5809454f5810f7e603cbd02daa036scroggo      (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
6523965825b97a5809454f5810f7e603cbd02daa036scroggo   {
6533965825b97a5809454f5810f7e603cbd02daa036scroggo      int ret;
6543965825b97a5809454f5810f7e603cbd02daa036scroggo
6553965825b97a5809454f5810f7e603cbd02daa036scroggo      /* We have data for zlib, but we must check that zlib
6563965825b97a5809454f5810f7e603cbd02daa036scroggo       * has someplace to put the results.  It doesn't matter
6573965825b97a5809454f5810f7e603cbd02daa036scroggo       * if we don't expect any results -- it may be the input
6583965825b97a5809454f5810f7e603cbd02daa036scroggo       * data is just the LZ end code.
6593965825b97a5809454f5810f7e603cbd02daa036scroggo       */
6603965825b97a5809454f5810f7e603cbd02daa036scroggo      if (!(png_ptr->zstream.avail_out > 0))
6613965825b97a5809454f5810f7e603cbd02daa036scroggo      {
6623965825b97a5809454f5810f7e603cbd02daa036scroggo         /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
6633965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
6643965825b97a5809454f5810f7e603cbd02daa036scroggo             png_ptr->iwidth) + 1);
6653965825b97a5809454f5810f7e603cbd02daa036scroggo
6663965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->zstream.next_out = png_ptr->row_buf;
6673965825b97a5809454f5810f7e603cbd02daa036scroggo      }
6683965825b97a5809454f5810f7e603cbd02daa036scroggo
6693965825b97a5809454f5810f7e603cbd02daa036scroggo      /* Using Z_SYNC_FLUSH here means that an unterminated
6703965825b97a5809454f5810f7e603cbd02daa036scroggo       * LZ stream (a stream with a missing end code) can still
6713965825b97a5809454f5810f7e603cbd02daa036scroggo       * be handled, otherwise (Z_NO_FLUSH) a future zlib
6723965825b97a5809454f5810f7e603cbd02daa036scroggo       * implementation might defer output and therefore
6733965825b97a5809454f5810f7e603cbd02daa036scroggo       * change the current behavior (see comments in inflate.c
6743965825b97a5809454f5810f7e603cbd02daa036scroggo       * for why this doesn't happen at present with zlib 1.2.5).
6753965825b97a5809454f5810f7e603cbd02daa036scroggo       */
6763965825b97a5809454f5810f7e603cbd02daa036scroggo      ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH);
6773965825b97a5809454f5810f7e603cbd02daa036scroggo
6783965825b97a5809454f5810f7e603cbd02daa036scroggo      /* Check for any failure before proceeding. */
6793965825b97a5809454f5810f7e603cbd02daa036scroggo      if (ret != Z_OK && ret != Z_STREAM_END)
6803965825b97a5809454f5810f7e603cbd02daa036scroggo      {
6813965825b97a5809454f5810f7e603cbd02daa036scroggo         /* Terminate the decompression. */
6823965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
6833965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->zowner = 0;
6843965825b97a5809454f5810f7e603cbd02daa036scroggo
6853965825b97a5809454f5810f7e603cbd02daa036scroggo         /* This may be a truncated stream (missing or
6863965825b97a5809454f5810f7e603cbd02daa036scroggo          * damaged end code).  Treat that as a warning.
6873965825b97a5809454f5810f7e603cbd02daa036scroggo          */
6883965825b97a5809454f5810f7e603cbd02daa036scroggo         if (png_ptr->row_number >= png_ptr->num_rows ||
6893965825b97a5809454f5810f7e603cbd02daa036scroggo             png_ptr->pass > 6)
6903965825b97a5809454f5810f7e603cbd02daa036scroggo            png_warning(png_ptr, "Truncated compressed data in IDAT");
6913965825b97a5809454f5810f7e603cbd02daa036scroggo
6923965825b97a5809454f5810f7e603cbd02daa036scroggo         else
6933965825b97a5809454f5810f7e603cbd02daa036scroggo            png_error(png_ptr, "Decompression error in IDAT");
6943965825b97a5809454f5810f7e603cbd02daa036scroggo
6953965825b97a5809454f5810f7e603cbd02daa036scroggo         /* Skip the check on unprocessed input */
6963965825b97a5809454f5810f7e603cbd02daa036scroggo         return;
6973965825b97a5809454f5810f7e603cbd02daa036scroggo      }
6983965825b97a5809454f5810f7e603cbd02daa036scroggo
6993965825b97a5809454f5810f7e603cbd02daa036scroggo      /* Did inflate output any data? */
7003965825b97a5809454f5810f7e603cbd02daa036scroggo      if (png_ptr->zstream.next_out != png_ptr->row_buf)
7013965825b97a5809454f5810f7e603cbd02daa036scroggo      {
7023965825b97a5809454f5810f7e603cbd02daa036scroggo         /* Is this unexpected data after the last row?
7033965825b97a5809454f5810f7e603cbd02daa036scroggo          * If it is, artificially terminate the LZ output
7043965825b97a5809454f5810f7e603cbd02daa036scroggo          * here.
7053965825b97a5809454f5810f7e603cbd02daa036scroggo          */
7063965825b97a5809454f5810f7e603cbd02daa036scroggo         if (png_ptr->row_number >= png_ptr->num_rows ||
7073965825b97a5809454f5810f7e603cbd02daa036scroggo             png_ptr->pass > 6)
7083965825b97a5809454f5810f7e603cbd02daa036scroggo         {
7093965825b97a5809454f5810f7e603cbd02daa036scroggo            /* Extra data. */
7103965825b97a5809454f5810f7e603cbd02daa036scroggo            png_warning(png_ptr, "Extra compressed data in IDAT");
7113965825b97a5809454f5810f7e603cbd02daa036scroggo            png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
7123965825b97a5809454f5810f7e603cbd02daa036scroggo            png_ptr->zowner = 0;
7133965825b97a5809454f5810f7e603cbd02daa036scroggo
7143965825b97a5809454f5810f7e603cbd02daa036scroggo            /* Do no more processing; skip the unprocessed
7153965825b97a5809454f5810f7e603cbd02daa036scroggo             * input check below.
7163965825b97a5809454f5810f7e603cbd02daa036scroggo             */
7173965825b97a5809454f5810f7e603cbd02daa036scroggo            return;
7183965825b97a5809454f5810f7e603cbd02daa036scroggo         }
7193965825b97a5809454f5810f7e603cbd02daa036scroggo
7203965825b97a5809454f5810f7e603cbd02daa036scroggo         /* Do we have a complete row? */
7213965825b97a5809454f5810f7e603cbd02daa036scroggo         if (png_ptr->zstream.avail_out == 0)
7223965825b97a5809454f5810f7e603cbd02daa036scroggo            png_push_process_row(png_ptr);
7233965825b97a5809454f5810f7e603cbd02daa036scroggo      }
7243965825b97a5809454f5810f7e603cbd02daa036scroggo
7253965825b97a5809454f5810f7e603cbd02daa036scroggo      /* And check for the end of the stream. */
7263965825b97a5809454f5810f7e603cbd02daa036scroggo      if (ret == Z_STREAM_END)
7273965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
7283965825b97a5809454f5810f7e603cbd02daa036scroggo   }
7293965825b97a5809454f5810f7e603cbd02daa036scroggo
7303965825b97a5809454f5810f7e603cbd02daa036scroggo   /* All the data should have been processed, if anything
7313965825b97a5809454f5810f7e603cbd02daa036scroggo    * is left at this point we have bytes of IDAT data
7323965825b97a5809454f5810f7e603cbd02daa036scroggo    * after the zlib end code.
7333965825b97a5809454f5810f7e603cbd02daa036scroggo    */
7343965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->zstream.avail_in > 0)
7353965825b97a5809454f5810f7e603cbd02daa036scroggo      png_warning(png_ptr, "Extra compression data in IDAT");
7363965825b97a5809454f5810f7e603cbd02daa036scroggo}
7373965825b97a5809454f5810f7e603cbd02daa036scroggo
7383965825b97a5809454f5810f7e603cbd02daa036scroggovoid /* PRIVATE */
7393965825b97a5809454f5810f7e603cbd02daa036scroggopng_push_process_row(png_structrp png_ptr)
7403965825b97a5809454f5810f7e603cbd02daa036scroggo{
7413965825b97a5809454f5810f7e603cbd02daa036scroggo   /* 1.5.6: row_info moved out of png_struct to a local here. */
7423965825b97a5809454f5810f7e603cbd02daa036scroggo   png_row_info row_info;
7433965825b97a5809454f5810f7e603cbd02daa036scroggo
7443965825b97a5809454f5810f7e603cbd02daa036scroggo   row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
7453965825b97a5809454f5810f7e603cbd02daa036scroggo   row_info.color_type = png_ptr->color_type;
7463965825b97a5809454f5810f7e603cbd02daa036scroggo   row_info.bit_depth = png_ptr->bit_depth;
7473965825b97a5809454f5810f7e603cbd02daa036scroggo   row_info.channels = png_ptr->channels;
7483965825b97a5809454f5810f7e603cbd02daa036scroggo   row_info.pixel_depth = png_ptr->pixel_depth;
7493965825b97a5809454f5810f7e603cbd02daa036scroggo   row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
7503965825b97a5809454f5810f7e603cbd02daa036scroggo
7513965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
7523965825b97a5809454f5810f7e603cbd02daa036scroggo   {
7533965825b97a5809454f5810f7e603cbd02daa036scroggo      if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
7543965825b97a5809454f5810f7e603cbd02daa036scroggo         png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
7553965825b97a5809454f5810f7e603cbd02daa036scroggo            png_ptr->prev_row + 1, png_ptr->row_buf[0]);
7563965825b97a5809454f5810f7e603cbd02daa036scroggo      else
7573965825b97a5809454f5810f7e603cbd02daa036scroggo         png_error(png_ptr, "bad adaptive filter value");
7583965825b97a5809454f5810f7e603cbd02daa036scroggo   }
7593965825b97a5809454f5810f7e603cbd02daa036scroggo
7603965825b97a5809454f5810f7e603cbd02daa036scroggo   /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
7613965825b97a5809454f5810f7e603cbd02daa036scroggo    * 1.5.6, while the buffer really is this big in current versions of libpng
7623965825b97a5809454f5810f7e603cbd02daa036scroggo    * it may not be in the future, so this was changed just to copy the
7633965825b97a5809454f5810f7e603cbd02daa036scroggo    * interlaced row count:
7643965825b97a5809454f5810f7e603cbd02daa036scroggo    */
7653965825b97a5809454f5810f7e603cbd02daa036scroggo   memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
7663965825b97a5809454f5810f7e603cbd02daa036scroggo
7673965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_TRANSFORMS_SUPPORTED
7683965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->transformations != 0)
7693965825b97a5809454f5810f7e603cbd02daa036scroggo      png_do_read_transformations(png_ptr, &row_info);
7703965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
7713965825b97a5809454f5810f7e603cbd02daa036scroggo
7723965825b97a5809454f5810f7e603cbd02daa036scroggo   /* The transformed pixel depth should match the depth now in row_info. */
7733965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->transformed_pixel_depth == 0)
7743965825b97a5809454f5810f7e603cbd02daa036scroggo   {
7753965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->transformed_pixel_depth = row_info.pixel_depth;
7763965825b97a5809454f5810f7e603cbd02daa036scroggo      if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
7773965825b97a5809454f5810f7e603cbd02daa036scroggo         png_error(png_ptr, "progressive row overflow");
7783965825b97a5809454f5810f7e603cbd02daa036scroggo   }
7793965825b97a5809454f5810f7e603cbd02daa036scroggo
7803965825b97a5809454f5810f7e603cbd02daa036scroggo   else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
7813965825b97a5809454f5810f7e603cbd02daa036scroggo      png_error(png_ptr, "internal progressive row size calculation error");
7823965825b97a5809454f5810f7e603cbd02daa036scroggo
7833965825b97a5809454f5810f7e603cbd02daa036scroggo
7843965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_INTERLACING_SUPPORTED
7853965825b97a5809454f5810f7e603cbd02daa036scroggo   /* Expand interlaced rows to full size */
7863965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->interlaced != 0 &&
7873965825b97a5809454f5810f7e603cbd02daa036scroggo       (png_ptr->transformations & PNG_INTERLACE) != 0)
7883965825b97a5809454f5810f7e603cbd02daa036scroggo   {
7893965825b97a5809454f5810f7e603cbd02daa036scroggo      if (png_ptr->pass < 6)
7903965825b97a5809454f5810f7e603cbd02daa036scroggo         png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
7913965825b97a5809454f5810f7e603cbd02daa036scroggo            png_ptr->transformations);
7923965825b97a5809454f5810f7e603cbd02daa036scroggo
7933965825b97a5809454f5810f7e603cbd02daa036scroggo      switch (png_ptr->pass)
7943965825b97a5809454f5810f7e603cbd02daa036scroggo      {
7953965825b97a5809454f5810f7e603cbd02daa036scroggo         case 0:
7963965825b97a5809454f5810f7e603cbd02daa036scroggo         {
7973965825b97a5809454f5810f7e603cbd02daa036scroggo            int i;
7983965825b97a5809454f5810f7e603cbd02daa036scroggo            for (i = 0; i < 8 && png_ptr->pass == 0; i++)
7993965825b97a5809454f5810f7e603cbd02daa036scroggo            {
8003965825b97a5809454f5810f7e603cbd02daa036scroggo               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
8013965825b97a5809454f5810f7e603cbd02daa036scroggo               png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
8023965825b97a5809454f5810f7e603cbd02daa036scroggo            }
8033965825b97a5809454f5810f7e603cbd02daa036scroggo
8043965825b97a5809454f5810f7e603cbd02daa036scroggo            if (png_ptr->pass == 2) /* Pass 1 might be empty */
8053965825b97a5809454f5810f7e603cbd02daa036scroggo            {
8063965825b97a5809454f5810f7e603cbd02daa036scroggo               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
8073965825b97a5809454f5810f7e603cbd02daa036scroggo               {
8083965825b97a5809454f5810f7e603cbd02daa036scroggo                  png_push_have_row(png_ptr, NULL);
8093965825b97a5809454f5810f7e603cbd02daa036scroggo                  png_read_push_finish_row(png_ptr);
8103965825b97a5809454f5810f7e603cbd02daa036scroggo               }
8113965825b97a5809454f5810f7e603cbd02daa036scroggo            }
8123965825b97a5809454f5810f7e603cbd02daa036scroggo
8133965825b97a5809454f5810f7e603cbd02daa036scroggo            if (png_ptr->pass == 4 && png_ptr->height <= 4)
8143965825b97a5809454f5810f7e603cbd02daa036scroggo            {
8153965825b97a5809454f5810f7e603cbd02daa036scroggo               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
8163965825b97a5809454f5810f7e603cbd02daa036scroggo               {
8173965825b97a5809454f5810f7e603cbd02daa036scroggo                  png_push_have_row(png_ptr, NULL);
8183965825b97a5809454f5810f7e603cbd02daa036scroggo                  png_read_push_finish_row(png_ptr);
8193965825b97a5809454f5810f7e603cbd02daa036scroggo               }
8203965825b97a5809454f5810f7e603cbd02daa036scroggo            }
8213965825b97a5809454f5810f7e603cbd02daa036scroggo
8223965825b97a5809454f5810f7e603cbd02daa036scroggo            if (png_ptr->pass == 6 && png_ptr->height <= 4)
8233965825b97a5809454f5810f7e603cbd02daa036scroggo            {
8243965825b97a5809454f5810f7e603cbd02daa036scroggo                png_push_have_row(png_ptr, NULL);
8253965825b97a5809454f5810f7e603cbd02daa036scroggo                png_read_push_finish_row(png_ptr);
8263965825b97a5809454f5810f7e603cbd02daa036scroggo            }
8273965825b97a5809454f5810f7e603cbd02daa036scroggo
8283965825b97a5809454f5810f7e603cbd02daa036scroggo            break;
8293965825b97a5809454f5810f7e603cbd02daa036scroggo         }
8303965825b97a5809454f5810f7e603cbd02daa036scroggo
8313965825b97a5809454f5810f7e603cbd02daa036scroggo         case 1:
8323965825b97a5809454f5810f7e603cbd02daa036scroggo         {
8333965825b97a5809454f5810f7e603cbd02daa036scroggo            int i;
8343965825b97a5809454f5810f7e603cbd02daa036scroggo            for (i = 0; i < 8 && png_ptr->pass == 1; i++)
8353965825b97a5809454f5810f7e603cbd02daa036scroggo            {
8363965825b97a5809454f5810f7e603cbd02daa036scroggo               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
8373965825b97a5809454f5810f7e603cbd02daa036scroggo               png_read_push_finish_row(png_ptr);
8383965825b97a5809454f5810f7e603cbd02daa036scroggo            }
8393965825b97a5809454f5810f7e603cbd02daa036scroggo
8403965825b97a5809454f5810f7e603cbd02daa036scroggo            if (png_ptr->pass == 2) /* Skip top 4 generated rows */
8413965825b97a5809454f5810f7e603cbd02daa036scroggo            {
8423965825b97a5809454f5810f7e603cbd02daa036scroggo               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
8433965825b97a5809454f5810f7e603cbd02daa036scroggo               {
8443965825b97a5809454f5810f7e603cbd02daa036scroggo                  png_push_have_row(png_ptr, NULL);
8453965825b97a5809454f5810f7e603cbd02daa036scroggo                  png_read_push_finish_row(png_ptr);
8463965825b97a5809454f5810f7e603cbd02daa036scroggo               }
8473965825b97a5809454f5810f7e603cbd02daa036scroggo            }
8483965825b97a5809454f5810f7e603cbd02daa036scroggo
8493965825b97a5809454f5810f7e603cbd02daa036scroggo            break;
8503965825b97a5809454f5810f7e603cbd02daa036scroggo         }
8513965825b97a5809454f5810f7e603cbd02daa036scroggo
8523965825b97a5809454f5810f7e603cbd02daa036scroggo         case 2:
8533965825b97a5809454f5810f7e603cbd02daa036scroggo         {
8543965825b97a5809454f5810f7e603cbd02daa036scroggo            int i;
8553965825b97a5809454f5810f7e603cbd02daa036scroggo
8563965825b97a5809454f5810f7e603cbd02daa036scroggo            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
8573965825b97a5809454f5810f7e603cbd02daa036scroggo            {
8583965825b97a5809454f5810f7e603cbd02daa036scroggo               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
8593965825b97a5809454f5810f7e603cbd02daa036scroggo               png_read_push_finish_row(png_ptr);
8603965825b97a5809454f5810f7e603cbd02daa036scroggo            }
8613965825b97a5809454f5810f7e603cbd02daa036scroggo
8623965825b97a5809454f5810f7e603cbd02daa036scroggo            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
8633965825b97a5809454f5810f7e603cbd02daa036scroggo            {
8643965825b97a5809454f5810f7e603cbd02daa036scroggo               png_push_have_row(png_ptr, NULL);
8653965825b97a5809454f5810f7e603cbd02daa036scroggo               png_read_push_finish_row(png_ptr);
8663965825b97a5809454f5810f7e603cbd02daa036scroggo            }
8673965825b97a5809454f5810f7e603cbd02daa036scroggo
8683965825b97a5809454f5810f7e603cbd02daa036scroggo            if (png_ptr->pass == 4) /* Pass 3 might be empty */
8693965825b97a5809454f5810f7e603cbd02daa036scroggo            {
8703965825b97a5809454f5810f7e603cbd02daa036scroggo               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
8713965825b97a5809454f5810f7e603cbd02daa036scroggo               {
8723965825b97a5809454f5810f7e603cbd02daa036scroggo                  png_push_have_row(png_ptr, NULL);
8733965825b97a5809454f5810f7e603cbd02daa036scroggo                  png_read_push_finish_row(png_ptr);
8743965825b97a5809454f5810f7e603cbd02daa036scroggo               }
8753965825b97a5809454f5810f7e603cbd02daa036scroggo            }
8763965825b97a5809454f5810f7e603cbd02daa036scroggo
8773965825b97a5809454f5810f7e603cbd02daa036scroggo            break;
8783965825b97a5809454f5810f7e603cbd02daa036scroggo         }
8793965825b97a5809454f5810f7e603cbd02daa036scroggo
8803965825b97a5809454f5810f7e603cbd02daa036scroggo         case 3:
8813965825b97a5809454f5810f7e603cbd02daa036scroggo         {
8823965825b97a5809454f5810f7e603cbd02daa036scroggo            int i;
8833965825b97a5809454f5810f7e603cbd02daa036scroggo
8843965825b97a5809454f5810f7e603cbd02daa036scroggo            for (i = 0; i < 4 && png_ptr->pass == 3; i++)
8853965825b97a5809454f5810f7e603cbd02daa036scroggo            {
8863965825b97a5809454f5810f7e603cbd02daa036scroggo               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
8873965825b97a5809454f5810f7e603cbd02daa036scroggo               png_read_push_finish_row(png_ptr);
8883965825b97a5809454f5810f7e603cbd02daa036scroggo            }
8893965825b97a5809454f5810f7e603cbd02daa036scroggo
8903965825b97a5809454f5810f7e603cbd02daa036scroggo            if (png_ptr->pass == 4) /* Skip top two generated rows */
8913965825b97a5809454f5810f7e603cbd02daa036scroggo            {
8923965825b97a5809454f5810f7e603cbd02daa036scroggo               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
8933965825b97a5809454f5810f7e603cbd02daa036scroggo               {
8943965825b97a5809454f5810f7e603cbd02daa036scroggo                  png_push_have_row(png_ptr, NULL);
8953965825b97a5809454f5810f7e603cbd02daa036scroggo                  png_read_push_finish_row(png_ptr);
8963965825b97a5809454f5810f7e603cbd02daa036scroggo               }
8973965825b97a5809454f5810f7e603cbd02daa036scroggo            }
8983965825b97a5809454f5810f7e603cbd02daa036scroggo
8993965825b97a5809454f5810f7e603cbd02daa036scroggo            break;
9003965825b97a5809454f5810f7e603cbd02daa036scroggo         }
9013965825b97a5809454f5810f7e603cbd02daa036scroggo
9023965825b97a5809454f5810f7e603cbd02daa036scroggo         case 4:
9033965825b97a5809454f5810f7e603cbd02daa036scroggo         {
9043965825b97a5809454f5810f7e603cbd02daa036scroggo            int i;
9053965825b97a5809454f5810f7e603cbd02daa036scroggo
9063965825b97a5809454f5810f7e603cbd02daa036scroggo            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
9073965825b97a5809454f5810f7e603cbd02daa036scroggo            {
9083965825b97a5809454f5810f7e603cbd02daa036scroggo               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
9093965825b97a5809454f5810f7e603cbd02daa036scroggo               png_read_push_finish_row(png_ptr);
9103965825b97a5809454f5810f7e603cbd02daa036scroggo            }
9113965825b97a5809454f5810f7e603cbd02daa036scroggo
9123965825b97a5809454f5810f7e603cbd02daa036scroggo            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
9133965825b97a5809454f5810f7e603cbd02daa036scroggo            {
9143965825b97a5809454f5810f7e603cbd02daa036scroggo               png_push_have_row(png_ptr, NULL);
9153965825b97a5809454f5810f7e603cbd02daa036scroggo               png_read_push_finish_row(png_ptr);
9163965825b97a5809454f5810f7e603cbd02daa036scroggo            }
9173965825b97a5809454f5810f7e603cbd02daa036scroggo
9183965825b97a5809454f5810f7e603cbd02daa036scroggo            if (png_ptr->pass == 6) /* Pass 5 might be empty */
9193965825b97a5809454f5810f7e603cbd02daa036scroggo            {
9203965825b97a5809454f5810f7e603cbd02daa036scroggo               png_push_have_row(png_ptr, NULL);
9213965825b97a5809454f5810f7e603cbd02daa036scroggo               png_read_push_finish_row(png_ptr);
9223965825b97a5809454f5810f7e603cbd02daa036scroggo            }
9233965825b97a5809454f5810f7e603cbd02daa036scroggo
9243965825b97a5809454f5810f7e603cbd02daa036scroggo            break;
9253965825b97a5809454f5810f7e603cbd02daa036scroggo         }
9263965825b97a5809454f5810f7e603cbd02daa036scroggo
9273965825b97a5809454f5810f7e603cbd02daa036scroggo         case 5:
9283965825b97a5809454f5810f7e603cbd02daa036scroggo         {
9293965825b97a5809454f5810f7e603cbd02daa036scroggo            int i;
9303965825b97a5809454f5810f7e603cbd02daa036scroggo
9313965825b97a5809454f5810f7e603cbd02daa036scroggo            for (i = 0; i < 2 && png_ptr->pass == 5; i++)
9323965825b97a5809454f5810f7e603cbd02daa036scroggo            {
9333965825b97a5809454f5810f7e603cbd02daa036scroggo               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
9343965825b97a5809454f5810f7e603cbd02daa036scroggo               png_read_push_finish_row(png_ptr);
9353965825b97a5809454f5810f7e603cbd02daa036scroggo            }
9363965825b97a5809454f5810f7e603cbd02daa036scroggo
9373965825b97a5809454f5810f7e603cbd02daa036scroggo            if (png_ptr->pass == 6) /* Skip top generated row */
9383965825b97a5809454f5810f7e603cbd02daa036scroggo            {
9393965825b97a5809454f5810f7e603cbd02daa036scroggo               png_push_have_row(png_ptr, NULL);
9403965825b97a5809454f5810f7e603cbd02daa036scroggo               png_read_push_finish_row(png_ptr);
9413965825b97a5809454f5810f7e603cbd02daa036scroggo            }
9423965825b97a5809454f5810f7e603cbd02daa036scroggo
9433965825b97a5809454f5810f7e603cbd02daa036scroggo            break;
9443965825b97a5809454f5810f7e603cbd02daa036scroggo         }
9453965825b97a5809454f5810f7e603cbd02daa036scroggo
9463965825b97a5809454f5810f7e603cbd02daa036scroggo         default:
9473965825b97a5809454f5810f7e603cbd02daa036scroggo         case 6:
9483965825b97a5809454f5810f7e603cbd02daa036scroggo         {
9493965825b97a5809454f5810f7e603cbd02daa036scroggo            png_push_have_row(png_ptr, png_ptr->row_buf + 1);
9503965825b97a5809454f5810f7e603cbd02daa036scroggo            png_read_push_finish_row(png_ptr);
9513965825b97a5809454f5810f7e603cbd02daa036scroggo
9523965825b97a5809454f5810f7e603cbd02daa036scroggo            if (png_ptr->pass != 6)
9533965825b97a5809454f5810f7e603cbd02daa036scroggo               break;
9543965825b97a5809454f5810f7e603cbd02daa036scroggo
9553965825b97a5809454f5810f7e603cbd02daa036scroggo            png_push_have_row(png_ptr, NULL);
9563965825b97a5809454f5810f7e603cbd02daa036scroggo            png_read_push_finish_row(png_ptr);
9573965825b97a5809454f5810f7e603cbd02daa036scroggo         }
9583965825b97a5809454f5810f7e603cbd02daa036scroggo      }
9593965825b97a5809454f5810f7e603cbd02daa036scroggo   }
9603965825b97a5809454f5810f7e603cbd02daa036scroggo   else
9613965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
9623965825b97a5809454f5810f7e603cbd02daa036scroggo   {
9633965825b97a5809454f5810f7e603cbd02daa036scroggo      png_push_have_row(png_ptr, png_ptr->row_buf + 1);
9643965825b97a5809454f5810f7e603cbd02daa036scroggo      png_read_push_finish_row(png_ptr);
9653965825b97a5809454f5810f7e603cbd02daa036scroggo   }
9663965825b97a5809454f5810f7e603cbd02daa036scroggo}
9673965825b97a5809454f5810f7e603cbd02daa036scroggo
9683965825b97a5809454f5810f7e603cbd02daa036scroggovoid /* PRIVATE */
9693965825b97a5809454f5810f7e603cbd02daa036scroggopng_read_push_finish_row(png_structrp png_ptr)
9703965825b97a5809454f5810f7e603cbd02daa036scroggo{
9713965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_INTERLACING_SUPPORTED
9723965825b97a5809454f5810f7e603cbd02daa036scroggo   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
9733965825b97a5809454f5810f7e603cbd02daa036scroggo
9743965825b97a5809454f5810f7e603cbd02daa036scroggo   /* Start of interlace block */
9753965825b97a5809454f5810f7e603cbd02daa036scroggo   static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
9763965825b97a5809454f5810f7e603cbd02daa036scroggo
9773965825b97a5809454f5810f7e603cbd02daa036scroggo   /* Offset to next interlace block */
9783965825b97a5809454f5810f7e603cbd02daa036scroggo   static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
9793965825b97a5809454f5810f7e603cbd02daa036scroggo
9803965825b97a5809454f5810f7e603cbd02daa036scroggo   /* Start of interlace block in the y direction */
9813965825b97a5809454f5810f7e603cbd02daa036scroggo   static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
9823965825b97a5809454f5810f7e603cbd02daa036scroggo
9833965825b97a5809454f5810f7e603cbd02daa036scroggo   /* Offset to next interlace block in the y direction */
9843965825b97a5809454f5810f7e603cbd02daa036scroggo   static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
9853965825b97a5809454f5810f7e603cbd02daa036scroggo
9863965825b97a5809454f5810f7e603cbd02daa036scroggo   /* Height of interlace block.  This is not currently used - if you need
9873965825b97a5809454f5810f7e603cbd02daa036scroggo    * it, uncomment it here and in png.h
9883965825b97a5809454f5810f7e603cbd02daa036scroggo   static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
9893965825b97a5809454f5810f7e603cbd02daa036scroggo   */
9903965825b97a5809454f5810f7e603cbd02daa036scroggo#endif
9913965825b97a5809454f5810f7e603cbd02daa036scroggo
9923965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->row_number++;
9933965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->row_number < png_ptr->num_rows)
9943965825b97a5809454f5810f7e603cbd02daa036scroggo      return;
9953965825b97a5809454f5810f7e603cbd02daa036scroggo
9963965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_INTERLACING_SUPPORTED
9973965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->interlaced != 0)
9983965825b97a5809454f5810f7e603cbd02daa036scroggo   {
9993965825b97a5809454f5810f7e603cbd02daa036scroggo      png_ptr->row_number = 0;
10003965825b97a5809454f5810f7e603cbd02daa036scroggo      memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
10013965825b97a5809454f5810f7e603cbd02daa036scroggo
10023965825b97a5809454f5810f7e603cbd02daa036scroggo      do
10033965825b97a5809454f5810f7e603cbd02daa036scroggo      {
10043965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->pass++;
10053965825b97a5809454f5810f7e603cbd02daa036scroggo         if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
10063965825b97a5809454f5810f7e603cbd02daa036scroggo             (png_ptr->pass == 3 && png_ptr->width < 3) ||
10073965825b97a5809454f5810f7e603cbd02daa036scroggo             (png_ptr->pass == 5 && png_ptr->width < 2))
10083965825b97a5809454f5810f7e603cbd02daa036scroggo            png_ptr->pass++;
10093965825b97a5809454f5810f7e603cbd02daa036scroggo
10103965825b97a5809454f5810f7e603cbd02daa036scroggo         if (png_ptr->pass > 7)
10113965825b97a5809454f5810f7e603cbd02daa036scroggo            png_ptr->pass--;
10123965825b97a5809454f5810f7e603cbd02daa036scroggo
10133965825b97a5809454f5810f7e603cbd02daa036scroggo         if (png_ptr->pass >= 7)
10143965825b97a5809454f5810f7e603cbd02daa036scroggo            break;
10153965825b97a5809454f5810f7e603cbd02daa036scroggo
10163965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->iwidth = (png_ptr->width +
10173965825b97a5809454f5810f7e603cbd02daa036scroggo             png_pass_inc[png_ptr->pass] - 1 -
10183965825b97a5809454f5810f7e603cbd02daa036scroggo             png_pass_start[png_ptr->pass]) /
10193965825b97a5809454f5810f7e603cbd02daa036scroggo             png_pass_inc[png_ptr->pass];
10203965825b97a5809454f5810f7e603cbd02daa036scroggo
10213965825b97a5809454f5810f7e603cbd02daa036scroggo         if ((png_ptr->transformations & PNG_INTERLACE) != 0)
10223965825b97a5809454f5810f7e603cbd02daa036scroggo            break;
10233965825b97a5809454f5810f7e603cbd02daa036scroggo
10243965825b97a5809454f5810f7e603cbd02daa036scroggo         png_ptr->num_rows = (png_ptr->height +
10253965825b97a5809454f5810f7e603cbd02daa036scroggo             png_pass_yinc[png_ptr->pass] - 1 -
10263965825b97a5809454f5810f7e603cbd02daa036scroggo             png_pass_ystart[png_ptr->pass]) /
10273965825b97a5809454f5810f7e603cbd02daa036scroggo             png_pass_yinc[png_ptr->pass];
10283965825b97a5809454f5810f7e603cbd02daa036scroggo
10293965825b97a5809454f5810f7e603cbd02daa036scroggo      } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
10303965825b97a5809454f5810f7e603cbd02daa036scroggo   }
10313965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* READ_INTERLACING */
10323965825b97a5809454f5810f7e603cbd02daa036scroggo}
10333965825b97a5809454f5810f7e603cbd02daa036scroggo
10343965825b97a5809454f5810f7e603cbd02daa036scroggovoid /* PRIVATE */
10353965825b97a5809454f5810f7e603cbd02daa036scroggopng_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
10363965825b97a5809454f5810f7e603cbd02daa036scroggo{
10373965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->info_fn != NULL)
10383965825b97a5809454f5810f7e603cbd02daa036scroggo      (*(png_ptr->info_fn))(png_ptr, info_ptr);
10393965825b97a5809454f5810f7e603cbd02daa036scroggo}
10403965825b97a5809454f5810f7e603cbd02daa036scroggo
10413965825b97a5809454f5810f7e603cbd02daa036scroggovoid /* PRIVATE */
10423965825b97a5809454f5810f7e603cbd02daa036scroggopng_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
10433965825b97a5809454f5810f7e603cbd02daa036scroggo{
10443965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->end_fn != NULL)
10453965825b97a5809454f5810f7e603cbd02daa036scroggo      (*(png_ptr->end_fn))(png_ptr, info_ptr);
10463965825b97a5809454f5810f7e603cbd02daa036scroggo}
10473965825b97a5809454f5810f7e603cbd02daa036scroggo
10483965825b97a5809454f5810f7e603cbd02daa036scroggovoid /* PRIVATE */
10493965825b97a5809454f5810f7e603cbd02daa036scroggopng_push_have_row(png_structrp png_ptr, png_bytep row)
10503965825b97a5809454f5810f7e603cbd02daa036scroggo{
10513965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr->row_fn != NULL)
10523965825b97a5809454f5810f7e603cbd02daa036scroggo      (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
10533965825b97a5809454f5810f7e603cbd02daa036scroggo         (int)png_ptr->pass);
10543965825b97a5809454f5810f7e603cbd02daa036scroggo}
10553965825b97a5809454f5810f7e603cbd02daa036scroggo
10563965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_INTERLACING_SUPPORTED
10573965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI
10583965825b97a5809454f5810f7e603cbd02daa036scroggopng_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
10593965825b97a5809454f5810f7e603cbd02daa036scroggo    png_const_bytep new_row)
10603965825b97a5809454f5810f7e603cbd02daa036scroggo{
10613965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr == NULL)
10623965825b97a5809454f5810f7e603cbd02daa036scroggo      return;
10633965825b97a5809454f5810f7e603cbd02daa036scroggo
10643965825b97a5809454f5810f7e603cbd02daa036scroggo   /* new_row is a flag here - if it is NULL then the app callback was called
10653965825b97a5809454f5810f7e603cbd02daa036scroggo    * from an empty row (see the calls to png_struct::row_fn below), otherwise
10663965825b97a5809454f5810f7e603cbd02daa036scroggo    * it must be png_ptr->row_buf+1
10673965825b97a5809454f5810f7e603cbd02daa036scroggo    */
10683965825b97a5809454f5810f7e603cbd02daa036scroggo   if (new_row != NULL)
10693965825b97a5809454f5810f7e603cbd02daa036scroggo      png_combine_row(png_ptr, old_row, 1/*blocky display*/);
10703965825b97a5809454f5810f7e603cbd02daa036scroggo}
10713965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* READ_INTERLACING */
10723965825b97a5809454f5810f7e603cbd02daa036scroggo
10733965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI
10743965825b97a5809454f5810f7e603cbd02daa036scroggopng_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
10753965825b97a5809454f5810f7e603cbd02daa036scroggo    png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
10763965825b97a5809454f5810f7e603cbd02daa036scroggo    png_progressive_end_ptr end_fn)
10773965825b97a5809454f5810f7e603cbd02daa036scroggo{
10783965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr == NULL)
10793965825b97a5809454f5810f7e603cbd02daa036scroggo      return;
10803965825b97a5809454f5810f7e603cbd02daa036scroggo
10813965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->info_fn = info_fn;
10823965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->row_fn = row_fn;
10833965825b97a5809454f5810f7e603cbd02daa036scroggo   png_ptr->end_fn = end_fn;
10843965825b97a5809454f5810f7e603cbd02daa036scroggo
10853965825b97a5809454f5810f7e603cbd02daa036scroggo   png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
10863965825b97a5809454f5810f7e603cbd02daa036scroggo}
10873965825b97a5809454f5810f7e603cbd02daa036scroggo
10883965825b97a5809454f5810f7e603cbd02daa036scroggopng_voidp PNGAPI
10893965825b97a5809454f5810f7e603cbd02daa036scroggopng_get_progressive_ptr(png_const_structrp png_ptr)
10903965825b97a5809454f5810f7e603cbd02daa036scroggo{
10913965825b97a5809454f5810f7e603cbd02daa036scroggo   if (png_ptr == NULL)
10923965825b97a5809454f5810f7e603cbd02daa036scroggo      return (NULL);
10933965825b97a5809454f5810f7e603cbd02daa036scroggo
10943965825b97a5809454f5810f7e603cbd02daa036scroggo   return png_ptr->io_ptr;
10953965825b97a5809454f5810f7e603cbd02daa036scroggo}
10963965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* PROGRESSIVE_READ */
1097