xref: /plan9/sys/src/cmd/gs/libpng/pngwio.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier 
27dd7cddfSDavid du Colombier /* pngwio.c - functions for data output
37dd7cddfSDavid du Colombier  *
4*593dc095SDavid du Colombier  * libpng 1.2.8 - December 3, 2004
57dd7cddfSDavid du Colombier  * For conditions of distribution and use, see copyright notice in png.h
6*593dc095SDavid du Colombier  * Copyright (c) 1998-2004 Glenn Randers-Pehrson
7*593dc095SDavid du Colombier  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8*593dc095SDavid du Colombier  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
97dd7cddfSDavid du Colombier  *
10*593dc095SDavid du Colombier  * This file provides a location for all output.  Users who need
11*593dc095SDavid du Colombier  * special handling are expected to write functions that have the same
12*593dc095SDavid du Colombier  * arguments as these and perform similar functions, but that possibly
13*593dc095SDavid du Colombier  * use different output methods.  Note that you shouldn't change these
147dd7cddfSDavid du Colombier  * functions, but rather write replacement functions and then change
157dd7cddfSDavid du Colombier  * them at run time with png_set_write_fn(...).
167dd7cddfSDavid du Colombier  */
177dd7cddfSDavid du Colombier 
187dd7cddfSDavid du Colombier #define PNG_INTERNAL
197dd7cddfSDavid du Colombier #include "png.h"
20*593dc095SDavid du Colombier #ifdef PNG_WRITE_SUPPORTED
217dd7cddfSDavid du Colombier 
227dd7cddfSDavid du Colombier /* Write the data to whatever output you are using.  The default routine
237dd7cddfSDavid du Colombier    writes to a file pointer.  Note that this routine sometimes gets called
247dd7cddfSDavid du Colombier    with very small lengths, so you should implement some kind of simple
257dd7cddfSDavid du Colombier    buffering if you are using unbuffered writes.  This should never be asked
26*593dc095SDavid du Colombier    to write more than 64K on a 16 bit machine.  */
277dd7cddfSDavid du Colombier 
28*593dc095SDavid du Colombier void /* PRIVATE */
png_write_data(png_structp png_ptr,png_bytep data,png_size_t length)297dd7cddfSDavid du Colombier png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
307dd7cddfSDavid du Colombier {
317dd7cddfSDavid du Colombier    if (png_ptr->write_data_fn != NULL )
327dd7cddfSDavid du Colombier       (*(png_ptr->write_data_fn))(png_ptr, data, length);
337dd7cddfSDavid du Colombier    else
347dd7cddfSDavid du Colombier       png_error(png_ptr, "Call to NULL write function");
357dd7cddfSDavid du Colombier }
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier #if !defined(PNG_NO_STDIO)
38*593dc095SDavid du Colombier /* This is the function that does the actual writing of data.  If you are
397dd7cddfSDavid du Colombier    not writing to a standard C stream, you should create a replacement
407dd7cddfSDavid du Colombier    write_data function and use it at run time with png_set_write_fn(), rather
417dd7cddfSDavid du Colombier    than changing the library. */
427dd7cddfSDavid du Colombier #ifndef USE_FAR_KEYWORD
43*593dc095SDavid du Colombier void PNGAPI
png_default_write_data(png_structp png_ptr,png_bytep data,png_size_t length)447dd7cddfSDavid du Colombier png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
457dd7cddfSDavid du Colombier {
467dd7cddfSDavid du Colombier    png_uint_32 check;
477dd7cddfSDavid du Colombier 
48*593dc095SDavid du Colombier #if defined(_WIN32_WCE)
49*593dc095SDavid du Colombier    if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
50*593dc095SDavid du Colombier       check = 0;
51*593dc095SDavid du Colombier #else
52*593dc095SDavid du Colombier    check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
53*593dc095SDavid du Colombier #endif
547dd7cddfSDavid du Colombier    if (check != length)
557dd7cddfSDavid du Colombier       png_error(png_ptr, "Write Error");
567dd7cddfSDavid du Colombier }
577dd7cddfSDavid du Colombier #else
587dd7cddfSDavid du Colombier /* this is the model-independent version. Since the standard I/O library
597dd7cddfSDavid du Colombier    can't handle far buffers in the medium and small models, we have to copy
607dd7cddfSDavid du Colombier    the data.
617dd7cddfSDavid du Colombier */
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier #define NEAR_BUF_SIZE 1024
647dd7cddfSDavid du Colombier #define MIN(a,b) (a <= b ? a : b)
657dd7cddfSDavid du Colombier 
66*593dc095SDavid du Colombier void PNGAPI
png_default_write_data(png_structp png_ptr,png_bytep data,png_size_t length)677dd7cddfSDavid du Colombier png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
687dd7cddfSDavid du Colombier {
697dd7cddfSDavid du Colombier    png_uint_32 check;
707dd7cddfSDavid du Colombier    png_byte *near_data;  /* Needs to be "png_byte *" instead of "png_bytep" */
71*593dc095SDavid du Colombier    png_FILE_p io_ptr;
727dd7cddfSDavid du Colombier 
737dd7cddfSDavid du Colombier    /* Check if data really is near. If so, use usual code. */
747dd7cddfSDavid du Colombier    near_data = (png_byte *)CVT_PTR_NOCHECK(data);
75*593dc095SDavid du Colombier    io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
767dd7cddfSDavid du Colombier    if ((png_bytep)near_data == data)
777dd7cddfSDavid du Colombier    {
78*593dc095SDavid du Colombier #if defined(_WIN32_WCE)
79*593dc095SDavid du Colombier       if ( !WriteFile(io_ptr, near_data, length, &check, NULL) )
80*593dc095SDavid du Colombier          check = 0;
81*593dc095SDavid du Colombier #else
827dd7cddfSDavid du Colombier       check = fwrite(near_data, 1, length, io_ptr);
83*593dc095SDavid du Colombier #endif
847dd7cddfSDavid du Colombier    }
857dd7cddfSDavid du Colombier    else
867dd7cddfSDavid du Colombier    {
877dd7cddfSDavid du Colombier       png_byte buf[NEAR_BUF_SIZE];
887dd7cddfSDavid du Colombier       png_size_t written, remaining, err;
897dd7cddfSDavid du Colombier       check = 0;
907dd7cddfSDavid du Colombier       remaining = length;
917dd7cddfSDavid du Colombier       do
927dd7cddfSDavid du Colombier       {
937dd7cddfSDavid du Colombier          written = MIN(NEAR_BUF_SIZE, remaining);
947dd7cddfSDavid du Colombier          png_memcpy(buf, data, written); /* copy far buffer to near buffer */
95*593dc095SDavid du Colombier #if defined(_WIN32_WCE)
96*593dc095SDavid du Colombier          if ( !WriteFile(io_ptr, buf, written, &err, NULL) )
97*593dc095SDavid du Colombier             err = 0;
98*593dc095SDavid du Colombier #else
997dd7cddfSDavid du Colombier          err = fwrite(buf, 1, written, io_ptr);
100*593dc095SDavid du Colombier #endif
1017dd7cddfSDavid du Colombier          if (err != written)
1027dd7cddfSDavid du Colombier             break;
1037dd7cddfSDavid du Colombier          else
1047dd7cddfSDavid du Colombier             check += err;
1057dd7cddfSDavid du Colombier          data += written;
1067dd7cddfSDavid du Colombier          remaining -= written;
1077dd7cddfSDavid du Colombier       }
1087dd7cddfSDavid du Colombier       while (remaining != 0);
1097dd7cddfSDavid du Colombier    }
1107dd7cddfSDavid du Colombier    if (check != length)
1117dd7cddfSDavid du Colombier       png_error(png_ptr, "Write Error");
1127dd7cddfSDavid du Colombier }
1137dd7cddfSDavid du Colombier 
1147dd7cddfSDavid du Colombier #endif
1157dd7cddfSDavid du Colombier #endif
1167dd7cddfSDavid du Colombier 
1177dd7cddfSDavid du Colombier /* This function is called to output any data pending writing (normally
1187dd7cddfSDavid du Colombier    to disk).  After png_flush is called, there should be no data pending
1197dd7cddfSDavid du Colombier    writing in any buffers. */
1207dd7cddfSDavid du Colombier #if defined(PNG_WRITE_FLUSH_SUPPORTED)
121*593dc095SDavid du Colombier void /* PRIVATE */
png_flush(png_structp png_ptr)1227dd7cddfSDavid du Colombier png_flush(png_structp png_ptr)
1237dd7cddfSDavid du Colombier {
1247dd7cddfSDavid du Colombier    if (png_ptr->output_flush_fn != NULL)
1257dd7cddfSDavid du Colombier       (*(png_ptr->output_flush_fn))(png_ptr);
1267dd7cddfSDavid du Colombier }
1277dd7cddfSDavid du Colombier 
1287dd7cddfSDavid du Colombier #if !defined(PNG_NO_STDIO)
129*593dc095SDavid du Colombier void PNGAPI
png_default_flush(png_structp png_ptr)1307dd7cddfSDavid du Colombier png_default_flush(png_structp png_ptr)
1317dd7cddfSDavid du Colombier {
132*593dc095SDavid du Colombier #if !defined(_WIN32_WCE)
133*593dc095SDavid du Colombier    png_FILE_p io_ptr;
134*593dc095SDavid du Colombier    io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
1357dd7cddfSDavid du Colombier    if (io_ptr != NULL)
1367dd7cddfSDavid du Colombier       fflush(io_ptr);
137*593dc095SDavid du Colombier #endif
1387dd7cddfSDavid du Colombier }
1397dd7cddfSDavid du Colombier #endif
1407dd7cddfSDavid du Colombier #endif
1417dd7cddfSDavid du Colombier 
1427dd7cddfSDavid du Colombier /* This function allows the application to supply new output functions for
1437dd7cddfSDavid du Colombier    libpng if standard C streams aren't being used.
1447dd7cddfSDavid du Colombier 
1457dd7cddfSDavid du Colombier    This function takes as its arguments:
1467dd7cddfSDavid du Colombier    png_ptr       - pointer to a png output data structure
1477dd7cddfSDavid du Colombier    io_ptr        - pointer to user supplied structure containing info about
1487dd7cddfSDavid du Colombier                    the output functions.  May be NULL.
149*593dc095SDavid du Colombier    write_data_fn - pointer to a new output function that takes as its
1507dd7cddfSDavid du Colombier                    arguments a pointer to a png_struct, a pointer to
151*593dc095SDavid du Colombier                    data to be written, and a 32-bit unsigned int that is
1527dd7cddfSDavid du Colombier                    the number of bytes to be written.  The new write
1537dd7cddfSDavid du Colombier                    function should call png_error(png_ptr, "Error msg")
1547dd7cddfSDavid du Colombier                    to exit and output any fatal error messages.
155*593dc095SDavid du Colombier    flush_data_fn - pointer to a new flush function that takes as its
1567dd7cddfSDavid du Colombier                    arguments a pointer to a png_struct.  After a call to
1577dd7cddfSDavid du Colombier                    the flush function, there should be no data in any buffers
1587dd7cddfSDavid du Colombier                    or pending transmission.  If the output method doesn't do
1597dd7cddfSDavid du Colombier                    any buffering of ouput, a function prototype must still be
1607dd7cddfSDavid du Colombier                    supplied although it doesn't have to do anything.  If
1617dd7cddfSDavid du Colombier                    PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
1627dd7cddfSDavid du Colombier                    time, output_flush_fn will be ignored, although it must be
1637dd7cddfSDavid du Colombier                    supplied for compatibility. */
164*593dc095SDavid du Colombier void PNGAPI
png_set_write_fn(png_structp png_ptr,png_voidp io_ptr,png_rw_ptr write_data_fn,png_flush_ptr output_flush_fn)1657dd7cddfSDavid du Colombier png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
1667dd7cddfSDavid du Colombier    png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
1677dd7cddfSDavid du Colombier {
1687dd7cddfSDavid du Colombier    png_ptr->io_ptr = io_ptr;
1697dd7cddfSDavid du Colombier 
1707dd7cddfSDavid du Colombier #if !defined(PNG_NO_STDIO)
1717dd7cddfSDavid du Colombier    if (write_data_fn != NULL)
1727dd7cddfSDavid du Colombier       png_ptr->write_data_fn = write_data_fn;
1737dd7cddfSDavid du Colombier    else
1747dd7cddfSDavid du Colombier       png_ptr->write_data_fn = png_default_write_data;
1757dd7cddfSDavid du Colombier #else
1767dd7cddfSDavid du Colombier    png_ptr->write_data_fn = write_data_fn;
1777dd7cddfSDavid du Colombier #endif
1787dd7cddfSDavid du Colombier 
1797dd7cddfSDavid du Colombier #if defined(PNG_WRITE_FLUSH_SUPPORTED)
1807dd7cddfSDavid du Colombier #if !defined(PNG_NO_STDIO)
1817dd7cddfSDavid du Colombier    if (output_flush_fn != NULL)
1827dd7cddfSDavid du Colombier       png_ptr->output_flush_fn = output_flush_fn;
1837dd7cddfSDavid du Colombier    else
1847dd7cddfSDavid du Colombier       png_ptr->output_flush_fn = png_default_flush;
1857dd7cddfSDavid du Colombier #else
1867dd7cddfSDavid du Colombier    png_ptr->output_flush_fn = output_flush_fn;
1877dd7cddfSDavid du Colombier #endif
1887dd7cddfSDavid du Colombier #endif /* PNG_WRITE_FLUSH_SUPPORTED */
1897dd7cddfSDavid du Colombier 
1907dd7cddfSDavid du Colombier    /* It is an error to read while writing a png file */
191*593dc095SDavid du Colombier    if (png_ptr->read_data_fn != NULL)
192*593dc095SDavid du Colombier    {
1937dd7cddfSDavid du Colombier       png_ptr->read_data_fn = NULL;
194*593dc095SDavid du Colombier       png_warning(png_ptr,
195*593dc095SDavid du Colombier          "Attempted to set both read_data_fn and write_data_fn in");
196*593dc095SDavid du Colombier       png_warning(png_ptr,
197*593dc095SDavid du Colombier          "the same structure.  Resetting read_data_fn to NULL.");
198*593dc095SDavid du Colombier    }
1997dd7cddfSDavid du Colombier }
2007dd7cddfSDavid du Colombier 
2017dd7cddfSDavid du Colombier #if defined(USE_FAR_KEYWORD)
2027dd7cddfSDavid du Colombier #if defined(_MSC_VER)
png_far_to_near(png_structp png_ptr,png_voidp ptr,int check)203*593dc095SDavid du Colombier void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
2047dd7cddfSDavid du Colombier {
2057dd7cddfSDavid du Colombier    void *near_ptr;
2067dd7cddfSDavid du Colombier    void FAR *far_ptr;
2077dd7cddfSDavid du Colombier    FP_OFF(near_ptr) = FP_OFF(ptr);
2087dd7cddfSDavid du Colombier    far_ptr = (void FAR *)near_ptr;
2097dd7cddfSDavid du Colombier    if(check != 0)
2107dd7cddfSDavid du Colombier       if(FP_SEG(ptr) != FP_SEG(far_ptr))
2117dd7cddfSDavid du Colombier          png_error(png_ptr,"segment lost in conversion");
2127dd7cddfSDavid du Colombier    return(near_ptr);
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier #  else
png_far_to_near(png_structp png_ptr,png_voidp ptr,int check)215*593dc095SDavid du Colombier void *png_far_to_near(png_structp png_ptr,png_voidp ptr, int check)
2167dd7cddfSDavid du Colombier {
2177dd7cddfSDavid du Colombier    void *near_ptr;
2187dd7cddfSDavid du Colombier    void FAR *far_ptr;
2197dd7cddfSDavid du Colombier    near_ptr = (void FAR *)ptr;
2207dd7cddfSDavid du Colombier    far_ptr = (void FAR *)near_ptr;
2217dd7cddfSDavid du Colombier    if(check != 0)
2227dd7cddfSDavid du Colombier       if(far_ptr != ptr)
2237dd7cddfSDavid du Colombier          png_error(png_ptr,"segment lost in conversion");
2247dd7cddfSDavid du Colombier    return(near_ptr);
2257dd7cddfSDavid du Colombier }
2267dd7cddfSDavid du Colombier #   endif
2277dd7cddfSDavid du Colombier #   endif
228*593dc095SDavid du Colombier #endif /* PNG_WRITE_SUPPORTED */
229