Initial revision
[rrdtool.git] / libraries / libpng-1.0.9 / pngwio.c
1
2 /* pngwio.c - functions for data output
3  *
4  * libpng 1.0.9 - January 31, 2001
5  * For conditions of distribution and use, see copyright notice in png.h
6  * Copyright (c) 1998-2001 Glenn Randers-Pehrson
7  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9  *
10  * This file provides a location for all output.  Users who need
11  * special handling are expected to write functions that have the same
12  * arguments as these and perform similar functions, but that possibly
13  * use different output methods.  Note that you shouldn't change these
14  * functions, but rather write replacement functions and then change
15  * them at run time with png_set_write_fn(...).
16  */
17
18 #define PNG_INTERNAL
19 #include "png.h"
20
21 /* Write the data to whatever output you are using.  The default routine
22    writes to a file pointer.  Note that this routine sometimes gets called
23    with very small lengths, so you should implement some kind of simple
24    buffering if you are using unbuffered writes.  This should never be asked
25    to write more than 64K on a 16 bit machine.  */
26
27 void /* PRIVATE */
28 png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
29 {
30    if (png_ptr->write_data_fn != NULL )
31       (*(png_ptr->write_data_fn))(png_ptr, data, length);
32    else
33       png_error(png_ptr, "Call to NULL write function");
34 }
35
36 #if !defined(PNG_NO_STDIO)
37 /* This is the function that does the actual writing of data.  If you are
38    not writing to a standard C stream, you should create a replacement
39    write_data function and use it at run time with png_set_write_fn(), rather
40    than changing the library. */
41 #ifndef USE_FAR_KEYWORD
42 static void /* PRIVATE */
43 png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
44 {
45    png_uint_32 check;
46
47 #if defined(_WIN32_WCE)
48    if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
49       check = 0;
50 #else
51    check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
52 #endif
53    if (check != length)
54       png_error(png_ptr, "Write Error");
55 }
56 #else
57 /* this is the model-independent version. Since the standard I/O library
58    can't handle far buffers in the medium and small models, we have to copy
59    the data.
60 */
61
62 #define NEAR_BUF_SIZE 1024
63 #define MIN(a,b) (a <= b ? a : b)
64
65 static void /* PRIVATE */
66 png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
67 {
68    png_uint_32 check;
69    png_byte *near_data;  /* Needs to be "png_byte *" instead of "png_bytep" */
70    png_FILE_p io_ptr;
71
72    /* Check if data really is near. If so, use usual code. */
73    near_data = (png_byte *)CVT_PTR_NOCHECK(data);
74    io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
75    if ((png_bytep)near_data == data)
76    {
77 #if defined(_WIN32_WCE)
78       if ( !WriteFile(io_ptr, near_data, length, &check, NULL) )
79          check = 0;
80 #else
81       check = fwrite(near_data, 1, length, io_ptr);
82 #endif
83    }
84    else
85    {
86       png_byte buf[NEAR_BUF_SIZE];
87       png_size_t written, remaining, err;
88       check = 0;
89       remaining = length;
90       do
91       {
92          written = MIN(NEAR_BUF_SIZE, remaining);
93          png_memcpy(buf, data, written); /* copy far buffer to near buffer */
94 #if defined(_WIN32_WCE)
95          if ( !WriteFile(io_ptr, buf, written, &err, NULL) )
96             err = 0;
97 #else
98          err = fwrite(buf, 1, written, io_ptr);
99 #endif
100          if (err != written)
101             break;
102          else
103             check += err;
104          data += written;
105          remaining -= written;
106       }
107       while (remaining != 0);
108    }
109    if (check != length)
110       png_error(png_ptr, "Write Error");
111 }
112
113 #endif
114 #endif
115
116 /* This function is called to output any data pending writing (normally
117    to disk).  After png_flush is called, there should be no data pending
118    writing in any buffers. */
119 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
120 void /* PRIVATE */
121 png_flush(png_structp png_ptr)
122 {
123    if (png_ptr->output_flush_fn != NULL)
124       (*(png_ptr->output_flush_fn))(png_ptr);
125 }
126
127 #if !defined(PNG_NO_STDIO)
128 static void /* PRIVATE */
129 png_default_flush(png_structp png_ptr)
130 {
131 #if !defined(_WIN32_WCE)
132    png_FILE_p io_ptr;
133    io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
134    if (io_ptr != NULL)
135       fflush(io_ptr);
136 #endif
137 }
138 #endif
139 #endif
140
141 /* This function allows the application to supply new output functions for
142    libpng if standard C streams aren't being used.
143
144    This function takes as its arguments:
145    png_ptr       - pointer to a png output data structure
146    io_ptr        - pointer to user supplied structure containing info about
147                    the output functions.  May be NULL.
148    write_data_fn - pointer to a new output function that takes as its
149                    arguments a pointer to a png_struct, a pointer to
150                    data to be written, and a 32-bit unsigned int that is
151                    the number of bytes to be written.  The new write
152                    function should call png_error(png_ptr, "Error msg")
153                    to exit and output any fatal error messages.
154    flush_data_fn - pointer to a new flush function that takes as its
155                    arguments a pointer to a png_struct.  After a call to
156                    the flush function, there should be no data in any buffers
157                    or pending transmission.  If the output method doesn't do
158                    any buffering of ouput, a function prototype must still be
159                    supplied although it doesn't have to do anything.  If
160                    PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
161                    time, output_flush_fn will be ignored, although it must be
162                    supplied for compatibility. */
163 void PNGAPI
164 png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
165    png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
166 {
167    png_ptr->io_ptr = io_ptr;
168
169 #if !defined(PNG_NO_STDIO)
170    if (write_data_fn != NULL)
171       png_ptr->write_data_fn = write_data_fn;
172    else
173       png_ptr->write_data_fn = png_default_write_data;
174 #else
175    png_ptr->write_data_fn = write_data_fn;
176 #endif
177
178 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
179 #if !defined(PNG_NO_STDIO)
180    if (output_flush_fn != NULL)
181       png_ptr->output_flush_fn = output_flush_fn;
182    else
183       png_ptr->output_flush_fn = png_default_flush;
184 #else
185    png_ptr->output_flush_fn = output_flush_fn;
186 #endif
187 #endif /* PNG_WRITE_FLUSH_SUPPORTED */
188
189    /* It is an error to read while writing a png file */
190    if (png_ptr->read_data_fn != NULL)
191    {
192       png_ptr->read_data_fn = NULL;
193       png_warning(png_ptr,
194          "Attempted to set both read_data_fn and write_data_fn in");
195       png_warning(png_ptr,
196          "the same structure.  Resetting read_data_fn to NULL.");
197    }
198 }
199
200 #if defined(USE_FAR_KEYWORD)
201 #if defined(_MSC_VER)
202 void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
203 {
204    void *near_ptr;
205    void FAR *far_ptr;
206    FP_OFF(near_ptr) = FP_OFF(ptr);
207    far_ptr = (void FAR *)near_ptr;
208    if(check != 0)
209       if(FP_SEG(ptr) != FP_SEG(far_ptr))
210          png_error(png_ptr,"segment lost in conversion");
211    return(near_ptr);
212 }
213 #  else
214 void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
215 {
216    void *near_ptr;
217    void FAR *far_ptr;
218    near_ptr = (void FAR *)ptr;
219    far_ptr = (void FAR *)near_ptr;
220    if(check != 0)
221       if(far_ptr != ptr)
222          png_error(png_ptr,"segment lost in conversion");
223    return(near_ptr);
224 }
225 #   endif
226 #   endif