xref: /aosp_15_r20/external/libpng/pngpread.c (revision a67afe4df73cf47866eedc69947994b8ff839aba)
1*a67afe4dSAndroid Build Coastguard Worker 
2*a67afe4dSAndroid Build Coastguard Worker /* pngpread.c - read a png file in push mode
3*a67afe4dSAndroid Build Coastguard Worker  *
4*a67afe4dSAndroid Build Coastguard Worker  * Copyright (c) 2018-2024 Cosmin Truta
5*a67afe4dSAndroid Build Coastguard Worker  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
6*a67afe4dSAndroid Build Coastguard Worker  * Copyright (c) 1996-1997 Andreas Dilger
7*a67afe4dSAndroid Build Coastguard Worker  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
8*a67afe4dSAndroid Build Coastguard Worker  *
9*a67afe4dSAndroid Build Coastguard Worker  * This code is released under the libpng license.
10*a67afe4dSAndroid Build Coastguard Worker  * For conditions of distribution and use, see the disclaimer
11*a67afe4dSAndroid Build Coastguard Worker  * and license in png.h
12*a67afe4dSAndroid Build Coastguard Worker  */
13*a67afe4dSAndroid Build Coastguard Worker 
14*a67afe4dSAndroid Build Coastguard Worker #include "pngpriv.h"
15*a67afe4dSAndroid Build Coastguard Worker 
16*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
17*a67afe4dSAndroid Build Coastguard Worker 
18*a67afe4dSAndroid Build Coastguard Worker /* Push model modes */
19*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_SIG_MODE   0
20*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_CHUNK_MODE 1
21*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_IDAT_MODE  2
22*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_tEXt_MODE  4
23*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_zTXt_MODE  5
24*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_DONE_MODE  6
25*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_iTXt_MODE  7
26*a67afe4dSAndroid Build Coastguard Worker #define PNG_ERROR_MODE      8
27*a67afe4dSAndroid Build Coastguard Worker 
28*a67afe4dSAndroid Build Coastguard Worker #define PNG_PUSH_SAVE_BUFFER_IF_FULL \
29*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->push_length + 4 > png_ptr->buffer_size) \
30*a67afe4dSAndroid Build Coastguard Worker    { png_push_save_buffer(png_ptr); return; }
31*a67afe4dSAndroid Build Coastguard Worker #define PNG_PUSH_SAVE_BUFFER_IF_LT(N) \
32*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->buffer_size < N) \
33*a67afe4dSAndroid Build Coastguard Worker    { png_push_save_buffer(png_ptr); return; }
34*a67afe4dSAndroid Build Coastguard Worker 
35*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_process_data(png_structrp png_ptr,png_inforp info_ptr,png_bytep buffer,size_t buffer_size)36*a67afe4dSAndroid Build Coastguard Worker png_process_data(png_structrp png_ptr, png_inforp info_ptr,
37*a67afe4dSAndroid Build Coastguard Worker     png_bytep buffer, size_t buffer_size)
38*a67afe4dSAndroid Build Coastguard Worker {
39*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr == NULL || info_ptr == NULL)
40*a67afe4dSAndroid Build Coastguard Worker       return;
41*a67afe4dSAndroid Build Coastguard Worker 
42*a67afe4dSAndroid Build Coastguard Worker    png_push_restore_buffer(png_ptr, buffer, buffer_size);
43*a67afe4dSAndroid Build Coastguard Worker 
44*a67afe4dSAndroid Build Coastguard Worker    while (png_ptr->buffer_size)
45*a67afe4dSAndroid Build Coastguard Worker    {
46*a67afe4dSAndroid Build Coastguard Worker       png_process_some_data(png_ptr, info_ptr);
47*a67afe4dSAndroid Build Coastguard Worker    }
48*a67afe4dSAndroid Build Coastguard Worker }
49*a67afe4dSAndroid Build Coastguard Worker 
50*a67afe4dSAndroid Build Coastguard Worker size_t PNGAPI
png_process_data_pause(png_structrp png_ptr,int save)51*a67afe4dSAndroid Build Coastguard Worker png_process_data_pause(png_structrp png_ptr, int save)
52*a67afe4dSAndroid Build Coastguard Worker {
53*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr != NULL)
54*a67afe4dSAndroid Build Coastguard Worker    {
55*a67afe4dSAndroid Build Coastguard Worker       /* It's easiest for the caller if we do the save; then the caller doesn't
56*a67afe4dSAndroid Build Coastguard Worker        * have to supply the same data again:
57*a67afe4dSAndroid Build Coastguard Worker        */
58*a67afe4dSAndroid Build Coastguard Worker       if (save != 0)
59*a67afe4dSAndroid Build Coastguard Worker          png_push_save_buffer(png_ptr);
60*a67afe4dSAndroid Build Coastguard Worker       else
61*a67afe4dSAndroid Build Coastguard Worker       {
62*a67afe4dSAndroid Build Coastguard Worker          /* This includes any pending saved bytes: */
63*a67afe4dSAndroid Build Coastguard Worker          size_t remaining = png_ptr->buffer_size;
64*a67afe4dSAndroid Build Coastguard Worker          png_ptr->buffer_size = 0;
65*a67afe4dSAndroid Build Coastguard Worker 
66*a67afe4dSAndroid Build Coastguard Worker          /* So subtract the saved buffer size, unless all the data
67*a67afe4dSAndroid Build Coastguard Worker           * is actually 'saved', in which case we just return 0
68*a67afe4dSAndroid Build Coastguard Worker           */
69*a67afe4dSAndroid Build Coastguard Worker          if (png_ptr->save_buffer_size < remaining)
70*a67afe4dSAndroid Build Coastguard Worker             return remaining - png_ptr->save_buffer_size;
71*a67afe4dSAndroid Build Coastguard Worker       }
72*a67afe4dSAndroid Build Coastguard Worker    }
73*a67afe4dSAndroid Build Coastguard Worker 
74*a67afe4dSAndroid Build Coastguard Worker    return 0;
75*a67afe4dSAndroid Build Coastguard Worker }
76*a67afe4dSAndroid Build Coastguard Worker 
77*a67afe4dSAndroid Build Coastguard Worker png_uint_32 PNGAPI
png_process_data_skip(png_structrp png_ptr)78*a67afe4dSAndroid Build Coastguard Worker png_process_data_skip(png_structrp png_ptr)
79*a67afe4dSAndroid Build Coastguard Worker {
80*a67afe4dSAndroid Build Coastguard Worker /* TODO: Deprecate and remove this API.
81*a67afe4dSAndroid Build Coastguard Worker  * Somewhere the implementation of this seems to have been lost,
82*a67afe4dSAndroid Build Coastguard Worker  * or abandoned.  It was only to support some internal back-door access
83*a67afe4dSAndroid Build Coastguard Worker  * to png_struct) in libpng-1.4.x.
84*a67afe4dSAndroid Build Coastguard Worker  */
85*a67afe4dSAndroid Build Coastguard Worker    png_app_warning(png_ptr,
86*a67afe4dSAndroid Build Coastguard Worker "png_process_data_skip is not implemented in any current version of libpng");
87*a67afe4dSAndroid Build Coastguard Worker    return 0;
88*a67afe4dSAndroid Build Coastguard Worker }
89*a67afe4dSAndroid Build Coastguard Worker 
90*a67afe4dSAndroid Build Coastguard Worker /* What we do with the incoming data depends on what we were previously
91*a67afe4dSAndroid Build Coastguard Worker  * doing before we ran out of data...
92*a67afe4dSAndroid Build Coastguard Worker  */
93*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_process_some_data(png_structrp png_ptr,png_inforp info_ptr)94*a67afe4dSAndroid Build Coastguard Worker png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
95*a67afe4dSAndroid Build Coastguard Worker {
96*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr == NULL)
97*a67afe4dSAndroid Build Coastguard Worker       return;
98*a67afe4dSAndroid Build Coastguard Worker 
99*a67afe4dSAndroid Build Coastguard Worker    switch (png_ptr->process_mode)
100*a67afe4dSAndroid Build Coastguard Worker    {
101*a67afe4dSAndroid Build Coastguard Worker       case PNG_READ_SIG_MODE:
102*a67afe4dSAndroid Build Coastguard Worker       {
103*a67afe4dSAndroid Build Coastguard Worker          png_push_read_sig(png_ptr, info_ptr);
104*a67afe4dSAndroid Build Coastguard Worker          break;
105*a67afe4dSAndroid Build Coastguard Worker       }
106*a67afe4dSAndroid Build Coastguard Worker 
107*a67afe4dSAndroid Build Coastguard Worker       case PNG_READ_CHUNK_MODE:
108*a67afe4dSAndroid Build Coastguard Worker       {
109*a67afe4dSAndroid Build Coastguard Worker          png_push_read_chunk(png_ptr, info_ptr);
110*a67afe4dSAndroid Build Coastguard Worker          break;
111*a67afe4dSAndroid Build Coastguard Worker       }
112*a67afe4dSAndroid Build Coastguard Worker 
113*a67afe4dSAndroid Build Coastguard Worker       case PNG_READ_IDAT_MODE:
114*a67afe4dSAndroid Build Coastguard Worker       {
115*a67afe4dSAndroid Build Coastguard Worker          png_push_read_IDAT(png_ptr);
116*a67afe4dSAndroid Build Coastguard Worker          break;
117*a67afe4dSAndroid Build Coastguard Worker       }
118*a67afe4dSAndroid Build Coastguard Worker 
119*a67afe4dSAndroid Build Coastguard Worker       default:
120*a67afe4dSAndroid Build Coastguard Worker       {
121*a67afe4dSAndroid Build Coastguard Worker          png_ptr->buffer_size = 0;
122*a67afe4dSAndroid Build Coastguard Worker          break;
123*a67afe4dSAndroid Build Coastguard Worker       }
124*a67afe4dSAndroid Build Coastguard Worker    }
125*a67afe4dSAndroid Build Coastguard Worker }
126*a67afe4dSAndroid Build Coastguard Worker 
127*a67afe4dSAndroid Build Coastguard Worker /* Read any remaining signature bytes from the stream and compare them with
128*a67afe4dSAndroid Build Coastguard Worker  * the correct PNG signature.  It is possible that this routine is called
129*a67afe4dSAndroid Build Coastguard Worker  * with bytes already read from the signature, either because they have been
130*a67afe4dSAndroid Build Coastguard Worker  * checked by the calling application, or because of multiple calls to this
131*a67afe4dSAndroid Build Coastguard Worker  * routine.
132*a67afe4dSAndroid Build Coastguard Worker  */
133*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_read_sig(png_structrp png_ptr,png_inforp info_ptr)134*a67afe4dSAndroid Build Coastguard Worker png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
135*a67afe4dSAndroid Build Coastguard Worker {
136*a67afe4dSAndroid Build Coastguard Worker    size_t num_checked = png_ptr->sig_bytes; /* SAFE, does not exceed 8 */
137*a67afe4dSAndroid Build Coastguard Worker    size_t num_to_check = 8 - num_checked;
138*a67afe4dSAndroid Build Coastguard Worker 
139*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->buffer_size < num_to_check)
140*a67afe4dSAndroid Build Coastguard Worker    {
141*a67afe4dSAndroid Build Coastguard Worker       num_to_check = png_ptr->buffer_size;
142*a67afe4dSAndroid Build Coastguard Worker    }
143*a67afe4dSAndroid Build Coastguard Worker 
144*a67afe4dSAndroid Build Coastguard Worker    png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
145*a67afe4dSAndroid Build Coastguard Worker        num_to_check);
146*a67afe4dSAndroid Build Coastguard Worker    png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
147*a67afe4dSAndroid Build Coastguard Worker 
148*a67afe4dSAndroid Build Coastguard Worker    if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
149*a67afe4dSAndroid Build Coastguard Worker    {
150*a67afe4dSAndroid Build Coastguard Worker       if (num_checked < 4 &&
151*a67afe4dSAndroid Build Coastguard Worker           png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0)
152*a67afe4dSAndroid Build Coastguard Worker          png_error(png_ptr, "Not a PNG file");
153*a67afe4dSAndroid Build Coastguard Worker 
154*a67afe4dSAndroid Build Coastguard Worker       else
155*a67afe4dSAndroid Build Coastguard Worker          png_error(png_ptr, "PNG file corrupted by ASCII conversion");
156*a67afe4dSAndroid Build Coastguard Worker    }
157*a67afe4dSAndroid Build Coastguard Worker    else
158*a67afe4dSAndroid Build Coastguard Worker    {
159*a67afe4dSAndroid Build Coastguard Worker       if (png_ptr->sig_bytes >= 8)
160*a67afe4dSAndroid Build Coastguard Worker       {
161*a67afe4dSAndroid Build Coastguard Worker          png_ptr->process_mode = PNG_READ_CHUNK_MODE;
162*a67afe4dSAndroid Build Coastguard Worker       }
163*a67afe4dSAndroid Build Coastguard Worker    }
164*a67afe4dSAndroid Build Coastguard Worker }
165*a67afe4dSAndroid Build Coastguard Worker 
166*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_read_chunk(png_structrp png_ptr,png_inforp info_ptr)167*a67afe4dSAndroid Build Coastguard Worker png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
168*a67afe4dSAndroid Build Coastguard Worker {
169*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 chunk_name;
170*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
171*a67afe4dSAndroid Build Coastguard Worker    int keep; /* unknown handling method */
172*a67afe4dSAndroid Build Coastguard Worker #endif
173*a67afe4dSAndroid Build Coastguard Worker 
174*a67afe4dSAndroid Build Coastguard Worker    /* First we make sure we have enough data for the 4-byte chunk name
175*a67afe4dSAndroid Build Coastguard Worker     * and the 4-byte chunk length before proceeding with decoding the
176*a67afe4dSAndroid Build Coastguard Worker     * chunk data.  To fully decode each of these chunks, we also make
177*a67afe4dSAndroid Build Coastguard Worker     * sure we have enough data in the buffer for the 4-byte CRC at the
178*a67afe4dSAndroid Build Coastguard Worker     * end of every chunk (except IDAT, which is handled separately).
179*a67afe4dSAndroid Build Coastguard Worker     */
180*a67afe4dSAndroid Build Coastguard Worker    if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
181*a67afe4dSAndroid Build Coastguard Worker    {
182*a67afe4dSAndroid Build Coastguard Worker       png_byte chunk_length[4];
183*a67afe4dSAndroid Build Coastguard Worker       png_byte chunk_tag[4];
184*a67afe4dSAndroid Build Coastguard Worker 
185*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_LT(8)
186*a67afe4dSAndroid Build Coastguard Worker       png_push_fill_buffer(png_ptr, chunk_length, 4);
187*a67afe4dSAndroid Build Coastguard Worker       png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
188*a67afe4dSAndroid Build Coastguard Worker       png_reset_crc(png_ptr);
189*a67afe4dSAndroid Build Coastguard Worker       png_crc_read(png_ptr, chunk_tag, 4);
190*a67afe4dSAndroid Build Coastguard Worker       png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
191*a67afe4dSAndroid Build Coastguard Worker       png_check_chunk_name(png_ptr, png_ptr->chunk_name);
192*a67afe4dSAndroid Build Coastguard Worker       png_check_chunk_length(png_ptr, png_ptr->push_length);
193*a67afe4dSAndroid Build Coastguard Worker       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
194*a67afe4dSAndroid Build Coastguard Worker    }
195*a67afe4dSAndroid Build Coastguard Worker 
196*a67afe4dSAndroid Build Coastguard Worker    chunk_name = png_ptr->chunk_name;
197*a67afe4dSAndroid Build Coastguard Worker 
198*a67afe4dSAndroid Build Coastguard Worker    if (chunk_name == png_IDAT)
199*a67afe4dSAndroid Build Coastguard Worker    {
200*a67afe4dSAndroid Build Coastguard Worker       if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
201*a67afe4dSAndroid Build Coastguard Worker          png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
202*a67afe4dSAndroid Build Coastguard Worker 
203*a67afe4dSAndroid Build Coastguard Worker       /* If we reach an IDAT chunk, this means we have read all of the
204*a67afe4dSAndroid Build Coastguard Worker        * header chunks, and we can start reading the image (or if this
205*a67afe4dSAndroid Build Coastguard Worker        * is called after the image has been read - we have an error).
206*a67afe4dSAndroid Build Coastguard Worker        */
207*a67afe4dSAndroid Build Coastguard Worker       if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
208*a67afe4dSAndroid Build Coastguard Worker          png_error(png_ptr, "Missing IHDR before IDAT");
209*a67afe4dSAndroid Build Coastguard Worker 
210*a67afe4dSAndroid Build Coastguard Worker       else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
211*a67afe4dSAndroid Build Coastguard Worker           (png_ptr->mode & PNG_HAVE_PLTE) == 0)
212*a67afe4dSAndroid Build Coastguard Worker          png_error(png_ptr, "Missing PLTE before IDAT");
213*a67afe4dSAndroid Build Coastguard Worker 
214*a67afe4dSAndroid Build Coastguard Worker       png_ptr->process_mode = PNG_READ_IDAT_MODE;
215*a67afe4dSAndroid Build Coastguard Worker 
216*a67afe4dSAndroid Build Coastguard Worker       if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
217*a67afe4dSAndroid Build Coastguard Worker          if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
218*a67afe4dSAndroid Build Coastguard Worker             if (png_ptr->push_length == 0)
219*a67afe4dSAndroid Build Coastguard Worker                return;
220*a67afe4dSAndroid Build Coastguard Worker 
221*a67afe4dSAndroid Build Coastguard Worker       png_ptr->mode |= PNG_HAVE_IDAT;
222*a67afe4dSAndroid Build Coastguard Worker 
223*a67afe4dSAndroid Build Coastguard Worker       if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
224*a67afe4dSAndroid Build Coastguard Worker          png_benign_error(png_ptr, "Too many IDATs found");
225*a67afe4dSAndroid Build Coastguard Worker    }
226*a67afe4dSAndroid Build Coastguard Worker 
227*a67afe4dSAndroid Build Coastguard Worker    if (chunk_name == png_IHDR)
228*a67afe4dSAndroid Build Coastguard Worker    {
229*a67afe4dSAndroid Build Coastguard Worker       if (png_ptr->push_length != 13)
230*a67afe4dSAndroid Build Coastguard Worker          png_error(png_ptr, "Invalid IHDR length");
231*a67afe4dSAndroid Build Coastguard Worker 
232*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
233*a67afe4dSAndroid Build Coastguard Worker       png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
234*a67afe4dSAndroid Build Coastguard Worker    }
235*a67afe4dSAndroid Build Coastguard Worker 
236*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_IEND)
237*a67afe4dSAndroid Build Coastguard Worker    {
238*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
239*a67afe4dSAndroid Build Coastguard Worker       png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
240*a67afe4dSAndroid Build Coastguard Worker 
241*a67afe4dSAndroid Build Coastguard Worker       png_ptr->process_mode = PNG_READ_DONE_MODE;
242*a67afe4dSAndroid Build Coastguard Worker       png_push_have_end(png_ptr, info_ptr);
243*a67afe4dSAndroid Build Coastguard Worker    }
244*a67afe4dSAndroid Build Coastguard Worker 
245*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
246*a67afe4dSAndroid Build Coastguard Worker    else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
247*a67afe4dSAndroid Build Coastguard Worker    {
248*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
249*a67afe4dSAndroid Build Coastguard Worker       png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
250*a67afe4dSAndroid Build Coastguard Worker 
251*a67afe4dSAndroid Build Coastguard Worker       if (chunk_name == png_PLTE)
252*a67afe4dSAndroid Build Coastguard Worker          png_ptr->mode |= PNG_HAVE_PLTE;
253*a67afe4dSAndroid Build Coastguard Worker    }
254*a67afe4dSAndroid Build Coastguard Worker #endif
255*a67afe4dSAndroid Build Coastguard Worker 
256*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_PLTE)
257*a67afe4dSAndroid Build Coastguard Worker    {
258*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
259*a67afe4dSAndroid Build Coastguard Worker       png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
260*a67afe4dSAndroid Build Coastguard Worker    }
261*a67afe4dSAndroid Build Coastguard Worker 
262*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_IDAT)
263*a67afe4dSAndroid Build Coastguard Worker    {
264*a67afe4dSAndroid Build Coastguard Worker       png_ptr->idat_size = png_ptr->push_length;
265*a67afe4dSAndroid Build Coastguard Worker       png_ptr->process_mode = PNG_READ_IDAT_MODE;
266*a67afe4dSAndroid Build Coastguard Worker       png_push_have_info(png_ptr, info_ptr);
267*a67afe4dSAndroid Build Coastguard Worker       png_ptr->zstream.avail_out =
268*a67afe4dSAndroid Build Coastguard Worker           (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
269*a67afe4dSAndroid Build Coastguard Worker           png_ptr->iwidth) + 1;
270*a67afe4dSAndroid Build Coastguard Worker       png_ptr->zstream.next_out = png_ptr->row_buf;
271*a67afe4dSAndroid Build Coastguard Worker       return;
272*a67afe4dSAndroid Build Coastguard Worker    }
273*a67afe4dSAndroid Build Coastguard Worker 
274*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_gAMA_SUPPORTED
275*a67afe4dSAndroid Build Coastguard Worker    else if (png_ptr->chunk_name == png_gAMA)
276*a67afe4dSAndroid Build Coastguard Worker    {
277*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
278*a67afe4dSAndroid Build Coastguard Worker       png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
279*a67afe4dSAndroid Build Coastguard Worker    }
280*a67afe4dSAndroid Build Coastguard Worker 
281*a67afe4dSAndroid Build Coastguard Worker #endif
282*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_sBIT_SUPPORTED
283*a67afe4dSAndroid Build Coastguard Worker    else if (png_ptr->chunk_name == png_sBIT)
284*a67afe4dSAndroid Build Coastguard Worker    {
285*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
286*a67afe4dSAndroid Build Coastguard Worker       png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
287*a67afe4dSAndroid Build Coastguard Worker    }
288*a67afe4dSAndroid Build Coastguard Worker 
289*a67afe4dSAndroid Build Coastguard Worker #endif
290*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_cHRM_SUPPORTED
291*a67afe4dSAndroid Build Coastguard Worker    else if (png_ptr->chunk_name == png_cHRM)
292*a67afe4dSAndroid Build Coastguard Worker    {
293*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
294*a67afe4dSAndroid Build Coastguard Worker       png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
295*a67afe4dSAndroid Build Coastguard Worker    }
296*a67afe4dSAndroid Build Coastguard Worker 
297*a67afe4dSAndroid Build Coastguard Worker #endif
298*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_eXIf_SUPPORTED
299*a67afe4dSAndroid Build Coastguard Worker    else if (png_ptr->chunk_name == png_eXIf)
300*a67afe4dSAndroid Build Coastguard Worker    {
301*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
302*a67afe4dSAndroid Build Coastguard Worker       png_handle_eXIf(png_ptr, info_ptr, png_ptr->push_length);
303*a67afe4dSAndroid Build Coastguard Worker    }
304*a67afe4dSAndroid Build Coastguard Worker 
305*a67afe4dSAndroid Build Coastguard Worker #endif
306*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_sRGB_SUPPORTED
307*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_sRGB)
308*a67afe4dSAndroid Build Coastguard Worker    {
309*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
310*a67afe4dSAndroid Build Coastguard Worker       png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
311*a67afe4dSAndroid Build Coastguard Worker    }
312*a67afe4dSAndroid Build Coastguard Worker 
313*a67afe4dSAndroid Build Coastguard Worker #endif
314*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_iCCP_SUPPORTED
315*a67afe4dSAndroid Build Coastguard Worker    else if (png_ptr->chunk_name == png_iCCP)
316*a67afe4dSAndroid Build Coastguard Worker    {
317*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
318*a67afe4dSAndroid Build Coastguard Worker       png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
319*a67afe4dSAndroid Build Coastguard Worker    }
320*a67afe4dSAndroid Build Coastguard Worker 
321*a67afe4dSAndroid Build Coastguard Worker #endif
322*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_sPLT_SUPPORTED
323*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_sPLT)
324*a67afe4dSAndroid Build Coastguard Worker    {
325*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
326*a67afe4dSAndroid Build Coastguard Worker       png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
327*a67afe4dSAndroid Build Coastguard Worker    }
328*a67afe4dSAndroid Build Coastguard Worker 
329*a67afe4dSAndroid Build Coastguard Worker #endif
330*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_tRNS_SUPPORTED
331*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_tRNS)
332*a67afe4dSAndroid Build Coastguard Worker    {
333*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
334*a67afe4dSAndroid Build Coastguard Worker       png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
335*a67afe4dSAndroid Build Coastguard Worker    }
336*a67afe4dSAndroid Build Coastguard Worker 
337*a67afe4dSAndroid Build Coastguard Worker #endif
338*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_bKGD_SUPPORTED
339*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_bKGD)
340*a67afe4dSAndroid Build Coastguard Worker    {
341*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
342*a67afe4dSAndroid Build Coastguard Worker       png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
343*a67afe4dSAndroid Build Coastguard Worker    }
344*a67afe4dSAndroid Build Coastguard Worker 
345*a67afe4dSAndroid Build Coastguard Worker #endif
346*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_hIST_SUPPORTED
347*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_hIST)
348*a67afe4dSAndroid Build Coastguard Worker    {
349*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
350*a67afe4dSAndroid Build Coastguard Worker       png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
351*a67afe4dSAndroid Build Coastguard Worker    }
352*a67afe4dSAndroid Build Coastguard Worker 
353*a67afe4dSAndroid Build Coastguard Worker #endif
354*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_pHYs_SUPPORTED
355*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_pHYs)
356*a67afe4dSAndroid Build Coastguard Worker    {
357*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
358*a67afe4dSAndroid Build Coastguard Worker       png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
359*a67afe4dSAndroid Build Coastguard Worker    }
360*a67afe4dSAndroid Build Coastguard Worker 
361*a67afe4dSAndroid Build Coastguard Worker #endif
362*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_oFFs_SUPPORTED
363*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_oFFs)
364*a67afe4dSAndroid Build Coastguard Worker    {
365*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
366*a67afe4dSAndroid Build Coastguard Worker       png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
367*a67afe4dSAndroid Build Coastguard Worker    }
368*a67afe4dSAndroid Build Coastguard Worker #endif
369*a67afe4dSAndroid Build Coastguard Worker 
370*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_pCAL_SUPPORTED
371*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_pCAL)
372*a67afe4dSAndroid Build Coastguard Worker    {
373*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
374*a67afe4dSAndroid Build Coastguard Worker       png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
375*a67afe4dSAndroid Build Coastguard Worker    }
376*a67afe4dSAndroid Build Coastguard Worker 
377*a67afe4dSAndroid Build Coastguard Worker #endif
378*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_sCAL_SUPPORTED
379*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_sCAL)
380*a67afe4dSAndroid Build Coastguard Worker    {
381*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
382*a67afe4dSAndroid Build Coastguard Worker       png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
383*a67afe4dSAndroid Build Coastguard Worker    }
384*a67afe4dSAndroid Build Coastguard Worker 
385*a67afe4dSAndroid Build Coastguard Worker #endif
386*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_tIME_SUPPORTED
387*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_tIME)
388*a67afe4dSAndroid Build Coastguard Worker    {
389*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
390*a67afe4dSAndroid Build Coastguard Worker       png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
391*a67afe4dSAndroid Build Coastguard Worker    }
392*a67afe4dSAndroid Build Coastguard Worker 
393*a67afe4dSAndroid Build Coastguard Worker #endif
394*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_tEXt_SUPPORTED
395*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_tEXt)
396*a67afe4dSAndroid Build Coastguard Worker    {
397*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
398*a67afe4dSAndroid Build Coastguard Worker       png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
399*a67afe4dSAndroid Build Coastguard Worker    }
400*a67afe4dSAndroid Build Coastguard Worker 
401*a67afe4dSAndroid Build Coastguard Worker #endif
402*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_zTXt_SUPPORTED
403*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_zTXt)
404*a67afe4dSAndroid Build Coastguard Worker    {
405*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
406*a67afe4dSAndroid Build Coastguard Worker       png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
407*a67afe4dSAndroid Build Coastguard Worker    }
408*a67afe4dSAndroid Build Coastguard Worker 
409*a67afe4dSAndroid Build Coastguard Worker #endif
410*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_iTXt_SUPPORTED
411*a67afe4dSAndroid Build Coastguard Worker    else if (chunk_name == png_iTXt)
412*a67afe4dSAndroid Build Coastguard Worker    {
413*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
414*a67afe4dSAndroid Build Coastguard Worker       png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
415*a67afe4dSAndroid Build Coastguard Worker    }
416*a67afe4dSAndroid Build Coastguard Worker #endif
417*a67afe4dSAndroid Build Coastguard Worker 
418*a67afe4dSAndroid Build Coastguard Worker    else
419*a67afe4dSAndroid Build Coastguard Worker    {
420*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_FULL
421*a67afe4dSAndroid Build Coastguard Worker       png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
422*a67afe4dSAndroid Build Coastguard Worker           PNG_HANDLE_CHUNK_AS_DEFAULT);
423*a67afe4dSAndroid Build Coastguard Worker    }
424*a67afe4dSAndroid Build Coastguard Worker 
425*a67afe4dSAndroid Build Coastguard Worker    png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
426*a67afe4dSAndroid Build Coastguard Worker }
427*a67afe4dSAndroid Build Coastguard Worker 
428*a67afe4dSAndroid Build Coastguard Worker void PNGCBAPI
png_push_fill_buffer(png_structp png_ptr,png_bytep buffer,size_t length)429*a67afe4dSAndroid Build Coastguard Worker png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, size_t length)
430*a67afe4dSAndroid Build Coastguard Worker {
431*a67afe4dSAndroid Build Coastguard Worker    png_bytep ptr;
432*a67afe4dSAndroid Build Coastguard Worker 
433*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr == NULL)
434*a67afe4dSAndroid Build Coastguard Worker       return;
435*a67afe4dSAndroid Build Coastguard Worker 
436*a67afe4dSAndroid Build Coastguard Worker    ptr = buffer;
437*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->save_buffer_size != 0)
438*a67afe4dSAndroid Build Coastguard Worker    {
439*a67afe4dSAndroid Build Coastguard Worker       size_t save_size;
440*a67afe4dSAndroid Build Coastguard Worker 
441*a67afe4dSAndroid Build Coastguard Worker       if (length < png_ptr->save_buffer_size)
442*a67afe4dSAndroid Build Coastguard Worker          save_size = length;
443*a67afe4dSAndroid Build Coastguard Worker 
444*a67afe4dSAndroid Build Coastguard Worker       else
445*a67afe4dSAndroid Build Coastguard Worker          save_size = png_ptr->save_buffer_size;
446*a67afe4dSAndroid Build Coastguard Worker 
447*a67afe4dSAndroid Build Coastguard Worker       memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
448*a67afe4dSAndroid Build Coastguard Worker       length -= save_size;
449*a67afe4dSAndroid Build Coastguard Worker       ptr += save_size;
450*a67afe4dSAndroid Build Coastguard Worker       png_ptr->buffer_size -= save_size;
451*a67afe4dSAndroid Build Coastguard Worker       png_ptr->save_buffer_size -= save_size;
452*a67afe4dSAndroid Build Coastguard Worker       png_ptr->save_buffer_ptr += save_size;
453*a67afe4dSAndroid Build Coastguard Worker    }
454*a67afe4dSAndroid Build Coastguard Worker    if (length != 0 && png_ptr->current_buffer_size != 0)
455*a67afe4dSAndroid Build Coastguard Worker    {
456*a67afe4dSAndroid Build Coastguard Worker       size_t save_size;
457*a67afe4dSAndroid Build Coastguard Worker 
458*a67afe4dSAndroid Build Coastguard Worker       if (length < png_ptr->current_buffer_size)
459*a67afe4dSAndroid Build Coastguard Worker          save_size = length;
460*a67afe4dSAndroid Build Coastguard Worker 
461*a67afe4dSAndroid Build Coastguard Worker       else
462*a67afe4dSAndroid Build Coastguard Worker          save_size = png_ptr->current_buffer_size;
463*a67afe4dSAndroid Build Coastguard Worker 
464*a67afe4dSAndroid Build Coastguard Worker       memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
465*a67afe4dSAndroid Build Coastguard Worker       png_ptr->buffer_size -= save_size;
466*a67afe4dSAndroid Build Coastguard Worker       png_ptr->current_buffer_size -= save_size;
467*a67afe4dSAndroid Build Coastguard Worker       png_ptr->current_buffer_ptr += save_size;
468*a67afe4dSAndroid Build Coastguard Worker    }
469*a67afe4dSAndroid Build Coastguard Worker }
470*a67afe4dSAndroid Build Coastguard Worker 
471*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_save_buffer(png_structrp png_ptr)472*a67afe4dSAndroid Build Coastguard Worker png_push_save_buffer(png_structrp png_ptr)
473*a67afe4dSAndroid Build Coastguard Worker {
474*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->save_buffer_size != 0)
475*a67afe4dSAndroid Build Coastguard Worker    {
476*a67afe4dSAndroid Build Coastguard Worker       if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
477*a67afe4dSAndroid Build Coastguard Worker       {
478*a67afe4dSAndroid Build Coastguard Worker          size_t i, istop;
479*a67afe4dSAndroid Build Coastguard Worker          png_bytep sp;
480*a67afe4dSAndroid Build Coastguard Worker          png_bytep dp;
481*a67afe4dSAndroid Build Coastguard Worker 
482*a67afe4dSAndroid Build Coastguard Worker          istop = png_ptr->save_buffer_size;
483*a67afe4dSAndroid Build Coastguard Worker          for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
484*a67afe4dSAndroid Build Coastguard Worker              i < istop; i++, sp++, dp++)
485*a67afe4dSAndroid Build Coastguard Worker          {
486*a67afe4dSAndroid Build Coastguard Worker             *dp = *sp;
487*a67afe4dSAndroid Build Coastguard Worker          }
488*a67afe4dSAndroid Build Coastguard Worker       }
489*a67afe4dSAndroid Build Coastguard Worker    }
490*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
491*a67afe4dSAndroid Build Coastguard Worker        png_ptr->save_buffer_max)
492*a67afe4dSAndroid Build Coastguard Worker    {
493*a67afe4dSAndroid Build Coastguard Worker       size_t new_max;
494*a67afe4dSAndroid Build Coastguard Worker       png_bytep old_buffer;
495*a67afe4dSAndroid Build Coastguard Worker 
496*a67afe4dSAndroid Build Coastguard Worker       if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
497*a67afe4dSAndroid Build Coastguard Worker           (png_ptr->current_buffer_size + 256))
498*a67afe4dSAndroid Build Coastguard Worker       {
499*a67afe4dSAndroid Build Coastguard Worker          png_error(png_ptr, "Potential overflow of save_buffer");
500*a67afe4dSAndroid Build Coastguard Worker       }
501*a67afe4dSAndroid Build Coastguard Worker 
502*a67afe4dSAndroid Build Coastguard Worker       new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
503*a67afe4dSAndroid Build Coastguard Worker       old_buffer = png_ptr->save_buffer;
504*a67afe4dSAndroid Build Coastguard Worker       png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
505*a67afe4dSAndroid Build Coastguard Worker           (size_t)new_max);
506*a67afe4dSAndroid Build Coastguard Worker 
507*a67afe4dSAndroid Build Coastguard Worker       if (png_ptr->save_buffer == NULL)
508*a67afe4dSAndroid Build Coastguard Worker       {
509*a67afe4dSAndroid Build Coastguard Worker          png_free(png_ptr, old_buffer);
510*a67afe4dSAndroid Build Coastguard Worker          png_error(png_ptr, "Insufficient memory for save_buffer");
511*a67afe4dSAndroid Build Coastguard Worker       }
512*a67afe4dSAndroid Build Coastguard Worker 
513*a67afe4dSAndroid Build Coastguard Worker       if (old_buffer)
514*a67afe4dSAndroid Build Coastguard Worker          memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
515*a67afe4dSAndroid Build Coastguard Worker       else if (png_ptr->save_buffer_size)
516*a67afe4dSAndroid Build Coastguard Worker          png_error(png_ptr, "save_buffer error");
517*a67afe4dSAndroid Build Coastguard Worker       png_free(png_ptr, old_buffer);
518*a67afe4dSAndroid Build Coastguard Worker       png_ptr->save_buffer_max = new_max;
519*a67afe4dSAndroid Build Coastguard Worker    }
520*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->current_buffer_size)
521*a67afe4dSAndroid Build Coastguard Worker    {
522*a67afe4dSAndroid Build Coastguard Worker       memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
523*a67afe4dSAndroid Build Coastguard Worker          png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
524*a67afe4dSAndroid Build Coastguard Worker       png_ptr->save_buffer_size += png_ptr->current_buffer_size;
525*a67afe4dSAndroid Build Coastguard Worker       png_ptr->current_buffer_size = 0;
526*a67afe4dSAndroid Build Coastguard Worker    }
527*a67afe4dSAndroid Build Coastguard Worker    png_ptr->save_buffer_ptr = png_ptr->save_buffer;
528*a67afe4dSAndroid Build Coastguard Worker    png_ptr->buffer_size = 0;
529*a67afe4dSAndroid Build Coastguard Worker }
530*a67afe4dSAndroid Build Coastguard Worker 
531*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_restore_buffer(png_structrp png_ptr,png_bytep buffer,size_t buffer_length)532*a67afe4dSAndroid Build Coastguard Worker png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
533*a67afe4dSAndroid Build Coastguard Worker     size_t buffer_length)
534*a67afe4dSAndroid Build Coastguard Worker {
535*a67afe4dSAndroid Build Coastguard Worker    png_ptr->current_buffer = buffer;
536*a67afe4dSAndroid Build Coastguard Worker    png_ptr->current_buffer_size = buffer_length;
537*a67afe4dSAndroid Build Coastguard Worker    png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
538*a67afe4dSAndroid Build Coastguard Worker    png_ptr->current_buffer_ptr = png_ptr->current_buffer;
539*a67afe4dSAndroid Build Coastguard Worker }
540*a67afe4dSAndroid Build Coastguard Worker 
541*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_read_IDAT(png_structrp png_ptr)542*a67afe4dSAndroid Build Coastguard Worker png_push_read_IDAT(png_structrp png_ptr)
543*a67afe4dSAndroid Build Coastguard Worker {
544*a67afe4dSAndroid Build Coastguard Worker    if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
545*a67afe4dSAndroid Build Coastguard Worker    {
546*a67afe4dSAndroid Build Coastguard Worker       png_byte chunk_length[4];
547*a67afe4dSAndroid Build Coastguard Worker       png_byte chunk_tag[4];
548*a67afe4dSAndroid Build Coastguard Worker 
549*a67afe4dSAndroid Build Coastguard Worker       /* TODO: this code can be commoned up with the same code in push_read */
550*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_LT(8)
551*a67afe4dSAndroid Build Coastguard Worker       png_push_fill_buffer(png_ptr, chunk_length, 4);
552*a67afe4dSAndroid Build Coastguard Worker       png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
553*a67afe4dSAndroid Build Coastguard Worker       png_reset_crc(png_ptr);
554*a67afe4dSAndroid Build Coastguard Worker       png_crc_read(png_ptr, chunk_tag, 4);
555*a67afe4dSAndroid Build Coastguard Worker       png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
556*a67afe4dSAndroid Build Coastguard Worker       png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
557*a67afe4dSAndroid Build Coastguard Worker 
558*a67afe4dSAndroid Build Coastguard Worker       if (png_ptr->chunk_name != png_IDAT)
559*a67afe4dSAndroid Build Coastguard Worker       {
560*a67afe4dSAndroid Build Coastguard Worker          png_ptr->process_mode = PNG_READ_CHUNK_MODE;
561*a67afe4dSAndroid Build Coastguard Worker 
562*a67afe4dSAndroid Build Coastguard Worker          if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
563*a67afe4dSAndroid Build Coastguard Worker             png_error(png_ptr, "Not enough compressed data");
564*a67afe4dSAndroid Build Coastguard Worker 
565*a67afe4dSAndroid Build Coastguard Worker          return;
566*a67afe4dSAndroid Build Coastguard Worker       }
567*a67afe4dSAndroid Build Coastguard Worker 
568*a67afe4dSAndroid Build Coastguard Worker       png_ptr->idat_size = png_ptr->push_length;
569*a67afe4dSAndroid Build Coastguard Worker    }
570*a67afe4dSAndroid Build Coastguard Worker 
571*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
572*a67afe4dSAndroid Build Coastguard Worker    {
573*a67afe4dSAndroid Build Coastguard Worker       size_t save_size = png_ptr->save_buffer_size;
574*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 idat_size = png_ptr->idat_size;
575*a67afe4dSAndroid Build Coastguard Worker 
576*a67afe4dSAndroid Build Coastguard Worker       /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
577*a67afe4dSAndroid Build Coastguard Worker        * are of different types and we don't know which variable has the fewest
578*a67afe4dSAndroid Build Coastguard Worker        * bits.  Carefully select the smaller and cast it to the type of the
579*a67afe4dSAndroid Build Coastguard Worker        * larger - this cannot overflow.  Do not cast in the following test - it
580*a67afe4dSAndroid Build Coastguard Worker        * will break on either 16-bit or 64-bit platforms.
581*a67afe4dSAndroid Build Coastguard Worker        */
582*a67afe4dSAndroid Build Coastguard Worker       if (idat_size < save_size)
583*a67afe4dSAndroid Build Coastguard Worker          save_size = (size_t)idat_size;
584*a67afe4dSAndroid Build Coastguard Worker 
585*a67afe4dSAndroid Build Coastguard Worker       else
586*a67afe4dSAndroid Build Coastguard Worker          idat_size = (png_uint_32)save_size;
587*a67afe4dSAndroid Build Coastguard Worker 
588*a67afe4dSAndroid Build Coastguard Worker       png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
589*a67afe4dSAndroid Build Coastguard Worker 
590*a67afe4dSAndroid Build Coastguard Worker       png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
591*a67afe4dSAndroid Build Coastguard Worker 
592*a67afe4dSAndroid Build Coastguard Worker       png_ptr->idat_size -= idat_size;
593*a67afe4dSAndroid Build Coastguard Worker       png_ptr->buffer_size -= save_size;
594*a67afe4dSAndroid Build Coastguard Worker       png_ptr->save_buffer_size -= save_size;
595*a67afe4dSAndroid Build Coastguard Worker       png_ptr->save_buffer_ptr += save_size;
596*a67afe4dSAndroid Build Coastguard Worker    }
597*a67afe4dSAndroid Build Coastguard Worker 
598*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0)
599*a67afe4dSAndroid Build Coastguard Worker    {
600*a67afe4dSAndroid Build Coastguard Worker       size_t save_size = png_ptr->current_buffer_size;
601*a67afe4dSAndroid Build Coastguard Worker       png_uint_32 idat_size = png_ptr->idat_size;
602*a67afe4dSAndroid Build Coastguard Worker 
603*a67afe4dSAndroid Build Coastguard Worker       /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
604*a67afe4dSAndroid Build Coastguard Worker        * are of different types and we don't know which variable has the fewest
605*a67afe4dSAndroid Build Coastguard Worker        * bits.  Carefully select the smaller and cast it to the type of the
606*a67afe4dSAndroid Build Coastguard Worker        * larger - this cannot overflow.
607*a67afe4dSAndroid Build Coastguard Worker        */
608*a67afe4dSAndroid Build Coastguard Worker       if (idat_size < save_size)
609*a67afe4dSAndroid Build Coastguard Worker          save_size = (size_t)idat_size;
610*a67afe4dSAndroid Build Coastguard Worker 
611*a67afe4dSAndroid Build Coastguard Worker       else
612*a67afe4dSAndroid Build Coastguard Worker          idat_size = (png_uint_32)save_size;
613*a67afe4dSAndroid Build Coastguard Worker 
614*a67afe4dSAndroid Build Coastguard Worker       png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
615*a67afe4dSAndroid Build Coastguard Worker 
616*a67afe4dSAndroid Build Coastguard Worker       png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
617*a67afe4dSAndroid Build Coastguard Worker 
618*a67afe4dSAndroid Build Coastguard Worker       png_ptr->idat_size -= idat_size;
619*a67afe4dSAndroid Build Coastguard Worker       png_ptr->buffer_size -= save_size;
620*a67afe4dSAndroid Build Coastguard Worker       png_ptr->current_buffer_size -= save_size;
621*a67afe4dSAndroid Build Coastguard Worker       png_ptr->current_buffer_ptr += save_size;
622*a67afe4dSAndroid Build Coastguard Worker    }
623*a67afe4dSAndroid Build Coastguard Worker 
624*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->idat_size == 0)
625*a67afe4dSAndroid Build Coastguard Worker    {
626*a67afe4dSAndroid Build Coastguard Worker       PNG_PUSH_SAVE_BUFFER_IF_LT(4)
627*a67afe4dSAndroid Build Coastguard Worker       png_crc_finish(png_ptr, 0);
628*a67afe4dSAndroid Build Coastguard Worker       png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
629*a67afe4dSAndroid Build Coastguard Worker       png_ptr->mode |= PNG_AFTER_IDAT;
630*a67afe4dSAndroid Build Coastguard Worker       png_ptr->zowner = 0;
631*a67afe4dSAndroid Build Coastguard Worker    }
632*a67afe4dSAndroid Build Coastguard Worker }
633*a67afe4dSAndroid Build Coastguard Worker 
634*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_process_IDAT_data(png_structrp png_ptr,png_bytep buffer,size_t buffer_length)635*a67afe4dSAndroid Build Coastguard Worker png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
636*a67afe4dSAndroid Build Coastguard Worker     size_t buffer_length)
637*a67afe4dSAndroid Build Coastguard Worker {
638*a67afe4dSAndroid Build Coastguard Worker    /* The caller checks for a non-zero buffer length. */
639*a67afe4dSAndroid Build Coastguard Worker    if (!(buffer_length > 0) || buffer == NULL)
640*a67afe4dSAndroid Build Coastguard Worker       png_error(png_ptr, "No IDAT data (internal error)");
641*a67afe4dSAndroid Build Coastguard Worker 
642*a67afe4dSAndroid Build Coastguard Worker    /* This routine must process all the data it has been given
643*a67afe4dSAndroid Build Coastguard Worker     * before returning, calling the row callback as required to
644*a67afe4dSAndroid Build Coastguard Worker     * handle the uncompressed results.
645*a67afe4dSAndroid Build Coastguard Worker     */
646*a67afe4dSAndroid Build Coastguard Worker    png_ptr->zstream.next_in = buffer;
647*a67afe4dSAndroid Build Coastguard Worker    /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
648*a67afe4dSAndroid Build Coastguard Worker    png_ptr->zstream.avail_in = (uInt)buffer_length;
649*a67afe4dSAndroid Build Coastguard Worker 
650*a67afe4dSAndroid Build Coastguard Worker    /* Keep going until the decompressed data is all processed
651*a67afe4dSAndroid Build Coastguard Worker     * or the stream marked as finished.
652*a67afe4dSAndroid Build Coastguard Worker     */
653*a67afe4dSAndroid Build Coastguard Worker    while (png_ptr->zstream.avail_in > 0 &&
654*a67afe4dSAndroid Build Coastguard Worker       (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
655*a67afe4dSAndroid Build Coastguard Worker    {
656*a67afe4dSAndroid Build Coastguard Worker       int ret;
657*a67afe4dSAndroid Build Coastguard Worker 
658*a67afe4dSAndroid Build Coastguard Worker       /* We have data for zlib, but we must check that zlib
659*a67afe4dSAndroid Build Coastguard Worker        * has someplace to put the results.  It doesn't matter
660*a67afe4dSAndroid Build Coastguard Worker        * if we don't expect any results -- it may be the input
661*a67afe4dSAndroid Build Coastguard Worker        * data is just the LZ end code.
662*a67afe4dSAndroid Build Coastguard Worker        */
663*a67afe4dSAndroid Build Coastguard Worker       if (!(png_ptr->zstream.avail_out > 0))
664*a67afe4dSAndroid Build Coastguard Worker       {
665*a67afe4dSAndroid Build Coastguard Worker          /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
666*a67afe4dSAndroid Build Coastguard Worker          png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
667*a67afe4dSAndroid Build Coastguard Worker              png_ptr->iwidth) + 1);
668*a67afe4dSAndroid Build Coastguard Worker 
669*a67afe4dSAndroid Build Coastguard Worker          png_ptr->zstream.next_out = png_ptr->row_buf;
670*a67afe4dSAndroid Build Coastguard Worker       }
671*a67afe4dSAndroid Build Coastguard Worker 
672*a67afe4dSAndroid Build Coastguard Worker       /* Using Z_SYNC_FLUSH here means that an unterminated
673*a67afe4dSAndroid Build Coastguard Worker        * LZ stream (a stream with a missing end code) can still
674*a67afe4dSAndroid Build Coastguard Worker        * be handled, otherwise (Z_NO_FLUSH) a future zlib
675*a67afe4dSAndroid Build Coastguard Worker        * implementation might defer output and therefore
676*a67afe4dSAndroid Build Coastguard Worker        * change the current behavior (see comments in inflate.c
677*a67afe4dSAndroid Build Coastguard Worker        * for why this doesn't happen at present with zlib 1.2.5).
678*a67afe4dSAndroid Build Coastguard Worker        */
679*a67afe4dSAndroid Build Coastguard Worker       ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH);
680*a67afe4dSAndroid Build Coastguard Worker 
681*a67afe4dSAndroid Build Coastguard Worker       /* Check for any failure before proceeding. */
682*a67afe4dSAndroid Build Coastguard Worker       if (ret != Z_OK && ret != Z_STREAM_END)
683*a67afe4dSAndroid Build Coastguard Worker       {
684*a67afe4dSAndroid Build Coastguard Worker          /* Terminate the decompression. */
685*a67afe4dSAndroid Build Coastguard Worker          png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
686*a67afe4dSAndroid Build Coastguard Worker          png_ptr->zowner = 0;
687*a67afe4dSAndroid Build Coastguard Worker 
688*a67afe4dSAndroid Build Coastguard Worker          /* This may be a truncated stream (missing or
689*a67afe4dSAndroid Build Coastguard Worker           * damaged end code).  Treat that as a warning.
690*a67afe4dSAndroid Build Coastguard Worker           */
691*a67afe4dSAndroid Build Coastguard Worker          if (png_ptr->row_number >= png_ptr->num_rows ||
692*a67afe4dSAndroid Build Coastguard Worker              png_ptr->pass > 6)
693*a67afe4dSAndroid Build Coastguard Worker             png_warning(png_ptr, "Truncated compressed data in IDAT");
694*a67afe4dSAndroid Build Coastguard Worker 
695*a67afe4dSAndroid Build Coastguard Worker          else
696*a67afe4dSAndroid Build Coastguard Worker          {
697*a67afe4dSAndroid Build Coastguard Worker             if (ret == Z_DATA_ERROR)
698*a67afe4dSAndroid Build Coastguard Worker                png_benign_error(png_ptr, "IDAT: ADLER32 checksum mismatch");
699*a67afe4dSAndroid Build Coastguard Worker             else
700*a67afe4dSAndroid Build Coastguard Worker                png_error(png_ptr, "Decompression error in IDAT");
701*a67afe4dSAndroid Build Coastguard Worker          }
702*a67afe4dSAndroid Build Coastguard Worker 
703*a67afe4dSAndroid Build Coastguard Worker          /* Skip the check on unprocessed input */
704*a67afe4dSAndroid Build Coastguard Worker          return;
705*a67afe4dSAndroid Build Coastguard Worker       }
706*a67afe4dSAndroid Build Coastguard Worker 
707*a67afe4dSAndroid Build Coastguard Worker       /* Did inflate output any data? */
708*a67afe4dSAndroid Build Coastguard Worker       if (png_ptr->zstream.next_out != png_ptr->row_buf)
709*a67afe4dSAndroid Build Coastguard Worker       {
710*a67afe4dSAndroid Build Coastguard Worker          /* Is this unexpected data after the last row?
711*a67afe4dSAndroid Build Coastguard Worker           * If it is, artificially terminate the LZ output
712*a67afe4dSAndroid Build Coastguard Worker           * here.
713*a67afe4dSAndroid Build Coastguard Worker           */
714*a67afe4dSAndroid Build Coastguard Worker          if (png_ptr->row_number >= png_ptr->num_rows ||
715*a67afe4dSAndroid Build Coastguard Worker              png_ptr->pass > 6)
716*a67afe4dSAndroid Build Coastguard Worker          {
717*a67afe4dSAndroid Build Coastguard Worker             /* Extra data. */
718*a67afe4dSAndroid Build Coastguard Worker             png_warning(png_ptr, "Extra compressed data in IDAT");
719*a67afe4dSAndroid Build Coastguard Worker             png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
720*a67afe4dSAndroid Build Coastguard Worker             png_ptr->zowner = 0;
721*a67afe4dSAndroid Build Coastguard Worker 
722*a67afe4dSAndroid Build Coastguard Worker             /* Do no more processing; skip the unprocessed
723*a67afe4dSAndroid Build Coastguard Worker              * input check below.
724*a67afe4dSAndroid Build Coastguard Worker              */
725*a67afe4dSAndroid Build Coastguard Worker             return;
726*a67afe4dSAndroid Build Coastguard Worker          }
727*a67afe4dSAndroid Build Coastguard Worker 
728*a67afe4dSAndroid Build Coastguard Worker          /* Do we have a complete row? */
729*a67afe4dSAndroid Build Coastguard Worker          if (png_ptr->zstream.avail_out == 0)
730*a67afe4dSAndroid Build Coastguard Worker             png_push_process_row(png_ptr);
731*a67afe4dSAndroid Build Coastguard Worker       }
732*a67afe4dSAndroid Build Coastguard Worker 
733*a67afe4dSAndroid Build Coastguard Worker       /* And check for the end of the stream. */
734*a67afe4dSAndroid Build Coastguard Worker       if (ret == Z_STREAM_END)
735*a67afe4dSAndroid Build Coastguard Worker          png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
736*a67afe4dSAndroid Build Coastguard Worker    }
737*a67afe4dSAndroid Build Coastguard Worker 
738*a67afe4dSAndroid Build Coastguard Worker    /* All the data should have been processed, if anything
739*a67afe4dSAndroid Build Coastguard Worker     * is left at this point we have bytes of IDAT data
740*a67afe4dSAndroid Build Coastguard Worker     * after the zlib end code.
741*a67afe4dSAndroid Build Coastguard Worker     */
742*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->zstream.avail_in > 0)
743*a67afe4dSAndroid Build Coastguard Worker       png_warning(png_ptr, "Extra compression data in IDAT");
744*a67afe4dSAndroid Build Coastguard Worker }
745*a67afe4dSAndroid Build Coastguard Worker 
746*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_process_row(png_structrp png_ptr)747*a67afe4dSAndroid Build Coastguard Worker png_push_process_row(png_structrp png_ptr)
748*a67afe4dSAndroid Build Coastguard Worker {
749*a67afe4dSAndroid Build Coastguard Worker    /* 1.5.6: row_info moved out of png_struct to a local here. */
750*a67afe4dSAndroid Build Coastguard Worker    png_row_info row_info;
751*a67afe4dSAndroid Build Coastguard Worker 
752*a67afe4dSAndroid Build Coastguard Worker    row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
753*a67afe4dSAndroid Build Coastguard Worker    row_info.color_type = png_ptr->color_type;
754*a67afe4dSAndroid Build Coastguard Worker    row_info.bit_depth = png_ptr->bit_depth;
755*a67afe4dSAndroid Build Coastguard Worker    row_info.channels = png_ptr->channels;
756*a67afe4dSAndroid Build Coastguard Worker    row_info.pixel_depth = png_ptr->pixel_depth;
757*a67afe4dSAndroid Build Coastguard Worker    row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
758*a67afe4dSAndroid Build Coastguard Worker 
759*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
760*a67afe4dSAndroid Build Coastguard Worker    {
761*a67afe4dSAndroid Build Coastguard Worker       if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
762*a67afe4dSAndroid Build Coastguard Worker          png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
763*a67afe4dSAndroid Build Coastguard Worker             png_ptr->prev_row + 1, png_ptr->row_buf[0]);
764*a67afe4dSAndroid Build Coastguard Worker       else
765*a67afe4dSAndroid Build Coastguard Worker          png_error(png_ptr, "bad adaptive filter value");
766*a67afe4dSAndroid Build Coastguard Worker    }
767*a67afe4dSAndroid Build Coastguard Worker 
768*a67afe4dSAndroid Build Coastguard Worker    /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
769*a67afe4dSAndroid Build Coastguard Worker     * 1.5.6, while the buffer really is this big in current versions of libpng
770*a67afe4dSAndroid Build Coastguard Worker     * it may not be in the future, so this was changed just to copy the
771*a67afe4dSAndroid Build Coastguard Worker     * interlaced row count:
772*a67afe4dSAndroid Build Coastguard Worker     */
773*a67afe4dSAndroid Build Coastguard Worker    memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
774*a67afe4dSAndroid Build Coastguard Worker 
775*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_TRANSFORMS_SUPPORTED
776*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->transformations != 0)
777*a67afe4dSAndroid Build Coastguard Worker       png_do_read_transformations(png_ptr, &row_info);
778*a67afe4dSAndroid Build Coastguard Worker #endif
779*a67afe4dSAndroid Build Coastguard Worker 
780*a67afe4dSAndroid Build Coastguard Worker    /* The transformed pixel depth should match the depth now in row_info. */
781*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->transformed_pixel_depth == 0)
782*a67afe4dSAndroid Build Coastguard Worker    {
783*a67afe4dSAndroid Build Coastguard Worker       png_ptr->transformed_pixel_depth = row_info.pixel_depth;
784*a67afe4dSAndroid Build Coastguard Worker       if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
785*a67afe4dSAndroid Build Coastguard Worker          png_error(png_ptr, "progressive row overflow");
786*a67afe4dSAndroid Build Coastguard Worker    }
787*a67afe4dSAndroid Build Coastguard Worker 
788*a67afe4dSAndroid Build Coastguard Worker    else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
789*a67afe4dSAndroid Build Coastguard Worker       png_error(png_ptr, "internal progressive row size calculation error");
790*a67afe4dSAndroid Build Coastguard Worker 
791*a67afe4dSAndroid Build Coastguard Worker 
792*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_INTERLACING_SUPPORTED
793*a67afe4dSAndroid Build Coastguard Worker    /* Expand interlaced rows to full size */
794*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->interlaced != 0 &&
795*a67afe4dSAndroid Build Coastguard Worker        (png_ptr->transformations & PNG_INTERLACE) != 0)
796*a67afe4dSAndroid Build Coastguard Worker    {
797*a67afe4dSAndroid Build Coastguard Worker       if (png_ptr->pass < 6)
798*a67afe4dSAndroid Build Coastguard Worker          png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
799*a67afe4dSAndroid Build Coastguard Worker              png_ptr->transformations);
800*a67afe4dSAndroid Build Coastguard Worker 
801*a67afe4dSAndroid Build Coastguard Worker       switch (png_ptr->pass)
802*a67afe4dSAndroid Build Coastguard Worker       {
803*a67afe4dSAndroid Build Coastguard Worker          case 0:
804*a67afe4dSAndroid Build Coastguard Worker          {
805*a67afe4dSAndroid Build Coastguard Worker             int i;
806*a67afe4dSAndroid Build Coastguard Worker             for (i = 0; i < 8 && png_ptr->pass == 0; i++)
807*a67afe4dSAndroid Build Coastguard Worker             {
808*a67afe4dSAndroid Build Coastguard Worker                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
809*a67afe4dSAndroid Build Coastguard Worker                png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
810*a67afe4dSAndroid Build Coastguard Worker             }
811*a67afe4dSAndroid Build Coastguard Worker 
812*a67afe4dSAndroid Build Coastguard Worker             if (png_ptr->pass == 2) /* Pass 1 might be empty */
813*a67afe4dSAndroid Build Coastguard Worker             {
814*a67afe4dSAndroid Build Coastguard Worker                for (i = 0; i < 4 && png_ptr->pass == 2; i++)
815*a67afe4dSAndroid Build Coastguard Worker                {
816*a67afe4dSAndroid Build Coastguard Worker                   png_push_have_row(png_ptr, NULL);
817*a67afe4dSAndroid Build Coastguard Worker                   png_read_push_finish_row(png_ptr);
818*a67afe4dSAndroid Build Coastguard Worker                }
819*a67afe4dSAndroid Build Coastguard Worker             }
820*a67afe4dSAndroid Build Coastguard Worker 
821*a67afe4dSAndroid Build Coastguard Worker             if (png_ptr->pass == 4 && png_ptr->height <= 4)
822*a67afe4dSAndroid Build Coastguard Worker             {
823*a67afe4dSAndroid Build Coastguard Worker                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
824*a67afe4dSAndroid Build Coastguard Worker                {
825*a67afe4dSAndroid Build Coastguard Worker                   png_push_have_row(png_ptr, NULL);
826*a67afe4dSAndroid Build Coastguard Worker                   png_read_push_finish_row(png_ptr);
827*a67afe4dSAndroid Build Coastguard Worker                }
828*a67afe4dSAndroid Build Coastguard Worker             }
829*a67afe4dSAndroid Build Coastguard Worker 
830*a67afe4dSAndroid Build Coastguard Worker             if (png_ptr->pass == 6 && png_ptr->height <= 4)
831*a67afe4dSAndroid Build Coastguard Worker             {
832*a67afe4dSAndroid Build Coastguard Worker                 png_push_have_row(png_ptr, NULL);
833*a67afe4dSAndroid Build Coastguard Worker                 png_read_push_finish_row(png_ptr);
834*a67afe4dSAndroid Build Coastguard Worker             }
835*a67afe4dSAndroid Build Coastguard Worker 
836*a67afe4dSAndroid Build Coastguard Worker             break;
837*a67afe4dSAndroid Build Coastguard Worker          }
838*a67afe4dSAndroid Build Coastguard Worker 
839*a67afe4dSAndroid Build Coastguard Worker          case 1:
840*a67afe4dSAndroid Build Coastguard Worker          {
841*a67afe4dSAndroid Build Coastguard Worker             int i;
842*a67afe4dSAndroid Build Coastguard Worker             for (i = 0; i < 8 && png_ptr->pass == 1; i++)
843*a67afe4dSAndroid Build Coastguard Worker             {
844*a67afe4dSAndroid Build Coastguard Worker                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
845*a67afe4dSAndroid Build Coastguard Worker                png_read_push_finish_row(png_ptr);
846*a67afe4dSAndroid Build Coastguard Worker             }
847*a67afe4dSAndroid Build Coastguard Worker 
848*a67afe4dSAndroid Build Coastguard Worker             if (png_ptr->pass == 2) /* Skip top 4 generated rows */
849*a67afe4dSAndroid Build Coastguard Worker             {
850*a67afe4dSAndroid Build Coastguard Worker                for (i = 0; i < 4 && png_ptr->pass == 2; i++)
851*a67afe4dSAndroid Build Coastguard Worker                {
852*a67afe4dSAndroid Build Coastguard Worker                   png_push_have_row(png_ptr, NULL);
853*a67afe4dSAndroid Build Coastguard Worker                   png_read_push_finish_row(png_ptr);
854*a67afe4dSAndroid Build Coastguard Worker                }
855*a67afe4dSAndroid Build Coastguard Worker             }
856*a67afe4dSAndroid Build Coastguard Worker 
857*a67afe4dSAndroid Build Coastguard Worker             break;
858*a67afe4dSAndroid Build Coastguard Worker          }
859*a67afe4dSAndroid Build Coastguard Worker 
860*a67afe4dSAndroid Build Coastguard Worker          case 2:
861*a67afe4dSAndroid Build Coastguard Worker          {
862*a67afe4dSAndroid Build Coastguard Worker             int i;
863*a67afe4dSAndroid Build Coastguard Worker 
864*a67afe4dSAndroid Build Coastguard Worker             for (i = 0; i < 4 && png_ptr->pass == 2; i++)
865*a67afe4dSAndroid Build Coastguard Worker             {
866*a67afe4dSAndroid Build Coastguard Worker                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
867*a67afe4dSAndroid Build Coastguard Worker                png_read_push_finish_row(png_ptr);
868*a67afe4dSAndroid Build Coastguard Worker             }
869*a67afe4dSAndroid Build Coastguard Worker 
870*a67afe4dSAndroid Build Coastguard Worker             for (i = 0; i < 4 && png_ptr->pass == 2; i++)
871*a67afe4dSAndroid Build Coastguard Worker             {
872*a67afe4dSAndroid Build Coastguard Worker                png_push_have_row(png_ptr, NULL);
873*a67afe4dSAndroid Build Coastguard Worker                png_read_push_finish_row(png_ptr);
874*a67afe4dSAndroid Build Coastguard Worker             }
875*a67afe4dSAndroid Build Coastguard Worker 
876*a67afe4dSAndroid Build Coastguard Worker             if (png_ptr->pass == 4) /* Pass 3 might be empty */
877*a67afe4dSAndroid Build Coastguard Worker             {
878*a67afe4dSAndroid Build Coastguard Worker                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
879*a67afe4dSAndroid Build Coastguard Worker                {
880*a67afe4dSAndroid Build Coastguard Worker                   png_push_have_row(png_ptr, NULL);
881*a67afe4dSAndroid Build Coastguard Worker                   png_read_push_finish_row(png_ptr);
882*a67afe4dSAndroid Build Coastguard Worker                }
883*a67afe4dSAndroid Build Coastguard Worker             }
884*a67afe4dSAndroid Build Coastguard Worker 
885*a67afe4dSAndroid Build Coastguard Worker             break;
886*a67afe4dSAndroid Build Coastguard Worker          }
887*a67afe4dSAndroid Build Coastguard Worker 
888*a67afe4dSAndroid Build Coastguard Worker          case 3:
889*a67afe4dSAndroid Build Coastguard Worker          {
890*a67afe4dSAndroid Build Coastguard Worker             int i;
891*a67afe4dSAndroid Build Coastguard Worker 
892*a67afe4dSAndroid Build Coastguard Worker             for (i = 0; i < 4 && png_ptr->pass == 3; i++)
893*a67afe4dSAndroid Build Coastguard Worker             {
894*a67afe4dSAndroid Build Coastguard Worker                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
895*a67afe4dSAndroid Build Coastguard Worker                png_read_push_finish_row(png_ptr);
896*a67afe4dSAndroid Build Coastguard Worker             }
897*a67afe4dSAndroid Build Coastguard Worker 
898*a67afe4dSAndroid Build Coastguard Worker             if (png_ptr->pass == 4) /* Skip top two generated rows */
899*a67afe4dSAndroid Build Coastguard Worker             {
900*a67afe4dSAndroid Build Coastguard Worker                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
901*a67afe4dSAndroid Build Coastguard Worker                {
902*a67afe4dSAndroid Build Coastguard Worker                   png_push_have_row(png_ptr, NULL);
903*a67afe4dSAndroid Build Coastguard Worker                   png_read_push_finish_row(png_ptr);
904*a67afe4dSAndroid Build Coastguard Worker                }
905*a67afe4dSAndroid Build Coastguard Worker             }
906*a67afe4dSAndroid Build Coastguard Worker 
907*a67afe4dSAndroid Build Coastguard Worker             break;
908*a67afe4dSAndroid Build Coastguard Worker          }
909*a67afe4dSAndroid Build Coastguard Worker 
910*a67afe4dSAndroid Build Coastguard Worker          case 4:
911*a67afe4dSAndroid Build Coastguard Worker          {
912*a67afe4dSAndroid Build Coastguard Worker             int i;
913*a67afe4dSAndroid Build Coastguard Worker 
914*a67afe4dSAndroid Build Coastguard Worker             for (i = 0; i < 2 && png_ptr->pass == 4; i++)
915*a67afe4dSAndroid Build Coastguard Worker             {
916*a67afe4dSAndroid Build Coastguard Worker                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
917*a67afe4dSAndroid Build Coastguard Worker                png_read_push_finish_row(png_ptr);
918*a67afe4dSAndroid Build Coastguard Worker             }
919*a67afe4dSAndroid Build Coastguard Worker 
920*a67afe4dSAndroid Build Coastguard Worker             for (i = 0; i < 2 && png_ptr->pass == 4; i++)
921*a67afe4dSAndroid Build Coastguard Worker             {
922*a67afe4dSAndroid Build Coastguard Worker                png_push_have_row(png_ptr, NULL);
923*a67afe4dSAndroid Build Coastguard Worker                png_read_push_finish_row(png_ptr);
924*a67afe4dSAndroid Build Coastguard Worker             }
925*a67afe4dSAndroid Build Coastguard Worker 
926*a67afe4dSAndroid Build Coastguard Worker             if (png_ptr->pass == 6) /* Pass 5 might be empty */
927*a67afe4dSAndroid Build Coastguard Worker             {
928*a67afe4dSAndroid Build Coastguard Worker                png_push_have_row(png_ptr, NULL);
929*a67afe4dSAndroid Build Coastguard Worker                png_read_push_finish_row(png_ptr);
930*a67afe4dSAndroid Build Coastguard Worker             }
931*a67afe4dSAndroid Build Coastguard Worker 
932*a67afe4dSAndroid Build Coastguard Worker             break;
933*a67afe4dSAndroid Build Coastguard Worker          }
934*a67afe4dSAndroid Build Coastguard Worker 
935*a67afe4dSAndroid Build Coastguard Worker          case 5:
936*a67afe4dSAndroid Build Coastguard Worker          {
937*a67afe4dSAndroid Build Coastguard Worker             int i;
938*a67afe4dSAndroid Build Coastguard Worker 
939*a67afe4dSAndroid Build Coastguard Worker             for (i = 0; i < 2 && png_ptr->pass == 5; i++)
940*a67afe4dSAndroid Build Coastguard Worker             {
941*a67afe4dSAndroid Build Coastguard Worker                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
942*a67afe4dSAndroid Build Coastguard Worker                png_read_push_finish_row(png_ptr);
943*a67afe4dSAndroid Build Coastguard Worker             }
944*a67afe4dSAndroid Build Coastguard Worker 
945*a67afe4dSAndroid Build Coastguard Worker             if (png_ptr->pass == 6) /* Skip top generated row */
946*a67afe4dSAndroid Build Coastguard Worker             {
947*a67afe4dSAndroid Build Coastguard Worker                png_push_have_row(png_ptr, NULL);
948*a67afe4dSAndroid Build Coastguard Worker                png_read_push_finish_row(png_ptr);
949*a67afe4dSAndroid Build Coastguard Worker             }
950*a67afe4dSAndroid Build Coastguard Worker 
951*a67afe4dSAndroid Build Coastguard Worker             break;
952*a67afe4dSAndroid Build Coastguard Worker          }
953*a67afe4dSAndroid Build Coastguard Worker 
954*a67afe4dSAndroid Build Coastguard Worker          default:
955*a67afe4dSAndroid Build Coastguard Worker          case 6:
956*a67afe4dSAndroid Build Coastguard Worker          {
957*a67afe4dSAndroid Build Coastguard Worker             png_push_have_row(png_ptr, png_ptr->row_buf + 1);
958*a67afe4dSAndroid Build Coastguard Worker             png_read_push_finish_row(png_ptr);
959*a67afe4dSAndroid Build Coastguard Worker 
960*a67afe4dSAndroid Build Coastguard Worker             if (png_ptr->pass != 6)
961*a67afe4dSAndroid Build Coastguard Worker                break;
962*a67afe4dSAndroid Build Coastguard Worker 
963*a67afe4dSAndroid Build Coastguard Worker             png_push_have_row(png_ptr, NULL);
964*a67afe4dSAndroid Build Coastguard Worker             png_read_push_finish_row(png_ptr);
965*a67afe4dSAndroid Build Coastguard Worker          }
966*a67afe4dSAndroid Build Coastguard Worker       }
967*a67afe4dSAndroid Build Coastguard Worker    }
968*a67afe4dSAndroid Build Coastguard Worker    else
969*a67afe4dSAndroid Build Coastguard Worker #endif
970*a67afe4dSAndroid Build Coastguard Worker    {
971*a67afe4dSAndroid Build Coastguard Worker       png_push_have_row(png_ptr, png_ptr->row_buf + 1);
972*a67afe4dSAndroid Build Coastguard Worker       png_read_push_finish_row(png_ptr);
973*a67afe4dSAndroid Build Coastguard Worker    }
974*a67afe4dSAndroid Build Coastguard Worker }
975*a67afe4dSAndroid Build Coastguard Worker 
976*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_read_push_finish_row(png_structrp png_ptr)977*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_structrp png_ptr)
978*a67afe4dSAndroid Build Coastguard Worker {
979*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_INTERLACING_SUPPORTED
980*a67afe4dSAndroid Build Coastguard Worker    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
981*a67afe4dSAndroid Build Coastguard Worker 
982*a67afe4dSAndroid Build Coastguard Worker    /* Start of interlace block */
983*a67afe4dSAndroid Build Coastguard Worker    static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
984*a67afe4dSAndroid Build Coastguard Worker 
985*a67afe4dSAndroid Build Coastguard Worker    /* Offset to next interlace block */
986*a67afe4dSAndroid Build Coastguard Worker    static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
987*a67afe4dSAndroid Build Coastguard Worker 
988*a67afe4dSAndroid Build Coastguard Worker    /* Start of interlace block in the y direction */
989*a67afe4dSAndroid Build Coastguard Worker    static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
990*a67afe4dSAndroid Build Coastguard Worker 
991*a67afe4dSAndroid Build Coastguard Worker    /* Offset to next interlace block in the y direction */
992*a67afe4dSAndroid Build Coastguard Worker    static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
993*a67afe4dSAndroid Build Coastguard Worker 
994*a67afe4dSAndroid Build Coastguard Worker    /* Height of interlace block.  This is not currently used - if you need
995*a67afe4dSAndroid Build Coastguard Worker     * it, uncomment it here and in png.h
996*a67afe4dSAndroid Build Coastguard Worker    static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
997*a67afe4dSAndroid Build Coastguard Worker    */
998*a67afe4dSAndroid Build Coastguard Worker #endif
999*a67afe4dSAndroid Build Coastguard Worker 
1000*a67afe4dSAndroid Build Coastguard Worker    png_ptr->row_number++;
1001*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->row_number < png_ptr->num_rows)
1002*a67afe4dSAndroid Build Coastguard Worker       return;
1003*a67afe4dSAndroid Build Coastguard Worker 
1004*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_INTERLACING_SUPPORTED
1005*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->interlaced != 0)
1006*a67afe4dSAndroid Build Coastguard Worker    {
1007*a67afe4dSAndroid Build Coastguard Worker       png_ptr->row_number = 0;
1008*a67afe4dSAndroid Build Coastguard Worker       memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
1009*a67afe4dSAndroid Build Coastguard Worker 
1010*a67afe4dSAndroid Build Coastguard Worker       do
1011*a67afe4dSAndroid Build Coastguard Worker       {
1012*a67afe4dSAndroid Build Coastguard Worker          png_ptr->pass++;
1013*a67afe4dSAndroid Build Coastguard Worker          if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
1014*a67afe4dSAndroid Build Coastguard Worker              (png_ptr->pass == 3 && png_ptr->width < 3) ||
1015*a67afe4dSAndroid Build Coastguard Worker              (png_ptr->pass == 5 && png_ptr->width < 2))
1016*a67afe4dSAndroid Build Coastguard Worker             png_ptr->pass++;
1017*a67afe4dSAndroid Build Coastguard Worker 
1018*a67afe4dSAndroid Build Coastguard Worker          if (png_ptr->pass > 7)
1019*a67afe4dSAndroid Build Coastguard Worker             png_ptr->pass--;
1020*a67afe4dSAndroid Build Coastguard Worker 
1021*a67afe4dSAndroid Build Coastguard Worker          if (png_ptr->pass >= 7)
1022*a67afe4dSAndroid Build Coastguard Worker             break;
1023*a67afe4dSAndroid Build Coastguard Worker 
1024*a67afe4dSAndroid Build Coastguard Worker          png_ptr->iwidth = (png_ptr->width +
1025*a67afe4dSAndroid Build Coastguard Worker              png_pass_inc[png_ptr->pass] - 1 -
1026*a67afe4dSAndroid Build Coastguard Worker              png_pass_start[png_ptr->pass]) /
1027*a67afe4dSAndroid Build Coastguard Worker              png_pass_inc[png_ptr->pass];
1028*a67afe4dSAndroid Build Coastguard Worker 
1029*a67afe4dSAndroid Build Coastguard Worker          if ((png_ptr->transformations & PNG_INTERLACE) != 0)
1030*a67afe4dSAndroid Build Coastguard Worker             break;
1031*a67afe4dSAndroid Build Coastguard Worker 
1032*a67afe4dSAndroid Build Coastguard Worker          png_ptr->num_rows = (png_ptr->height +
1033*a67afe4dSAndroid Build Coastguard Worker              png_pass_yinc[png_ptr->pass] - 1 -
1034*a67afe4dSAndroid Build Coastguard Worker              png_pass_ystart[png_ptr->pass]) /
1035*a67afe4dSAndroid Build Coastguard Worker              png_pass_yinc[png_ptr->pass];
1036*a67afe4dSAndroid Build Coastguard Worker 
1037*a67afe4dSAndroid Build Coastguard Worker       } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
1038*a67afe4dSAndroid Build Coastguard Worker    }
1039*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_INTERLACING */
1040*a67afe4dSAndroid Build Coastguard Worker }
1041*a67afe4dSAndroid Build Coastguard Worker 
1042*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_have_info(png_structrp png_ptr,png_inforp info_ptr)1043*a67afe4dSAndroid Build Coastguard Worker png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
1044*a67afe4dSAndroid Build Coastguard Worker {
1045*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->info_fn != NULL)
1046*a67afe4dSAndroid Build Coastguard Worker       (*(png_ptr->info_fn))(png_ptr, info_ptr);
1047*a67afe4dSAndroid Build Coastguard Worker }
1048*a67afe4dSAndroid Build Coastguard Worker 
1049*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_have_end(png_structrp png_ptr,png_inforp info_ptr)1050*a67afe4dSAndroid Build Coastguard Worker png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
1051*a67afe4dSAndroid Build Coastguard Worker {
1052*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->end_fn != NULL)
1053*a67afe4dSAndroid Build Coastguard Worker       (*(png_ptr->end_fn))(png_ptr, info_ptr);
1054*a67afe4dSAndroid Build Coastguard Worker }
1055*a67afe4dSAndroid Build Coastguard Worker 
1056*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_have_row(png_structrp png_ptr,png_bytep row)1057*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_structrp png_ptr, png_bytep row)
1058*a67afe4dSAndroid Build Coastguard Worker {
1059*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr->row_fn != NULL)
1060*a67afe4dSAndroid Build Coastguard Worker       (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
1061*a67afe4dSAndroid Build Coastguard Worker           (int)png_ptr->pass);
1062*a67afe4dSAndroid Build Coastguard Worker }
1063*a67afe4dSAndroid Build Coastguard Worker 
1064*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_INTERLACING_SUPPORTED
1065*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_progressive_combine_row(png_const_structrp png_ptr,png_bytep old_row,png_const_bytep new_row)1066*a67afe4dSAndroid Build Coastguard Worker png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
1067*a67afe4dSAndroid Build Coastguard Worker     png_const_bytep new_row)
1068*a67afe4dSAndroid Build Coastguard Worker {
1069*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr == NULL)
1070*a67afe4dSAndroid Build Coastguard Worker       return;
1071*a67afe4dSAndroid Build Coastguard Worker 
1072*a67afe4dSAndroid Build Coastguard Worker    /* new_row is a flag here - if it is NULL then the app callback was called
1073*a67afe4dSAndroid Build Coastguard Worker     * from an empty row (see the calls to png_struct::row_fn below), otherwise
1074*a67afe4dSAndroid Build Coastguard Worker     * it must be png_ptr->row_buf+1
1075*a67afe4dSAndroid Build Coastguard Worker     */
1076*a67afe4dSAndroid Build Coastguard Worker    if (new_row != NULL)
1077*a67afe4dSAndroid Build Coastguard Worker       png_combine_row(png_ptr, old_row, 1/*blocky display*/);
1078*a67afe4dSAndroid Build Coastguard Worker }
1079*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_INTERLACING */
1080*a67afe4dSAndroid Build Coastguard Worker 
1081*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_progressive_read_fn(png_structrp png_ptr,png_voidp progressive_ptr,png_progressive_info_ptr info_fn,png_progressive_row_ptr row_fn,png_progressive_end_ptr end_fn)1082*a67afe4dSAndroid Build Coastguard Worker png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
1083*a67afe4dSAndroid Build Coastguard Worker     png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
1084*a67afe4dSAndroid Build Coastguard Worker     png_progressive_end_ptr end_fn)
1085*a67afe4dSAndroid Build Coastguard Worker {
1086*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr == NULL)
1087*a67afe4dSAndroid Build Coastguard Worker       return;
1088*a67afe4dSAndroid Build Coastguard Worker 
1089*a67afe4dSAndroid Build Coastguard Worker    png_ptr->info_fn = info_fn;
1090*a67afe4dSAndroid Build Coastguard Worker    png_ptr->row_fn = row_fn;
1091*a67afe4dSAndroid Build Coastguard Worker    png_ptr->end_fn = end_fn;
1092*a67afe4dSAndroid Build Coastguard Worker 
1093*a67afe4dSAndroid Build Coastguard Worker    png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
1094*a67afe4dSAndroid Build Coastguard Worker }
1095*a67afe4dSAndroid Build Coastguard Worker 
1096*a67afe4dSAndroid Build Coastguard Worker png_voidp PNGAPI
png_get_progressive_ptr(png_const_structrp png_ptr)1097*a67afe4dSAndroid Build Coastguard Worker png_get_progressive_ptr(png_const_structrp png_ptr)
1098*a67afe4dSAndroid Build Coastguard Worker {
1099*a67afe4dSAndroid Build Coastguard Worker    if (png_ptr == NULL)
1100*a67afe4dSAndroid Build Coastguard Worker       return NULL;
1101*a67afe4dSAndroid Build Coastguard Worker 
1102*a67afe4dSAndroid Build Coastguard Worker    return png_ptr->io_ptr;
1103*a67afe4dSAndroid Build Coastguard Worker }
1104*a67afe4dSAndroid Build Coastguard Worker #endif /* PROGRESSIVE_READ */
1105