[llvm-commits] [parallel] CVS: llvm/runtime/libpng/contrib/gregbook/LICENSE Makefile.sgi Makefile.unx Makefile.w32 README makevms.com readpng.c readpng.h readpng2.c readpng2.h rpng-win.c rpng-x.c rpng2-win.c rpng2-x.c toucan.png wpng.c writepng.c writepng.h

Misha Brukman brukman at cs.uiuc.edu
Mon Mar 1 18:09:29 PST 2004


Changes in directory llvm/runtime/libpng/contrib/gregbook:

LICENSE added (r1.1.2.1)
Makefile.sgi added (r1.1.2.1)
Makefile.unx added (r1.1.2.1)
Makefile.w32 added (r1.1.2.1)
README added (r1.1.2.1)
makevms.com added (r1.1.2.1)
readpng.c added (r1.1.2.1)
readpng.h added (r1.1.2.1)
readpng2.c added (r1.1.2.1)
readpng2.h added (r1.1.2.1)
rpng-win.c added (r1.1.2.1)
rpng-x.c added (r1.1.2.1)
rpng2-win.c added (r1.1.2.1)
rpng2-x.c added (r1.1.2.1)
toucan.png added (r1.1.2.1)
wpng.c added (r1.1.2.1)
writepng.c added (r1.1.2.1)
writepng.h added (r1.1.2.1)

---
Log message:

Merge from trunk

---
Diffs of the changes:  (+7089 -0)

Index: llvm/runtime/libpng/contrib/gregbook/LICENSE
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/LICENSE:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:55 2004
--- llvm/runtime/libpng/contrib/gregbook/LICENSE	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,26 ----
+   ---------------------------------------------------------------------------
+ 
+       Copyright (c) 1998-2001 Greg Roelofs.  All rights reserved.
+ 
+       This software is provided "as is," without warranty of any kind,
+       express or implied.  In no event shall the author or contributors
+       be held liable for any damages arising in any way from the use of
+       this software.
+ 
+       Permission is granted to anyone to use this software for any purpose,
+       including commercial applications, and to alter it and redistribute
+       it freely, subject to the following restrictions:
+ 
+       1. Redistributions of source code must retain the above copyright
+          notice, disclaimer, and this list of conditions.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, disclaimer, and this list of conditions in the documenta-
+          tion and/or other materials provided with the distribution.
+       3. All advertising materials mentioning features or use of this
+          software must display the following acknowledgment:
+ 
+             This product includes software developed by Greg Roelofs
+             and contributors for the book, "PNG: The Definitive Guide,"
+             published by O'Reilly and Associates.
+ 
+   ---------------------------------------------------------------------------


Index: llvm/runtime/libpng/contrib/gregbook/Makefile.sgi
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/Makefile.sgi:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:55 2004
--- llvm/runtime/libpng/contrib/gregbook/Makefile.sgi	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,104 ----
+ # Sample makefile for rpng-x / rpng2-x / wpng for SGI using cc and make.
+ # Greg Roelofs
+ # Last modified:  7 March 2002
+ #
+ #	The programs built by this makefile are described in the book,
+ #	"PNG:  The Definitive Guide," by Greg Roelofs (O'Reilly and
+ #	Associates, 1999).  Go buy a copy, eh?  Buy some for friends
+ #	and family, too.  (Not that this is a blatant plug or anything.)
+ #
+ # Invoke this makefile from a shell prompt in the usual way; for example:
+ #
+ #	make -f Makefile.sgi
+ #
+ # This makefile assumes libpng and zlib have already been built or downloaded
+ # and are both installed in /usr/local/{include,lib} (as indicated by the
+ # PNG* and Z* macros below).  Edit as appropriate--choose only ONE each of
+ # the PNGINC, PNGLIB, ZINC and ZLIB lines.
+ #
+ # This makefile builds dynamically linked executables (against libpng and zlib,
+ # that is), but that can be changed by uncommenting the appropriate PNGLIB and
+ # ZLIB lines.
+ 
+ 
+ # macros --------------------------------------------------------------------
+ 
+ PNGINC = -I/usr/local/include/libpng12
+ PNGLIB = -L/usr/local/lib -lpng12	  # dynamically linked against libpng
+ #PNGLIB = /usr/local/lib/libpng12.a # statically linked against libpng
+ # or:
+ #PNGINC = -I../..
+ #PNGLIB = -L../.. -lpng
+ #PNGLIB = ../../libpng.a
+ 
+ ZINC = -I/usr/local/include
+ ZLIB = -L/usr/local/lib -lz		# dynamically linked against zlib
+ #ZLIB = /usr/local/lib/libz.a		# statically linked against zlib
+ #ZINC = -I../zlib
+ #ZLIB = -L../zlib -lz
+ #ZLIB = ../../../zlib/libz.a
+ 
+ XINC = -I/usr/include/X11		# old-style, stock X distributions
+ XLIB = -L/usr/lib/X11 -lX11
+ #XINC = -I/usr/openwin/include    	# Sun workstations (OpenWindows)
+ #XLIB = -L/usr/openwin/lib -lX11
+ #XINC = -I/usr/X11R6/include		# new X distributions (XFree86, etc.)
+ #XLIB = -L/usr/X11R6/lib -lX11
+ 
+ INCS = $(PNGINC) $(ZINC) $(XINC)
+ RLIBS = $(PNGLIB) $(ZLIB) $(XLIB) -lm
+ WLIBS = $(PNGLIB) $(ZLIB)
+ 
+ CC = cc
+ LD = cc
+ RM = rm -f
+ # ABI must be the same as that used to build libpng.
+ ABI=
+ CFLAGS = $(ABI) -O -fullwarn $(INCS)
+ LDFLAGS = $(ABI)
+ O = .o
+ E =
+ 
+ RPNG  = rpng-x
+ RPNG2 = rpng2-x
+ WPNG  = wpng
+ 
+ ROBJS  = $(RPNG)$(O) readpng$(O)
+ ROBJS2 = $(RPNG2)$(O) readpng2$(O)
+ WOBJS  = $(WPNG)$(O) writepng$(O)
+ 
+ EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E)
+ 
+ 
+ # implicit make rules -------------------------------------------------------
+ 
+ .c$(O):
+ 	$(CC) -c $(CFLAGS) $<
+ 
+ 
+ # dependencies --------------------------------------------------------------
+ 
+ all:  $(EXES)
+ 
+ $(RPNG)$(E): $(ROBJS)
+ 	$(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBS)
+ 
+ $(RPNG2)$(E): $(ROBJS2)
+ 	$(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBS)
+ 
+ $(WPNG)$(E): $(WOBJS)
+ 	$(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBS)
+ 
+ $(RPNG)$(O):	$(RPNG).c readpng.h
+ $(RPNG2)$(O):	$(RPNG2).c readpng2.h
+ $(WPNG)$(O):	$(WPNG).c writepng.h
+ 
+ readpng$(O):	readpng.c readpng.h
+ readpng2$(O):	readpng2.c readpng2.h
+ writepng$(O):	writepng.c writepng.h
+ 
+ 
+ # maintenance ---------------------------------------------------------------
+ 
+ clean:
+ 	$(RM) $(EXES) $(ROBJS) $(ROBJS2) $(WOBJS)


Index: llvm/runtime/libpng/contrib/gregbook/Makefile.unx
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/Makefile.unx:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:55 2004
--- llvm/runtime/libpng/contrib/gregbook/Makefile.unx	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,104 ----
+ # Sample makefile for rpng-x / rpng2-x / wpng using gcc and make.
+ # Greg Roelofs
+ # Last modified:  7 March 2002
+ #
+ #	The programs built by this makefile are described in the book,
+ #	"PNG:  The Definitive Guide," by Greg Roelofs (O'Reilly and
+ #	Associates, 1999).  Go buy a copy, eh?  Buy some for friends
+ #	and family, too.  (Not that this is a blatant plug or anything.)
+ #
+ # Invoke this makefile from a shell prompt in the usual way; for example:
+ #
+ #	make -f Makefile.unx
+ #
+ # This makefile assumes libpng and zlib have already been built or downloaded
+ # and are both installed in /usr/local/{include,lib} (as indicated by the
+ # PNG* and Z* macros below).  Edit as appropriate--choose only ONE each of
+ # the PNGINC, PNGLIB, ZINC and ZLIB lines.
+ #
+ # This makefile builds statically linked executables (against libpng and zlib,
+ # that is), but that can be changed by uncommenting the appropriate PNGLIB and
+ # ZLIB lines.
+ 
+ 
+ # macros --------------------------------------------------------------------
+ 
+ PNGINC = -I/usr/local/include/libpng12
+ #PNGLIB = -L/usr/local/lib -lpng12 # dynamically linked against libpng
+ PNGLIB = /usr/local/lib/libpng12.a # statically linked against libpng
+ # or:
+ #PNGINC = -I../libpng
+ #PNGLIB = -L../libpng -lpng
+ #PNGLIB = ../libpng/libpng.a
+ 
+ ZINC = -I/usr/local/include
+ #ZLIB = -L/usr/local/lib -lz		# dynamically linked against zlib
+ ZLIB = /usr/local/lib/libz.a		# statically linked against zlib
+ #ZINC = -I../zlib
+ #ZLIB = -L../zlib -lz
+ #ZLIB = ../zlib/libz.a
+ 
+ #XINC = -I/usr/include			# old-style, stock X distributions
+ #XLIB = -L/usr/lib/X11 -lX11
+ #XINC = -I/usr/openwin/include		# Sun workstations (OpenWindows)
+ #XLIB = -L/usr/openwin/lib -lX11
+ XINC = -I/usr/X11R6/include		# new X distributions (XFree86, etc.)
+ XLIB = -L/usr/X11R6/lib -lX11
+ 
+ INCS = $(PNGINC) $(ZINC) $(XINC)
+ RLIBS = $(PNGLIB) $(ZLIB) $(XLIB) -lm
+ WLIBS = $(PNGLIB) $(ZLIB)
+ 
+ CC = gcc
+ LD = gcc
+ RM = rm -f
+ CFLAGS = -O -Wall $(INCS)
+ # [note that -Wall is a gcc-specific compilation flag ("most warnings on")]
+ # [-ansi, -pedantic and -W can also be used]
+ LDFLAGS =
+ O = .o
+ E =
+ 
+ RPNG  = rpng-x
+ RPNG2 = rpng2-x
+ WPNG  = wpng
+ 
+ ROBJS  = $(RPNG)$(O) readpng$(O)
+ ROBJS2 = $(RPNG2)$(O) readpng2$(O)
+ WOBJS  = $(WPNG)$(O) writepng$(O)
+ 
+ EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E)
+ 
+ 
+ # implicit make rules -------------------------------------------------------
+ 
+ .c$(O):
+ 	$(CC) -c $(CFLAGS) $<
+ 
+ 
+ # dependencies --------------------------------------------------------------
+ 
+ all:  $(EXES)
+ 
+ $(RPNG)$(E): $(ROBJS)
+ 	$(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBS)
+ 
+ $(RPNG2)$(E): $(ROBJS2)
+ 	$(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBS)
+ 
+ $(WPNG)$(E): $(WOBJS)
+ 	$(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBS)
+ 
+ $(RPNG)$(O):	$(RPNG).c readpng.h
+ $(RPNG2)$(O):	$(RPNG2).c readpng2.h
+ $(WPNG)$(O):	$(WPNG).c writepng.h
+ 
+ readpng$(O):	readpng.c readpng.h
+ readpng2$(O):	readpng2.c readpng2.h
+ writepng$(O):	writepng.c writepng.h
+ 
+ 
+ # maintenance ---------------------------------------------------------------
+ 
+ clean:
+ 	$(RM) $(EXES) $(ROBJS) $(ROBJS2) $(WOBJS)


Index: llvm/runtime/libpng/contrib/gregbook/Makefile.w32
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/Makefile.w32:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:55 2004
--- llvm/runtime/libpng/contrib/gregbook/Makefile.w32	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,112 ----
+ # Sample makefile for rpng-win / rpng2-win / wpng using MSVC and NMAKE.
+ # Greg Roelofs
+ # Last modified:  16 February 1999
+ #
+ #	The programs built by this makefile are described in the book,
+ #	"PNG:  The Definitive Guide," by Greg Roelofs (O'Reilly and
+ #	Associates, 1999).  Go buy a copy, eh?  Buy some for friends
+ #	and family, too.  (Not that this is a blatant plug or anything.)
+ #
+ # Invoke this makefile from a DOS prompt window via:
+ #
+ #	%devstudio%\vc\bin\vcvars32.bat
+ #	nmake -nologo -f Makefile.w32
+ #
+ # where %devstudio% is the installation directory for MSVC / DevStudio.  If
+ # you get "environment out of space" errors, create a desktop shortcut with
+ # "c:\windows\command.com /e:4096" as the program command line and set the
+ # working directory to this directory.  Then double-click to open the new
+ # DOS-prompt window with a bigger environment and retry the commands above.
+ # 
+ # This makefile assumes libpng and zlib have already been built or downloaded
+ # and are in subdirectories at the same level as the current subdirectory
+ # (as indicated by the PNGPATH and ZPATH macros below).  Edit as appropriate.
+ #
+ # Note that the names of the dynamic and static libpng and zlib libraries
+ # used below may change in later releases of the libraries.  This makefile
+ # builds statically linked executables, but that can be changed by uncom-
+ # menting the appropriate PNGLIB and ZLIB lines.
+ 
+ !include <ntwin32.mak>
+ 
+ 
+ # macros --------------------------------------------------------------------
+ 
+ PNGPATH = ../libpng
+ PNGINC = -I$(PNGPATH)
+ #PNGLIB = $(PNGPATH)/pngdll.lib
+ PNGLIB = $(PNGPATH)/libpng.lib
+ 
+ ZPATH = ../zlib
+ ZINC = -I$(ZPATH)
+ #ZLIB = $(ZPATH)/zlibdll.lib
+ ZLIB = $(ZPATH)/zlibstat.lib
+ 
+ WINLIBS = -defaultlib:user32.lib gdi32.lib
+ # ["real" apps may also need comctl32.lib, comdlg32.lib, winmm.lib, etc.]
+ 
+ INCS = $(PNGINC) $(ZINC)
+ RLIBS = $(PNGLIB) $(ZLIB) $(WINLIBS)
+ WLIBS = $(PNGLIB) $(ZLIB)
+ 
+ CC = cl
+ LD = link
+ RM = del
+ CFLAGS = -nologo -O -W3 $(INCS) $(cvars)
+ # [note that -Wall is an MSVC-specific compilation flag ("all warnings on")]
+ # [see %devstudio%\vc\include\win32.mak for cvars macro definition]
+ O = .obj
+ E = .exe
+ 
+ RLDFLAGS = -nologo -subsystem:windows
+ WLDFLAGS = -nologo
+ 
+ RPNG  = rpng-win
+ RPNG2 = rpng2-win
+ WPNG  = wpng
+ 
+ ROBJS  = $(RPNG)$(O) readpng$(O)
+ ROBJS2 = $(RPNG2)$(O) readpng2$(O)
+ WOBJS  = $(WPNG)$(O) writepng$(O)
+ 
+ EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E)
+ 
+ 
+ # implicit make rules -------------------------------------------------------
+ 
+ .c$(O):
+ 	$(CC) -c $(CFLAGS) $<
+ 
+ 
+ # dependencies --------------------------------------------------------------
+ 
+ all:  $(EXES)
+ 
+ $(RPNG)$(E): $(ROBJS)
+ 	$(LD) $(RLDFLAGS) -out:$@ $(ROBJS) $(RLIBS)
+ 
+ $(RPNG2)$(E): $(ROBJS2)
+ 	$(LD) $(RLDFLAGS) -out:$@ $(ROBJS2) $(RLIBS)
+ 
+ $(WPNG)$(E): $(WOBJS)
+ 	$(LD) $(WLDFLAGS) -out:$@ $(WOBJS) $(WLIBS)
+ 
+ $(RPNG)$(O):	$(RPNG).c readpng.h
+ $(RPNG2)$(O):	$(RPNG2).c readpng2.h
+ $(WPNG)$(O):	$(WPNG).c writepng.h
+ 
+ readpng$(O):	readpng.c readpng.h
+ readpng2$(O):	readpng2.c readpng2.h
+ writepng$(O):	writepng.c writepng.h
+ 
+ 
+ # maintenance ---------------------------------------------------------------
+ 
+ clean:
+ #	ideally we could just do this:
+ #	$(RM) $(EXES) $(ROBJS) $(ROBJS2) $(WOBJS)
+ #	...but the Windows "DEL" command is none too bright, so:
+ 	$(RM) r*$(E)
+ 	$(RM) w*$(E)
+ 	$(RM) r*$(O)
+ 	$(RM) w*$(O)


Index: llvm/runtime/libpng/contrib/gregbook/README
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/README:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:55 2004
--- llvm/runtime/libpng/contrib/gregbook/README	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,185 ----
+                      ===========================
+                       PNG: The Definitive Guide
+                      ===========================
+ 
+                              Source Code
+ 
+ Chapters 13, 14 and 15 of "PNG: The Definitive Guide" discuss three free,
+ cross-platform demo programs that show how to use the libpng reference
+ library:  rpng, rpng2 and wpng.  rpng and rpng2 are viewers; the first is
+ a very simple example that that shows how a standard file-viewer might use
+ libpng, while the second is designed to process streaming data and shows
+ how a web browser might be written.  wpng is a simple command-line program
+ that reads binary PGM and PPM files (the ``raw'' grayscale and RGB subsets
+ of PBMPLUS/NetPBM) and converts them to PNG.
+ 
+ The source code for all three demo programs currently compiles under
+ Unix, OpenVMS, and 32-bit Windows.  (Special thanks to Martin Zinser,
+ zinser at decus.de, for making the necessary changes for OpenVMS and for
+ providing an appropriate build script.)  Build instructions can be found
+ below.
+ 
+ Files:
+ 
+    README             this file
+    LICENSE            terms of distribution and reuse (BSD-like)
+ 
+    Makefile.unx       Unix makefile
+    Makefile.w32       Windows (MSVC) makefile
+    makevms.com        OpenVMS build script
+ 
+    rpng-win.c         Windows front end for the basic viewer
+    rpng-x.c           X Window System (Unix, OpenVMS) front end
+    readpng.c          generic back end for the basic viewer
+    readpng.h          header file for the basic viewer
+ 
+    rpng2-win.c        Windows front end for the progressive viewer
+    rpng2-x.c          X front end for the progressive viewer
+    readpng2.c         generic back end for the progressive viewer
+    readpng2.h         header file for the progressive viewer
+ 
+    wpng.c             generic (text) front end for the converter
+    writepng.c         generic back end for the converter
+    writepng.h         header file for the converter
+ 
+    toucan.png         transparent PNG for testing (by Stefan Schneider)
+ 
+ Note that, although the programs are designed to be functional, their
+ primary purpose is to illustrate how to use libpng to add PNG support to
+ other programs.  As such, their user interfaces are crude and definitely
+ are not intended for everyday use.
+ 
+ Please see http://www.libpng.org/pub/png/pngbook.html for further infor-
+ mation and links to the latest version of the source code, and Chapters
+ 13-15 of the book for detailed discussion of the three programs.
+ 
+ Greg Roelofs
+ newt at pobox.com
+ 30 June 2001
+ 
+ 
+ BUILD INSTRUCTIONS
+ 
+  - Prerequisites (in order of compilation):
+ 
+       - zlib		http://www.gzip.org/zlib/
+       - libpng		http://www.libpng.org/pub/png/libpng.html
+       - pngbook		http://www.libpng.org/pub/png/book/sources.html
+ 
+      The pngbook demo programs are explicitly designed to demonstrate proper
+      coding techniques for using the libpng reference library.  As a result,
+      you need to download and build both zlib (on which libpng depends) and
+      libpng.  A common build setup is to place the zlib, libpng and pngbook
+      subdirectory trees ("folders") in the same parent directory.  Then the
+      libpng build can refer to files in ../zlib (or ..\zlib or [-.zlib]),
+      and similarly for the pngbook build.
+ 
+      Note that all three packages are designed to be built from a command
+      line by default; those who wish to use a graphical or other integrated
+      development environments are on their own.
+ 
+ 
+  - Unix:
+ 
+      Unpack the latest pngbook sources (which should correspond to this
+      README file) into a directory and change into that directory.
+ 
+      Copy Makefile.unx to Makefile and edit the PNG* and Z* variables
+      appropriately (possibly also the X* variables if necessary).
+ 
+      make
+ 
+      There is no "install" target, so copy the three executables somewhere
+      in your path or run them from the current directory.  All three will
+      print a basic usage screen when run without any command-line arguments;
+      see the book for more details.
+ 
+ 
+  - Windows:
+ 
+      Unpack the latest pngbook sources (which should correspond to this
+      README file) into a folder, open a "DOS shell" or "command prompt"
+      or equivalent command-line window, and cd into the folder where you
+      unpacked the source code.
+ 
+      For MSVC, set up the necessary environment variables by invoking
+  
+         %devstudio%\vc\bin\vcvars32.bat
+ 
+      where where %devstudio% is the installation directory for MSVC /
+      DevStudio.  If you get "environment out of space" errors under 95/98,
+      create a desktop shortcut with "c:\windows\command.com /e:4096" as
+      the program command line and set the working directory to the pngbook
+      directory.  Then double-click to open the new DOS-prompt window with
+      a bigger environment and retry the commands above.
+ 
+      Copy Makefile.w32 to Makefile and edit the PNGPATH and ZPATH variables
+      appropriately (possibly also the "INC" and "LIB" variables if needed).
+      Note that the names of the dynamic and static libpng and zlib libraries
+      used in the makefile may change in later releases of the libraries.
+      Also note that, as of libpng version 1.0.5, MSVC DLL builds do not work.
+      This makefile therefore builds statically linked executables, but if
+      the DLL problems ever get fixed, uncommenting the appropriate PNGLIB
+      and ZLIB lines will build dynamically linked executables instead.
+ 
+      Do the build by typing
+ 
+         nmake
+ 
+      The result should be three executables:  rpng-win.exe, rpng2-win.exe,
+      and wpng.exe.  Copy them somewhere in your PATH or run them from the
+      current folder.  Like the Unix versions, the two windowed programs
+      (rpng and rpng2) now display a usage screen in a console window when
+      invoked without command-line arguments; this is new behavior as of
+      the June 2001 release.  Note that the programs use the Unix-style "-"
+      character to specify options, instead of the more common DOS/Windows
+      "/" character.  (For example:  "rpng2-win -bgpat 4 foo.png", not
+      "rpng2-win /bgpat 4 foo.png")
+ 
+ 
+  - OpenVMS:
+ 
+      Unpack the pngbook sources into a subdirectory and change into that
+      subdirectory.
+ 
+      Edit makevms.com appropriately, specifically the zpath and pngpath
+      variables.
+ 
+      @makevms
+ 
+      To run the programs, they probably first need to be set up as "foreign
+      symbols," with "disk" and "dir" set appropriately:
+ 
+      $ rpng == "$disk:[dir]rpng-x.exe"
+      $ rpng2 == "$disk:[dir]rpng2-x.exe"
+      $ wpng == "$disk:[dir]wpng.exe"
+ 
+      All three will print a basic usage screen when run without any command-
+      line arguments; see the book for more details.  Note that the options
+      style is Unix-like, i.e., preceded by "-" rather than "/".
+ 
+ 
+ RUNNING THE PROGRAMS:  (VERY) BRIEF INTRO
+ 
+      rpng is a simple PNG viewer that can display transparent PNGs with a
+      specified background color; for example,
+ 
+ 	rpng -bgcolor #ff0000 toucan.png
+ 
+      would display the image with a red background.  rpng2 is a progressive
+      viewer that simulates a web browser in some respects; it can display
+      images against either a background color or a dynamically generated
+      background image.  For example:
+ 
+ 	rpng2 -bgpat 16 toucan.png
+ 
+      wpng is a purely command-line image converter from binary PBMPLUS/NetPBM
+      format (.pgm or .ppm) to PNG; for example,
+ 
+ 	wpng -time < toucan.ppm > toucan.png
+ 
+      would convert the specified PPM file (using redirection) to PNG, auto-
+      matically setting the PNG modification-time chunk.
+ 
+      All options can be abbreviated to the shortest unique value; for example,
+      "-bgc" for -bgcolor (versus "-bgp" for -bgpat), or "-g" for -gamma.


Index: llvm/runtime/libpng/contrib/gregbook/makevms.com
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/makevms.com:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:55 2004
--- llvm/runtime/libpng/contrib/gregbook/makevms.com	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,132 ----
+ $!------------------------------------------------------------------------------
+ $! make "PNG: The Definitive Guide" demo programs (for X) under OpenVMS
+ $!
+ $! Script created by Martin Zinser for libpng; modified by Greg Roelofs
+ $! for standalone pngbook source distribution.
+ $!
+ $!
+ $!    Set locations where zlib and libpng sources live.
+ $!
+ $ zpath   = ""
+ $ pngpath = ""
+ $!
+ $ if f$search("[---.zlib]zlib.h").nes."" then zpath = "[---.zlib]"
+ $ if f$search("[--]png.h").nes."" then pngpath = "[--]"
+ $!
+ $ if f$search("[-.zlib]zlib.h").nes."" then zpath = "[-.zlib]"
+ $ if f$search("[-.libpng]png.h").nes."" then pngpath = "[-.libpng]"
+ $!
+ $ if zpath .eqs. ""
+ $ then
+ $   write sys$output "zlib include not found. Exiting..."
+ $   exit 2
+ $ endif 
+ $!
+ $ if pngpath .eqs. ""
+ $ then
+ $   write sys$output "libpng include not found. Exiting..."
+ $   exit 2
+ $ endif 
+ $!
+ $!    Look for the compiler used.
+ $!
+ $ ccopt="/include=(''zpath',''pngpath')"
+ $ if f$getsyi("HW_MODEL").ge.1024
+ $ then
+ $  ccopt = "/prefix=all"+ccopt
+ $  comp  = "__decc__=1"
+ $  if f$trnlnm("SYS").eqs."" then define sys sys$library:
+ $ else
+ $  if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs.""
+ $   then
+ $    if f$trnlnm("SYS").eqs."" then define sys sys$library:
+ $    if f$search("SYS$SYSTEM:VAXC.EXE").eqs.""
+ $     then
+ $      comp  = "__gcc__=1"
+ $      CC :== GCC
+ $     else
+ $      comp = "__vaxc__=1"
+ $     endif
+ $   else
+ $    if f$trnlnm("SYS").eqs."" then define sys decc$library_include:
+ $    ccopt = "/decc/prefix=all"+ccopt
+ $    comp  = "__decc__=1"
+ $  endif
+ $ endif
+ $ open/write lopt lib.opt
+ $ write lopt "''pngpath'libpng.olb/lib"
+ $ write lopt "''zpath'libz.olb/lib"
+ $ close lopt
+ $ open/write xopt x11.opt
+ $ write xopt "sys$library:decw$xlibshr.exe/share"
+ $ close xopt
+ $!
+ $!    Build 'em.
+ $!
+ $ write sys$output "Compiling PNG book programs ..."
+ $   CALL MAKE readpng.OBJ "cc ''CCOPT' readpng" -
+ 	readpng.c readpng.h
+ $   CALL MAKE readpng2.OBJ "cc ''CCOPT' readpng2" -
+ 	readpng2.c readpng2.h
+ $   CALL MAKE writepng.OBJ "cc ''CCOPT' writepng" -
+ 	writepng.c writepng.h
+ $   write sys$output "Building rpng-x..."
+ $   CALL MAKE rpng-x.OBJ "cc ''CCOPT' rpng-x" -
+ 	rpng-x.c readpng.h
+ $   call make rpng-x.exe -
+ 	"LINK rpng-x,readpng,lib.opt/opt,x11.opt/opt" -
+ 	rpng-x.obj readpng.obj
+ $   write sys$output "Building rpng2-x..."
+ $   CALL MAKE rpng2-x.OBJ "cc ''CCOPT' rpng2-x" -
+ 	rpng2-x.c readpng2.h
+ $   call make rpng2-x.exe -
+ 	"LINK rpng2-x,readpng2,lib.opt/opt,x11.opt/opt" -
+ 	rpng2-x.obj readpng2.obj
+ $   write sys$output "Building wpng..."
+ $   CALL MAKE wpng.OBJ "cc ''CCOPT' wpng" -
+ 	wpng.c writepng.h
+ $   call make wpng.exe -
+ 	"LINK wpng,writepng,lib.opt/opt" -
+ 	wpng.obj writepng.obj
+ $ exit
+ $!
+ $!
+ $MAKE: SUBROUTINE   !SUBROUTINE TO CHECK DEPENDENCIES
+ $ V = 'F$Verify(0)
+ $! P1 = What we are trying to make
+ $! P2 = Command to make it
+ $! P3 - P8  What it depends on
+ $
+ $ If F$Search(P1) .Eqs. "" Then Goto Makeit
+ $ Time = F$CvTime(F$File(P1,"RDT"))
+ $arg=3
+ $Loop:
+ $       Argument = P'arg
+ $       If Argument .Eqs. "" Then Goto Exit
+ $       El=0
+ $Loop2:
+ $       File = F$Element(El," ",Argument)
+ $       If File .Eqs. " " Then Goto Endl
+ $       AFile = ""
+ $Loop3:
+ $       OFile = AFile
+ $       AFile = F$Search(File)
+ $       If AFile .Eqs. "" .Or. AFile .Eqs. OFile Then Goto NextEl
+ $       If F$CvTime(F$File(AFile,"RDT")) .Ges. Time Then Goto Makeit
+ $       Goto Loop3
+ $NextEL:
+ $       El = El + 1
+ $       Goto Loop2
+ $EndL:
+ $ arg=arg+1
+ $ If arg .Le. 8 Then Goto Loop
+ $ Goto Exit
+ $
+ $Makeit:
+ $ VV=F$VERIFY(0)
+ $ write sys$output P2
+ $ 'P2
+ $ VV='F$Verify(VV)
+ $Exit:
+ $ If V Then Set Verify
+ $ENDSUBROUTINE


Index: llvm/runtime/libpng/contrib/gregbook/readpng.c
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/readpng.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:55 2004
--- llvm/runtime/libpng/contrib/gregbook/readpng.c	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,280 ----
+ /*---------------------------------------------------------------------------
+ 
+    rpng - simple PNG display program                              readpng.c
+ 
+   ---------------------------------------------------------------------------
+ 
+       Copyright (c) 1998-2000 Greg Roelofs.  All rights reserved.
+ 
+       This software is provided "as is," without warranty of any kind,
+       express or implied.  In no event shall the author or contributors
+       be held liable for any damages arising in any way from the use of
+       this software.
+ 
+       Permission is granted to anyone to use this software for any purpose,
+       including commercial applications, and to alter it and redistribute
+       it freely, subject to the following restrictions:
+ 
+       1. Redistributions of source code must retain the above copyright
+          notice, disclaimer, and this list of conditions.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, disclaimer, and this list of conditions in the documenta-
+          tion and/or other materials provided with the distribution.
+       3. All advertising materials mentioning features or use of this
+          software must display the following acknowledgment:
+ 
+             This product includes software developed by Greg Roelofs
+             and contributors for the book, "PNG: The Definitive Guide,"
+             published by O'Reilly and Associates.
+ 
+   ---------------------------------------------------------------------------*/
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ 
+ #include "png.h"        /* libpng header; includes zlib.h */
+ #include "readpng.h"    /* typedefs, common macros, public prototypes */
+ 
+ /* future versions of libpng will provide this macro: */
+ #ifndef png_jmpbuf
+ #  define png_jmpbuf(png_ptr)   ((png_ptr)->jmpbuf)
+ #endif
+ 
+ 
+ static png_structp png_ptr = NULL;
+ static png_infop info_ptr = NULL;
+ 
+ png_uint_32  width, height;
+ int  bit_depth, color_type;
+ uch  *image_data = NULL;
+ 
+ 
+ void readpng_version_info(void)
+ {
+     fprintf(stderr, "   Compiled with libpng %s; using libpng %s.\n",
+       PNG_LIBPNG_VER_STRING, png_libpng_ver);
+     fprintf(stderr, "   Compiled with zlib %s; using zlib %s.\n",
+       ZLIB_VERSION, zlib_version);
+ }
+ 
+ 
+ /* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
+ 
+ int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
+ {
+     uch sig[8];
+ 
+ 
+     /* first do a quick check that the file really is a PNG image; could
+      * have used slightly more general png_sig_cmp() function instead */
+ 
+     fread(sig, 1, 8, infile);
+     if (!png_check_sig(sig, 8))
+         return 1;   /* bad signature */
+ 
+ 
+     /* could pass pointers to user-defined error handlers instead of NULLs: */
+ 
+     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+     if (!png_ptr)
+         return 4;   /* out of memory */
+ 
+     info_ptr = png_create_info_struct(png_ptr);
+     if (!info_ptr) {
+         png_destroy_read_struct(&png_ptr, NULL, NULL);
+         return 4;   /* out of memory */
+     }
+ 
+ 
+     /* we could create a second info struct here (end_info), but it's only
+      * useful if we want to keep pre- and post-IDAT chunk info separated
+      * (mainly for PNG-aware image editors and converters) */
+ 
+ 
+     /* setjmp() must be called in every function that calls a PNG-reading
+      * libpng function */
+ 
+     if (setjmp(png_jmpbuf(png_ptr))) {
+         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+         return 2;
+     }
+ 
+ 
+     png_init_io(png_ptr, infile);
+     png_set_sig_bytes(png_ptr, 8);  /* we already read the 8 signature bytes */
+ 
+     png_read_info(png_ptr, info_ptr);  /* read all PNG info up to image data */
+ 
+ 
+     /* alternatively, could make separate calls to png_get_image_width(),
+      * etc., but want bit_depth and color_type for later [don't care about
+      * compression_type and filter_type => NULLs] */
+ 
+     png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+       NULL, NULL, NULL);
+     *pWidth = width;
+     *pHeight = height;
+ 
+ 
+     /* OK, that's all we need for now; return happy */
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ /* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error;
+  * scales values to 8-bit if necessary */
+ 
+ int readpng_get_bgcolor(uch *red, uch *green, uch *blue)
+ {
+     png_color_16p pBackground;
+ 
+ 
+     /* setjmp() must be called in every function that calls a PNG-reading
+      * libpng function */
+ 
+     if (setjmp(png_jmpbuf(png_ptr))) {
+         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+         return 2;
+     }
+ 
+ 
+     if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
+         return 1;
+ 
+     /* it is not obvious from the libpng documentation, but this function
+      * takes a pointer to a pointer, and it always returns valid red, green
+      * and blue values, regardless of color_type: */
+ 
+     png_get_bKGD(png_ptr, info_ptr, &pBackground);
+ 
+ 
+     /* however, it always returns the raw bKGD data, regardless of any
+      * bit-depth transformations, so check depth and adjust if necessary */
+ 
+     if (bit_depth == 16) {
+         *red   = pBackground->red   >> 8;
+         *green = pBackground->green >> 8;
+         *blue  = pBackground->blue  >> 8;
+     } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
+         if (bit_depth == 1)
+             *red = *green = *blue = pBackground->gray? 255 : 0;
+         else if (bit_depth == 2)
+             *red = *green = *blue = (255/3) * pBackground->gray;
+         else /* bit_depth == 4 */
+             *red = *green = *blue = (255/15) * pBackground->gray;
+     } else {
+         *red   = (uch)pBackground->red;
+         *green = (uch)pBackground->green;
+         *blue  = (uch)pBackground->blue;
+     }
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ /* display_exponent == LUT_exponent * CRT_exponent */
+ 
+ uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
+ {
+     double  gamma;
+     png_uint_32  i, rowbytes;
+     png_bytepp  row_pointers = NULL;
+ 
+ 
+     /* setjmp() must be called in every function that calls a PNG-reading
+      * libpng function */
+ 
+     if (setjmp(png_jmpbuf(png_ptr))) {
+         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+         return NULL;
+     }
+ 
+ 
+     /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
+      * transparency chunks to full alpha channel; strip 16-bit-per-sample
+      * images to 8 bits per sample; and convert grayscale to RGB[A] */
+ 
+     if (color_type == PNG_COLOR_TYPE_PALETTE)
+         png_set_expand(png_ptr);
+     if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+         png_set_expand(png_ptr);
+     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+         png_set_expand(png_ptr);
+     if (bit_depth == 16)
+         png_set_strip_16(png_ptr);
+     if (color_type == PNG_COLOR_TYPE_GRAY ||
+         color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+         png_set_gray_to_rgb(png_ptr);
+ 
+ 
+     /* unlike the example in the libpng documentation, we have *no* idea where
+      * this file may have come from--so if it doesn't have a file gamma, don't
+      * do any correction ("do no harm") */
+ 
+     if (png_get_gAMA(png_ptr, info_ptr, &gamma))
+         png_set_gamma(png_ptr, display_exponent, gamma);
+ 
+ 
+     /* all transformations have been registered; now update info_ptr data,
+      * get rowbytes and channels, and allocate image memory */
+ 
+     png_read_update_info(png_ptr, info_ptr);
+ 
+     *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+     *pChannels = (int)png_get_channels(png_ptr, info_ptr);
+ 
+     if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) {
+         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+         return NULL;
+     }
+     if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) {
+         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+         free(image_data);
+         image_data = NULL;
+         return NULL;
+     }
+ 
+     Trace((stderr, "readpng_get_image:  channels = %d, rowbytes = %ld, height = %ld\n", *pChannels, rowbytes, height));
+ 
+ 
+     /* set the individual row_pointers to point at the correct offsets */
+ 
+     for (i = 0;  i < height;  ++i)
+         row_pointers[i] = image_data + i*rowbytes;
+ 
+ 
+     /* now we can go ahead and just read the whole image */
+ 
+     png_read_image(png_ptr, row_pointers);
+ 
+ 
+     /* and we're done!  (png_read_end() can be omitted if no processing of
+      * post-IDAT text/time/etc. is desired) */
+ 
+     free(row_pointers);
+     row_pointers = NULL;
+ 
+     png_read_end(png_ptr, NULL);
+ 
+     return image_data;
+ }
+ 
+ 
+ void readpng_cleanup(int free_image_data)
+ {
+     if (free_image_data && image_data) {
+         free(image_data);
+         image_data = NULL;
+     }
+ 
+     if (png_ptr && info_ptr) {
+         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+         png_ptr = NULL;
+         info_ptr = NULL;
+     }
+ }


Index: llvm/runtime/libpng/contrib/gregbook/readpng.h
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/readpng.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:55 2004
--- llvm/runtime/libpng/contrib/gregbook/readpng.h	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,64 ----
+ /*---------------------------------------------------------------------------
+ 
+    rpng - simple PNG display program                              readpng.h
+ 
+   ---------------------------------------------------------------------------
+ 
+       Copyright (c) 1998-2000 Greg Roelofs.  All rights reserved.
+ 
+       This software is provided "as is," without warranty of any kind,
+       express or implied.  In no event shall the author or contributors
+       be held liable for any damages arising in any way from the use of
+       this software.
+ 
+       Permission is granted to anyone to use this software for any purpose,
+       including commercial applications, and to alter it and redistribute
+       it freely, subject to the following restrictions:
+ 
+       1. Redistributions of source code must retain the above copyright
+          notice, disclaimer, and this list of conditions.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, disclaimer, and this list of conditions in the documenta-
+          tion and/or other materials provided with the distribution.
+       3. All advertising materials mentioning features or use of this
+          software must display the following acknowledgment:
+ 
+             This product includes software developed by Greg Roelofs
+             and contributors for the book, "PNG: The Definitive Guide,"
+             published by O'Reilly and Associates.
+ 
+   ---------------------------------------------------------------------------*/
+ 
+ #ifndef TRUE
+ #  define TRUE 1
+ #  define FALSE 0
+ #endif
+ 
+ #ifndef MAX
+ #  define MAX(a,b)  ((a) > (b)? (a) : (b))
+ #  define MIN(a,b)  ((a) < (b)? (a) : (b))
+ #endif
+ 
+ #ifdef DEBUG
+ #  define Trace(x)  {fprintf x ; fflush(stderr); fflush(stdout);}
+ #else
+ #  define Trace(x)  ;
+ #endif
+ 
+ typedef unsigned char   uch;
+ typedef unsigned short  ush;
+ typedef unsigned long   ulg;
+ 
+ 
+ /* prototypes for public functions in readpng.c */
+ 
+ void readpng_version_info(void);
+ 
+ int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight);
+ 
+ int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue);
+ 
+ uch *readpng_get_image(double display_exponent, int *pChannels,
+                        ulg *pRowbytes);
+ 
+ void readpng_cleanup(int free_image_data);


Index: llvm/runtime/libpng/contrib/gregbook/readpng2.c
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/readpng2.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:55 2004
--- llvm/runtime/libpng/contrib/gregbook/readpng2.c	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,624 ----
+ /*---------------------------------------------------------------------------
+ 
+    rpng2 - progressive-model PNG display program                 readpng2.c
+ 
+   ---------------------------------------------------------------------------
+ 
+    Changelog:
+     - 1.01:  initial public release
+     - 1.02:  added code to skip unused chunks (GR-P)
+ 
+   ---------------------------------------------------------------------------
+ 
+       Copyright (c) 1998-2002 Greg Roelofs.  All rights reserved.
+ 
+       This software is provided "as is," without warranty of any kind,
+       express or implied.  In no event shall the author or contributors
+       be held liable for any damages arising in any way from the use of
+       this software.
+ 
+       Permission is granted to anyone to use this software for any purpose,
+       including commercial applications, and to alter it and redistribute
+       it freely, subject to the following restrictions:
+ 
+       1. Redistributions of source code must retain the above copyright
+          notice, disclaimer, and this list of conditions.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, disclaimer, and this list of conditions in the documenta-
+          tion and/or other materials provided with the distribution.
+       3. All advertising materials mentioning features or use of this
+          software must display the following acknowledgment:
+ 
+             This product includes software developed by Greg Roelofs
+             and contributors for the book, "PNG: The Definitive Guide,"
+             published by O'Reilly and Associates.
+ 
+   ---------------------------------------------------------------------------*/
+ 
+ 
+ #include <stdlib.h>     /* for exit() prototype */
+ 
+ #include "png.h"        /* libpng header; includes zlib.h and setjmp.h */
+ #include "readpng2.h"   /* typedefs, common macros, public prototypes */
+ 
+ 
+ /* local prototypes */
+ 
+ static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr);
+ static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row,
+                                  png_uint_32 row_num, int pass);
+ static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr);
+ static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg);
+ 
+ 
+ 
+ 
+ void readpng2_version_info(void)
+ {
+ #if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \
+     (defined(__i386__) || defined(_M_IX86)) && \
+     defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
+     /*
+      * WARNING:  This preprocessor approach means that the following code
+      *           cannot be used with a libpng DLL older than 1.2.0--the
+      *           compiled-in symbols for the new functions will not exist.
+      *           (Could use dlopen() and dlsym() on Unix and corresponding
+      *           calls for Windows, but not portable...)
+      */
+     {
+         int mmxsupport = png_mmx_support();
+         if (mmxsupport < 0)
+             fprintf(stderr, "   Compiled with libpng %s; using libpng %s "
+               "without MMX support.\n", PNG_LIBPNG_VER_STRING, png_libpng_ver);
+         else {
+             int compilerID;
+             png_uint_32 mmx_mask = png_get_mmx_flagmask(
+               PNG_SELECT_READ | PNG_SELECT_WRITE, &compilerID);
+ 
+             fprintf(stderr, "   Compiled with libpng %s; using libpng %s "
+               "with MMX support\n   (%s version).", PNG_LIBPNG_VER_STRING,
+               png_libpng_ver, compilerID == 1? "MSVC++" :
+               (compilerID == 2? "GNU C" : "unknown"));
+             fprintf(stderr, "  Processor %s MMX instructions.\n",
+               mmxsupport? "supports" : "does not support");
+             if (mmxsupport > 0) {
+                 int num_optims = 0;
+ 
+                 fprintf(stderr,
+                   "      Potential MMX optimizations supported by libpng:\n");
+                 if (mmx_mask & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)
+                     ++num_optims;
+                 if (mmx_mask & PNG_ASM_FLAG_MMX_READ_FILTER_UP)
+                     ++num_optims;
+                 if (mmx_mask & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)
+                     ++num_optims;
+                 if (mmx_mask & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)
+                     ++num_optims;
+                 if (num_optims)
+                     fprintf(stderr,
+                       "         decoding %s row filters (reading)\n",
+                       (num_optims == 4)? "all non-trivial" : "some");
+                 if (mmx_mask & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW) {
+                     fprintf(stderr, "         combining rows (reading)\n");
+                     ++num_optims;
+                 }
+                 if (mmx_mask & PNG_ASM_FLAG_MMX_READ_INTERLACE) {
+                     fprintf(stderr,
+                       "         expanding interlacing (reading)\n");
+                     ++num_optims;
+                 }
+                 mmx_mask &= ~( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  \
+                              | PNG_ASM_FLAG_MMX_READ_INTERLACE    \
+                              | PNG_ASM_FLAG_MMX_READ_FILTER_SUB   \
+                              | PNG_ASM_FLAG_MMX_READ_FILTER_UP    \
+                              | PNG_ASM_FLAG_MMX_READ_FILTER_AVG   \
+                              | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH );
+                 if (mmx_mask) {
+                     fprintf(stderr, "         other (unknown)\n");
+                     ++num_optims;
+                 }
+                 if (num_optims == 0)
+                     fprintf(stderr, "         (none)\n");
+             }
+         }
+     }
+ #else
+     fprintf(stderr, "   Compiled with libpng %s; using libpng %s "
+       "without MMX support.\n", PNG_LIBPNG_VER_STRING, png_libpng_ver);
+ #endif
+ 
+     fprintf(stderr, "   Compiled with zlib %s; using zlib %s.\n",
+       ZLIB_VERSION, zlib_version);
+ }
+ 
+ 
+ 
+ 
+ int readpng2_check_sig(uch *sig, int num)
+ {
+     return png_check_sig(sig, num);
+ }
+ 
+ 
+ 
+ 
+ /* returns 0 for success, 2 for libpng problem, 4 for out of memory */
+ 
+ int readpng2_init(mainprog_info *mainprog_ptr)
+ {
+     png_structp  png_ptr;       /* note:  temporary variables! */
+     png_infop  info_ptr;
+ 
+ 
+     /* could also replace libpng warning-handler (final NULL), but no need: */
+ 
+     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr,
+       readpng2_error_handler, NULL);
+     if (!png_ptr)
+         return 4;   /* out of memory */
+ 
+     info_ptr = png_create_info_struct(png_ptr);
+     if (!info_ptr) {
+         png_destroy_read_struct(&png_ptr, NULL, NULL);
+         return 4;   /* out of memory */
+     }
+ 
+ 
+     /* we could create a second info struct here (end_info), but it's only
+      * useful if we want to keep pre- and post-IDAT chunk info separated
+      * (mainly for PNG-aware image editors and converters) */
+ 
+ 
+     /* setjmp() must be called in every function that calls a PNG-reading
+      * libpng function, unless an alternate error handler was installed--
+      * but compatible error handlers must either use longjmp() themselves
+      * (as in this program) or exit immediately, so here we are: */
+ 
+     if (setjmp(mainprog_ptr->jmpbuf)) {
+         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+         return 2;
+     }
+ 
+     /* prepare the reader to ignore all recognized chunks whose data isn't
+      * going to be used, i.e., all chunks recognized by libpng except for
+      * IHDR, PLTE, IDAT, IEND, tRNS, bKGD, gAMA, and sRGB : */
+ 
+ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+     {
+ #ifndef HANDLE_CHUNK_NEVER
+ /* prior to libpng-1.2.5, this macro was internal, so we define it here. */
+ # define HANDLE_CHUNK_NEVER 1
+ #endif
+        /* these byte strings were copied from png.h.
+         * If a future libpng version recognizes more chunks, add them
+         * to this list.  If a future version of readpng2.c recognizes
+         * more chunks, delete them from this list. */
+        png_byte png_chunk_types_to_ignore[]=
+           { 99,  72,  82,  77, '\0', /* cHRM */
+            104,  73,  83,  84, '\0', /* hIST */
+            105,  67,  67,  80, '\0', /* iCCP */
+            105,  84,  88, 116, '\0', /* iTXt */
+            111,  70,  70, 115, '\0', /* oFFs */
+            112,  67,  65,  76, '\0', /* pCAL */
+            115,  67,  65,  76, '\0', /* sCAL */
+            112,  72,  89, 115, '\0', /* pHYs */
+            115,  66,  73,  84, '\0', /* sBIT */
+            115,  80,  76,  84, '\0', /* sPLT */
+            116,  69,  88, 116, '\0', /* tEXt */
+            116,  73,  77,  69, '\0', /* tIME */
+            122,  84,  88, 116, '\0'}; /* zTXt */
+ #define NUM_PNG_CHUNK_TYPES_TO_IGNORE 13
+ 
+     png_set_keep_unknown_chunks(png_ptr, HANDLE_CHUNK_NEVER,
+         png_chunk_types_to_ignore, NUM_PNG_CHUNK_TYPES_TO_IGNORE);
+     }
+ #endif
+ 
+     /* instead of doing png_init_io() here, now we set up our callback
+      * functions for progressive decoding */
+ 
+     png_set_progressive_read_fn(png_ptr, mainprog_ptr,
+       readpng2_info_callback, readpng2_row_callback, readpng2_end_callback);
+ 
+ 
+     /*
+      * may as well enable or disable MMX routines here, if supported;
+      *
+      * to enable all:  mask = png_get_mmx_flagmask (
+      *                   PNG_SELECT_READ | PNG_SELECT_WRITE, &compilerID);
+      *                 flags = png_get_asm_flags (png_ptr);
+      *                 flags |= mask;
+      *                 png_set_asm_flags (png_ptr, flags);
+      *
+      * to disable all:  mask = png_get_mmx_flagmask (
+      *                   PNG_SELECT_READ | PNG_SELECT_WRITE, &compilerID);
+      *                  flags = png_get_asm_flags (png_ptr);
+      *                  flags &= ~mask;
+      *                  png_set_asm_flags (png_ptr, flags);
+      */
+ 
+ #if (defined(__i386__) || defined(_M_IX86)) && \
+     defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200)
+     /*
+      * WARNING:  This preprocessor approach means that the following code
+      *           cannot be used with a libpng DLL older than 1.2.0--the
+      *           compiled-in symbols for the new functions will not exist.
+      *           (Could use dlopen() and dlsym() on Unix and corresponding
+      *           calls for Windows, but not portable...)
+      */
+     {
+ #ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+         png_uint_32 mmx_disable_mask = 0;
+         png_uint_32 asm_flags, mmx_mask;
+         int compilerID;
+ 
+         if (mainprog_ptr->nommxfilters)
+             mmx_disable_mask |= ( PNG_ASM_FLAG_MMX_READ_FILTER_SUB   \
+                                 | PNG_ASM_FLAG_MMX_READ_FILTER_UP    \
+                                 | PNG_ASM_FLAG_MMX_READ_FILTER_AVG   \
+                                 | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH );
+         if (mainprog_ptr->nommxcombine)
+             mmx_disable_mask |= PNG_ASM_FLAG_MMX_READ_COMBINE_ROW;
+         if (mainprog_ptr->nommxinterlace)
+             mmx_disable_mask |= PNG_ASM_FLAG_MMX_READ_INTERLACE;
+         asm_flags = png_get_asm_flags(png_ptr);
+         png_set_asm_flags(png_ptr, asm_flags & ~mmx_disable_mask);
+ 
+ 
+         /* Now query libpng's asm settings, just for yuks.  Note that this
+          * differs from the querying of its *potential* MMX capabilities
+          * in readpng2_version_info(); this is true runtime verification. */
+ 
+         asm_flags = png_get_asm_flags(png_ptr);
+         mmx_mask = png_get_mmx_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE,
+           &compilerID);
+         if (asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_COMPILED)
+             fprintf(stderr,
+               "  MMX support (%s version) is compiled into libpng\n",
+               compilerID == 1? "MSVC++" :
+               (compilerID == 2? "GNU C" : "unknown"));
+         else
+             fprintf(stderr, "  MMX support is not compiled into libpng\n");
+         fprintf(stderr, "  MMX instructions are %ssupported by CPU\n",
+           (asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU)? "" : "not ");
+         fprintf(stderr, "  MMX read support for combining rows is %sabled\n",
+           (asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)? "en" : "dis");
+         fprintf(stderr,
+           "  MMX read support for expanding interlacing is %sabled\n",
+           (asm_flags & PNG_ASM_FLAG_MMX_READ_INTERLACE)? "en" : "dis");
+         fprintf(stderr, "  MMX read support for \"sub\" filter is %sabled\n",
+           (asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)? "en" : "dis");
+         fprintf(stderr, "  MMX read support for \"up\" filter is %sabled\n",
+           (asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP)? "en" : "dis");
+         fprintf(stderr, "  MMX read support for \"avg\" filter is %sabled\n",
+           (asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)? "en" : "dis");
+         fprintf(stderr, "  MMX read support for \"Paeth\" filter is %sabled\n",
+           (asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)? "en" : "dis");
+         asm_flags &= (mmx_mask & ~( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  \
+                                   | PNG_ASM_FLAG_MMX_READ_INTERLACE    \
+                                   | PNG_ASM_FLAG_MMX_READ_FILTER_SUB   \
+                                   | PNG_ASM_FLAG_MMX_READ_FILTER_UP    \
+                                   | PNG_ASM_FLAG_MMX_READ_FILTER_AVG   \
+                                   | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ));
+         if (asm_flags)
+             fprintf(stderr,
+               "  additional MMX support is also enabled (0x%02lx)\n",
+               asm_flags);
+ #else  /* !PNG_ASSEMBLER_CODE_SUPPORTED */
+         fprintf(stderr, "  MMX querying is disabled in libpng.\n");
+ #endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
+     }
+ #endif
+ 
+ 
+     /* make sure we save our pointers for use in readpng2_decode_data() */
+ 
+     mainprog_ptr->png_ptr = png_ptr;
+     mainprog_ptr->info_ptr = info_ptr;
+ 
+ 
+     /* and that's all there is to initialization */
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ /* returns 0 for success, 2 for libpng (longjmp) problem */
+ 
+ int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length)
+ {
+     png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
+     png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
+ 
+ 
+     /* setjmp() must be called in every function that calls a PNG-reading
+      * libpng function */
+ 
+     if (setjmp(mainprog_ptr->jmpbuf)) {
+         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+         mainprog_ptr->png_ptr = NULL;
+         mainprog_ptr->info_ptr = NULL;
+         return 2;
+     }
+ 
+ 
+     /* hand off the next chunk of input data to libpng for decoding */
+ 
+     png_process_data(png_ptr, info_ptr, rawbuf, length);
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr)
+ {
+     mainprog_info  *mainprog_ptr;
+     int  color_type, bit_depth;
+     double  gamma;
+ 
+ 
+     /* setjmp() doesn't make sense here, because we'd either have to exit(),
+      * longjmp() ourselves, or return control to libpng, which doesn't want
+      * to see us again.  By not doing anything here, libpng will instead jump
+      * to readpng2_decode_data(), which can return an error value to the main
+      * program. */
+ 
+ 
+     /* retrieve the pointer to our special-purpose struct, using the png_ptr
+      * that libpng passed back to us (i.e., not a global this time--there's
+      * no real difference for a single image, but for a multithreaded browser
+      * decoding several PNG images at the same time, one needs to avoid mixing
+      * up different images' structs) */
+ 
+     mainprog_ptr = png_get_progressive_ptr(png_ptr);
+ 
+     if (mainprog_ptr == NULL) {         /* we be hosed */
+         fprintf(stderr,
+           "readpng2 error:  main struct not recoverable in info_callback.\n");
+         fflush(stderr);
+         return;
+         /*
+          * Alternatively, we could call our error-handler just like libpng
+          * does, which would effectively terminate the program.  Since this
+          * can only happen if png_ptr gets redirected somewhere odd or the
+          * main PNG struct gets wiped, we're probably toast anyway.  (If
+          * png_ptr itself is NULL, we would not have been called.)
+          */
+     }
+ 
+ 
+     /* this is just like in the non-progressive case */
+ 
+     png_get_IHDR(png_ptr, info_ptr, &mainprog_ptr->width,
+       &mainprog_ptr->height, &bit_depth, &color_type, NULL, NULL, NULL);
+ 
+ 
+     /* since we know we've read all of the PNG file's "header" (i.e., up
+      * to IDAT), we can check for a background color here */
+ 
+     if (mainprog_ptr->need_bgcolor &&
+         png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD))
+     {
+         png_color_16p pBackground;
+ 
+         /* it is not obvious from the libpng documentation, but this function
+          * takes a pointer to a pointer, and it always returns valid red,
+          * green and blue values, regardless of color_type: */
+         png_get_bKGD(png_ptr, info_ptr, &pBackground);
+ 
+         /* however, it always returns the raw bKGD data, regardless of any
+          * bit-depth transformations, so check depth and adjust if necessary */
+         if (bit_depth == 16) {
+             mainprog_ptr->bg_red   = pBackground->red   >> 8;
+             mainprog_ptr->bg_green = pBackground->green >> 8;
+             mainprog_ptr->bg_blue  = pBackground->blue  >> 8;
+         } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
+             if (bit_depth == 1)
+                 mainprog_ptr->bg_red = mainprog_ptr->bg_green =
+                   mainprog_ptr->bg_blue = pBackground->gray? 255 : 0;
+             else if (bit_depth == 2)
+                 mainprog_ptr->bg_red = mainprog_ptr->bg_green =
+                   mainprog_ptr->bg_blue = (255/3) * pBackground->gray;
+             else /* bit_depth == 4 */
+                 mainprog_ptr->bg_red = mainprog_ptr->bg_green =
+                   mainprog_ptr->bg_blue = (255/15) * pBackground->gray;
+         } else {
+             mainprog_ptr->bg_red   = (uch)pBackground->red;
+             mainprog_ptr->bg_green = (uch)pBackground->green;
+             mainprog_ptr->bg_blue  = (uch)pBackground->blue;
+         }
+     }
+ 
+ 
+     /* as before, let libpng expand palette images to RGB, low-bit-depth
+      * grayscale images to 8 bits, transparency chunks to full alpha channel;
+      * strip 16-bit-per-sample images to 8 bits per sample; and convert
+      * grayscale to RGB[A] */
+ 
+     if (color_type == PNG_COLOR_TYPE_PALETTE)
+         png_set_expand(png_ptr);
+     if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+         png_set_expand(png_ptr);
+     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+         png_set_expand(png_ptr);
+     if (bit_depth == 16)
+         png_set_strip_16(png_ptr);
+     if (color_type == PNG_COLOR_TYPE_GRAY ||
+         color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+         png_set_gray_to_rgb(png_ptr);
+ 
+ 
+     /* Unlike the basic viewer, which was designed to operate on local files,
+      * this program is intended to simulate a web browser--even though we
+      * actually read from a local file, too.  But because we are pretending
+      * that most of the images originate on the Internet, we follow the recom-
+      * mendation of the sRGB proposal and treat unlabelled images (no gAMA
+      * chunk) as existing in the sRGB color space.  That is, we assume that
+      * such images have a file gamma of 0.45455, which corresponds to a PC-like
+      * display system.  This change in assumptions will have no effect on a
+      * PC-like system, but on a Mac, SGI, NeXT or other system with a non-
+      * identity lookup table, it will darken unlabelled images, which effec-
+      * tively favors images from PC-like systems over those originating on
+      * the local platform.  Note that mainprog_ptr->display_exponent is the
+      * "gamma" value for the entire display system, i.e., the product of
+      * LUT_exponent and CRT_exponent. */
+ 
+     if (png_get_gAMA(png_ptr, info_ptr, &gamma))
+         png_set_gamma(png_ptr, mainprog_ptr->display_exponent, gamma);
+     else
+         png_set_gamma(png_ptr, mainprog_ptr->display_exponent, 0.45455);
+ 
+ 
+     /* we'll let libpng expand interlaced images, too */
+ 
+     mainprog_ptr->passes = png_set_interlace_handling(png_ptr);
+ 
+ 
+     /* all transformations have been registered; now update info_ptr data and
+      * then get rowbytes and channels */
+ 
+     png_read_update_info(png_ptr, info_ptr);
+ 
+     mainprog_ptr->rowbytes = (int)png_get_rowbytes(png_ptr, info_ptr);
+     mainprog_ptr->channels = png_get_channels(png_ptr, info_ptr);
+ 
+ 
+     /* Call the main program to allocate memory for the image buffer and
+      * initialize windows and whatnot.  (The old-style function-pointer
+      * invocation is used for compatibility with a few supposedly ANSI
+      * compilers that nevertheless barf on "fn_ptr()"-style syntax.) */
+ 
+     (*mainprog_ptr->mainprog_init)();
+ 
+ 
+     /* and that takes care of initialization */
+ 
+     return;
+ }
+ 
+ 
+ 
+ 
+ 
+ static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row,
+                                   png_uint_32 row_num, int pass)
+ {
+     mainprog_info  *mainprog_ptr;
+ 
+ 
+     /* first check whether the row differs from the previous pass; if not,
+      * nothing to combine or display */
+ 
+     if (!new_row)
+         return;
+ 
+ 
+     /* retrieve the pointer to our special-purpose struct so we can access
+      * the old rows and image-display callback function */
+ 
+     mainprog_ptr = png_get_progressive_ptr(png_ptr);
+ 
+ 
+     /* save the pass number for optional use by the front end */
+ 
+     mainprog_ptr->pass = pass;
+ 
+ 
+     /* have libpng either combine the new row data with the existing row data
+      * from previous passes (if interlaced) or else just copy the new row
+      * into the main program's image buffer */
+ 
+     png_progressive_combine_row(png_ptr, mainprog_ptr->row_pointers[row_num],
+       new_row);
+ 
+ 
+     /* finally, call the display routine in the main program with the number
+      * of the row we just updated */
+ 
+     (*mainprog_ptr->mainprog_display_row)(row_num);
+ 
+ 
+     /* and we're ready for more */
+ 
+     return;
+ }
+ 
+ 
+ 
+ 
+ 
+ static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr)
+ {
+     mainprog_info  *mainprog_ptr;
+ 
+ 
+     /* retrieve the pointer to our special-purpose struct */
+ 
+     mainprog_ptr = png_get_progressive_ptr(png_ptr);
+ 
+ 
+     /* let the main program know that it should flush any buffered image
+      * data to the display now and set a "done" flag or whatever, but note
+      * that it SHOULD NOT DESTROY THE PNG STRUCTS YET--in other words, do
+      * NOT call readpng2_cleanup() either here or in the finish_display()
+      * routine; wait until control returns to the main program via
+      * readpng2_decode_data() */
+ 
+     (*mainprog_ptr->mainprog_finish_display)();
+ 
+ 
+     /* all done */
+ 
+     return;
+ }
+ 
+ 
+ 
+ 
+ 
+ void readpng2_cleanup(mainprog_info *mainprog_ptr)
+ {
+     png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
+     png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
+ 
+     if (png_ptr && info_ptr)
+         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ 
+     mainprog_ptr->png_ptr = NULL;
+     mainprog_ptr->info_ptr = NULL;
+ }
+ 
+ 
+ 
+ 
+ 
+ static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg)
+ {
+     mainprog_info  *mainprog_ptr;
+ 
+     /* This function, aside from the extra step of retrieving the "error
+      * pointer" (below) and the fact that it exists within the application
+      * rather than within libpng, is essentially identical to libpng's
+      * default error handler.  The second point is critical:  since both
+      * setjmp() and longjmp() are called from the same code, they are
+      * guaranteed to have compatible notions of how big a jmp_buf is,
+      * regardless of whether _BSD_SOURCE or anything else has (or has not)
+      * been defined. */
+ 
+     fprintf(stderr, "readpng2 libpng error: %s\n", msg);
+     fflush(stderr);
+ 
+     mainprog_ptr = png_get_error_ptr(png_ptr);
+     if (mainprog_ptr == NULL) {         /* we are completely hosed now */
+         fprintf(stderr,
+           "readpng2 severe error:  jmpbuf not recoverable; terminating.\n");
+         fflush(stderr);
+         exit(99);
+     }
+ 
+     longjmp(mainprog_ptr->jmpbuf, 1);
+ }


Index: llvm/runtime/libpng/contrib/gregbook/readpng2.h
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/readpng2.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:55 2004
--- llvm/runtime/libpng/contrib/gregbook/readpng2.h	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,91 ----
+ /*---------------------------------------------------------------------------
+ 
+    rpng2 - progressive-model PNG display program                 readpng2.h
+ 
+   ---------------------------------------------------------------------------
+ 
+       Copyright (c) 1998-2001 Greg Roelofs.  All rights reserved.
+ 
+       This software is provided "as is," without warranty of any kind,
+       express or implied.  In no event shall the author or contributors
+       be held liable for any damages arising in any way from the use of
+       this software.
+ 
+       Permission is granted to anyone to use this software for any purpose,
+       including commercial applications, and to alter it and redistribute
+       it freely, subject to the following restrictions:
+ 
+       1. Redistributions of source code must retain the above copyright
+          notice, disclaimer, and this list of conditions.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, disclaimer, and this list of conditions in the documenta-
+          tion and/or other materials provided with the distribution.
+       3. All advertising materials mentioning features or use of this
+          software must display the following acknowledgment:
+ 
+             This product includes software developed by Greg Roelofs
+             and contributors for the book, "PNG: The Definitive Guide,"
+             published by O'Reilly and Associates.
+ 
+   ---------------------------------------------------------------------------*/
+ 
+ #ifndef TRUE
+ #  define TRUE 1
+ #  define FALSE 0
+ #endif
+ 
+ #ifndef MAX
+ #  define MAX(a,b)  ((a) > (b)? (a) : (b))
+ #  define MIN(a,b)  ((a) < (b)? (a) : (b))
+ #endif
+ 
+ #ifdef DEBUG
+ #  define Trace(x)  {fprintf x ; fflush(stderr); fflush(stdout);}
+ #else
+ #  define Trace(x)  ;
+ #endif
+ 
+ typedef unsigned char   uch;
+ typedef unsigned short  ush;
+ typedef unsigned long   ulg;
+ 
+ typedef struct _mainprog_info {
+     double display_exponent;
+     ulg width;
+     ulg height;
+     void *png_ptr;
+     void *info_ptr;
+     void (*mainprog_init)(void);
+     void (*mainprog_display_row)(ulg row_num);
+     void (*mainprog_finish_display)(void);
+     uch *image_data;
+     uch **row_pointers;
+     jmp_buf jmpbuf;
+     int passes;              /* not used */
+     int pass;
+     int rowbytes;
+     int channels;
+     int need_bgcolor;
+ #if (defined(__i386__) || defined(_M_IX86))
+     int nommxfilters;
+     int nommxcombine;
+     int nommxinterlace;
+ #endif
+     int done;
+     uch bg_red;
+     uch bg_green;
+     uch bg_blue;
+ } mainprog_info;
+ 
+ 
+ /* prototypes for public functions in readpng2.c */
+ 
+ void readpng2_version_info(void);
+ 
+ int readpng2_check_sig(uch *sig, int num);
+ 
+ int readpng2_init(mainprog_info *mainprog_ptr);
+ 
+ int readpng2_decode_data(mainprog_info *mainprog_ptr, uch *rawbuf, ulg length);
+ 
+ void readpng2_cleanup(mainprog_info *mainprog_ptr);


Index: llvm/runtime/libpng/contrib/gregbook/rpng-win.c
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/rpng-win.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:55 2004
--- llvm/runtime/libpng/contrib/gregbook/rpng-win.c	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,642 ----
+ /*---------------------------------------------------------------------------
+ 
+    rpng - simple PNG display program                             rpng-win.c
+ 
+    This program decodes and displays PNG images, with gamma correction and
+    optionally with a user-specified background color (in case the image has
+    transparency).  It is very nearly the most basic PNG viewer possible.
+    This version is for 32-bit Windows; it may compile under 16-bit Windows
+    with a little tweaking (or maybe not).
+ 
+    to do:
+     - handle quoted command-line args (especially filenames with spaces)
+     - have minimum window width:  oh well
+     - use %.1023s to simplify truncation of title-bar string?
+ 
+   ---------------------------------------------------------------------------
+ 
+    Changelog:
+     - 1.00:  initial public release
+     - 1.01:  modified to allow abbreviated options; fixed long/ulong mis-
+               match; switched to png_jmpbuf() macro
+     - 1.02:  added extra set of parentheses to png_jmpbuf() macro; fixed
+               command-line parsing bug
+     - 1.10:  enabled "message window"/console (thanks to David Geldreich)
+ 
+   ---------------------------------------------------------------------------
+ 
+       Copyright (c) 1998-2001 Greg Roelofs.  All rights reserved.
+ 
+       This software is provided "as is," without warranty of any kind,
+       express or implied.  In no event shall the author or contributors
+       be held liable for any damages arising in any way from the use of
+       this software.
+ 
+       Permission is granted to anyone to use this software for any purpose,
+       including commercial applications, and to alter it and redistribute
+       it freely, subject to the following restrictions:
+ 
+       1. Redistributions of source code must retain the above copyright
+          notice, disclaimer, and this list of conditions.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, disclaimer, and this list of conditions in the documenta-
+          tion and/or other materials provided with the distribution.
+       3. All advertising materials mentioning features or use of this
+          software must display the following acknowledgment:
+ 
+             This product includes software developed by Greg Roelofs
+             and contributors for the book, "PNG: The Definitive Guide,"
+             published by O'Reilly and Associates.
+ 
+   ---------------------------------------------------------------------------*/
+ 
+ #define PROGNAME  "rpng-win"
+ #define LONGNAME  "Simple PNG Viewer for Windows"
+ #define VERSION   "1.20 of 28 May 2001"
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <time.h>
+ #include <windows.h>
+ #include <conio.h>      /* only for _getch() */
+ 
+ /* #define DEBUG  :  this enables the Trace() macros */
+ 
+ #include "readpng.h"    /* typedefs, common macros, readpng prototypes */
+ 
+ 
+ /* could just include png.h, but this macro is the only thing we need
+  * (name and typedefs changed to local versions); note that side effects
+  * only happen with alpha (which could easily be avoided with
+  * "ush acopy = (alpha);") */
+ 
+ #define alpha_composite(composite, fg, alpha, bg) {               \
+     ush temp = ((ush)(fg)*(ush)(alpha) +                          \
+                 (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128);  \
+     (composite) = (uch)((temp + (temp >> 8)) >> 8);               \
+ }
+ 
+ 
+ /* local prototypes */
+ static int        rpng_win_create_window(HINSTANCE hInst, int showmode);
+ static int        rpng_win_display_image(void);
+ static void       rpng_win_cleanup(void);
+ LRESULT CALLBACK  rpng_win_wndproc(HWND, UINT, WPARAM, LPARAM);
+ 
+ 
+ static char titlebar[1024], *window_name = titlebar;
+ static char *progname = PROGNAME;
+ static char *appname = LONGNAME;
+ static char *icon_name = PROGNAME;     /* GRR:  not (yet) used */
+ static char *filename;
+ static FILE *infile;
+ 
+ static char *bgstr;
+ static uch bg_red=0, bg_green=0, bg_blue=0;
+ 
+ static double display_exponent;
+ 
+ static ulg image_width, image_height, image_rowbytes;
+ static int image_channels;
+ static uch *image_data;
+ 
+ /* Windows-specific variables */
+ static ulg wimage_rowbytes;
+ static uch *dib;
+ static uch *wimage_data;
+ static BITMAPINFOHEADER *bmih;
+ 
+ static HWND global_hwnd;
+ 
+ 
+ 
+ 
+ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode)
+ {
+     char *args[1024];                 /* arbitrary limit, but should suffice */
+     char *p, *q, **argv = args;
+     int argc = 0;
+     int rc, alen, flen;
+     int error = 0;
+     int have_bg = FALSE;
+     double LUT_exponent;              /* just the lookup table */
+     double CRT_exponent = 2.2;        /* just the monitor */
+     double default_display_exponent;  /* whole display system */
+     MSG msg;
+ 
+ 
+     filename = (char *)NULL;
+ 
+ 
+     /* First reenable console output, which normally goes to the bit bucket
+      * for windowed apps.  Closing the console window will terminate the
+      * app.  Thanks to David.Geldreich at realviz.com for supplying the magical
+      * incantation. */
+ 
+     AllocConsole();
+     freopen("CONOUT$", "a", stderr);
+     freopen("CONOUT$", "a", stdout);
+ 
+ 
+     /* Next set the default value for our display-system exponent, i.e.,
+      * the product of the CRT exponent and the exponent corresponding to
+      * the frame-buffer's lookup table (LUT), if any.  This is not an
+      * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
+      * ones), but it should cover 99% of the current possibilities.  And
+      * yes, these ifdefs are completely wasted in a Windows program... */
+ 
+ #if defined(NeXT)
+     LUT_exponent = 1.0 / 2.2;
+     /*
+     if (some_next_function_that_returns_gamma(&next_gamma))
+         LUT_exponent = 1.0 / next_gamma;
+      */
+ #elif defined(sgi)
+     LUT_exponent = 1.0 / 1.7;
+     /* there doesn't seem to be any documented function to get the
+      * "gamma" value, so we do it the hard way */
+     infile = fopen("/etc/config/system.glGammaVal", "r");
+     if (infile) {
+         double sgi_gamma;
+ 
+         fgets(tmpline, 80, infile);
+         fclose(infile);
+         sgi_gamma = atof(tmpline);
+         if (sgi_gamma > 0.0)
+             LUT_exponent = 1.0 / sgi_gamma;
+     }
+ #elif defined(Macintosh)
+     LUT_exponent = 1.8 / 2.61;
+     /*
+     if (some_mac_function_that_returns_gamma(&mac_gamma))
+         LUT_exponent = mac_gamma / 2.61;
+      */
+ #else
+     LUT_exponent = 1.0;   /* assume no LUT:  most PCs */
+ #endif
+ 
+     /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
+     default_display_exponent = LUT_exponent * CRT_exponent;
+ 
+ 
+     /* If the user has set the SCREEN_GAMMA environment variable as suggested
+      * (somewhat imprecisely) in the libpng documentation, use that; otherwise
+      * use the default value we just calculated.  Either way, the user may
+      * override this via a command-line option. */
+ 
+     if ((p = getenv("SCREEN_GAMMA")) != NULL)
+         display_exponent = atof(p);
+     else
+         display_exponent = default_display_exponent;
+ 
+ 
+     /* Windows really hates command lines, so we have to set up our own argv.
+      * Note that we do NOT bother with quoted arguments here, so don't use
+      * filenames with spaces in 'em! */
+ 
+     argv[argc++] = PROGNAME;
+     p = cmd;
+     for (;;) {
+         if (*p == ' ')
+             while (*++p == ' ')
+                 ;
+         /* now p points at the first non-space after some spaces */
+         if (*p == '\0')
+             break;    /* nothing after the spaces:  done */
+         argv[argc++] = q = p;
+         while (*q && *q != ' ')
+             ++q;
+         /* now q points at a space or the end of the string */
+         if (*q == '\0')
+             break;    /* last argv already terminated; quit */
+         *q = '\0';    /* change space to terminator */
+         p = q + 1;
+     }
+     argv[argc] = NULL;   /* terminate the argv array itself */
+ 
+ 
+     /* Now parse the command line for options and the PNG filename. */
+ 
+     while (*++argv && !error) {
+         if (!strncmp(*argv, "-gamma", 2)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 display_exponent = atof(*argv);
+                 if (display_exponent <= 0.0)
+                     ++error;
+             }
+         } else if (!strncmp(*argv, "-bgcolor", 2)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 bgstr = *argv;
+                 if (strlen(bgstr) != 7 || bgstr[0] != '#')
+                     ++error;
+                 else
+                     have_bg = TRUE;
+             }
+         } else {
+             if (**argv != '-') {
+                 filename = *argv;
+                 if (argv[1])   /* shouldn't be any more args after filename */
+                     ++error;
+             } else
+                 ++error;   /* not expecting any other options */
+         }
+     }
+ 
+     if (!filename) {
+         ++error;
+     } else if (!(infile = fopen(filename, "rb"))) {
+         fprintf(stderr, PROGNAME ":  can't open PNG file [%s]\n", filename);
+         ++error;
+     } else {
+         if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) {
+             switch (rc) {
+                 case 1:
+                     fprintf(stderr, PROGNAME
+                       ":  [%s] is not a PNG file: incorrect signature\n",
+                       filename);
+                     break;
+                 case 2:
+                     fprintf(stderr, PROGNAME
+                       ":  [%s] has bad IHDR (libpng longjmp)\n",
+                       filename);
+                     break;
+                 case 4:
+                     fprintf(stderr, PROGNAME ":  insufficient memory\n");
+                     break;
+                 default:
+                     fprintf(stderr, PROGNAME
+                       ":  unknown readpng_init() error\n");
+                     break;
+             }
+             ++error;
+         }
+         if (error)
+             fclose(infile);
+     }
+ 
+ 
+     /* usage screen */
+ 
+     if (error) {
+         int ch;
+ 
+         fprintf(stderr, "\n%s %s:  %s\n\n", PROGNAME, VERSION, appname);
+         readpng_version_info();
+         fprintf(stderr, "\n"
+           "Usage:  %s [-gamma exp] [-bgcolor bg] file.png\n"
+           "    exp \ttransfer-function exponent (``gamma'') of the display\n"
+           "\t\t  system in floating-point format (e.g., ``%.1f''); equal\n"
+           "\t\t  to the product of the lookup-table exponent (varies)\n"
+           "\t\t  and the CRT exponent (usually 2.2); must be positive\n"
+           "    bg  \tdesired background color in 7-character hex RGB format\n"
+           "\t\t  (e.g., ``#ff7700'' for orange:  same as HTML colors);\n"
+           "\t\t  used with transparent images\n"
+           "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n"
+           "Press Q or Esc to quit this usage screen.\n"
+           "\n", PROGNAME, default_display_exponent);
+         do
+             ch = _getch();
+         while (ch != 'q' && ch != 'Q' && ch != 0x1B);
+         exit(1);
+     } else {
+         fprintf(stderr, "\n%s %s:  %s\n", PROGNAME, VERSION, appname);
+         fprintf(stderr,
+           "\n   [console window:  closing this window will terminate %s]\n\n",
+           PROGNAME);
+     }
+ 
+ 
+     /* set the title-bar string, but make sure buffer doesn't overflow */
+ 
+     alen = strlen(appname);
+     flen = strlen(filename);
+     if (alen + flen + 3 > 1023)
+         sprintf(titlebar, "%s:  ...%s", appname, filename+(alen+flen+6-1023));
+     else
+         sprintf(titlebar, "%s:  %s", appname, filename);
+ 
+ 
+     /* if the user didn't specify a background color on the command line,
+      * check for one in the PNG file--if not, the initialized values of 0
+      * (black) will be used */
+ 
+     if (have_bg)
+         sscanf(bgstr+1, "%2x%2x%2x", &bg_red, &bg_green, &bg_blue);
+     else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) {
+         readpng_cleanup(TRUE);
+         fprintf(stderr, PROGNAME
+           ":  libpng error while checking for background color\n");
+         exit(2);
+     }
+ 
+ 
+     /* do the basic Windows initialization stuff, make the window and fill it
+      * with the background color */
+ 
+     if (rpng_win_create_window(hInst, showmode))
+         exit(2);
+ 
+ 
+     /* decode the image, all at once */
+ 
+     Trace((stderr, "calling readpng_get_image()\n"))
+     image_data = readpng_get_image(display_exponent, &image_channels,
+       &image_rowbytes);
+     Trace((stderr, "done with readpng_get_image()\n"))
+ 
+ 
+     /* done with PNG file, so clean up to minimize memory usage (but do NOT
+      * nuke image_data!) */
+ 
+     readpng_cleanup(FALSE);
+     fclose(infile);
+ 
+     if (!image_data) {
+         fprintf(stderr, PROGNAME ":  unable to decode PNG image\n");
+         exit(3);
+     }
+ 
+ 
+     /* display image (composite with background if requested) */
+ 
+     Trace((stderr, "calling rpng_win_display_image()\n"))
+     if (rpng_win_display_image()) {
+         free(image_data);
+         exit(4);
+     }
+     Trace((stderr, "done with rpng_win_display_image()\n"))
+ 
+ 
+     /* wait for the user to tell us when to quit */
+ 
+     printf(
+       "Done.  Press Q, Esc or mouse button 1 (within image window) to quit.\n");
+     fflush(stdout);
+ 
+     while (GetMessage(&msg, NULL, 0, 0)) {
+         TranslateMessage(&msg);
+         DispatchMessage(&msg);
+     }
+ 
+ 
+     /* OK, we're done:  clean up all image and Windows resources and go away */
+ 
+     rpng_win_cleanup();
+ 
+     return msg.wParam;
+ }
+ 
+ 
+ 
+ 
+ 
+ static int rpng_win_create_window(HINSTANCE hInst, int showmode)
+ {
+     uch *dest;
+     int extra_width, extra_height;
+     ulg i, j;
+     WNDCLASSEX wndclass;
+ 
+ 
+ /*---------------------------------------------------------------------------
+     Allocate memory for the display-specific version of the image (round up
+     to multiple of 4 for Windows DIB).
+   ---------------------------------------------------------------------------*/
+ 
+     wimage_rowbytes = ((3*image_width + 3L) >> 2) << 2;
+ 
+     if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) +
+                               wimage_rowbytes*image_height)))
+     {
+         return 4;   /* fail */
+     }
+ 
+ /*---------------------------------------------------------------------------
+     Initialize the DIB.  Negative height means to use top-down BMP ordering
+     (must be uncompressed, but that's what we want).  Bit count of 1, 4 or 8
+     implies a colormap of RGBX quads, but 24-bit BMPs just use B,G,R values
+     directly => wimage_data begins immediately after BMP header.
+   ---------------------------------------------------------------------------*/
+ 
+     memset(dib, 0, sizeof(BITMAPINFOHEADER));
+     bmih = (BITMAPINFOHEADER *)dib;
+     bmih->biSize = sizeof(BITMAPINFOHEADER);
+     bmih->biWidth = image_width;
+     bmih->biHeight = -((long)image_height);
+     bmih->biPlanes = 1;
+     bmih->biBitCount = 24;
+     bmih->biCompression = 0;
+     wimage_data = dib + sizeof(BITMAPINFOHEADER);
+ 
+ /*---------------------------------------------------------------------------
+     Fill in background color (black by default); data are in BGR order.
+   ---------------------------------------------------------------------------*/
+ 
+     for (j = 0;  j < image_height;  ++j) {
+         dest = wimage_data + j*wimage_rowbytes;
+         for (i = image_width;  i > 0;  --i) {
+             *dest++ = bg_blue;
+             *dest++ = bg_green;
+             *dest++ = bg_red;
+         }
+     }
+ 
+ /*---------------------------------------------------------------------------
+     Set the window parameters.
+   ---------------------------------------------------------------------------*/
+ 
+     memset(&wndclass, 0, sizeof(wndclass));
+ 
+     wndclass.cbSize = sizeof(wndclass);
+     wndclass.style = CS_HREDRAW | CS_VREDRAW;
+     wndclass.lpfnWndProc = rpng_win_wndproc;
+     wndclass.hInstance = hInst;
+     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+     wndclass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
+     wndclass.lpszMenuName = NULL;
+     wndclass.lpszClassName = progname;
+     wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+ 
+     RegisterClassEx(&wndclass);
+ 
+ /*---------------------------------------------------------------------------
+     Finally, create the window.
+   ---------------------------------------------------------------------------*/
+ 
+     extra_width  = 2*(GetSystemMetrics(SM_CXBORDER) +
+                       GetSystemMetrics(SM_CXDLGFRAME));
+     extra_height = 2*(GetSystemMetrics(SM_CYBORDER) +
+                       GetSystemMetrics(SM_CYDLGFRAME)) +
+                       GetSystemMetrics(SM_CYCAPTION);
+ 
+     global_hwnd = CreateWindow(progname, titlebar, WS_OVERLAPPEDWINDOW,
+       CW_USEDEFAULT, CW_USEDEFAULT, image_width+extra_width,
+       image_height+extra_height, NULL, NULL, hInst, NULL);
+ 
+     ShowWindow(global_hwnd, showmode);
+     UpdateWindow(global_hwnd);
+ 
+     return 0;
+ 
+ } /* end function rpng_win_create_window() */
+ 
+ 
+ 
+ 
+ 
+ static int rpng_win_display_image()
+ {
+     uch *src, *dest;
+     uch r, g, b, a;
+     ulg i, row, lastrow;
+     RECT rect;
+ 
+ 
+     Trace((stderr, "beginning display loop (image_channels == %d)\n",
+       image_channels))
+     Trace((stderr, "(width = %ld, rowbytes = %ld, wimage_rowbytes = %d)\n",
+       image_width, image_rowbytes, wimage_rowbytes))
+ 
+ 
+ /*---------------------------------------------------------------------------
+     Blast image data to buffer.  This whole routine takes place before the
+     message loop begins, so there's no real point in any pseudo-progressive
+     display...
+   ---------------------------------------------------------------------------*/
+ 
+     for (lastrow = row = 0;  row < image_height;  ++row) {
+         src = image_data + row*image_rowbytes;
+         dest = wimage_data + row*wimage_rowbytes;
+         if (image_channels == 3) {
+             for (i = image_width;  i > 0;  --i) {
+                 r = *src++;
+                 g = *src++;
+                 b = *src++;
+                 *dest++ = b;
+                 *dest++ = g;   /* note reverse order */
+                 *dest++ = r;
+             }
+         } else /* if (image_channels == 4) */ {
+             for (i = image_width;  i > 0;  --i) {
+                 r = *src++;
+                 g = *src++;
+                 b = *src++;
+                 a = *src++;
+                 if (a == 255) {
+                     *dest++ = b;
+                     *dest++ = g;
+                     *dest++ = r;
+                 } else if (a == 0) {
+                     *dest++ = bg_blue;
+                     *dest++ = bg_green;
+                     *dest++ = bg_red;
+                 } else {
+                     /* this macro (copied from png.h) composites the
+                      * foreground and background values and puts the
+                      * result into the first argument; there are no
+                      * side effects with the first argument */
+                     alpha_composite(*dest++, b, a, bg_blue);
+                     alpha_composite(*dest++, g, a, bg_green);
+                     alpha_composite(*dest++, r, a, bg_red);
+                 }
+             }
+         }
+         /* display after every 16 lines */
+         if (((row+1) & 0xf) == 0) {
+             rect.left = 0L;
+             rect.top = (LONG)lastrow;
+             rect.right = (LONG)image_width;      /* possibly off by one? */
+             rect.bottom = (LONG)lastrow + 16L;   /* possibly off by one? */
+             InvalidateRect(global_hwnd, &rect, FALSE);
+             UpdateWindow(global_hwnd);     /* similar to XFlush() */
+             lastrow = row + 1;
+         }
+     }
+ 
+     Trace((stderr, "calling final image-flush routine\n"))
+     if (lastrow < image_height) {
+         rect.left = 0L;
+         rect.top = (LONG)lastrow;
+         rect.right = (LONG)image_width;      /* possibly off by one? */
+         rect.bottom = (LONG)image_height;    /* possibly off by one? */
+         InvalidateRect(global_hwnd, &rect, FALSE);
+         UpdateWindow(global_hwnd);     /* similar to XFlush() */
+     }
+ 
+ /*
+     last param determines whether or not background is wiped before paint
+     InvalidateRect(global_hwnd, NULL, TRUE);
+     UpdateWindow(global_hwnd);
+  */
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ 
+ static void rpng_win_cleanup()
+ {
+     if (image_data) {
+         free(image_data);
+         image_data = NULL;
+     }
+ 
+     if (dib) {
+         free(dib);
+         dib = NULL;
+     }
+ }
+ 
+ 
+ 
+ 
+ 
+ LRESULT CALLBACK rpng_win_wndproc(HWND hwnd, UINT iMsg, WPARAM wP, LPARAM lP)
+ {
+     HDC         hdc;
+     PAINTSTRUCT ps;
+     int rc;
+ 
+     switch (iMsg) {
+         case WM_CREATE:
+             /* one-time processing here, if any */
+             return 0;
+ 
+         case WM_PAINT:
+             hdc = BeginPaint(hwnd, &ps);
+                     /*                    dest                          */
+             rc = StretchDIBits(hdc, 0, 0, image_width, image_height,
+                     /*                    source                        */
+                                     0, 0, image_width, image_height,
+                                     wimage_data, (BITMAPINFO *)bmih,
+                     /*              iUsage: no clue                     */
+                                     0, SRCCOPY);
+             EndPaint(hwnd, &ps);
+             return 0;
+ 
+         /* wait for the user to tell us when to quit */
+         case WM_CHAR:
+             switch (wP) {      /* only need one, so ignore repeat count */
+                 case 'q':
+                 case 'Q':
+                 case 0x1B:     /* Esc key */
+                     PostQuitMessage(0);
+             }
+             return 0;
+ 
+         case WM_LBUTTONDOWN:   /* another way of quitting */
+         case WM_DESTROY:
+             PostQuitMessage(0);
+             return 0;
+     }
+ 
+     return DefWindowProc(hwnd, iMsg, wP, lP);
+ }


Index: llvm/runtime/libpng/contrib/gregbook/rpng-x.c
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/rpng-x.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:55 2004
--- llvm/runtime/libpng/contrib/gregbook/rpng-x.c	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,858 ----
+ /*---------------------------------------------------------------------------
+ 
+    rpng - simple PNG display program                               rpng-x.c
+ 
+    This program decodes and displays PNG images, with gamma correction and
+    optionally with a user-specified background color (in case the image has
+    transparency).  It is very nearly the most basic PNG viewer possible.
+    This version is for the X Window System (tested by author under Unix and
+    by Martin Zinser under OpenVMS; may work under OS/2 with some tweaking).
+ 
+    to do:
+     - 8-bit support
+     - use %.1023s to simplify truncation of title-bar string?
+ 
+   ---------------------------------------------------------------------------
+ 
+    Changelog:
+     - 1.01:  initial public release
+     - 1.02:  modified to allow abbreviated options; fixed long/ulong mis-
+               match; switched to png_jmpbuf() macro
+     - 1.10:  added support for non-default visuals; fixed X pixel-conversion
+     - 1.11:  added extra set of parentheses to png_jmpbuf() macro; fixed
+               command-line parsing bug
+     - 1.12:  fixed small X memory leak (thanks to Francois Petitjean)
+     - 1.13:  fixed XFreeGC() crash bug
+ 
+   ---------------------------------------------------------------------------
+ 
+       Copyright (c) 1998-2001 Greg Roelofs.  All rights reserved.
+ 
+       This software is provided "as is," without warranty of any kind,
+       express or implied.  In no event shall the author or contributors
+       be held liable for any damages arising in any way from the use of
+       this software.
+ 
+       Permission is granted to anyone to use this software for any purpose,
+       including commercial applications, and to alter it and redistribute
+       it freely, subject to the following restrictions:
+ 
+       1. Redistributions of source code must retain the above copyright
+          notice, disclaimer, and this list of conditions.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, disclaimer, and this list of conditions in the documenta-
+          tion and/or other materials provided with the distribution.
+       3. All advertising materials mentioning features or use of this
+          software must display the following acknowledgment:
+ 
+             This product includes software developed by Greg Roelofs
+             and contributors for the book, "PNG: The Definitive Guide,"
+             published by O'Reilly and Associates.
+ 
+   ---------------------------------------------------------------------------*/
+ 
+ #define PROGNAME  "rpng-x"
+ #define LONGNAME  "Simple PNG Viewer for X"
+ #define VERSION   "1.13 of 16 August 2001"
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <time.h>
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+ #include <X11/Xos.h>
+ #include <X11/keysym.h>
+ 
+ /* #define DEBUG  :  this enables the Trace() macros */
+ 
+ #include "readpng.h"   /* typedefs, common macros, readpng prototypes */
+ 
+ 
+ /* could just include png.h, but this macro is the only thing we need
+  * (name and typedefs changed to local versions); note that side effects
+  * only happen with alpha (which could easily be avoided with
+  * "ush acopy = (alpha);") */
+ 
+ #define alpha_composite(composite, fg, alpha, bg) {               \
+     ush temp = ((ush)(fg)*(ush)(alpha) +                          \
+                 (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128);  \
+     (composite) = (uch)((temp + (temp >> 8)) >> 8);               \
+ }
+ 
+ 
+ /* local prototypes */
+ static int  rpng_x_create_window(void);
+ static int  rpng_x_display_image(void);
+ static void rpng_x_cleanup(void);
+ static int  rpng_x_msb(ulg u32val);
+ 
+ 
+ static char titlebar[1024], *window_name = titlebar;
+ static char *appname = LONGNAME;
+ static char *icon_name = PROGNAME;
+ static char *filename;
+ static FILE *infile;
+ 
+ static char *bgstr;
+ static uch bg_red=0, bg_green=0, bg_blue=0;
+ 
+ static double display_exponent;
+ 
+ static ulg image_width, image_height, image_rowbytes;
+ static int image_channels;
+ static uch *image_data;
+ 
+ /* X-specific variables */
+ static char *displayname;
+ static XImage *ximage;
+ static Display *display;
+ static int depth;
+ static Visual *visual;
+ static XVisualInfo *visual_list;
+ static int RShift, GShift, BShift;
+ static ulg RMask, GMask, BMask;
+ static Window window;
+ static GC gc;
+ static Colormap colormap;
+ 
+ static int have_nondefault_visual = FALSE;
+ static int have_colormap = FALSE;
+ static int have_window = FALSE;
+ static int have_gc = FALSE;
+ /*
+ ulg numcolors=0, pixels[256];
+ ush reds[256], greens[256], blues[256];
+  */
+ 
+ 
+ 
+ 
+ int main(int argc, char **argv)
+ {
+ #ifdef sgi
+     char tmpline[80];
+ #endif
+     char *p;
+     int rc, alen, flen;
+     int error = 0;
+     int have_bg = FALSE;
+     double LUT_exponent;               /* just the lookup table */
+     double CRT_exponent = 2.2;         /* just the monitor */
+     double default_display_exponent;   /* whole display system */
+     XEvent e;
+     KeySym k;
+ 
+ 
+     displayname = (char *)NULL;
+     filename = (char *)NULL;
+ 
+ 
+     /* First set the default value for our display-system exponent, i.e.,
+      * the product of the CRT exponent and the exponent corresponding to
+      * the frame-buffer's lookup table (LUT), if any.  This is not an
+      * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
+      * ones), but it should cover 99% of the current possibilities. */
+ 
+ #if defined(NeXT)
+     LUT_exponent = 1.0 / 2.2;
+     /*
+     if (some_next_function_that_returns_gamma(&next_gamma))
+         LUT_exponent = 1.0 / next_gamma;
+      */
+ #elif defined(sgi)
+     LUT_exponent = 1.0 / 1.7;
+     /* there doesn't seem to be any documented function to get the
+      * "gamma" value, so we do it the hard way */
+     infile = fopen("/etc/config/system.glGammaVal", "r");
+     if (infile) {
+         double sgi_gamma;
+ 
+         fgets(tmpline, 80, infile);
+         fclose(infile);
+         sgi_gamma = atof(tmpline);
+         if (sgi_gamma > 0.0)
+             LUT_exponent = 1.0 / sgi_gamma;
+     }
+ #elif defined(Macintosh)
+     LUT_exponent = 1.8 / 2.61;
+     /*
+     if (some_mac_function_that_returns_gamma(&mac_gamma))
+         LUT_exponent = mac_gamma / 2.61;
+      */
+ #else
+     LUT_exponent = 1.0;   /* assume no LUT:  most PCs */
+ #endif
+ 
+     /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
+     default_display_exponent = LUT_exponent * CRT_exponent;
+ 
+ 
+     /* If the user has set the SCREEN_GAMMA environment variable as suggested
+      * (somewhat imprecisely) in the libpng documentation, use that; otherwise
+      * use the default value we just calculated.  Either way, the user may
+      * override this via a command-line option. */
+ 
+     if ((p = getenv("SCREEN_GAMMA")) != NULL)
+         display_exponent = atof(p);
+     else
+         display_exponent = default_display_exponent;
+ 
+ 
+     /* Now parse the command line for options and the PNG filename. */
+ 
+     while (*++argv && !error) {
+         if (!strncmp(*argv, "-display", 2)) {
+             if (!*++argv)
+                 ++error;
+             else
+                 displayname = *argv;
+         } else if (!strncmp(*argv, "-gamma", 2)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 display_exponent = atof(*argv);
+                 if (display_exponent <= 0.0)
+                     ++error;
+             }
+         } else if (!strncmp(*argv, "-bgcolor", 2)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 bgstr = *argv;
+                 if (strlen(bgstr) != 7 || bgstr[0] != '#')
+                     ++error; 
+                 else 
+                     have_bg = TRUE;
+             }
+         } else {
+             if (**argv != '-') {
+                 filename = *argv;
+                 if (argv[1])   /* shouldn't be any more args after filename */
+                     ++error;
+             } else
+                 ++error;   /* not expecting any other options */
+         }
+     }
+ 
+     if (!filename) {
+         ++error;
+     } else if (!(infile = fopen(filename, "rb"))) {
+         fprintf(stderr, PROGNAME ":  can't open PNG file [%s]\n", filename);
+         ++error;
+     } else {
+         if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) {
+             switch (rc) {
+                 case 1:
+                     fprintf(stderr, PROGNAME
+                       ":  [%s] is not a PNG file: incorrect signature\n",
+                       filename);
+                     break;
+                 case 2:
+                     fprintf(stderr, PROGNAME
+                       ":  [%s] has bad IHDR (libpng longjmp)\n",
+                       filename);
+                     break;
+                 case 4:
+                     fprintf(stderr, PROGNAME ":  insufficient memory\n");
+                     break;
+                 default:
+                     fprintf(stderr, PROGNAME
+                       ":  unknown readpng_init() error\n");
+                     break;
+             }
+             ++error;
+         } else {
+             display = XOpenDisplay(displayname);
+             if (!display) {
+                 readpng_cleanup(TRUE);
+                 fprintf(stderr, PROGNAME ":  can't open X display [%s]\n",
+                   displayname? displayname : "default");
+                 ++error;
+             }
+         }
+         if (error)
+             fclose(infile);
+     }
+ 
+ 
+     /* usage screen */
+ 
+     if (error) {
+         fprintf(stderr, "\n%s %s:  %s\n", PROGNAME, VERSION, appname);
+         readpng_version_info();
+         fprintf(stderr, "\n"
+           "Usage:  %s [-display xdpy] [-gamma exp] [-bgcolor bg] file.png\n"
+           "    xdpy\tname of the target X display (e.g., ``hostname:0'')\n"
+           "    exp \ttransfer-function exponent (``gamma'') of the display\n"
+           "\t\t  system in floating-point format (e.g., ``%.1f''); equal\n"
+           "\t\t  to the product of the lookup-table exponent (varies)\n"
+           "\t\t  and the CRT exponent (usually 2.2); must be positive\n"
+           "    bg  \tdesired background color in 7-character hex RGB format\n"
+           "\t\t  (e.g., ``#ff7700'' for orange:  same as HTML colors);\n"
+           "\t\t  used with transparent images\n"
+           "\nPress Q, Esc or mouse button 1 (within image window, after image\n"
+           "is displayed) to quit.\n"
+           "\n", PROGNAME, default_display_exponent);
+         exit(1);
+     }
+ 
+ 
+     /* set the title-bar string, but make sure buffer doesn't overflow */
+ 
+     alen = strlen(appname);
+     flen = strlen(filename);
+     if (alen + flen + 3 > 1023)
+         sprintf(titlebar, "%s:  ...%s", appname, filename+(alen+flen+6-1023));
+     else
+         sprintf(titlebar, "%s:  %s", appname, filename);
+ 
+ 
+     /* if the user didn't specify a background color on the command line,
+      * check for one in the PNG file--if not, the initialized values of 0
+      * (black) will be used */
+ 
+     if (have_bg) {
+         unsigned r, g, b;   /* this approach quiets compiler warnings */
+ 
+         sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
+         bg_red   = (uch)r;
+         bg_green = (uch)g;
+         bg_blue  = (uch)b;
+     } else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) {
+         readpng_cleanup(TRUE);
+         fprintf(stderr, PROGNAME
+           ":  libpng error while checking for background color\n");
+         exit(2);
+     }
+ 
+ 
+     /* do the basic X initialization stuff, make the window and fill it
+      * with the background color */
+ 
+     if (rpng_x_create_window())
+         exit(2);
+ 
+ 
+     /* decode the image, all at once */
+ 
+     Trace((stderr, "calling readpng_get_image()\n"))
+     image_data = readpng_get_image(display_exponent, &image_channels,
+       &image_rowbytes);
+     Trace((stderr, "done with readpng_get_image()\n"))
+ 
+ 
+     /* done with PNG file, so clean up to minimize memory usage (but do NOT
+      * nuke image_data!) */
+ 
+     readpng_cleanup(FALSE);
+     fclose(infile);
+ 
+     if (!image_data) {
+         fprintf(stderr, PROGNAME ":  unable to decode PNG image\n");
+         exit(3);
+     }
+ 
+ 
+     /* display image (composite with background if requested) */
+ 
+     Trace((stderr, "calling rpng_x_display_image()\n"))
+     if (rpng_x_display_image()) {
+         free(image_data);
+         exit(4);
+     }
+     Trace((stderr, "done with rpng_x_display_image()\n"))
+ 
+ 
+     /* wait for the user to tell us when to quit */
+ 
+     printf(
+       "Done.  Press Q, Esc or mouse button 1 (within image window) to quit.\n");
+     fflush(stdout);
+ 
+     do
+         XNextEvent(display, &e);
+     while (!(e.type == ButtonPress && e.xbutton.button == Button1) &&
+            !(e.type == KeyPress &&    /*  v--- or 1 for shifted keys */
+              ((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape) ));
+ 
+ 
+     /* OK, we're done:  clean up all image and X resources and go away */
+ 
+     rpng_x_cleanup();
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ 
+ static int rpng_x_create_window(void)
+ {
+     uch *xdata;
+     int need_colormap = FALSE;
+     int screen, pad;
+     ulg bg_pixel = 0L;
+     ulg attrmask;
+     Window root;
+     XEvent e;
+     XGCValues gcvalues;
+     XSetWindowAttributes attr;
+     XSizeHints *size_hints;
+     XTextProperty windowName, *pWindowName = &windowName;
+     XTextProperty iconName, *pIconName = &iconName;
+     XVisualInfo visual_info;
+     XWMHints *wm_hints;
+ 
+ 
+     screen = DefaultScreen(display);
+     depth = DisplayPlanes(display, screen);
+     root = RootWindow(display, screen);
+ 
+ #ifdef DEBUG
+     XSynchronize(display, True);
+ #endif
+ 
+ #if 0
+ /* GRR:  add 8-bit support */
+     if (/* depth != 8 && */ depth != 16 && depth != 24 && depth != 32) {
+         fprintf(stderr,
+           "screen depth %d not supported (only 16-, 24- or 32-bit TrueColor)\n",
+           depth);
+         return 2;
+     }
+ 
+     XMatchVisualInfo(display, screen, depth,
+       (depth == 8)? PseudoColor : TrueColor, &visual_info);
+     visual = visual_info.visual;
+ #else
+     if (depth != 16 && depth != 24 && depth != 32) {
+         int visuals_matched = 0;
+ 
+         Trace((stderr, "default depth is %d:  checking other visuals\n",
+           depth))
+ 
+         /* 24-bit first */
+         visual_info.screen = screen;
+         visual_info.depth = 24;
+         visual_list = XGetVisualInfo(display,
+           VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched);
+         if (visuals_matched == 0) {
+ /* GRR:  add 15-, 16- and 32-bit TrueColor visuals (also DirectColor?) */
+             fprintf(stderr, "default screen depth %d not supported, and no"
+               " 24-bit visuals found\n", depth);
+             return 2;
+         }
+         Trace((stderr, "XGetVisualInfo() returned %d 24-bit visuals\n",
+           visuals_matched))
+         visual = visual_list[0].visual;
+         depth = visual_list[0].depth;
+ /*
+         colormap_size = visual_list[0].colormap_size;
+         visual_class = visual->class;
+         visualID = XVisualIDFromVisual(visual);
+  */
+         have_nondefault_visual = TRUE;
+         need_colormap = TRUE;
+     } else {
+         XMatchVisualInfo(display, screen, depth, TrueColor, &visual_info);
+         visual = visual_info.visual;
+     }
+ #endif
+ 
+     RMask = visual->red_mask;
+     GMask = visual->green_mask;
+     BMask = visual->blue_mask;
+ 
+ /* GRR:  add/check 8-bit support */
+     if (depth == 8 || need_colormap) {
+         colormap = XCreateColormap(display, root, visual, AllocNone);
+         if (!colormap) {
+             fprintf(stderr, "XCreateColormap() failed\n");
+             return 2;
+         }
+         have_colormap = TRUE;
+     }
+     if (depth == 15 || depth == 16) {
+         RShift = 15 - rpng_x_msb(RMask);    /* these are right-shifts */
+         GShift = 15 - rpng_x_msb(GMask);
+         BShift = 15 - rpng_x_msb(BMask);
+     } else if (depth > 16) {
+ #define NO_24BIT_MASKS
+ #ifdef NO_24BIT_MASKS
+         RShift = rpng_x_msb(RMask) - 7;     /* these are left-shifts */
+         GShift = rpng_x_msb(GMask) - 7;
+         BShift = rpng_x_msb(BMask) - 7;
+ #else
+         RShift = 7 - rpng_x_msb(RMask);     /* these are right-shifts, too */
+         GShift = 7 - rpng_x_msb(GMask);
+         BShift = 7 - rpng_x_msb(BMask);
+ #endif
+     }
+     if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) {
+         fprintf(stderr, "rpng internal logic error:  negative X shift(s)!\n");
+         return 2;
+     }
+ 
+ /*---------------------------------------------------------------------------
+     Finally, create the window.
+   ---------------------------------------------------------------------------*/
+ 
+     attr.backing_store = Always;
+     attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
+     attrmask = CWBackingStore | CWEventMask;
+     if (have_nondefault_visual) {
+         attr.colormap = colormap;
+         attr.background_pixel = 0;
+         attr.border_pixel = 1;
+         attrmask |= CWColormap | CWBackPixel | CWBorderPixel;
+     }
+ 
+     window = XCreateWindow(display, root, 0, 0, image_width, image_height, 0,
+       depth, InputOutput, visual, attrmask, &attr);
+ 
+     if (window == None) {
+         fprintf(stderr, "XCreateWindow() failed\n");
+         return 2;
+     } else
+         have_window = TRUE;
+ 
+     if (depth == 8)
+         XSetWindowColormap(display, window, colormap);
+ 
+     if (!XStringListToTextProperty(&window_name, 1, pWindowName))
+         pWindowName = NULL;
+     if (!XStringListToTextProperty(&icon_name, 1, pIconName))
+         pIconName = NULL;
+ 
+     /* OK if either hints allocation fails; XSetWMProperties() allows NULLs */
+ 
+     if ((size_hints = XAllocSizeHints()) != NULL) {
+         /* window will not be resizable */
+         size_hints->flags = PMinSize | PMaxSize;
+         size_hints->min_width = size_hints->max_width = (int)image_width;
+         size_hints->min_height = size_hints->max_height = (int)image_height;
+     }
+ 
+     if ((wm_hints = XAllocWMHints()) != NULL) {
+         wm_hints->initial_state = NormalState;
+         wm_hints->input = True;
+      /* wm_hints->icon_pixmap = icon_pixmap; */
+         wm_hints->flags = StateHint | InputHint  /* | IconPixmapHint */ ;
+     }
+ 
+     XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0,
+       size_hints, wm_hints, NULL);
+ 
+     /* various properties and hints no longer needed; free memory */
+     if (pWindowName)
+        XFree(pWindowName->value);
+     if (pIconName)
+        XFree(pIconName->value);
+     if (size_hints)
+         XFree(size_hints);
+     if (wm_hints)
+        XFree(wm_hints);
+ 
+     XMapWindow(display, window);
+ 
+     gc = XCreateGC(display, window, 0, &gcvalues);
+     have_gc = TRUE;
+ 
+ /*---------------------------------------------------------------------------
+     Fill window with the specified background color.
+   ---------------------------------------------------------------------------*/
+ 
+     if (depth == 24 || depth == 32) {
+         bg_pixel = ((ulg)bg_red   << RShift) |
+                    ((ulg)bg_green << GShift) |
+                    ((ulg)bg_blue  << BShift);
+     } else if (depth == 16) {
+         bg_pixel = ((((ulg)bg_red   << 8) >> RShift) & RMask) |
+                    ((((ulg)bg_green << 8) >> GShift) & GMask) |
+                    ((((ulg)bg_blue  << 8) >> BShift) & BMask);
+     } else /* depth == 8 */ {
+ 
+         /* GRR:  add 8-bit support */
+ 
+     }
+ 
+     XSetForeground(display, gc, bg_pixel);
+     XFillRectangle(display, window, gc, 0, 0, image_width, image_height);
+ 
+ /*---------------------------------------------------------------------------
+     Wait for first Expose event to do any drawing, then flush.
+   ---------------------------------------------------------------------------*/
+ 
+     do
+         XNextEvent(display, &e);
+     while (e.type != Expose || e.xexpose.count);
+ 
+     XFlush(display);
+ 
+ /*---------------------------------------------------------------------------
+     Allocate memory for the X- and display-specific version of the image.
+   ---------------------------------------------------------------------------*/
+ 
+     if (depth == 24 || depth == 32) {
+         xdata = (uch *)malloc(4*image_width*image_height);
+         pad = 32;
+     } else if (depth == 16) {
+         xdata = (uch *)malloc(2*image_width*image_height);
+         pad = 16;
+     } else /* depth == 8 */ {
+         xdata = (uch *)malloc(image_width*image_height);
+         pad = 8;
+     }
+ 
+     if (!xdata) {
+         fprintf(stderr, PROGNAME ":  unable to allocate image memory\n");
+         return 4;
+     }
+ 
+     ximage = XCreateImage(display, visual, depth, ZPixmap, 0,
+       (char *)xdata, image_width, image_height, pad, 0);
+ 
+     if (!ximage) {
+         fprintf(stderr, PROGNAME ":  XCreateImage() failed\n");
+         free(xdata);
+         return 3;
+     }
+ 
+     /* to avoid testing the byte order every pixel (or doubling the size of
+      * the drawing routine with a giant if-test), we arbitrarily set the byte
+      * order to MSBFirst and let Xlib worry about inverting things on little-
+      * endian machines (like Linux/x86, old VAXen, etc.)--this is not the most
+      * efficient approach (the giant if-test would be better), but in the
+      * interest of clarity, we take the easy way out... */
+ 
+     ximage->byte_order = MSBFirst;
+ 
+     return 0;
+ 
+ } /* end function rpng_x_create_window() */
+ 
+ 
+ 
+ 
+ 
+ static int rpng_x_display_image(void)
+ {
+     uch *src;
+     char *dest;
+     uch r, g, b, a;
+     ulg i, row, lastrow = 0;
+     ulg pixel;
+     int ximage_rowbytes = ximage->bytes_per_line;
+ /*  int bpp = ximage->bits_per_pixel;  */
+ 
+ 
+     Trace((stderr, "beginning display loop (image_channels == %d)\n",
+       image_channels))
+     Trace((stderr, "   (width = %ld, rowbytes = %ld, ximage_rowbytes = %d)\n",
+       image_width, image_rowbytes, ximage_rowbytes))
+     Trace((stderr, "   (bpp = %d)\n", ximage->bits_per_pixel))
+     Trace((stderr, "   (byte_order = %s)\n", ximage->byte_order == MSBFirst?
+       "MSBFirst" : (ximage->byte_order == LSBFirst? "LSBFirst" : "unknown")))
+ 
+     if (depth == 24 || depth == 32) {
+         ulg red, green, blue;
+ 
+         for (lastrow = row = 0;  row < image_height;  ++row) {
+             src = image_data + row*image_rowbytes;
+             dest = ximage->data + row*ximage_rowbytes;
+             if (image_channels == 3) {
+                 for (i = image_width;  i > 0;  --i) {
+                     red   = *src++;
+                     green = *src++;
+                     blue  = *src++;
+ #ifdef NO_24BIT_MASKS
+                     pixel = (red   << RShift) |
+                             (green << GShift) |
+                             (blue  << BShift);
+                     /* recall that we set ximage->byte_order = MSBFirst above */
+                     /* GRR BUG:  this assumes bpp == 32, but may be 24: */
+                     *dest++ = (char)((pixel >> 24) & 0xff);
+                     *dest++ = (char)((pixel >> 16) & 0xff);
+                     *dest++ = (char)((pixel >>  8) & 0xff);
+                     *dest++ = (char)( pixel        & 0xff);
+ #else
+                     red   = (RShift < 0)? red   << (-RShift) : red   >> RShift;
+                     green = (GShift < 0)? green << (-GShift) : green >> GShift;
+                     blue  = (BShift < 0)? blue  << (-BShift) : blue  >> BShift;
+                     pixel = (red & RMask) | (green & GMask) | (blue & BMask);
+                     /* recall that we set ximage->byte_order = MSBFirst above */
+                     *dest++ = (char)((pixel >> 24) & 0xff);
+                     *dest++ = (char)((pixel >> 16) & 0xff);
+                     *dest++ = (char)((pixel >>  8) & 0xff);
+                     *dest++ = (char)( pixel        & 0xff);
+ #endif
+                 }
+             } else /* if (image_channels == 4) */ {
+                 for (i = image_width;  i > 0;  --i) {
+                     r = *src++;
+                     g = *src++;
+                     b = *src++;
+                     a = *src++;
+                     if (a == 255) {
+                         red   = r;
+                         green = g;
+                         blue  = b;
+                     } else if (a == 0) {
+                         red   = bg_red;
+                         green = bg_green;
+                         blue  = bg_blue;
+                     } else {
+                         /* this macro (from png.h) composites the foreground
+                          * and background values and puts the result into the
+                          * first argument */
+                         alpha_composite(red,   r, a, bg_red);
+                         alpha_composite(green, g, a, bg_green);
+                         alpha_composite(blue,  b, a, bg_blue);
+                     }
+                     pixel = (red   << RShift) |
+                             (green << GShift) |
+                             (blue  << BShift);
+                     /* recall that we set ximage->byte_order = MSBFirst above */
+                     *dest++ = (char)((pixel >> 24) & 0xff);
+                     *dest++ = (char)((pixel >> 16) & 0xff);
+                     *dest++ = (char)((pixel >>  8) & 0xff);
+                     *dest++ = (char)( pixel        & 0xff);
+                 }
+             }
+             /* display after every 16 lines */
+             if (((row+1) & 0xf) == 0) {
+                 XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
+                   (int)lastrow, image_width, 16);
+                 XFlush(display);
+                 lastrow = row + 1;
+             }
+         }
+ 
+     } else if (depth == 16) {
+         ush red, green, blue;
+ 
+         for (lastrow = row = 0;  row < image_height;  ++row) {
+             src = image_data + row*image_rowbytes;
+             dest = ximage->data + row*ximage_rowbytes;
+             if (image_channels == 3) {
+                 for (i = image_width;  i > 0;  --i) {
+                     red   = ((ush)(*src) << 8);
+                     ++src;
+                     green = ((ush)(*src) << 8);
+                     ++src;
+                     blue  = ((ush)(*src) << 8);
+                     ++src;
+                     pixel = ((red   >> RShift) & RMask) |
+                             ((green >> GShift) & GMask) |
+                             ((blue  >> BShift) & BMask);
+                     /* recall that we set ximage->byte_order = MSBFirst above */
+                     *dest++ = (char)((pixel >>  8) & 0xff);
+                     *dest++ = (char)( pixel        & 0xff);
+                 }
+             } else /* if (image_channels == 4) */ {
+                 for (i = image_width;  i > 0;  --i) {
+                     r = *src++;
+                     g = *src++;
+                     b = *src++;
+                     a = *src++;
+                     if (a == 255) {
+                         red   = ((ush)r << 8);
+                         green = ((ush)g << 8);
+                         blue  = ((ush)b << 8);
+                     } else if (a == 0) {
+                         red   = ((ush)bg_red   << 8);
+                         green = ((ush)bg_green << 8);
+                         blue  = ((ush)bg_blue  << 8);
+                     } else {
+                         /* this macro (from png.h) composites the foreground
+                          * and background values and puts the result back into
+                          * the first argument (== fg byte here:  safe) */
+                         alpha_composite(r, r, a, bg_red);
+                         alpha_composite(g, g, a, bg_green);
+                         alpha_composite(b, b, a, bg_blue);
+                         red   = ((ush)r << 8);
+                         green = ((ush)g << 8);
+                         blue  = ((ush)b << 8);
+                     }
+                     pixel = ((red   >> RShift) & RMask) |
+                             ((green >> GShift) & GMask) |
+                             ((blue  >> BShift) & BMask);
+                     /* recall that we set ximage->byte_order = MSBFirst above */
+                     *dest++ = (char)((pixel >>  8) & 0xff);
+                     *dest++ = (char)( pixel        & 0xff);
+                 }
+             }
+             /* display after every 16 lines */
+             if (((row+1) & 0xf) == 0) {
+                 XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
+                   (int)lastrow, image_width, 16);
+                 XFlush(display);
+                 lastrow = row + 1;
+             }
+         }
+ 
+     } else /* depth == 8 */ {
+ 
+         /* GRR:  add 8-bit support */
+ 
+     }
+ 
+     Trace((stderr, "calling final XPutImage()\n"))
+     if (lastrow < image_height) {
+         XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
+           (int)lastrow, image_width, image_height-lastrow);
+         XFlush(display);
+     }
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ static void rpng_x_cleanup(void)
+ {
+     if (image_data) {
+         free(image_data);
+         image_data = NULL;
+     }
+ 
+     if (ximage) {
+         if (ximage->data) {
+             free(ximage->data);           /* we allocated it, so we free it */
+             ximage->data = (char *)NULL;  /*  instead of XDestroyImage() */
+         }
+         XDestroyImage(ximage);
+         ximage = NULL;
+     }
+ 
+     if (have_gc)
+         XFreeGC(display, gc);
+ 
+     if (have_window)
+         XDestroyWindow(display, window);
+ 
+     if (have_colormap)
+         XFreeColormap(display, colormap);
+ 
+     if (have_nondefault_visual)
+         XFree(visual_list);
+ }
+ 
+ 
+ 
+ 
+ 
+ static int rpng_x_msb(ulg u32val)
+ {
+     int i;
+ 
+     for (i = 31;  i >= 0;  --i) {
+         if (u32val & 0x80000000L)
+             break;
+         u32val <<= 1;
+     }
+     return i;
+ }


Index: llvm/runtime/libpng/contrib/gregbook/rpng2-win.c
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/rpng2-win.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:56 2004
--- llvm/runtime/libpng/contrib/gregbook/rpng2-win.c	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,1166 ----
+ /*---------------------------------------------------------------------------
+ 
+    rpng2 - progressive-model PNG display program                rpng2-win.c
+ 
+    This program decodes and displays PNG files progressively, as if it were
+    a web browser (though the front end is only set up to read from files).
+    It supports gamma correction, user-specified background colors, and user-
+    specified background patterns (for transparent images).  This version is
+    for 32-bit Windows; it may compile under 16-bit Windows with a little
+    tweaking (or maybe not).  Thanks to Adam Costello and Pieter S. van der
+    Meulen for the "diamond" and "radial waves" patterns, respectively.
+ 
+    to do:
+     - handle quoted command-line args (especially filenames with spaces)
+     - finish resizable checkerboard-gradient (sizes 4-128?)
+     - use %.1023s to simplify truncation of title-bar string?
+     - have minimum window width:  oh well
+ 
+   ---------------------------------------------------------------------------
+ 
+    Changelog:
+     - 1.01:  initial public release
+     - 1.02:  fixed cut-and-paste error in usage screen (oops...)
+     - 1.03:  modified to allow abbreviated options
+     - 1.04:  removed bogus extra argument from usage fprintf() [Glenn R-P?];
+               fixed command-line parsing bug
+     - 1.10:  enabled "message window"/console (thanks to David Geldreich)
+     - 1.20:  added runtime MMX-enabling/disabling and new -mmx* options
+     - 1.21:  made minor tweak to usage screen to fit within 25-line console
+ 
+   ---------------------------------------------------------------------------
+ 
+       Copyright (c) 1998-2001 Greg Roelofs.  All rights reserved.
+ 
+       This software is provided "as is," without warranty of any kind,
+       express or implied.  In no event shall the author or contributors
+       be held liable for any damages arising in any way from the use of
+       this software.
+ 
+       Permission is granted to anyone to use this software for any purpose,
+       including commercial applications, and to alter it and redistribute
+       it freely, subject to the following restrictions:
+ 
+       1. Redistributions of source code must retain the above copyright
+          notice, disclaimer, and this list of conditions.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, disclaimer, and this list of conditions in the documenta-
+          tion and/or other materials provided with the distribution.
+       3. All advertising materials mentioning features or use of this
+          software must display the following acknowledgment:
+ 
+             This product includes software developed by Greg Roelofs
+             and contributors for the book, "PNG: The Definitive Guide,"
+             published by O'Reilly and Associates.
+ 
+   ---------------------------------------------------------------------------*/
+ 
+ #define PROGNAME  "rpng2-win"
+ #define LONGNAME  "Progressive PNG Viewer for Windows"
+ #define VERSION   "1.21 of 29 June 2001"
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <setjmp.h>    /* for jmpbuf declaration in readpng2.h */
+ #include <time.h>
+ #include <math.h>      /* only for PvdM background code */
+ #include <windows.h>
+ #include <conio.h>     /* only for _getch() */
+ 
+ /* all for PvdM background code: */
+ #ifndef PI
+ #  define PI             3.141592653589793238
+ #endif
+ #define PI_2             (PI*0.5)
+ #define INV_PI_360       (360.0 / PI)
+ #define MAX(a,b)         (a>b?a:b)
+ #define MIN(a,b)         (a<b?a:b)
+ #define CLIP(a,min,max)  MAX(min,MIN((a),max))
+ #define ABS(a)           ((a)<0?-(a):(a))
+ #define CLIP8P(c)        MAX(0,(MIN((c),255)))   /* 8-bit pos. integer (uch) */
+ #define ROUNDF(f)        ((int)(f + 0.5))
+ 
+ #define rgb1_max   bg_freq
+ #define rgb1_min   bg_gray
+ #define rgb2_max   bg_bsat
+ #define rgb2_min   bg_brot
+ 
+ /* #define DEBUG */     /* this enables the Trace() macros */
+ 
+ #include "readpng2.h"   /* typedefs, common macros, readpng2 prototypes */
+ 
+ 
+ /* could just include png.h, but this macro is the only thing we need
+  * (name and typedefs changed to local versions); note that side effects
+  * only happen with alpha (which could easily be avoided with
+  * "ush acopy = (alpha);") */
+ 
+ #define alpha_composite(composite, fg, alpha, bg) {               \
+     ush temp = ((ush)(fg)*(ush)(alpha) +                          \
+                 (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128);  \
+     (composite) = (uch)((temp + (temp >> 8)) >> 8);               \
+ }
+ 
+ 
+ #define INBUFSIZE 4096   /* with pseudo-timing on (1 sec delay/block), this
+                           *  block size corresponds roughly to a download
+                           *  speed 10% faster than theoretical 33.6K maximum
+                           *  (assuming 8 data bits, 1 stop bit and no other
+                           *  overhead) */
+ 
+ /* local prototypes */
+ static void       rpng2_win_init(void);
+ static int        rpng2_win_create_window(void);
+ static int        rpng2_win_load_bg_image(void);
+ static void       rpng2_win_display_row(ulg row);
+ static void       rpng2_win_finish_display(void);
+ static void       rpng2_win_cleanup(void);
+ LRESULT CALLBACK  rpng2_win_wndproc(HWND, UINT, WPARAM, LPARAM);
+ 
+ 
+ static char titlebar[1024], *window_name = titlebar;
+ static char *progname = PROGNAME;
+ static char *appname = LONGNAME;
+ static char *icon_name = PROGNAME;    /* GRR:  not (yet) used */
+ static char *filename;
+ static FILE *infile;
+ 
+ static mainprog_info rpng2_info;
+ 
+ static uch inbuf[INBUFSIZE];
+ static int incount;
+ 
+ static int pat = 6;         /* must be less than num_bgpat */
+ static int bg_image = 0;
+ static int bgscale = 16;
+ static ulg bg_rowbytes;
+ static uch *bg_data;
+ 
+ static struct rgb_color {
+     uch r, g, b;
+ } rgb[] = {
+     {  0,   0,   0},    /*  0:  black */
+     {255, 255, 255},    /*  1:  white */
+     {173, 132,  57},    /*  2:  tan */
+     { 64, 132,   0},    /*  3:  medium green */
+     {189, 117,   1},    /*  4:  gold */
+     {253, 249,   1},    /*  5:  yellow */
+     {  0,   0, 255},    /*  6:  blue */
+     {  0,   0, 120},    /*  7:  medium blue */
+     {255,   0, 255},    /*  8:  magenta */
+     { 64,   0,  64},    /*  9:  dark magenta */
+     {255,   0,   0},    /* 10:  red */
+     { 64,   0,   0},    /* 11:  dark red */
+     {255, 127,   0},    /* 12:  orange */
+     {192,  96,   0},    /* 13:  darker orange */
+     { 24,  60,   0},    /* 14:  dark green-yellow */
+     { 85, 125, 200}     /* 15:  ice blue */
+ };
+ /* not used for now, but should be for error-checking:
+ static int num_rgb = sizeof(rgb) / sizeof(struct rgb_color);
+  */
+ 
+ /*
+     This whole struct is a fairly cheesy way to keep the number of
+     command-line options to a minimum.  The radial-waves background
+     type is a particularly poor fit to the integer elements of the
+     struct...but a few macros and a little fixed-point math will do
+     wonders for ya.
+ 
+     type bits:
+        F E D C B A 9 8 7 6 5 4 3 2 1 0
+                              | | | | |
+                              | | +-+-+-- 0 = sharp-edged checkerboard
+                              | |         1 = soft diamonds
+                              | |         2 = radial waves
+                              | |       3-7 = undefined
+                              | +-- gradient #2 inverted?
+                              +-- alternating columns inverted?
+  */
+ static struct background_pattern {
+     ush type;
+     int rgb1_max, rgb1_min;     /* or bg_freq, bg_gray */
+     int rgb2_max, rgb2_min;     /* or bg_bsat, bg_brot (both scaled by 10)*/
+ } bg[] = {
+     {0+8,   2,0,  1,15},        /* checkered:  tan/black vs. white/ice blue */
+     {0+24,  2,0,  1,0},         /* checkered:  tan/black vs. white/black */
+     {0+8,   4,5,  0,2},         /* checkered:  gold/yellow vs. black/tan */
+     {0+8,   4,5,  0,6},         /* checkered:  gold/yellow vs. black/blue */
+     {0,     7,0,  8,9},         /* checkered:  deep blue/black vs. magenta */
+     {0+8,  13,0,  5,14},        /* checkered:  orange/black vs. yellow */
+     {0+8,  12,0, 10,11},        /* checkered:  orange/black vs. red */
+     {1,     7,0,  8,0},         /* diamonds:  deep blue/black vs. magenta */
+     {1,    12,0, 11,0},         /* diamonds:  orange vs. dark red */
+     {1,    10,0,  7,0},         /* diamonds:  red vs. medium blue */
+     {1,     4,0,  5,0},         /* diamonds:  gold vs. yellow */
+     {1,     3,0,  0,0},         /* diamonds:  medium green vs. black */
+     {2,    16, 100,  20,   0},  /* radial:  ~hard radial color-beams */
+     {2,    18, 100,  10,   2},  /* radial:  soft, curved radial color-beams */
+     {2,    16, 256, 100, 250},  /* radial:  very tight spiral */
+     {2, 10000, 256,  11,   0}   /* radial:  dipole-moire' (almost fractal) */
+ };
+ static int num_bgpat = sizeof(bg) / sizeof(struct background_pattern);
+ 
+ 
+ /* Windows-specific global variables (could go in struct, but messy...) */
+ static ulg wimage_rowbytes;
+ static uch *dib;
+ static uch *wimage_data;
+ static BITMAPINFOHEADER *bmih;
+ 
+ static HWND global_hwnd;
+ static HINSTANCE global_hInst;
+ static int global_showmode;
+ 
+ 
+ 
+ 
+ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode)
+ {
+     char *args[1024];                 /* arbitrary limit, but should suffice */
+     char **argv = args;
+     char *p, *q, *bgstr = NULL;
+     int argc = 0;
+     int rc, alen, flen;
+     int error = 0;
+     int timing = FALSE;
+     int have_bg = FALSE;
+     double LUT_exponent;              /* just the lookup table */
+     double CRT_exponent = 2.2;        /* just the monitor */
+     double default_display_exponent;  /* whole display system */
+     MSG msg;
+ 
+ 
+     /* First initialize a few things, just to be sure--memset takes care of
+      * default background color (black), booleans (FALSE), pointers (NULL),
+      * etc. */
+ 
+     global_hInst = hInst;
+     global_showmode = showmode;
+     filename = (char *)NULL;
+     memset(&rpng2_info, 0, sizeof(mainprog_info));
+ 
+ 
+     /* Next reenable console output, which normally goes to the bit bucket
+      * for windowed apps.  Closing the console window will terminate the
+      * app.  Thanks to David.Geldreich at realviz.com for supplying the magical
+      * incantation. */
+ 
+     AllocConsole();
+     freopen("CONOUT$", "a", stderr);
+     freopen("CONOUT$", "a", stdout);
+ 
+ 
+     /* Set the default value for our display-system exponent, i.e., the
+      * product of the CRT exponent and the exponent corresponding to
+      * the frame-buffer's lookup table (LUT), if any.  This is not an
+      * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
+      * ones), but it should cover 99% of the current possibilities.  And
+      * yes, these ifdefs are completely wasted in a Windows program... */
+ 
+ #if defined(NeXT)
+     /* third-party utilities can modify the default LUT exponent */
+     LUT_exponent = 1.0 / 2.2;
+     /*
+     if (some_next_function_that_returns_gamma(&next_gamma))
+         LUT_exponent = 1.0 / next_gamma;
+      */
+ #elif defined(sgi)
+     LUT_exponent = 1.0 / 1.7;
+     /* there doesn't seem to be any documented function to
+      * get the "gamma" value, so we do it the hard way */
+     infile = fopen("/etc/config/system.glGammaVal", "r");
+     if (infile) {
+         double sgi_gamma;
+ 
+         fgets(tmpline, 80, infile);
+         fclose(infile);
+         sgi_gamma = atof(tmpline);
+         if (sgi_gamma > 0.0)
+             LUT_exponent = 1.0 / sgi_gamma;
+     }
+ #elif defined(Macintosh)
+     LUT_exponent = 1.8 / 2.61;
+     /*
+     if (some_mac_function_that_returns_gamma(&mac_gamma))
+         LUT_exponent = mac_gamma / 2.61;
+      */
+ #else
+     LUT_exponent = 1.0;   /* assume no LUT:  most PCs */
+ #endif
+ 
+     /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
+     default_display_exponent = LUT_exponent * CRT_exponent;
+ 
+ 
+     /* If the user has set the SCREEN_GAMMA environment variable as suggested
+      * (somewhat imprecisely) in the libpng documentation, use that; otherwise
+      * use the default value we just calculated.  Either way, the user may
+      * override this via a command-line option. */
+ 
+     if ((p = getenv("SCREEN_GAMMA")) != NULL)
+         rpng2_info.display_exponent = atof(p);
+     else
+         rpng2_info.display_exponent = default_display_exponent;
+ 
+ 
+     /* Windows really hates command lines, so we have to set up our own argv.
+      * Note that we do NOT bother with quoted arguments here, so don't use
+      * filenames with spaces in 'em! */
+ 
+     argv[argc++] = PROGNAME;
+     p = cmd;
+     for (;;) {
+         if (*p == ' ')
+             while (*++p == ' ')
+                 ;
+         /* now p points at the first non-space after some spaces */
+         if (*p == '\0')
+             break;    /* nothing after the spaces:  done */
+         argv[argc++] = q = p;
+         while (*q && *q != ' ')
+             ++q;
+         /* now q points at a space or the end of the string */
+         if (*q == '\0')
+             break;    /* last argv already terminated; quit */
+         *q = '\0';    /* change space to terminator */
+         p = q + 1;
+     }
+     argv[argc] = NULL;   /* terminate the argv array itself */
+ 
+ 
+     /* Now parse the command line for options and the PNG filename. */
+ 
+     while (*++argv && !error) {
+         if (!strncmp(*argv, "-gamma", 2)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 rpng2_info.display_exponent = atof(*argv);
+                 if (rpng2_info.display_exponent <= 0.0)
+                     ++error;
+             }
+         } else if (!strncmp(*argv, "-bgcolor", 4)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 bgstr = *argv;
+                 if (strlen(bgstr) != 7 || bgstr[0] != '#')
+                     ++error;
+                 else {
+                     have_bg = TRUE;
+                     bg_image = FALSE;
+                 }
+             }
+         } else if (!strncmp(*argv, "-bgpat", 4)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 pat = atoi(*argv) - 1;
+                 if (pat < 0 || pat >= num_bgpat)
+                     ++error;
+                 else {
+                     bg_image = TRUE;
+                     have_bg = FALSE;
+                 }
+             }
+         } else if (!strncmp(*argv, "-timing", 2)) {
+             timing = TRUE;
+ #if (defined(__i386__) || defined(_M_IX86))
+         } else if (!strncmp(*argv, "-nommxfilters", 7)) {
+             rpng2_info.nommxfilters = TRUE;
+         } else if (!strncmp(*argv, "-nommxcombine", 7)) {
+             rpng2_info.nommxcombine = TRUE;
+         } else if (!strncmp(*argv, "-nommxinterlace", 7)) {
+             rpng2_info.nommxinterlace = TRUE;
+         } else if (!strcmp(*argv, "-nommx")) {
+             rpng2_info.nommxfilters = TRUE;
+             rpng2_info.nommxcombine = TRUE;
+             rpng2_info.nommxinterlace = TRUE;
+ #endif
+         } else {
+             if (**argv != '-') {
+                 filename = *argv;
+                 if (argv[1])   /* shouldn't be any more args after filename */
+                     ++error;
+             } else
+                 ++error;   /* not expecting any other options */
+         }
+     }
+ 
+     if (!filename) {
+         ++error;
+     } else if (!(infile = fopen(filename, "rb"))) {
+         fprintf(stderr, PROGNAME ":  can't open PNG file [%s]\n", filename);
+         ++error;
+     } else {
+         incount = fread(inbuf, 1, INBUFSIZE, infile);
+         if (incount < 8 || !readpng2_check_sig(inbuf, 8)) {
+             fprintf(stderr, PROGNAME
+               ":  [%s] is not a PNG file: incorrect signature\n",
+               filename);
+             ++error;
+         } else if ((rc = readpng2_init(&rpng2_info)) != 0) {
+             switch (rc) {
+                 case 2:
+                     fprintf(stderr, PROGNAME
+                       ":  [%s] has bad IHDR (libpng longjmp)\n",
+                       filename);
+                     break;
+                 case 4:
+                     fprintf(stderr, PROGNAME ":  insufficient memory\n");
+                     break;
+                 default:
+                     fprintf(stderr, PROGNAME
+                       ":  unknown readpng2_init() error\n");
+                     break;
+             }
+             ++error;
+         }
+         if (error)
+             fclose(infile);
+     }
+ 
+ 
+     /* usage screen */
+ 
+     if (error) {
+         int ch;
+ 
+         fprintf(stderr, "\n%s %s:  %s\n\n", PROGNAME, VERSION, appname);
+         readpng2_version_info();
+         fprintf(stderr, "\n"
+           "Usage:  %s [-gamma exp] [-bgcolor bg | -bgpat pat] [-timing]\n"
+ #if (defined(__i386__) || defined(_M_IX86))
+           "        %*s [[-nommxfilters] [-nommxcombine] [-nommxinterlace] | -nommx]\n"
+ #endif
+           "        %*s file.png\n\n"
+           "    exp \ttransfer-function exponent (``gamma'') of the display\n"
+           "\t\t  system in floating-point format (e.g., ``%.1f''); equal\n"
+           "\t\t  to the product of the lookup-table exponent (varies)\n"
+           "\t\t  and the CRT exponent (usually 2.2); must be positive\n"
+           "    bg  \tdesired background color in 7-character hex RGB format\n"
+           "\t\t  (e.g., ``#ff7700'' for orange:  same as HTML colors);\n"
+           "\t\t  used with transparent images; overrides -bgpat option\n"
+           "    pat \tdesired background pattern number (1-%d); used with\n"
+           "\t\t  transparent images; overrides -bgcolor option\n"
+           "    -timing\tenables delay for every block read, to simulate modem\n"
+           "\t\t  download of image (~36 Kbps)\n"
+ #if (defined(__i386__) || defined(_M_IX86))
+           "    -nommx*\tdisable optimized MMX routines for decoding row filters,\n"
+           "\t\t  combining rows, and expanding interlacing, respectively\n"
+ #endif
+           "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n"
+           "Press Q or Esc to quit this usage screen. ",
+           PROGNAME,
+ #if (defined(__i386__) || defined(_M_IX86))
+           strlen(PROGNAME), " ",
+ #endif
+           strlen(PROGNAME), " ", default_display_exponent, num_bgpat);
+         fflush(stderr);
+         do
+             ch = _getch();
+         while (ch != 'q' && ch != 'Q' && ch != 0x1B);
+         exit(1);
+     } else {
+         fprintf(stderr, "\n%s %s:  %s\n", PROGNAME, VERSION, appname);
+         fprintf(stderr,
+           "\n   [console window:  closing this window will terminate %s]\n\n",
+           PROGNAME);
+         fflush(stderr);
+     }
+ 
+ 
+     /* set the title-bar string, but make sure buffer doesn't overflow */
+ 
+     alen = strlen(appname);
+     flen = strlen(filename);
+     if (alen + flen + 3 > 1023)
+         sprintf(titlebar, "%s:  ...%s", appname, filename+(alen+flen+6-1023));
+     else
+         sprintf(titlebar, "%s:  %s", appname, filename);
+ 
+ 
+     /* set some final rpng2_info variables before entering main data loop */
+ 
+     if (have_bg) {
+         unsigned r, g, b;   /* this approach quiets compiler warnings */
+ 
+         sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
+         rpng2_info.bg_red   = (uch)r;
+         rpng2_info.bg_green = (uch)g;
+         rpng2_info.bg_blue  = (uch)b;
+     } else
+         rpng2_info.need_bgcolor = TRUE;
+ 
+     rpng2_info.done = FALSE;
+     rpng2_info.mainprog_init = rpng2_win_init;
+     rpng2_info.mainprog_display_row = rpng2_win_display_row;
+     rpng2_info.mainprog_finish_display = rpng2_win_finish_display;
+ 
+ 
+     /* OK, this is the fun part:  call readpng2_decode_data() at the start of
+      * the loop to deal with our first buffer of data (read in above to verify
+      * that the file is a PNG image), then loop through the file and continue
+      * calling the same routine to handle each chunk of data.  It in turn
+      * passes the data to libpng, which will invoke one or more of our call-
+      * backs as decoded data become available.  We optionally call Sleep() for
+      * one second per iteration to simulate downloading the image via an analog
+      * modem. */
+ 
+     for (;;) {
+         Trace((stderr, "about to call readpng2_decode_data()\n"))
+         if (readpng2_decode_data(&rpng2_info, inbuf, incount))
+             ++error;
+         Trace((stderr, "done with readpng2_decode_data()\n"))
+         if (error || feof(infile) || rpng2_info.done)
+             break;
+         if (timing)
+             Sleep(1000L);
+         incount = fread(inbuf, 1, INBUFSIZE, infile);
+     }
+ 
+ 
+     /* clean up PNG stuff and report any decoding errors */
+ 
+     fclose(infile);
+     Trace((stderr, "about to call readpng2_cleanup()\n"))
+     readpng2_cleanup(&rpng2_info);
+ 
+     if (error) {
+         fprintf(stderr, PROGNAME ":  libpng error while decoding PNG image\n");
+         exit(3);
+     }
+ 
+ 
+     /* wait for the user to tell us when to quit */
+ 
+     while (GetMessage(&msg, NULL, 0, 0)) {
+         TranslateMessage(&msg);
+         DispatchMessage(&msg);
+     }
+ 
+ 
+     /* we're done:  clean up all image and Windows resources and go away */
+ 
+     Trace((stderr, "about to call rpng2_win_cleanup()\n"))
+     rpng2_win_cleanup();
+ 
+     return msg.wParam;
+ }
+ 
+ 
+ 
+ 
+ 
+ /* this function is called by readpng2_info_callback() in readpng2.c, which
+  * in turn is called by libpng after all of the pre-IDAT chunks have been
+  * read and processed--i.e., we now have enough info to finish initializing */
+ 
+ static void rpng2_win_init()
+ {
+     ulg i;
+     ulg rowbytes = rpng2_info.rowbytes;
+ 
+     Trace((stderr, "beginning rpng2_win_init()\n"))
+     Trace((stderr, "  rowbytes = %ld\n", rpng2_info.rowbytes))
+     Trace((stderr, "  width  = %ld\n", rpng2_info.width))
+     Trace((stderr, "  height = %ld\n", rpng2_info.height))
+ 
+     rpng2_info.image_data = (uch *)malloc(rowbytes * rpng2_info.height);
+     if (!rpng2_info.image_data) {
+         readpng2_cleanup(&rpng2_info);
+         return;
+     }
+ 
+     rpng2_info.row_pointers = (uch **)malloc(rpng2_info.height * sizeof(uch *));
+     if (!rpng2_info.row_pointers) {
+         free(rpng2_info.image_data);
+         rpng2_info.image_data = NULL;
+         readpng2_cleanup(&rpng2_info);
+         return;
+     }
+ 
+     for (i = 0;  i < rpng2_info.height;  ++i)
+         rpng2_info.row_pointers[i] = rpng2_info.image_data + i*rowbytes;
+ 
+ /*---------------------------------------------------------------------------
+     Do the basic Windows initialization stuff, make the window, and fill it
+     with the user-specified, file-specified or default background color.
+   ---------------------------------------------------------------------------*/
+ 
+     if (rpng2_win_create_window()) {
+         readpng2_cleanup(&rpng2_info);
+         return;
+     }
+ }
+ 
+ 
+ 
+ 
+ 
+ static int rpng2_win_create_window()
+ {
+     uch bg_red   = rpng2_info.bg_red;
+     uch bg_green = rpng2_info.bg_green;
+     uch bg_blue  = rpng2_info.bg_blue;
+     uch *dest;
+     int extra_width, extra_height;
+     ulg i, j;
+     WNDCLASSEX wndclass;
+     RECT rect;
+ 
+ 
+ /*---------------------------------------------------------------------------
+     Allocate memory for the display-specific version of the image (round up
+     to multiple of 4 for Windows DIB).
+   ---------------------------------------------------------------------------*/
+ 
+     wimage_rowbytes = ((3*rpng2_info.width + 3L) >> 2) << 2;
+ 
+     if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) +
+                               wimage_rowbytes*rpng2_info.height)))
+     {
+         return 4;   /* fail */
+     }
+ 
+ /*---------------------------------------------------------------------------
+     Initialize the DIB.  Negative height means to use top-down BMP ordering
+     (must be uncompressed, but that's what we want).  Bit count of 1, 4 or 8
+     implies a colormap of RGBX quads, but 24-bit BMPs just use B,G,R values
+     directly => wimage_data begins immediately after BMP header.
+   ---------------------------------------------------------------------------*/
+ 
+     memset(dib, 0, sizeof(BITMAPINFOHEADER));
+     bmih = (BITMAPINFOHEADER *)dib;
+     bmih->biSize = sizeof(BITMAPINFOHEADER);
+     bmih->biWidth = rpng2_info.width;
+     bmih->biHeight = -((long)rpng2_info.height);
+     bmih->biPlanes = 1;
+     bmih->biBitCount = 24;
+     bmih->biCompression = 0;
+     wimage_data = dib + sizeof(BITMAPINFOHEADER);
+ 
+ /*---------------------------------------------------------------------------
+     Fill window with the specified background color (default is black), but
+     defer loading faked "background image" until window is displayed (may be
+     slow to compute).  Data are in BGR order.
+   ---------------------------------------------------------------------------*/
+ 
+     if (bg_image) {   /* just fill with black for now */
+         memset(wimage_data, 0, wimage_rowbytes*rpng2_info.height);
+     } else {
+         for (j = 0;  j < rpng2_info.height;  ++j) {
+             dest = wimage_data + j*wimage_rowbytes;
+             for (i = rpng2_info.width;  i > 0;  --i) {
+                 *dest++ = bg_blue;
+                 *dest++ = bg_green;
+                 *dest++ = bg_red;
+             }
+         }
+     }
+ 
+ /*---------------------------------------------------------------------------
+     Set the window parameters.
+   ---------------------------------------------------------------------------*/
+ 
+     memset(&wndclass, 0, sizeof(wndclass));
+ 
+     wndclass.cbSize = sizeof(wndclass);
+     wndclass.style = CS_HREDRAW | CS_VREDRAW;
+     wndclass.lpfnWndProc = rpng2_win_wndproc;
+     wndclass.hInstance = global_hInst;
+     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+     wndclass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
+     wndclass.lpszMenuName = NULL;
+     wndclass.lpszClassName = progname;
+     wndclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+ 
+     RegisterClassEx(&wndclass);
+ 
+ /*---------------------------------------------------------------------------
+     Finally, create the window.
+   ---------------------------------------------------------------------------*/
+ 
+     extra_width  = 2*(GetSystemMetrics(SM_CXBORDER) +
+                       GetSystemMetrics(SM_CXDLGFRAME));
+     extra_height = 2*(GetSystemMetrics(SM_CYBORDER) +
+                       GetSystemMetrics(SM_CYDLGFRAME)) +
+                       GetSystemMetrics(SM_CYCAPTION);
+ 
+     global_hwnd = CreateWindow(progname, titlebar, WS_OVERLAPPEDWINDOW,
+       CW_USEDEFAULT, CW_USEDEFAULT, rpng2_info.width+extra_width,
+       rpng2_info.height+extra_height, NULL, NULL, global_hInst, NULL);
+ 
+     ShowWindow(global_hwnd, global_showmode);
+     UpdateWindow(global_hwnd);
+ 
+ /*---------------------------------------------------------------------------
+     Now compute the background image and display it.  If it fails (memory
+     allocation), revert to a plain background color.
+   ---------------------------------------------------------------------------*/
+ 
+     if (bg_image) {
+         static const char *msg = "Computing background image...";
+         int x, y, len = strlen(msg);
+         HDC hdc = GetDC(global_hwnd);
+         TEXTMETRIC tm;
+ 
+         GetTextMetrics(hdc, &tm);
+         x = (rpng2_info.width - len*tm.tmAveCharWidth)/2;
+         y = (rpng2_info.height - tm.tmHeight)/2;
+         SetBkMode(hdc, TRANSPARENT);
+         SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+         /* this can still begin out of bounds even if x is positive (???): */
+         TextOut(hdc, ((x < 0)? 0 : x), ((y < 0)? 0 : y), msg, len);
+         ReleaseDC(global_hwnd, hdc);
+ 
+         rpng2_win_load_bg_image();   /* resets bg_image if fails */
+     }
+ 
+     if (!bg_image) {
+         for (j = 0;  j < rpng2_info.height;  ++j) {
+             dest = wimage_data + j*wimage_rowbytes;
+             for (i = rpng2_info.width;  i > 0;  --i) {
+                 *dest++ = bg_blue;
+                 *dest++ = bg_green;
+                 *dest++ = bg_red;
+             }
+         }
+     }
+ 
+     rect.left = 0L;
+     rect.top = 0L;
+     rect.right = (LONG)rpng2_info.width;       /* possibly off by one? */
+     rect.bottom = (LONG)rpng2_info.height;     /* possibly off by one? */
+     InvalidateRect(global_hwnd, &rect, FALSE);
+     UpdateWindow(global_hwnd);                 /* similar to XFlush() */
+ 
+     return 0;
+ 
+ } /* end function rpng2_win_create_window() */
+ 
+ 
+ 
+ 
+ 
+ static int rpng2_win_load_bg_image()
+ {
+     uch *src, *dest;
+     uch r1, r2, g1, g2, b1, b2;
+     uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv;
+     int k, hmax, max;
+     int xidx, yidx, yidx_max = (bgscale-1);
+     int even_odd_vert, even_odd_horiz, even_odd;
+     int invert_gradient2 = (bg[pat].type & 0x08);
+     int invert_column;
+     ulg i, row;
+ 
+ /*---------------------------------------------------------------------------
+     Allocate buffer for fake background image to be used with transparent
+     images; if this fails, revert to plain background color.
+   ---------------------------------------------------------------------------*/
+ 
+     bg_rowbytes = 3 * rpng2_info.width;
+     bg_data = (uch *)malloc(bg_rowbytes * rpng2_info.height);
+     if (!bg_data) {
+         fprintf(stderr, PROGNAME
+           ":  unable to allocate memory for background image\n");
+         bg_image = 0;
+         return 1;
+     }
+ 
+ /*---------------------------------------------------------------------------
+     Vertical gradients (ramps) in NxN squares, alternating direction and
+     colors (N == bgscale).
+   ---------------------------------------------------------------------------*/
+ 
+     if ((bg[pat].type & 0x07) == 0) {
+         uch r1_min  = rgb[bg[pat].rgb1_min].r;
+         uch g1_min  = rgb[bg[pat].rgb1_min].g;
+         uch b1_min  = rgb[bg[pat].rgb1_min].b;
+         uch r2_min  = rgb[bg[pat].rgb2_min].r;
+         uch g2_min  = rgb[bg[pat].rgb2_min].g;
+         uch b2_min  = rgb[bg[pat].rgb2_min].b;
+         int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min;
+         int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min;
+         int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min;
+         int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min;
+         int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min;
+         int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min;
+ 
+         for (row = 0;  row < rpng2_info.height;  ++row) {
+             yidx = row % bgscale;
+             even_odd_vert = (row / bgscale) & 1;
+ 
+             r1 = r1_min + (r1_diff * yidx) / yidx_max;
+             g1 = g1_min + (g1_diff * yidx) / yidx_max;
+             b1 = b1_min + (b1_diff * yidx) / yidx_max;
+             r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max;
+             g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max;
+             b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max;
+ 
+             r2 = r2_min + (r2_diff * yidx) / yidx_max;
+             g2 = g2_min + (g2_diff * yidx) / yidx_max;
+             b2 = b2_min + (b2_diff * yidx) / yidx_max;
+             r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max;
+             g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max;
+             b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max;
+ 
+             dest = bg_data + row*bg_rowbytes;
+             for (i = 0;  i < rpng2_info.width;  ++i) {
+                 even_odd_horiz = (i / bgscale) & 1;
+                 even_odd = even_odd_vert ^ even_odd_horiz;
+                 invert_column =
+                   (even_odd_horiz && (bg[pat].type & 0x10));
+                 if (even_odd == 0) {         /* gradient #1 */
+                     if (invert_column) {
+                         *dest++ = r1_inv;
+                         *dest++ = g1_inv;
+                         *dest++ = b1_inv;
+                     } else {
+                         *dest++ = r1;
+                         *dest++ = g1;
+                         *dest++ = b1;
+                     }
+                 } else {                     /* gradient #2 */
+                     if ((invert_column && invert_gradient2) ||
+                         (!invert_column && !invert_gradient2))
+                     {
+                         *dest++ = r2;        /* not inverted or */
+                         *dest++ = g2;        /*  doubly inverted */
+                         *dest++ = b2;
+                     } else {
+                         *dest++ = r2_inv;
+                         *dest++ = g2_inv;    /* singly inverted */
+                         *dest++ = b2_inv;
+                     }
+                 }
+             }
+         }
+ 
+ /*---------------------------------------------------------------------------
+     Soft gradient-diamonds with scale = bgscale.  Code contributed by Adam
+     M. Costello.
+   ---------------------------------------------------------------------------*/
+ 
+     } else if ((bg[pat].type & 0x07) == 1) {
+ 
+         hmax = (bgscale-1)/2;   /* half the max weight of a color */
+         max = 2*hmax;           /* the max weight of a color */
+ 
+         r1 = rgb[bg[pat].rgb1_max].r;
+         g1 = rgb[bg[pat].rgb1_max].g;
+         b1 = rgb[bg[pat].rgb1_max].b;
+         r2 = rgb[bg[pat].rgb2_max].r;
+         g2 = rgb[bg[pat].rgb2_max].g;
+         b2 = rgb[bg[pat].rgb2_max].b;
+ 
+         for (row = 0;  row < rpng2_info.height;  ++row) {
+             yidx = row % bgscale;
+             if (yidx > hmax)
+                 yidx = bgscale-1 - yidx;
+             dest = bg_data + row*bg_rowbytes;
+             for (i = 0;  i < rpng2_info.width;  ++i) {
+                 xidx = i % bgscale;
+                 if (xidx > hmax)
+                     xidx = bgscale-1 - xidx;
+                 k = xidx + yidx;
+                 *dest++ = (k*r1 + (max-k)*r2) / max;
+                 *dest++ = (k*g1 + (max-k)*g2) / max;
+                 *dest++ = (k*b1 + (max-k)*b2) / max;
+             }
+         }
+ 
+ /*---------------------------------------------------------------------------
+     Radial "starburst" with azimuthal sinusoids; [eventually number of sinu-
+     soids will equal bgscale?].  This one is slow but very cool.  Code con-
+     tributed by Pieter S. van der Meulen (originally in Smalltalk).
+   ---------------------------------------------------------------------------*/
+ 
+     } else if ((bg[pat].type & 0x07) == 2) {
+         uch ch;
+         int ii, x, y, hw, hh, grayspot;
+         double freq, rotate, saturate, gray, intensity;
+         double angle=0.0, aoffset=0.0, maxDist, dist;
+         double red=0.0, green=0.0, blue=0.0, hue, s, v, f, p, q, t;
+ 
+         fprintf(stderr, "%s:  computing radial background...",
+           PROGNAME);
+         fflush(stderr);
+ 
+         hh = rpng2_info.height / 2;
+         hw = rpng2_info.width / 2;
+ 
+         /* variables for radial waves:
+          *   aoffset:  number of degrees to rotate hue [CURRENTLY NOT USED]
+          *   freq:  number of color beams originating from the center
+          *   grayspot:  size of the graying center area (anti-alias)
+          *   rotate:  rotation of the beams as a function of radius
+          *   saturate:  saturation of beams' shape azimuthally
+          */
+         angle = CLIP(angle, 0.0, 360.0);
+         grayspot = CLIP(bg[pat].bg_gray, 1, (hh + hw));
+         freq = MAX((double)bg[pat].bg_freq, 0.0);
+         saturate = (double)bg[pat].bg_bsat * 0.1;
+         rotate = (double)bg[pat].bg_brot * 0.1;
+         gray = 0.0;
+         intensity = 0.0;
+         maxDist = (double)((hw*hw) + (hh*hh));
+ 
+         for (row = 0;  row < rpng2_info.height;  ++row) {
+             y = row - hh;
+             dest = bg_data + row*bg_rowbytes;
+             for (i = 0;  i < rpng2_info.width;  ++i) {
+                 x = i - hw;
+                 angle = (x == 0)? PI_2 : atan((double)y / (double)x);
+                 gray = (double)MAX(ABS(y), ABS(x)) / grayspot;
+                 gray = MIN(1.0, gray);
+                 dist = (double)((x*x) + (y*y)) / maxDist;
+                 intensity = cos((angle+(rotate*dist*PI)) * freq) *
+                   gray * saturate;
+                 intensity = (MAX(MIN(intensity,1.0),-1.0) + 1.0) * 0.5;
+                 hue = (angle + PI) * INV_PI_360 + aoffset;
+                 s = gray * ((double)(ABS(x)+ABS(y)) / (double)(hw + hh));
+                 s = MIN(MAX(s,0.0), 1.0);
+                 v = MIN(MAX(intensity,0.0), 1.0);
+ 
+                 if (s == 0.0) {
+                     ch = (uch)(v * 255.0);
+                     *dest++ = ch;
+                     *dest++ = ch;
+                     *dest++ = ch;
+                 } else {
+                     if ((hue < 0.0) || (hue >= 360.0))
+                         hue -= (((int)(hue / 360.0)) * 360.0);
+                     hue /= 60.0;
+                     ii = (int)hue;
+                     f = hue - (double)ii;
+                     p = (1.0 - s) * v;
+                     q = (1.0 - (s * f)) * v;
+                     t = (1.0 - (s * (1.0 - f))) * v;
+                     if      (ii == 0) { red = v; green = t; blue = p; }
+                     else if (ii == 1) { red = q; green = v; blue = p; }
+                     else if (ii == 2) { red = p; green = v; blue = t; }
+                     else if (ii == 3) { red = p; green = q; blue = v; }
+                     else if (ii == 4) { red = t; green = p; blue = v; }
+                     else if (ii == 5) { red = v; green = p; blue = q; }
+                     *dest++ = (uch)(red * 255.0);
+                     *dest++ = (uch)(green * 255.0);
+                     *dest++ = (uch)(blue * 255.0);
+                 }
+             }
+         }
+         fprintf(stderr, "done.\n");
+         fflush(stderr);
+     }
+ 
+ /*---------------------------------------------------------------------------
+     Blast background image to display buffer before beginning PNG decode;
+     calling function will handle invalidation and UpdateWindow() call.
+   ---------------------------------------------------------------------------*/
+ 
+     for (row = 0;  row < rpng2_info.height;  ++row) {
+         src = bg_data + row*bg_rowbytes;
+         dest = wimage_data + row*wimage_rowbytes;
+         for (i = rpng2_info.width;  i > 0;  --i) {
+             r1 = *src++;
+             g1 = *src++;
+             b1 = *src++;
+             *dest++ = b1;
+             *dest++ = g1;   /* note reverse order */
+             *dest++ = r1;
+         }
+     }
+ 
+     return 0;
+ 
+ } /* end function rpng2_win_load_bg_image() */
+ 
+ 
+ 
+ 
+ 
+ static void rpng2_win_display_row(ulg row)
+ {
+     uch bg_red   = rpng2_info.bg_red;
+     uch bg_green = rpng2_info.bg_green;
+     uch bg_blue  = rpng2_info.bg_blue;
+     uch *src, *src2=NULL, *dest;
+     uch r, g, b, a;
+     ulg i;
+     static int rows=0;
+     static ulg firstrow;
+ 
+ /*---------------------------------------------------------------------------
+     rows and firstrow simply track how many rows (and which ones) have not
+     yet been displayed; alternatively, we could call InvalidateRect() for
+     every row and not bother with the records-keeping.
+   ---------------------------------------------------------------------------*/
+ 
+     Trace((stderr, "beginning rpng2_win_display_row()\n"))
+ 
+     if (rows == 0)
+         firstrow = row;   /* first row not yet displayed */
+ 
+     ++rows;   /* count of rows received but not yet displayed */
+ 
+ /*---------------------------------------------------------------------------
+     Aside from the use of the rpng2_info struct and the lack of an outer
+     loop (over rows), this routine is identical to rpng_win_display_image()
+     in the non-progressive version of the program.
+   ---------------------------------------------------------------------------*/
+ 
+     src = rpng2_info.image_data + row*rpng2_info.rowbytes;
+     if (bg_image)
+         src2 = bg_data + row*bg_rowbytes;
+     dest = wimage_data + row*wimage_rowbytes;
+ 
+     if (rpng2_info.channels == 3) {
+         for (i = rpng2_info.width;  i > 0;  --i) {
+             r = *src++;
+             g = *src++;
+             b = *src++;
+             *dest++ = b;
+             *dest++ = g;   /* note reverse order */
+             *dest++ = r;
+         }
+     } else /* if (rpng2_info.channels == 4) */ {
+         for (i = rpng2_info.width;  i > 0;  --i) {
+             r = *src++;
+             g = *src++;
+             b = *src++;
+             a = *src++;
+             if (bg_image) {
+                 bg_red   = *src2++;
+                 bg_green = *src2++;
+                 bg_blue  = *src2++;
+             }
+             if (a == 255) {
+                 *dest++ = b;
+                 *dest++ = g;
+                 *dest++ = r;
+             } else if (a == 0) {
+                 *dest++ = bg_blue;
+                 *dest++ = bg_green;
+                 *dest++ = bg_red;
+             } else {
+                 /* this macro (copied from png.h) composites the
+                  * foreground and background values and puts the
+                  * result into the first argument; there are no
+                  * side effects with the first argument */
+                 alpha_composite(*dest++, b, a, bg_blue);
+                 alpha_composite(*dest++, g, a, bg_green);
+                 alpha_composite(*dest++, r, a, bg_red);
+             }
+         }
+     }
+ 
+ /*---------------------------------------------------------------------------
+     Display after every 16 rows or when on last row.  (Region may include
+     previously displayed lines due to interlacing--i.e., not contiguous.)
+   ---------------------------------------------------------------------------*/
+ 
+     if ((rows & 0xf) == 0 || row == rpng2_info.height-1) {
+         RECT rect;
+ 
+         rect.left = 0L;
+         rect.top = (LONG)firstrow;
+         rect.right = (LONG)rpng2_info.width;       /* possibly off by one? */
+         rect.bottom = (LONG)row + 1L;              /* possibly off by one? */
+         InvalidateRect(global_hwnd, &rect, FALSE);
+         UpdateWindow(global_hwnd);                 /* similar to XFlush() */
+         rows = 0;
+     }
+ 
+ } /* end function rpng2_win_display_row() */
+ 
+ 
+ 
+ 
+ 
+ static void rpng2_win_finish_display()
+ {
+     Trace((stderr, "beginning rpng2_win_finish_display()\n"))
+ 
+     /* last row has already been displayed by rpng2_win_display_row(), so
+      * we have nothing to do here except set a flag and let the user know
+      * that the image is done */
+ 
+     rpng2_info.done = TRUE;
+     printf(
+       "Done.  Press Q, Esc or mouse button 1 (within image window) to quit.\n");
+     fflush(stdout);
+ }
+ 
+ 
+ 
+ 
+ 
+ static void rpng2_win_cleanup()
+ {
+     if (bg_image && bg_data) {
+         free(bg_data);
+         bg_data = NULL;
+     }
+ 
+     if (rpng2_info.image_data) {
+         free(rpng2_info.image_data);
+         rpng2_info.image_data = NULL;
+     }
+ 
+     if (rpng2_info.row_pointers) {
+         free(rpng2_info.row_pointers);
+         rpng2_info.row_pointers = NULL;
+     }
+ 
+     if (dib) {
+         free(dib);
+         dib = NULL;
+     }
+ }
+ 
+ 
+ 
+ 
+ 
+ LRESULT CALLBACK rpng2_win_wndproc(HWND hwnd, UINT iMsg, WPARAM wP, LPARAM lP)
+ {
+     HDC         hdc;
+     PAINTSTRUCT ps;
+     int rc;
+ 
+     switch (iMsg) {
+         case WM_CREATE:
+             /* one-time processing here, if any */
+             return 0;
+ 
+         case WM_PAINT:
+             hdc = BeginPaint(hwnd, &ps);
+             rc = StretchDIBits(hdc, 0, 0, rpng2_info.width, rpng2_info.height,
+                                     0, 0, rpng2_info.width, rpng2_info.height,
+                                     wimage_data, (BITMAPINFO *)bmih,
+                                     0, SRCCOPY);
+             EndPaint(hwnd, &ps);
+             return 0;
+ 
+         /* wait for the user to tell us when to quit */
+         case WM_CHAR:
+             switch (wP) {       /* only need one, so ignore repeat count */
+                 case 'q':
+                 case 'Q':
+                 case 0x1B:      /* Esc key */
+                     PostQuitMessage(0);
+             }
+             return 0;
+ 
+         case WM_LBUTTONDOWN:    /* another way of quitting */
+         case WM_DESTROY:
+             PostQuitMessage(0);
+             return 0;
+     }
+ 
+     return DefWindowProc(hwnd, iMsg, wP, lP);
+ }


Index: llvm/runtime/libpng/contrib/gregbook/rpng2-x.c
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/rpng2-x.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:56 2004
--- llvm/runtime/libpng/contrib/gregbook/rpng2-x.c	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,1408 ----
+ /*---------------------------------------------------------------------------
+ 
+    rpng2 - progressive-model PNG display program                  rpng2-x.c
+ 
+    This program decodes and displays PNG files progressively, as if it were
+    a web browser (though the front end is only set up to read from files).
+    It supports gamma correction, user-specified background colors, and user-
+    specified background patterns (for transparent images).  This version is
+    for the X Window System (tested by the author under Unix and by Martin
+    Zinser under OpenVMS; may work under OS/2 with a little tweaking).
+ 
+    Thanks to Adam Costello and Pieter S. van der Meulen for the "diamond"
+    and "radial waves" patterns, respectively.
+ 
+    to do:
+     - 8-bit support
+     - finish resizable checkerboard-gradient (sizes 4-128?)
+     - use %.1023s to simplify truncation of title-bar string?
+ 
+   ---------------------------------------------------------------------------
+ 
+    Changelog:
+     - 1.01:  initial public release
+     - 1.02:  modified to allow abbreviated options; fixed char/uchar mismatch
+     - 1.10:  added support for non-default visuals; fixed X pixel-conversion
+     - 1.11:  added -usleep option for demos; fixed command-line parsing bug
+     - 1.12:  added -pause option for demos and testing
+     - 1.20:  added runtime MMX-enabling/disabling and new -mmx* options
+     - 1.21:  fixed small X memory leak (thanks to Francois Petitjean)
+     - 1.22:  fixed XFreeGC() crash bug
+ 
+   ---------------------------------------------------------------------------
+ 
+       Copyright (c) 1998-2001 Greg Roelofs.  All rights reserved.
+ 
+       This software is provided "as is," without warranty of any kind,
+       express or implied.  In no event shall the author or contributors
+       be held liable for any damages arising in any way from the use of
+       this software.
+ 
+       Permission is granted to anyone to use this software for any purpose,
+       including commercial applications, and to alter it and redistribute
+       it freely, subject to the following restrictions:
+ 
+       1. Redistributions of source code must retain the above copyright
+          notice, disclaimer, and this list of conditions.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, disclaimer, and this list of conditions in the documenta-
+          tion and/or other materials provided with the distribution.
+       3. All advertising materials mentioning features or use of this
+          software must display the following acknowledgment:
+ 
+             This product includes software developed by Greg Roelofs
+             and contributors for the book, "PNG: The Definitive Guide,"
+             published by O'Reilly and Associates.
+ 
+   ---------------------------------------------------------------------------*/
+ 
+ #define PROGNAME  "rpng2-x"
+ #define LONGNAME  "Progressive PNG Viewer for X"
+ #define VERSION   "1.22 of 16 August 2001"
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <setjmp.h>       /* for jmpbuf declaration in readpng2.h */
+ #include <time.h>
+ #include <math.h>         /* only for PvdM background code */
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+ #include <X11/Xos.h>
+ #include <X11/keysym.h>   /* defines XK_* macros */
+ 
+ #ifdef VMS
+ #  include <unistd.h>
+ #endif
+ 
+ /* all for PvdM background code: */
+ #ifndef PI
+ #  define PI             3.141592653589793238
+ #endif
+ #define PI_2             (PI*0.5)
+ #define INV_PI_360       (360.0 / PI)
+ #define MAX(a,b)         (a>b?a:b)
+ #define MIN(a,b)         (a<b?a:b)
+ #define CLIP(a,min,max)  MAX(min,MIN((a),max))
+ #define ABS(a)           ((a)<0?-(a):(a))
+ #define CLIP8P(c)        MAX(0,(MIN((c),255)))   /* 8-bit pos. integer (uch) */
+ #define ROUNDF(f)        ((int)(f + 0.5))
+ 
+ #define rgb1_max   bg_freq
+ #define rgb1_min   bg_gray
+ #define rgb2_max   bg_bsat
+ #define rgb2_min   bg_brot
+ 
+ /* #define DEBUG */     /* this enables the Trace() macros */
+ 
+ #include "readpng2.h"   /* typedefs, common macros, readpng2 prototypes */
+ 
+ 
+ /* could just include png.h, but this macro is the only thing we need
+  * (name and typedefs changed to local versions); note that side effects
+  * only happen with alpha (which could easily be avoided with
+  * "ush acopy = (alpha);") */
+ 
+ #define alpha_composite(composite, fg, alpha, bg) {               \
+     ush temp = ((ush)(fg)*(ush)(alpha) +                          \
+                 (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128);  \
+     (composite) = (uch)((temp + (temp >> 8)) >> 8);               \
+ }
+ 
+ 
+ #define INBUFSIZE 4096   /* with pseudo-timing on (1 sec delay/block), this
+                           *  block size corresponds roughly to a download
+                           *  speed 10% faster than theoretical 33.6K maximum
+                           *  (assuming 8 data bits, 1 stop bit and no other
+                           *  overhead) */
+ 
+ /* local prototypes */
+ static void rpng2_x_init(void);
+ static int  rpng2_x_create_window(void);
+ static int  rpng2_x_load_bg_image(void);
+ static void rpng2_x_display_row(ulg row);
+ static void rpng2_x_finish_display(void);
+ static void rpng2_x_cleanup(void);
+ static int  rpng2_x_msb(ulg u32val);
+ 
+ 
+ static char titlebar[1024], *window_name = titlebar;
+ static char *appname = LONGNAME;
+ static char *icon_name = PROGNAME;
+ static char *filename;
+ static FILE *infile;
+ 
+ static mainprog_info rpng2_info;
+ 
+ static uch inbuf[INBUFSIZE];
+ static int incount;
+ 
+ static int pat = 6;        /* must be less than num_bgpat */
+ static int bg_image = 0;
+ static int bgscale = 16;
+ static ulg bg_rowbytes;
+ static uch *bg_data;
+ 
+ int pause_after_pass = FALSE;
+ int demo_timing = FALSE;
+ ulg usleep_duration = 0L;
+ 
+ static struct rgb_color {
+     uch r, g, b;
+ } rgb[] = {
+     {  0,   0,   0},    /*  0:  black */
+     {255, 255, 255},    /*  1:  white */
+     {173, 132,  57},    /*  2:  tan */
+     { 64, 132,   0},    /*  3:  medium green */
+     {189, 117,   1},    /*  4:  gold */
+     {253, 249,   1},    /*  5:  yellow */
+     {  0,   0, 255},    /*  6:  blue */
+     {  0,   0, 120},    /*  7:  medium blue */
+     {255,   0, 255},    /*  8:  magenta */
+     { 64,   0,  64},    /*  9:  dark magenta */
+     {255,   0,   0},    /* 10:  red */
+     { 64,   0,   0},    /* 11:  dark red */
+     {255, 127,   0},    /* 12:  orange */
+     {192,  96,   0},    /* 13:  darker orange */
+     { 24,  60,   0},    /* 14:  dark green-yellow */
+     { 85, 125, 200}     /* 15:  ice blue */
+ };
+ /* not used for now, but should be for error-checking:
+ static int num_rgb = sizeof(rgb) / sizeof(struct rgb_color);
+  */
+ 
+ /*
+     This whole struct is a fairly cheesy way to keep the number of
+     command-line options to a minimum.  The radial-waves background
+     type is a particularly poor fit to the integer elements of the
+     struct...but a few macros and a little fixed-point math will do
+     wonders for ya.
+ 
+     type bits:
+        F E D C B A 9 8 7 6 5 4 3 2 1 0
+                              | | | | |
+                              | | +-+-+-- 0 = sharp-edged checkerboard
+                              | |         1 = soft diamonds
+                              | |         2 = radial waves
+                              | |       3-7 = undefined
+                              | +-- gradient #2 inverted?
+                              +-- alternating columns inverted?
+  */
+ static struct background_pattern {
+     ush type;
+     int rgb1_max, rgb1_min;     /* or bg_freq, bg_gray */
+     int rgb2_max, rgb2_min;     /* or bg_bsat, bg_brot (both scaled by 10)*/
+ } bg[] = {
+     {0+8,   2,0,  1,15},        /* checkered:  tan/black vs. white/ice blue */
+     {0+24,  2,0,  1,0},         /* checkered:  tan/black vs. white/black */
+     {0+8,   4,5,  0,2},         /* checkered:  gold/yellow vs. black/tan */
+     {0+8,   4,5,  0,6},         /* checkered:  gold/yellow vs. black/blue */
+     {0,     7,0,  8,9},         /* checkered:  deep blue/black vs. magenta */
+     {0+8,  13,0,  5,14},        /* checkered:  orange/black vs. yellow */
+     {0+8,  12,0, 10,11},        /* checkered:  orange/black vs. red */
+     {1,     7,0,  8,0},         /* diamonds:  deep blue/black vs. magenta */
+     {1,    12,0, 11,0},         /* diamonds:  orange vs. dark red */
+     {1,    10,0,  7,0},         /* diamonds:  red vs. medium blue */
+     {1,     4,0,  5,0},         /* diamonds:  gold vs. yellow */
+     {1,     3,0,  0,0},         /* diamonds:  medium green vs. black */
+     {2,    16, 100,  20,   0},  /* radial:  ~hard radial color-beams */
+     {2,    18, 100,  10,   2},  /* radial:  soft, curved radial color-beams */
+     {2,    16, 256, 100, 250},  /* radial:  very tight spiral */
+     {2, 10000, 256,  11,   0}   /* radial:  dipole-moire' (almost fractal) */
+ };
+ static int num_bgpat = sizeof(bg) / sizeof(struct background_pattern);
+ 
+ 
+ /* X-specific variables */
+ static char *displayname;
+ static XImage *ximage;
+ static Display *display;
+ static int depth;
+ static Visual *visual;
+ static XVisualInfo *visual_list;
+ static int RShift, GShift, BShift;
+ static ulg RMask, GMask, BMask;
+ static Window window;
+ static GC gc;
+ static Colormap colormap;
+ 
+ static int have_nondefault_visual = FALSE;
+ static int have_colormap = FALSE;
+ static int have_window = FALSE;
+ static int have_gc = FALSE;
+ 
+ 
+ 
+ 
+ int main(int argc, char **argv)
+ {
+ #ifdef sgi
+     char tmpline[80];
+ #endif
+     char *p, *bgstr = NULL;
+     int rc, alen, flen;
+     int error = 0;
+     int timing = FALSE;
+     int have_bg = FALSE;
+     double LUT_exponent;                /* just the lookup table */
+     double CRT_exponent = 2.2;          /* just the monitor */
+     double default_display_exponent;    /* whole display system */
+     XEvent e;
+     KeySym k;
+ 
+ 
+     /* First initialize a few things, just to be sure--memset takes care of
+      * default background color (black), booleans (FALSE), pointers (NULL),
+      * etc. */
+ 
+     displayname = (char *)NULL;
+     filename = (char *)NULL;
+     memset(&rpng2_info, 0, sizeof(mainprog_info));
+ 
+ 
+     /* Set the default value for our display-system exponent, i.e., the
+      * product of the CRT exponent and the exponent corresponding to
+      * the frame-buffer's lookup table (LUT), if any.  This is not an
+      * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
+      * ones), but it should cover 99% of the current possibilities. */
+ 
+ #if defined(NeXT)
+     /* third-party utilities can modify the default LUT exponent */
+     LUT_exponent = 1.0 / 2.2;
+     /*
+     if (some_next_function_that_returns_gamma(&next_gamma))
+         LUT_exponent = 1.0 / next_gamma;
+      */
+ #elif defined(sgi)
+     LUT_exponent = 1.0 / 1.7;
+     /* there doesn't seem to be any documented function to
+      * get the "gamma" value, so we do it the hard way */
+     infile = fopen("/etc/config/system.glGammaVal", "r");
+     if (infile) {
+         double sgi_gamma;
+ 
+         fgets(tmpline, 80, infile);
+         fclose(infile);
+         sgi_gamma = atof(tmpline);
+         if (sgi_gamma > 0.0)
+             LUT_exponent = 1.0 / sgi_gamma;
+     }
+ #elif defined(Macintosh)
+     LUT_exponent = 1.8 / 2.61;
+     /*
+     if (some_mac_function_that_returns_gamma(&mac_gamma))
+         LUT_exponent = mac_gamma / 2.61;
+      */
+ #else
+     LUT_exponent = 1.0;   /* assume no LUT:  most PCs */
+ #endif
+ 
+     /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
+     default_display_exponent = LUT_exponent * CRT_exponent;
+ 
+ 
+     /* If the user has set the SCREEN_GAMMA environment variable as suggested
+      * (somewhat imprecisely) in the libpng documentation, use that; otherwise
+      * use the default value we just calculated.  Either way, the user may
+      * override this via a command-line option. */
+ 
+     if ((p = getenv("SCREEN_GAMMA")) != NULL)
+         rpng2_info.display_exponent = atof(p);
+     else
+         rpng2_info.display_exponent = default_display_exponent;
+ 
+ 
+     /* Now parse the command line for options and the PNG filename. */
+ 
+     while (*++argv && !error) {
+         if (!strncmp(*argv, "-display", 2)) {
+             if (!*++argv)
+                 ++error;
+             else
+                 displayname = *argv;
+         } else if (!strncmp(*argv, "-gamma", 2)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 rpng2_info.display_exponent = atof(*argv);
+                 if (rpng2_info.display_exponent <= 0.0)
+                     ++error;
+             }
+         } else if (!strncmp(*argv, "-bgcolor", 4)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 bgstr = *argv;
+                 if (strlen(bgstr) != 7 || bgstr[0] != '#')
+                     ++error;
+                 else {
+                     have_bg = TRUE;
+                     bg_image = FALSE;
+                 }
+             }
+         } else if (!strncmp(*argv, "-bgpat", 4)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 pat = atoi(*argv) - 1;
+                 if (pat < 0 || pat >= num_bgpat)
+                     ++error;
+                 else {
+                     bg_image = TRUE;
+                     have_bg = FALSE;
+                 }
+             }
+         } else if (!strncmp(*argv, "-usleep", 2)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 usleep_duration = (ulg)atol(*argv);
+                 demo_timing = TRUE;
+             }
+         } else if (!strncmp(*argv, "-pause", 2)) {
+             pause_after_pass = TRUE;
+         } else if (!strncmp(*argv, "-timing", 2)) {
+             timing = TRUE;
+ #if (defined(__i386__) || defined(_M_IX86))
+         } else if (!strncmp(*argv, "-nommxfilters", 7)) {
+             rpng2_info.nommxfilters = TRUE;
+         } else if (!strncmp(*argv, "-nommxcombine", 7)) {
+             rpng2_info.nommxcombine = TRUE;
+         } else if (!strncmp(*argv, "-nommxinterlace", 7)) {
+             rpng2_info.nommxinterlace = TRUE;
+         } else if (!strcmp(*argv, "-nommx")) {
+             rpng2_info.nommxfilters = TRUE;
+             rpng2_info.nommxcombine = TRUE;
+             rpng2_info.nommxinterlace = TRUE;
+ #endif
+         } else {
+             if (**argv != '-') {
+                 filename = *argv;
+                 if (argv[1])   /* shouldn't be any more args after filename */
+                     ++error;
+             } else
+                 ++error;   /* not expecting any other options */
+         }
+     }
+ 
+     if (!filename) {
+         ++error;
+     } else if (!(infile = fopen(filename, "rb"))) {
+         fprintf(stderr, PROGNAME ":  can't open PNG file [%s]\n", filename);
+         ++error;
+     } else {
+         incount = fread(inbuf, 1, INBUFSIZE, infile);
+         if (incount < 8 || !readpng2_check_sig(inbuf, 8)) {
+             fprintf(stderr, PROGNAME
+               ":  [%s] is not a PNG file: incorrect signature\n",
+               filename);
+             ++error;
+         } else if ((rc = readpng2_init(&rpng2_info)) != 0) {
+             switch (rc) {
+                 case 2:
+                     fprintf(stderr, PROGNAME
+                       ":  [%s] has bad IHDR (libpng longjmp)\n",
+                       filename);
+                     break;
+                 case 4:
+                     fprintf(stderr, PROGNAME ":  insufficient memory\n");
+                     break;
+                 default:
+                     fprintf(stderr, PROGNAME
+                       ":  unknown readpng2_init() error\n");
+                     break;
+             }
+             ++error;
+         } else {
+             display = XOpenDisplay(displayname);
+             if (!display) {
+                 readpng2_cleanup(&rpng2_info);
+                 fprintf(stderr, PROGNAME ":  can't open X display [%s]\n",
+                   displayname? displayname : "default");
+                 ++error;
+             }
+         }
+         if (error)
+             fclose(infile);
+     }
+ 
+ 
+     /* usage screen */
+ 
+     if (error) {
+         fprintf(stderr, "\n%s %s:  %s\n\n", PROGNAME, VERSION, appname);
+         readpng2_version_info();
+         fprintf(stderr, "\n"
+           "Usage:  %s [-display xdpy] [-gamma exp] [-bgcolor bg | -bgpat pat]\n"
+ #if (defined(__i386__) || defined(_M_IX86))
+           "        %*s [[-nommxfilters] [-nommxcombine] [-nommxinterlace] | -nommx]\n"
+ #endif
+           "        %*s [-usleep dur | -timing] [-pause] file.png\n\n"
+           "    xdpy\tname of the target X display (e.g., ``hostname:0'')\n"
+           "    exp \ttransfer-function exponent (``gamma'') of the display\n"
+           "\t\t  system in floating-point format (e.g., ``%.1f''); equal\n"
+           "\t\t  to the product of the lookup-table exponent (varies)\n"
+           "\t\t  and the CRT exponent (usually 2.2); must be positive\n"
+           "    bg  \tdesired background color in 7-character hex RGB format\n"
+           "\t\t  (e.g., ``#ff7700'' for orange:  same as HTML colors);\n"
+           "\t\t  used with transparent images; overrides -bgpat\n"
+           "    pat \tdesired background pattern number (1-%d); used with\n"
+           "\t\t  transparent images; overrides -bgcolor\n"
+ #if (defined(__i386__) || defined(_M_IX86))
+           "    -nommx*\tdisable optimized MMX routines for decoding row filters,\n"
+           "\t\t  combining rows, and expanding interlacing, respectively\n"
+ #endif
+           "    dur \tduration in microseconds to wait after displaying each\n"
+           "\t\t  row (for demo purposes)\n"
+           "    -timing\tenables delay for every block read, to simulate modem\n"
+           "\t\t  download of image (~36 Kbps)\n"
+           "    -pause\tpauses after displaying each pass until key pressed\n"
+           "\nPress Q, Esc or mouse button 1 (within image window, after image\n"
+           "is displayed) to quit.\n"
+           "\n", PROGNAME,
+ #if (defined(__i386__) || defined(_M_IX86))
+           strlen(PROGNAME), " ",
+ #endif
+           strlen(PROGNAME), " ", default_display_exponent, num_bgpat);
+         exit(1);
+     }
+ 
+ 
+     /* set the title-bar string, but make sure buffer doesn't overflow */
+ 
+     alen = strlen(appname);
+     flen = strlen(filename);
+     if (alen + flen + 3 > 1023)
+         sprintf(titlebar, "%s:  ...%s", appname, filename+(alen+flen+6-1023));
+     else
+         sprintf(titlebar, "%s:  %s", appname, filename);
+ 
+ 
+     /* set some final rpng2_info variables before entering main data loop */
+ 
+     if (have_bg) {
+         unsigned r, g, b;   /* this approach quiets compiler warnings */
+ 
+         sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
+         rpng2_info.bg_red   = (uch)r;
+         rpng2_info.bg_green = (uch)g;
+         rpng2_info.bg_blue  = (uch)b;
+     } else
+         rpng2_info.need_bgcolor = TRUE;
+ 
+     rpng2_info.done = FALSE;
+     rpng2_info.mainprog_init = rpng2_x_init;
+     rpng2_info.mainprog_display_row = rpng2_x_display_row;
+     rpng2_info.mainprog_finish_display = rpng2_x_finish_display;
+ 
+ 
+     /* OK, this is the fun part:  call readpng2_decode_data() at the start of
+      * the loop to deal with our first buffer of data (read in above to verify
+      * that the file is a PNG image), then loop through the file and continue
+      * calling the same routine to handle each chunk of data.  It in turn
+      * passes the data to libpng, which will invoke one or more of our call-
+      * backs as decoded data become available.  We optionally call sleep() for
+      * one second per iteration to simulate downloading the image via an analog
+      * modem. */
+ 
+     for (;;) {
+         Trace((stderr, "about to call readpng2_decode_data()\n"))
+         if (readpng2_decode_data(&rpng2_info, inbuf, incount))
+             ++error;
+         Trace((stderr, "done with readpng2_decode_data()\n"))
+         if (error || feof(infile) || rpng2_info.done)
+             break;
+         if (timing)
+             sleep(1);
+         incount = fread(inbuf, 1, INBUFSIZE, infile);
+     }
+ 
+ 
+     /* clean up PNG stuff and report any decoding errors */
+ 
+     fclose(infile);
+     Trace((stderr, "about to call readpng2_cleanup()\n"))
+     readpng2_cleanup(&rpng2_info);
+ 
+     if (error) {
+         fprintf(stderr, PROGNAME ":  libpng error while decoding PNG image\n");
+         exit(3);
+     }
+ 
+ 
+     /* wait for the user to tell us when to quit */
+ 
+     do
+         XNextEvent(display, &e);
+     while (!(e.type == ButtonPress && e.xbutton.button == Button1) &&
+            !(e.type == KeyPress &&    /*  v--- or 1 for shifted keys */
+              ((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape) ));
+ 
+ 
+     /* we're done:  clean up all image and X resources and go away */
+ 
+     Trace((stderr, "about to call rpng2_x_cleanup()\n"))
+     rpng2_x_cleanup();
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ 
+ /* this function is called by readpng2_info_callback() in readpng2.c, which
+  * in turn is called by libpng after all of the pre-IDAT chunks have been
+  * read and processed--i.e., we now have enough info to finish initializing */
+ 
+ static void rpng2_x_init(void)
+ {
+     ulg i;
+     ulg rowbytes = rpng2_info.rowbytes;
+ 
+     Trace((stderr, "beginning rpng2_x_init()\n"))
+     Trace((stderr, "  rowbytes = %ld\n", rpng2_info.rowbytes))
+     Trace((stderr, "  width  = %ld\n", rpng2_info.width))
+     Trace((stderr, "  height = %ld\n", rpng2_info.height))
+ 
+     rpng2_info.image_data = (uch *)malloc(rowbytes * rpng2_info.height);
+     if (!rpng2_info.image_data) {
+         readpng2_cleanup(&rpng2_info);
+         return;
+     }
+ 
+     rpng2_info.row_pointers = (uch **)malloc(rpng2_info.height * sizeof(uch *));
+     if (!rpng2_info.row_pointers) {
+         free(rpng2_info.image_data);
+         rpng2_info.image_data = NULL;
+         readpng2_cleanup(&rpng2_info);
+         return;
+     }
+ 
+     for (i = 0;  i < rpng2_info.height;  ++i)
+         rpng2_info.row_pointers[i] = rpng2_info.image_data + i*rowbytes;
+ 
+ 
+     /* do the basic X initialization stuff, make the window, and fill it with
+      * the user-specified, file-specified or default background color or
+      * pattern */
+ 
+     if (rpng2_x_create_window()) {
+ 
+         /* GRR TEMPORARY HACK:  this is fundamentally no different from cases
+          * above; libpng should longjmp() back to us when png_ptr goes away.
+          * If we/it segfault instead, seems like a libpng bug... */
+ 
+         /* we're here via libpng callback, so if window fails, clean and bail */
+ printf("readpng2_cleanup.\n");
+         readpng2_cleanup(&rpng2_info);
+         rpng2_x_cleanup();
+         exit(2);
+     }
+ }
+ 
+ 
+ 
+ 
+ 
+ static int rpng2_x_create_window(void)
+ {
+     ulg bg_red   = rpng2_info.bg_red;
+     ulg bg_green = rpng2_info.bg_green;
+     ulg bg_blue  = rpng2_info.bg_blue;
+     ulg bg_pixel = 0L;
+     ulg attrmask;
+     int need_colormap = FALSE;
+     int screen, pad;
+     uch *xdata;
+     Window root;
+     XEvent e;
+     XGCValues gcvalues;
+     XSetWindowAttributes attr;
+     XSizeHints *size_hints;
+     XTextProperty windowName, *pWindowName = &windowName;
+     XTextProperty iconName, *pIconName = &iconName;
+     XVisualInfo visual_info;
+     XWMHints *wm_hints;
+ 
+ 
+     Trace((stderr, "beginning rpng2_x_create_window()\n"))
+ 
+     screen = DefaultScreen(display);
+     depth = DisplayPlanes(display, screen);
+     root = RootWindow(display, screen);
+ 
+ #ifdef DEBUG
+     XSynchronize(display, True);
+ #endif
+ 
+     if (depth != 16 && depth != 24 && depth != 32) {
+         int visuals_matched = 0;
+ 
+         Trace((stderr, "default depth is %d:  checking other visuals\n",
+           depth))
+ 
+         /* 24-bit first */
+         visual_info.screen = screen;
+         visual_info.depth = 24;
+         visual_list = XGetVisualInfo(display,
+           VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched);
+         if (visuals_matched == 0) {
+ /* GRR:  add 15-, 16- and 32-bit TrueColor visuals (also DirectColor?) */
+             fprintf(stderr, "default screen depth %d not supported, and no"
+               " 24-bit visuals found\n", depth);
+             return 2;
+         }
+         Trace((stderr, "XGetVisualInfo() returned %d 24-bit visuals\n",
+           visuals_matched))
+         visual = visual_list[0].visual;
+         depth = visual_list[0].depth;
+ /*
+         colormap_size = visual_list[0].colormap_size;
+         visual_class = visual->class;
+         visualID = XVisualIDFromVisual(visual);
+  */
+         have_nondefault_visual = TRUE;
+         need_colormap = TRUE;
+     } else {
+         XMatchVisualInfo(display, screen, depth, TrueColor, &visual_info);
+         visual = visual_info.visual;
+     }
+ 
+     RMask = visual->red_mask;
+     GMask = visual->green_mask;
+     BMask = visual->blue_mask;
+ 
+ /* GRR:  add/check 8-bit support */
+     if (depth == 8 || need_colormap) {
+         colormap = XCreateColormap(display, root, visual, AllocNone);
+         if (!colormap) {
+             fprintf(stderr, "XCreateColormap() failed\n");
+             return 2;
+         }
+         have_colormap = TRUE;
+         if (depth == 8)
+             bg_image = FALSE;   /* gradient just wastes palette entries */
+     }
+     if (depth == 15 || depth == 16) {
+         RShift = 15 - rpng2_x_msb(RMask);    /* these are right-shifts */
+         GShift = 15 - rpng2_x_msb(GMask);
+         BShift = 15 - rpng2_x_msb(BMask);
+     } else if (depth > 16) {
+         RShift = rpng2_x_msb(RMask) - 7;     /* these are left-shifts */
+         GShift = rpng2_x_msb(GMask) - 7;
+         BShift = rpng2_x_msb(BMask) - 7;
+     }
+     if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) {
+         fprintf(stderr, "rpng2 internal logic error:  negative X shift(s)!\n");
+         return 2;
+     }
+ 
+ /*---------------------------------------------------------------------------
+     Finally, create the window.
+   ---------------------------------------------------------------------------*/
+ 
+     attr.backing_store = Always;
+     attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
+     attrmask = CWBackingStore | CWEventMask;
+     if (have_nondefault_visual) {
+         attr.colormap = colormap;
+         attr.background_pixel = 0;
+         attr.border_pixel = 1;
+         attrmask |= CWColormap | CWBackPixel | CWBorderPixel;
+     }
+ 
+     window = XCreateWindow(display, root, 0, 0, rpng2_info.width,
+       rpng2_info.height, 0, depth, InputOutput, visual, attrmask, &attr);
+ 
+     if (window == None) {
+         fprintf(stderr, "XCreateWindow() failed\n");
+         return 2;
+     } else
+         have_window = TRUE;
+ 
+     if (depth == 8)
+         XSetWindowColormap(display, window, colormap);
+ 
+     if (!XStringListToTextProperty(&window_name, 1, pWindowName))
+         pWindowName = NULL;
+     if (!XStringListToTextProperty(&icon_name, 1, pIconName))
+         pIconName = NULL;
+ 
+     /* OK if either hints allocation fails; XSetWMProperties() allows NULLs */
+ 
+     if ((size_hints = XAllocSizeHints()) != NULL) {
+         /* window will not be resizable */
+         size_hints->flags = PMinSize | PMaxSize;
+         size_hints->min_width = size_hints->max_width = (int)rpng2_info.width;
+         size_hints->min_height = size_hints->max_height =
+           (int)rpng2_info.height;
+     }
+ 
+     if ((wm_hints = XAllocWMHints()) != NULL) {
+         wm_hints->initial_state = NormalState;
+         wm_hints->input = True;
+      /* wm_hints->icon_pixmap = icon_pixmap; */
+         wm_hints->flags = StateHint | InputHint  /* | IconPixmapHint */ ;
+     }
+ 
+     XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0,
+       size_hints, wm_hints, NULL);
+ 
+     /* various properties and hints no longer needed; free memory */
+     if (pWindowName)
+        XFree(pWindowName->value);
+     if (pIconName)
+        XFree(pIconName->value);
+     if (size_hints)
+         XFree(size_hints);
+     if (wm_hints)
+        XFree(wm_hints);
+ 
+     XMapWindow(display, window);
+ 
+     gc = XCreateGC(display, window, 0, &gcvalues);
+     have_gc = TRUE;
+ 
+ /*---------------------------------------------------------------------------
+     Allocate memory for the X- and display-specific version of the image.
+   ---------------------------------------------------------------------------*/
+ 
+     if (depth == 24 || depth == 32) {
+         xdata = (uch *)malloc(4*rpng2_info.width*rpng2_info.height);
+         pad = 32;
+     } else if (depth == 16) {
+         xdata = (uch *)malloc(2*rpng2_info.width*rpng2_info.height);
+         pad = 16;
+     } else /* depth == 8 */ {
+         xdata = (uch *)malloc(rpng2_info.width*rpng2_info.height);
+         pad = 8;
+     }
+ 
+     if (!xdata) {
+         fprintf(stderr, PROGNAME ":  unable to allocate image memory\n");
+         return 4;
+     }
+ 
+     ximage = XCreateImage(display, visual, depth, ZPixmap, 0,
+       (char *)xdata, rpng2_info.width, rpng2_info.height, pad, 0);
+ 
+     if (!ximage) {
+         fprintf(stderr, PROGNAME ":  XCreateImage() failed\n");
+         free(xdata);
+         return 3;
+     }
+ 
+     /* to avoid testing the byte order every pixel (or doubling the size of
+      * the drawing routine with a giant if-test), we arbitrarily set the byte
+      * order to MSBFirst and let Xlib worry about inverting things on little-
+      * endian machines (e.g., Linux/x86, old VAXen, etc.)--this is not the
+      * most efficient approach (the giant if-test would be better), but in
+      * the interest of clarity, we'll take the easy way out... */
+ 
+     ximage->byte_order = MSBFirst;
+ 
+ /*---------------------------------------------------------------------------
+     Fill window with the specified background color (default is black) or
+     faked "background image" (but latter is disabled if 8-bit; gradients
+     just waste palette entries).
+   ---------------------------------------------------------------------------*/
+ 
+     if (bg_image)
+         rpng2_x_load_bg_image();    /* resets bg_image if fails */
+ 
+     if (!bg_image) {
+         if (depth == 24 || depth == 32) {
+             bg_pixel = (bg_red   << RShift) |
+                        (bg_green << GShift) |
+                        (bg_blue  << BShift);
+         } else if (depth == 16) {
+             bg_pixel = (((bg_red   << 8) >> RShift) & RMask) |
+                        (((bg_green << 8) >> GShift) & GMask) |
+                        (((bg_blue  << 8) >> BShift) & BMask);
+         } else /* depth == 8 */ {
+ 
+             /* GRR:  add 8-bit support */
+ 
+         }
+         XSetForeground(display, gc, bg_pixel);
+         XFillRectangle(display, window, gc, 0, 0, rpng2_info.width,
+           rpng2_info.height);
+     }
+ 
+ /*---------------------------------------------------------------------------
+     Wait for first Expose event to do any drawing, then flush and return.
+   ---------------------------------------------------------------------------*/
+ 
+     do
+         XNextEvent(display, &e);
+     while (e.type != Expose || e.xexpose.count);
+ 
+     XFlush(display);
+ 
+     return 0;
+ 
+ } /* end function rpng2_x_create_window() */
+ 
+ 
+ 
+ 
+ 
+ static int rpng2_x_load_bg_image(void)
+ {
+     uch *src;
+     char *dest;
+     uch r1, r2, g1, g2, b1, b2;
+     uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv;
+     int k, hmax, max;
+     int xidx, yidx, yidx_max = (bgscale-1);
+     int even_odd_vert, even_odd_horiz, even_odd;
+     int invert_gradient2 = (bg[pat].type & 0x08);
+     int invert_column;
+     int ximage_rowbytes = ximage->bytes_per_line;
+     ulg i, row;
+     ulg pixel;
+ 
+ /*---------------------------------------------------------------------------
+     Allocate buffer for fake background image to be used with transparent
+     images; if this fails, revert to plain background color.
+   ---------------------------------------------------------------------------*/
+ 
+     bg_rowbytes = 3 * rpng2_info.width;
+     bg_data = (uch *)malloc(bg_rowbytes * rpng2_info.height);
+     if (!bg_data) {
+         fprintf(stderr, PROGNAME
+           ":  unable to allocate memory for background image\n");
+         bg_image = 0;
+         return 1;
+     }
+ 
+ /*---------------------------------------------------------------------------
+     Vertical gradients (ramps) in NxN squares, alternating direction and
+     colors (N == bgscale).
+   ---------------------------------------------------------------------------*/
+ 
+     if ((bg[pat].type & 0x07) == 0) {
+         uch r1_min  = rgb[bg[pat].rgb1_min].r;
+         uch g1_min  = rgb[bg[pat].rgb1_min].g;
+         uch b1_min  = rgb[bg[pat].rgb1_min].b;
+         uch r2_min  = rgb[bg[pat].rgb2_min].r;
+         uch g2_min  = rgb[bg[pat].rgb2_min].g;
+         uch b2_min  = rgb[bg[pat].rgb2_min].b;
+         int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min;
+         int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min;
+         int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min;
+         int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min;
+         int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min;
+         int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min;
+ 
+         for (row = 0;  row < rpng2_info.height;  ++row) {
+             yidx = (int)(row % bgscale);
+             even_odd_vert = (int)((row / bgscale) & 1);
+ 
+             r1 = r1_min + (r1_diff * yidx) / yidx_max;
+             g1 = g1_min + (g1_diff * yidx) / yidx_max;
+             b1 = b1_min + (b1_diff * yidx) / yidx_max;
+             r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max;
+             g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max;
+             b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max;
+ 
+             r2 = r2_min + (r2_diff * yidx) / yidx_max;
+             g2 = g2_min + (g2_diff * yidx) / yidx_max;
+             b2 = b2_min + (b2_diff * yidx) / yidx_max;
+             r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max;
+             g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max;
+             b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max;
+ 
+             dest = (char *)bg_data + row*bg_rowbytes;
+             for (i = 0;  i < rpng2_info.width;  ++i) {
+                 even_odd_horiz = (int)((i / bgscale) & 1);
+                 even_odd = even_odd_vert ^ even_odd_horiz;
+                 invert_column =
+                   (even_odd_horiz && (bg[pat].type & 0x10));
+                 if (even_odd == 0) {        /* gradient #1 */
+                     if (invert_column) {
+                         *dest++ = r1_inv;
+                         *dest++ = g1_inv;
+                         *dest++ = b1_inv;
+                     } else {
+                         *dest++ = r1;
+                         *dest++ = g1;
+                         *dest++ = b1;
+                     }
+                 } else {                    /* gradient #2 */
+                     if ((invert_column && invert_gradient2) ||
+                         (!invert_column && !invert_gradient2))
+                     {
+                         *dest++ = r2;       /* not inverted or */
+                         *dest++ = g2;       /*  doubly inverted */
+                         *dest++ = b2;
+                     } else {
+                         *dest++ = r2_inv;
+                         *dest++ = g2_inv;   /* singly inverted */
+                         *dest++ = b2_inv;
+                     }
+                 }
+             }
+         }
+ 
+ /*---------------------------------------------------------------------------
+     Soft gradient-diamonds with scale = bgscale.  Code contributed by Adam
+     M. Costello.
+   ---------------------------------------------------------------------------*/
+ 
+     } else if ((bg[pat].type & 0x07) == 1) {
+ 
+         hmax = (bgscale-1)/2;   /* half the max weight of a color */
+         max = 2*hmax;           /* the max weight of a color */
+ 
+         r1 = rgb[bg[pat].rgb1_max].r;
+         g1 = rgb[bg[pat].rgb1_max].g;
+         b1 = rgb[bg[pat].rgb1_max].b;
+         r2 = rgb[bg[pat].rgb2_max].r;
+         g2 = rgb[bg[pat].rgb2_max].g;
+         b2 = rgb[bg[pat].rgb2_max].b;
+ 
+         for (row = 0;  row < rpng2_info.height;  ++row) {
+             yidx = (int)(row % bgscale);
+             if (yidx > hmax)
+                 yidx = bgscale-1 - yidx;
+             dest = (char *)bg_data + row*bg_rowbytes;
+             for (i = 0;  i < rpng2_info.width;  ++i) {
+                 xidx = (int)(i % bgscale);
+                 if (xidx > hmax)
+                     xidx = bgscale-1 - xidx;
+                 k = xidx + yidx;
+                 *dest++ = (k*r1 + (max-k)*r2) / max;
+                 *dest++ = (k*g1 + (max-k)*g2) / max;
+                 *dest++ = (k*b1 + (max-k)*b2) / max;
+             }
+         }
+ 
+ /*---------------------------------------------------------------------------
+     Radial "starburst" with azimuthal sinusoids; [eventually number of sinu-
+     soids will equal bgscale?].  This one is slow but very cool.  Code con-
+     tributed by Pieter S. van der Meulen (originally in Smalltalk).
+   ---------------------------------------------------------------------------*/
+ 
+     } else if ((bg[pat].type & 0x07) == 2) {
+         uch ch;
+         int ii, x, y, hw, hh, grayspot;
+         double freq, rotate, saturate, gray, intensity;
+         double angle=0.0, aoffset=0.0, maxDist, dist;
+         double red=0.0, green=0.0, blue=0.0, hue, s, v, f, p, q, t;
+ 
+         fprintf(stderr, "%s:  computing radial background...",
+           PROGNAME);
+         fflush(stderr);
+ 
+         hh = (int)(rpng2_info.height / 2);
+         hw = (int)(rpng2_info.width / 2);
+ 
+         /* variables for radial waves:
+          *   aoffset:  number of degrees to rotate hue [CURRENTLY NOT USED]
+          *   freq:  number of color beams originating from the center
+          *   grayspot:  size of the graying center area (anti-alias)
+          *   rotate:  rotation of the beams as a function of radius
+          *   saturate:  saturation of beams' shape azimuthally
+          */
+         angle = CLIP(angle, 0.0, 360.0);
+         grayspot = CLIP(bg[pat].bg_gray, 1, (hh + hw));
+         freq = MAX((double)bg[pat].bg_freq, 0.0);
+         saturate = (double)bg[pat].bg_bsat * 0.1;
+         rotate = (double)bg[pat].bg_brot * 0.1;
+         gray = 0.0;
+         intensity = 0.0;
+         maxDist = (double)((hw*hw) + (hh*hh));
+ 
+         for (row = 0;  row < rpng2_info.height;  ++row) {
+             y = (int)(row - hh);
+             dest = (char *)bg_data + row*bg_rowbytes;
+             for (i = 0;  i < rpng2_info.width;  ++i) {
+                 x = (int)(i - hw);
+                 angle = (x == 0)? PI_2 : atan((double)y / (double)x);
+                 gray = (double)MAX(ABS(y), ABS(x)) / grayspot;
+                 gray = MIN(1.0, gray);
+                 dist = (double)((x*x) + (y*y)) / maxDist;
+                 intensity = cos((angle+(rotate*dist*PI)) * freq) *
+                   gray * saturate;
+                 intensity = (MAX(MIN(intensity,1.0),-1.0) + 1.0) * 0.5;
+                 hue = (angle + PI) * INV_PI_360 + aoffset;
+                 s = gray * ((double)(ABS(x)+ABS(y)) / (double)(hw + hh));
+                 s = MIN(MAX(s,0.0), 1.0);
+                 v = MIN(MAX(intensity,0.0), 1.0);
+ 
+                 if (s == 0.0) {
+                     ch = (uch)(v * 255.0);
+                     *dest++ = ch;
+                     *dest++ = ch;
+                     *dest++ = ch;
+                 } else {
+                     if ((hue < 0.0) || (hue >= 360.0))
+                         hue -= (((int)(hue / 360.0)) * 360.0);
+                     hue /= 60.0;
+                     ii = (int)hue;
+                     f = hue - (double)ii;
+                     p = (1.0 - s) * v;
+                     q = (1.0 - (s * f)) * v;
+                     t = (1.0 - (s * (1.0 - f))) * v;
+                     if      (ii == 0) { red = v; green = t; blue = p; }
+                     else if (ii == 1) { red = q; green = v; blue = p; }
+                     else if (ii == 2) { red = p; green = v; blue = t; }
+                     else if (ii == 3) { red = p; green = q; blue = v; }
+                     else if (ii == 4) { red = t; green = p; blue = v; }
+                     else if (ii == 5) { red = v; green = p; blue = q; }
+                     *dest++ = (uch)(red * 255.0);
+                     *dest++ = (uch)(green * 255.0);
+                     *dest++ = (uch)(blue * 255.0);
+                 }
+             }
+         }
+         fprintf(stderr, "done.\n");
+         fflush(stderr);
+     }
+ 
+ /*---------------------------------------------------------------------------
+     Blast background image to display buffer before beginning PNG decode.
+   ---------------------------------------------------------------------------*/
+ 
+     if (depth == 24 || depth == 32) {
+         ulg red, green, blue;
+ 
+         for (row = 0;  row < rpng2_info.height;  ++row) {
+             src = bg_data + row*bg_rowbytes;
+             dest = ximage->data + row*ximage_rowbytes;
+             for (i = rpng2_info.width;  i > 0;  --i) {
+                 red   = *src++;
+                 green = *src++;
+                 blue  = *src++;
+                 pixel = (red   << RShift) |
+                         (green << GShift) |
+                         (blue  << BShift);
+                 /* recall that we set ximage->byte_order = MSBFirst above */
+                 /* GRR BUG:  this assumes bpp == 32, but may be 24: */
+                 *dest++ = (char)((pixel >> 24) & 0xff);
+                 *dest++ = (char)((pixel >> 16) & 0xff);
+                 *dest++ = (char)((pixel >>  8) & 0xff);
+                 *dest++ = (char)( pixel        & 0xff);
+             }
+         }
+ 
+     } else if (depth == 16) {
+         ush red, green, blue;
+ 
+         for (row = 0;  row < rpng2_info.height;  ++row) {
+             src = bg_data + row*bg_rowbytes;
+             dest = ximage->data + row*ximage_rowbytes;
+             for (i = rpng2_info.width;  i > 0;  --i) {
+                 red   = ((ush)(*src) << 8);  ++src;
+                 green = ((ush)(*src) << 8);  ++src;
+                 blue  = ((ush)(*src) << 8);  ++src;
+                 pixel = ((red   >> RShift) & RMask) |
+                         ((green >> GShift) & GMask) |
+                         ((blue  >> BShift) & BMask);
+                 /* recall that we set ximage->byte_order = MSBFirst above */
+                 *dest++ = (char)((pixel >>  8) & 0xff);
+                 *dest++ = (char)( pixel        & 0xff);
+             }
+         }
+ 
+     } else /* depth == 8 */ {
+ 
+         /* GRR:  add 8-bit support */
+ 
+     }
+ 
+     XPutImage(display, window, gc, ximage, 0, 0, 0, 0, rpng2_info.width,
+       rpng2_info.height);
+ 
+     return 0;
+ 
+ } /* end function rpng2_x_load_bg_image() */
+ 
+ 
+ 
+ 
+ 
+ static void rpng2_x_display_row(ulg row)
+ {
+     uch bg_red   = rpng2_info.bg_red;
+     uch bg_green = rpng2_info.bg_green;
+     uch bg_blue  = rpng2_info.bg_blue;
+     uch *src, *src2=NULL;
+     char *dest;
+     uch r, g, b, a;
+     int ximage_rowbytes = ximage->bytes_per_line;
+     ulg i, pixel;
+     static int rows=0, prevpass=(-1);
+     static ulg firstrow;
+ 
+ /*---------------------------------------------------------------------------
+     rows and firstrow simply track how many rows (and which ones) have not
+     yet been displayed; alternatively, we could call XPutImage() for every
+     row and not bother with the records-keeping.
+   ---------------------------------------------------------------------------*/
+ 
+     Trace((stderr, "beginning rpng2_x_display_row()\n"))
+ 
+     if (rpng2_info.pass != prevpass) {
+         if (pause_after_pass && rpng2_info.pass > 0) {
+             XEvent e;
+             KeySym k;
+ 
+             fprintf(stderr,
+               "%s:  end of pass %d of 7; click in image window to continue\n",
+               PROGNAME, prevpass + 1);
+             do
+                 XNextEvent(display, &e);
+             while (!(e.type == ButtonPress && e.xbutton.button == Button1)
+                    && !(e.type == KeyPress &&
+                    ((k = XLookupKeysym(&e.xkey, 0)) == XK_q
+                     || k == XK_Escape) )) ;
+         }
+         fprintf(stderr, "%s:  pass %d of 7\r", PROGNAME, rpng2_info.pass + 1);
+         fflush(stderr);
+         prevpass = rpng2_info.pass;
+     }
+ 
+     if (rows == 0)
+         firstrow = row;   /* first row that is not yet displayed */
+ 
+     ++rows;   /* count of rows received but not yet displayed */
+ 
+ /*---------------------------------------------------------------------------
+     Aside from the use of the rpng2_info struct, the lack of an outer loop
+     (over rows) and moving the XPutImage() call outside the "if (depth)"
+     tests, this routine is identical to rpng_x_display_image() in the non-
+     progressive version of the program.
+   ---------------------------------------------------------------------------*/
+ 
+     if (depth == 24 || depth == 32) {
+         ulg red, green, blue;
+ 
+         src = rpng2_info.image_data + row*rpng2_info.rowbytes;
+         if (bg_image)
+             src2 = bg_data + row*bg_rowbytes;
+         dest = ximage->data + row*ximage_rowbytes;
+         if (rpng2_info.channels == 3) {
+             for (i = rpng2_info.width;  i > 0;  --i) {
+                 red   = *src++;
+                 green = *src++;
+                 blue  = *src++;
+                 pixel = (red   << RShift) |
+                         (green << GShift) |
+                         (blue  << BShift);
+                 /* recall that we set ximage->byte_order = MSBFirst above */
+                 /* GRR BUG:  this assumes bpp == 32, but may be 24: */
+                 *dest++ = (char)((pixel >> 24) & 0xff);
+                 *dest++ = (char)((pixel >> 16) & 0xff);
+                 *dest++ = (char)((pixel >>  8) & 0xff);
+                 *dest++ = (char)( pixel        & 0xff);
+             }
+         } else /* if (rpng2_info.channels == 4) */ {
+             for (i = rpng2_info.width;  i > 0;  --i) {
+                 r = *src++;
+                 g = *src++;
+                 b = *src++;
+                 a = *src++;
+                 if (bg_image) {
+                     bg_red   = *src2++;
+                     bg_green = *src2++;
+                     bg_blue  = *src2++;
+                 }
+                 if (a == 255) {
+                     red   = r;
+                     green = g;
+                     blue  = b;
+                 } else if (a == 0) {
+                     red   = bg_red;
+                     green = bg_green;
+                     blue  = bg_blue;
+                 } else {
+                     /* this macro (from png.h) composites the foreground
+                      * and background values and puts the result into the
+                      * first argument */
+                     alpha_composite(red,   r, a, bg_red);
+                     alpha_composite(green, g, a, bg_green);
+                     alpha_composite(blue,  b, a, bg_blue);
+                 }
+                 pixel = (red   << RShift) |
+                         (green << GShift) |
+                         (blue  << BShift);
+                 /* recall that we set ximage->byte_order = MSBFirst above */
+                 /* GRR BUG:  this assumes bpp == 32, but may be 24: */
+                 *dest++ = (char)((pixel >> 24) & 0xff);
+                 *dest++ = (char)((pixel >> 16) & 0xff);
+                 *dest++ = (char)((pixel >>  8) & 0xff);
+                 *dest++ = (char)( pixel        & 0xff);
+             }
+         }
+ 
+     } else if (depth == 16) {
+         ush red, green, blue;
+ 
+         src = rpng2_info.row_pointers[row];
+         if (bg_image)
+             src2 = bg_data + row*bg_rowbytes;
+         dest = ximage->data + row*ximage_rowbytes;
+         if (rpng2_info.channels == 3) {
+             for (i = rpng2_info.width;  i > 0;  --i) {
+                 red   = ((ush)(*src) << 8);
+                 ++src;
+                 green = ((ush)(*src) << 8);
+                 ++src;
+                 blue  = ((ush)(*src) << 8);
+                 ++src;
+                 pixel = ((red   >> RShift) & RMask) |
+                         ((green >> GShift) & GMask) |
+                         ((blue  >> BShift) & BMask);
+                 /* recall that we set ximage->byte_order = MSBFirst above */
+                 *dest++ = (char)((pixel >>  8) & 0xff);
+                 *dest++ = (char)( pixel        & 0xff);
+             }
+         } else /* if (rpng2_info.channels == 4) */ {
+             for (i = rpng2_info.width;  i > 0;  --i) {
+                 r = *src++;
+                 g = *src++;
+                 b = *src++;
+                 a = *src++;
+                 if (bg_image) {
+                     bg_red   = *src2++;
+                     bg_green = *src2++;
+                     bg_blue  = *src2++;
+                 }
+                 if (a == 255) {
+                     red   = ((ush)r << 8);
+                     green = ((ush)g << 8);
+                     blue  = ((ush)b << 8);
+                 } else if (a == 0) {
+                     red   = ((ush)bg_red   << 8);
+                     green = ((ush)bg_green << 8);
+                     blue  = ((ush)bg_blue  << 8);
+                 } else {
+                     /* this macro (from png.h) composites the foreground
+                      * and background values and puts the result back into
+                      * the first argument (== fg byte here:  safe) */
+                     alpha_composite(r, r, a, bg_red);
+                     alpha_composite(g, g, a, bg_green);
+                     alpha_composite(b, b, a, bg_blue);
+                     red   = ((ush)r << 8);
+                     green = ((ush)g << 8);
+                     blue  = ((ush)b << 8);
+                 }
+                 pixel = ((red   >> RShift) & RMask) |
+                         ((green >> GShift) & GMask) |
+                         ((blue  >> BShift) & BMask);
+                 /* recall that we set ximage->byte_order = MSBFirst above */
+                 *dest++ = (char)((pixel >>  8) & 0xff);
+                 *dest++ = (char)( pixel        & 0xff);
+             }
+         }
+ 
+     } else /* depth == 8 */ {
+ 
+         /* GRR:  add 8-bit support */
+ 
+     }
+ 
+ 
+ /*---------------------------------------------------------------------------
+     Display after every 16 rows or when on one of last two rows.  (Region
+     may include previously displayed lines due to interlacing--i.e., not
+     contiguous.  Also, second-to-last row is final one in interlaced images
+     with odd number of rows.)  For demos, flush (and delay) after every 16th
+     row so "sparse" passes don't go twice as fast.
+   ---------------------------------------------------------------------------*/
+ 
+     if (demo_timing && (row - firstrow >= 16 || row >= rpng2_info.height-2)) {
+         XPutImage(display, window, gc, ximage, 0, (int)firstrow, 0,
+           (int)firstrow, rpng2_info.width, row - firstrow + 1);
+         XFlush(display);
+         rows = 0;
+         usleep(usleep_duration);
+     } else
+     if (!demo_timing && ((rows & 0xf) == 0 || row >= rpng2_info.height-2)) {
+         XPutImage(display, window, gc, ximage, 0, (int)firstrow, 0,
+           (int)firstrow, rpng2_info.width, row - firstrow + 1);
+         XFlush(display);
+         rows = 0;
+     }
+ 
+ }
+ 
+ 
+ 
+ 
+ 
+ static void rpng2_x_finish_display(void)
+ {
+     Trace((stderr, "beginning rpng2_x_finish_display()\n"))
+ 
+     /* last row has already been displayed by rpng2_x_display_row(), so we
+      * have nothing to do here except set a flag and let the user know that
+      * the image is done */
+ 
+     rpng2_info.done = TRUE;
+     printf(
+       "Done.  Press Q, Esc or mouse button 1 (within image window) to quit.\n");
+     fflush(stdout);
+ }
+ 
+ 
+ 
+ 
+ 
+ static void rpng2_x_cleanup(void)
+ {
+     if (bg_image && bg_data) {
+         free(bg_data);
+         bg_data = NULL;
+     }
+ 
+     if (rpng2_info.image_data) {
+         free(rpng2_info.image_data);
+         rpng2_info.image_data = NULL;
+     }
+ 
+     if (rpng2_info.row_pointers) {
+         free(rpng2_info.row_pointers);
+         rpng2_info.row_pointers = NULL;
+     }
+ 
+     if (ximage) {
+         if (ximage->data) {
+             free(ximage->data);           /* we allocated it, so we free it */
+             ximage->data = (char *)NULL;  /*  instead of XDestroyImage() */
+         }
+         XDestroyImage(ximage);
+         ximage = NULL;
+     }
+ 
+     if (have_gc)
+         XFreeGC(display, gc);
+ 
+     if (have_window)
+         XDestroyWindow(display, window);
+ 
+     if (have_colormap)
+         XFreeColormap(display, colormap);
+ 
+     if (have_nondefault_visual)
+         XFree(visual_list);
+ }
+ 
+ 
+ 
+ 
+ 
+ static int rpng2_x_msb(ulg u32val)
+ {
+     int i;
+ 
+     for (i = 31;  i >= 0;  --i) {
+         if (u32val & 0x80000000L)
+             break;
+         u32val <<= 1;
+     }
+     return i;
+ }


Index: llvm/runtime/libpng/contrib/gregbook/toucan.png


Index: llvm/runtime/libpng/contrib/gregbook/wpng.c
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/wpng.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:56 2004
--- llvm/runtime/libpng/contrib/gregbook/wpng.c	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,816 ----
+ /*---------------------------------------------------------------------------
+ 
+    wpng - simple PNG-writing program                                 wpng.c
+ 
+    This program converts certain NetPBM binary files (grayscale and RGB,
+    maxval = 255) to PNG.  Non-interlaced PNGs are written progressively;
+    interlaced PNGs are read and written in one memory-intensive blast.
+    Thanks to Jean-loup Gailly for providing the necessary trick to read
+    interactive text from the keyboard while stdin is redirected.
+ 
+    NOTE:  includes provisional support for PNM type "8" (portable alphamap)
+           images, presumed to be a 32-bit interleaved RGBA format; no pro-
+           vision for possible interleaved grayscale+alpha (16-bit) format.
+           THIS IS UNLIKELY TO BECOME AN OFFICIAL NETPBM ALPHA FORMAT!
+ 
+    to do:
+     - delete output file if quit before calling any writepng routines
+     - process backspace with -text option under DOS/Win? (currently get ^H)
+ 
+   ---------------------------------------------------------------------------
+ 
+    Changelog:
+     - 1.01:  initial public release
+     - 1.02:  modified to allow abbreviated options
+     - 1.03:  removed extraneous character from usage screen; fixed bug in
+               command-line parsing
+ 
+   ---------------------------------------------------------------------------
+ 
+       Copyright (c) 1998-2000 Greg Roelofs.  All rights reserved.
+ 
+       This software is provided "as is," without warranty of any kind,
+       express or implied.  In no event shall the author or contributors
+       be held liable for any damages arising in any way from the use of
+       this software.
+ 
+       Permission is granted to anyone to use this software for any purpose,
+       including commercial applications, and to alter it and redistribute
+       it freely, subject to the following restrictions:
+ 
+       1. Redistributions of source code must retain the above copyright
+          notice, disclaimer, and this list of conditions.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, disclaimer, and this list of conditions in the documenta-
+          tion and/or other materials provided with the distribution.
+       3. All advertising materials mentioning features or use of this
+          software must display the following acknowledgment:
+ 
+             This product includes software developed by Greg Roelofs
+             and contributors for the book, "PNG: The Definitive Guide,"
+             published by O'Reilly and Associates.
+ 
+   ---------------------------------------------------------------------------*/
+ 
+ #define PROGNAME  "wpng"
+ #define VERSION   "1.03 of 19 March 2000"
+ #define APPNAME   "Simple PGM/PPM/PAM to PNG Converter"
+ 
+ #if defined(__MSDOS__) || defined(__OS2__)
+ #  define DOS_OS2_W32
+ #elif defined(_WIN32) || defined(__WIN32__)
+ #  define DOS_OS2_W32
+ #endif
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <setjmp.h>     /* for jmpbuf declaration in writepng.h */
+ #include <time.h>
+ 
+ #ifdef DOS_OS2_W32
+ #  include <io.h>       /* for isatty(), setmode() prototypes */
+ #  include <fcntl.h>    /* O_BINARY for fdopen() without text translation */
+ #  ifdef __EMX__
+ #    ifndef getch
+ #      define getch() _read_kbd(0, 1, 0)    /* need getche() */
+ #    endif
+ #  else /* !__EMX__ */
+ #    ifdef __GO32__
+ #      include <pc.h>
+ #      define getch() getkey()  /* GRR:  need getche() */
+ #    else
+ #      include <conio.h>        /* for getche() console input */
+ #    endif
+ #  endif /* ?__EMX__ */
+ #  define FGETS(buf,len,stream)  dos_kbd_gets(buf,len)
+ #else
+ #  include <unistd.h>           /* for isatty() prototype */
+ #  define FGETS fgets
+ #endif
+ 
+ /* #define DEBUG  :  this enables the Trace() macros */
+ 
+ /* #define FORBID_LATIN1_CTRL  :  this requires the user to re-enter any
+    text that includes control characters discouraged by the PNG spec; text
+    that includes an escape character (27) must be re-entered regardless */
+ 
+ #include "writepng.h"   /* typedefs, common macros, writepng prototypes */
+ 
+ 
+ 
+ /* local prototypes */
+ 
+ static int  wpng_isvalid_latin1(uch *p, int len);
+ static void wpng_cleanup(void);
+ 
+ #ifdef DOS_OS2_W32
+    static char *dos_kbd_gets(char *buf, int len);
+ #endif
+ 
+ 
+ 
+ static mainprog_info wpng_info;   /* lone global */
+ 
+ 
+ 
+ int main(int argc, char **argv)
+ {
+ #ifndef DOS_OS2_W32
+     FILE *keybd;
+ #endif
+ #ifdef sgi
+     FILE *tmpfile;      /* or we could just use keybd, since no overlap */
+     char tmpline[80];
+ #endif
+     char *inname = NULL, outname[256];
+     char *p, pnmchar, pnmline[256];
+     char *bgstr, *textbuf = NULL;
+     ulg rowbytes;
+     int rc, len = 0;
+     int error = 0;
+     int text = FALSE;
+     int maxval;
+     double LUT_exponent;                /* just the lookup table */
+     double CRT_exponent = 2.2;          /* just the monitor */
+     double default_display_exponent;    /* whole display system */
+     double default_gamma = 0.0;
+ 
+ 
+     wpng_info.infile = NULL;
+     wpng_info.outfile = NULL;
+     wpng_info.image_data = NULL;
+     wpng_info.row_pointers = NULL;
+     wpng_info.filter = FALSE;
+     wpng_info.interlaced = FALSE;
+     wpng_info.have_bg = FALSE;
+     wpng_info.have_time = FALSE;
+     wpng_info.have_text = 0;
+     wpng_info.gamma = 0.0;
+ 
+ 
+     /* First get the default value for our display-system exponent, i.e.,
+      * the product of the CRT exponent and the exponent corresponding to
+      * the frame-buffer's lookup table (LUT), if any.  If the PNM image
+      * looks correct on the user's display system, its file gamma is the
+      * inverse of this value.  (Note that this is not an exhaustive list
+      * of LUT values--e.g., OpenStep has a lot of weird ones--but it should
+      * cover 99% of the current possibilities.  This section must ensure
+      * that default_display_exponent is positive.) */
+ 
+ #if defined(NeXT)
+     /* third-party utilities can modify the default LUT exponent */
+     LUT_exponent = 1.0 / 2.2;
+     /*
+     if (some_next_function_that_returns_gamma(&next_gamma))
+         LUT_exponent = 1.0 / next_gamma;
+      */
+ #elif defined(sgi)
+     LUT_exponent = 1.0 / 1.7;
+     /* there doesn't seem to be any documented function to
+      * get the "gamma" value, so we do it the hard way */
+     tmpfile = fopen("/etc/config/system.glGammaVal", "r");
+     if (tmpfile) {
+         double sgi_gamma;
+ 
+         fgets(tmpline, 80, tmpfile);
+         fclose(tmpfile);
+         sgi_gamma = atof(tmpline);
+         if (sgi_gamma > 0.0)
+             LUT_exponent = 1.0 / sgi_gamma;
+     }
+ #elif defined(Macintosh)
+     LUT_exponent = 1.8 / 2.61;
+     /*
+     if (some_mac_function_that_returns_gamma(&mac_gamma))
+         LUT_exponent = mac_gamma / 2.61;
+      */
+ #else
+     LUT_exponent = 1.0;   /* assume no LUT:  most PCs */
+ #endif
+ 
+     /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
+     default_display_exponent = LUT_exponent * CRT_exponent;
+ 
+ 
+     /* If the user has set the SCREEN_GAMMA environment variable as suggested
+      * (somewhat imprecisely) in the libpng documentation, use that; otherwise
+      * use the default value we just calculated.  Either way, the user may
+      * override this via a command-line option. */
+ 
+     if ((p = getenv("SCREEN_GAMMA")) != NULL) {
+         double exponent = atof(p);
+ 
+         if (exponent > 0.0)
+             default_gamma = 1.0 / exponent;
+     }
+ 
+     if (default_gamma == 0.0)
+         default_gamma = 1.0 / default_display_exponent;
+ 
+ 
+     /* Now parse the command line for options and the PNM filename. */
+ 
+     while (*++argv && !error) {
+         if (!strncmp(*argv, "-i", 2)) {
+             wpng_info.interlaced = TRUE;
+         } else if (!strncmp(*argv, "-time", 3)) {
+             wpng_info.modtime = time(NULL);
+             wpng_info.have_time = TRUE;
+         } else if (!strncmp(*argv, "-text", 3)) {
+             text = TRUE;
+         } else if (!strncmp(*argv, "-gamma", 2)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 wpng_info.gamma = atof(*argv);
+                 if (wpng_info.gamma <= 0.0)
+                     ++error;
+                 else if (wpng_info.gamma > 1.01)
+                     fprintf(stderr, PROGNAME
+                       " warning:  file gammas are usually less than 1.0\n");
+             }
+         } else if (!strncmp(*argv, "-bgcolor", 4)) {
+             if (!*++argv)
+                 ++error;
+             else {
+                 bgstr = *argv;
+                 if (strlen(bgstr) != 7 || bgstr[0] != '#')
+                     ++error;
+                 else {
+                     unsigned r, g, b;  /* this way quiets compiler warnings */
+ 
+                     sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
+                     wpng_info.bg_red   = (uch)r;
+                     wpng_info.bg_green = (uch)g;
+                     wpng_info.bg_blue  = (uch)b;
+                     wpng_info.have_bg = TRUE;
+                 }
+             }
+         } else {
+             if (**argv != '-') {
+                 inname = *argv;
+                 if (argv[1])   /* shouldn't be any more args after filename */
+                     ++error;
+             } else
+                 ++error;   /* not expecting any other options */
+         }
+     }
+ 
+ 
+     /* open the input and output files, or register an error and abort */
+ 
+     if (!inname) {
+         if (isatty(0)) {
+             fprintf(stderr, PROGNAME
+               ":  must give input filename or provide image data via stdin\n");
+             ++error;
+         } else {
+ #ifdef DOS_OS2_W32
+             /* some buggy C libraries require BOTH setmode() and fdopen(bin) */
+             setmode(fileno(stdin), O_BINARY);
+             setmode(fileno(stdout), O_BINARY);
+ #endif
+             if ((wpng_info.infile = fdopen(fileno(stdin), "rb")) == NULL) {
+                 fprintf(stderr, PROGNAME
+                   ":  unable to reopen stdin in binary mode\n");
+                 ++error;
+             } else
+             if ((wpng_info.outfile = fdopen(fileno(stdout), "wb")) == NULL) {
+                 fprintf(stderr, PROGNAME
+                   ":  unable to reopen stdout in binary mode\n");
+                 fclose(wpng_info.infile);
+                 ++error;
+             } else
+                 wpng_info.filter = TRUE;
+         }
+     } else if ((len = strlen(inname)) > 250) {
+         fprintf(stderr, PROGNAME ":  input filename is too long [%d chars]\n",
+           len);
+         ++error;
+     } else if (!(wpng_info.infile = fopen(inname, "rb"))) {
+         fprintf(stderr, PROGNAME ":  can't open input file [%s]\n", inname);
+         ++error;
+     }
+ 
+     if (!error) {
+         fgets(pnmline, 256, wpng_info.infile);
+         if (pnmline[0] != 'P' || ((pnmchar = pnmline[1]) != '5' &&
+             pnmchar != '6' && pnmchar != '8'))
+         {
+             fprintf(stderr, PROGNAME
+               ":  input file [%s] is not a binary PGM, PPM or PAM file\n",
+               inname);
+             ++error;
+         } else {
+             wpng_info.pnmtype = (int)(pnmchar - '0');
+             if (wpng_info.pnmtype != 8)
+                 wpng_info.have_bg = FALSE;  /* no need for bg if opaque */
+             do {
+                 fgets(pnmline, 256, wpng_info.infile);  /* lose any comments */
+             } while (pnmline[0] == '#');
+             sscanf(pnmline, "%ld %ld", &wpng_info.width, &wpng_info.height);
+             do {
+                 fgets(pnmline, 256, wpng_info.infile);  /* more comment lines */
+             } while (pnmline[0] == '#');
+             sscanf(pnmline, "%d", &maxval);
+             if (wpng_info.width <= 0L || wpng_info.height <= 0L ||
+                 maxval != 255)
+             {
+                 fprintf(stderr, PROGNAME
+                   ":  only positive width/height, maxval == 255 allowed \n");
+                 ++error;
+             }
+             wpng_info.sample_depth = 8;  /* <==> maxval 255 */
+ 
+             if (!wpng_info.filter) {
+                 /* make outname from inname */
+                 if ((p = strrchr(inname, '.')) == NULL ||
+                     (p - inname) != (len - 4))
+                 {
+                     strcpy(outname, inname);
+                     strcpy(outname+len, ".png");
+                 } else {
+                     len -= 4;
+                     strncpy(outname, inname, len);
+                     strcpy(outname+len, ".png");
+                 }
+                 /* check if outname already exists; if not, open */
+                 if ((wpng_info.outfile = fopen(outname, "rb")) != NULL) {
+                     fprintf(stderr, PROGNAME ":  output file exists [%s]\n",
+                       outname);
+                     fclose(wpng_info.outfile);
+                     ++error;
+                 } else if (!(wpng_info.outfile = fopen(outname, "wb"))) {
+                     fprintf(stderr, PROGNAME ":  can't open output file [%s]\n",
+                       outname);
+                     ++error;
+                 }
+             }
+         }
+         if (error) {
+             fclose(wpng_info.infile);
+             wpng_info.infile = NULL;
+             if (wpng_info.filter) {
+                 fclose(wpng_info.outfile);
+                 wpng_info.outfile = NULL;
+             }
+         }
+     }
+ 
+ 
+     /* if we had any errors, print usage and die horrible death...arrr! */
+ 
+     if (error) {
+         fprintf(stderr, "\n%s %s:  %s\n", PROGNAME, VERSION, APPNAME);
+         writepng_version_info();
+         fprintf(stderr, "\n"
+ "Usage:  %s [-gamma exp] [-bgcolor bg] [-text] [-time] [-interlace] pnmfile\n"
+ "or: ... | %s [-gamma exp] [-bgcolor bg] [-text] [-time] [-interlace] | ...\n"
+          "    exp \ttransfer-function exponent (``gamma'') of the image in\n"
+          "\t\t  floating-point format (e.g., ``%.5f''); if image looks\n"
+          "\t\t  correct on given display system, image gamma is equal to\n"
+          "\t\t  inverse of display-system exponent, i.e., 1 / (LUT * CRT)\n"
+          "\t\t  (where LUT = lookup-table exponent and CRT = CRT exponent;\n"
+          "\t\t  first varies, second is usually 2.2, all are positive)\n"
+          "    bg  \tdesired background color for alpha-channel images, in\n"
+          "\t\t  7-character hex RGB format (e.g., ``#ff7700'' for orange:\n"
+          "\t\t  same as HTML colors)\n"
+          "    -text\tprompt interactively for text info (tEXt chunks)\n"
+          "    -time\tinclude a tIME chunk (last modification time)\n"
+          "    -interlace\twrite interlaced PNG image\n"
+          "\n"
+ "pnmfile or stdin must be a binary PGM (`P5'), PPM (`P6') or (extremely\n"
+ "unofficial and unsupported!) PAM (`P8') file.  Currently it is required\n"
+ "to have maxval == 255 (i.e., no scaling).  If pnmfile is specified, it\n"
+ "is converted to the corresponding PNG file with the same base name but a\n"
+ "``.png'' extension; files read from stdin are converted and sent to stdout.\n"
+ "The conversion is progressive (low memory usage) unless interlacing is\n"
+ "requested; in that case the whole image will be buffered in memory and\n"
+ "written in one call.\n"
+          "\n", PROGNAME, PROGNAME, default_gamma);
+         exit(1);
+     }
+ 
+ 
+     /* prepare the text buffers for libpng's use; note that even though
+      * PNG's png_text struct includes a length field, we don't have to fill
+      * it out */
+ 
+     if (text &&
+ #ifndef DOS_OS2_W32
+         (keybd = fdopen(fileno(stderr), "r")) != NULL &&
+ #endif
+         (textbuf = (char *)malloc((5 + 9)*75)) != NULL)
+     {
+         int i, valid, result;
+ 
+         fprintf(stderr,
+           "Enter text info (no more than 72 characters per line);\n");
+         fprintf(stderr, "to skip a field, hit the <Enter> key.\n");
+         /* note:  just <Enter> leaves len == 1 */
+ 
+         do {
+             valid = TRUE;
+             p = textbuf + TEXT_TITLE_OFFSET;
+             fprintf(stderr, "  Title: ");
+             fflush(stderr);
+             if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
+                 if (p[len-1] == '\n')
+                     p[--len] = '\0';
+                 wpng_info.title = p;
+                 wpng_info.have_text |= TEXT_TITLE;
+                 if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
+                     fprintf(stderr, "    " PROGNAME " warning:  character code"
+                       " %u is %sdiscouraged by the PNG\n    specification "
+                       "[first occurrence was at character position #%d]\n",
+                       (unsigned)p[result], (p[result] == 27)? "strongly " : "",
+                       result+1);
+                     fflush(stderr);
+ #ifdef FORBID_LATIN1_CTRL
+                     wpng_info.have_text &= ~TEXT_TITLE;
+                     valid = FALSE;
+ #else
+                     if (p[result] == 27) {    /* escape character */
+                         wpng_info.have_text &= ~TEXT_TITLE;
+                         valid = FALSE;
+                     }
+ #endif
+                 }
+             }
+         } while (!valid);
+ 
+         do {
+             valid = TRUE;
+             p = textbuf + TEXT_AUTHOR_OFFSET;
+             fprintf(stderr, "  Author: ");
+             fflush(stderr);
+             if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
+                 if (p[len-1] == '\n')
+                     p[--len] = '\0';
+                 wpng_info.author = p;
+                 wpng_info.have_text |= TEXT_AUTHOR;
+                 if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
+                     fprintf(stderr, "    " PROGNAME " warning:  character code"
+                       " %u is %sdiscouraged by the PNG\n    specification "
+                       "[first occurrence was at character position #%d]\n",
+                       (unsigned)p[result], (p[result] == 27)? "strongly " : "",
+                       result+1);
+                     fflush(stderr);
+ #ifdef FORBID_LATIN1_CTRL
+                     wpng_info.have_text &= ~TEXT_AUTHOR;
+                     valid = FALSE;
+ #else
+                     if (p[result] == 27) {    /* escape character */
+                         wpng_info.have_text &= ~TEXT_AUTHOR;
+                         valid = FALSE;
+                     }
+ #endif
+                 }
+             }
+         } while (!valid);
+ 
+         do {
+             valid = TRUE;
+             p = textbuf + TEXT_DESC_OFFSET;
+             fprintf(stderr, "  Description (up to 9 lines):\n");
+             for (i = 1;  i < 10;  ++i) {
+                 fprintf(stderr, "    [%d] ", i);
+                 fflush(stderr);
+                 if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1)
+                     p += len;   /* now points at NULL; char before is newline */
+                 else
+                     break;
+             }
+             if ((len = p - (textbuf + TEXT_DESC_OFFSET)) > 1) {
+                 if (p[-1] == '\n') {
+                     p[-1] = '\0';
+                     --len;
+                 }
+                 wpng_info.desc = textbuf + TEXT_DESC_OFFSET;
+                 wpng_info.have_text |= TEXT_DESC;
+                 p = textbuf + TEXT_DESC_OFFSET;
+                 if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
+                     fprintf(stderr, "    " PROGNAME " warning:  character code"
+                       " %u is %sdiscouraged by the PNG\n    specification "
+                       "[first occurrence was at character position #%d]\n",
+                       (unsigned)p[result], (p[result] == 27)? "strongly " : "",
+                       result+1);
+                     fflush(stderr);
+ #ifdef FORBID_LATIN1_CTRL
+                     wpng_info.have_text &= ~TEXT_DESC;
+                     valid = FALSE;
+ #else
+                     if (p[result] == 27) {    /* escape character */
+                         wpng_info.have_text &= ~TEXT_DESC;
+                         valid = FALSE;
+                     }
+ #endif
+                 }
+             }
+         } while (!valid);
+ 
+         do {
+             valid = TRUE;
+             p = textbuf + TEXT_COPY_OFFSET;
+             fprintf(stderr, "  Copyright: ");
+             fflush(stderr);
+             if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
+                 if (p[len-1] == '\n')
+                     p[--len] = '\0';
+                 wpng_info.copyright = p;
+                 wpng_info.have_text |= TEXT_COPY;
+                 if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
+                     fprintf(stderr, "    " PROGNAME " warning:  character code"
+                       " %u is %sdiscouraged by the PNG\n    specification "
+                       "[first occurrence was at character position #%d]\n",
+                       (unsigned)p[result], (p[result] == 27)? "strongly " : "",
+                       result+1);
+                     fflush(stderr);
+ #ifdef FORBID_LATIN1_CTRL
+                     wpng_info.have_text &= ~TEXT_COPY;
+                     valid = FALSE;
+ #else
+                     if (p[result] == 27) {    /* escape character */
+                         wpng_info.have_text &= ~TEXT_COPY;
+                         valid = FALSE;
+                     }
+ #endif
+                 }
+             }
+         } while (!valid);
+ 
+         do {
+             valid = TRUE;
+             p = textbuf + TEXT_EMAIL_OFFSET;
+             fprintf(stderr, "  E-mail: ");
+             fflush(stderr);
+             if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
+                 if (p[len-1] == '\n')
+                     p[--len] = '\0';
+                 wpng_info.email = p;
+                 wpng_info.have_text |= TEXT_EMAIL;
+                 if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
+                     fprintf(stderr, "    " PROGNAME " warning:  character code"
+                       " %u is %sdiscouraged by the PNG\n    specification "
+                       "[first occurrence was at character position #%d]\n",
+                       (unsigned)p[result], (p[result] == 27)? "strongly " : "",
+                       result+1);
+                     fflush(stderr);
+ #ifdef FORBID_LATIN1_CTRL
+                     wpng_info.have_text &= ~TEXT_EMAIL;
+                     valid = FALSE;
+ #else
+                     if (p[result] == 27) {    /* escape character */
+                         wpng_info.have_text &= ~TEXT_EMAIL;
+                         valid = FALSE;
+                     }
+ #endif
+                 }
+             }
+         } while (!valid);
+ 
+         do {
+             valid = TRUE;
+             p = textbuf + TEXT_URL_OFFSET;
+             fprintf(stderr, "  URL: ");
+             fflush(stderr);
+             if (FGETS(p, 74, keybd) && (len = strlen(p)) > 1) {
+                 if (p[len-1] == '\n')
+                     p[--len] = '\0';
+                 wpng_info.url = p;
+                 wpng_info.have_text |= TEXT_URL;
+                 if ((result = wpng_isvalid_latin1((uch *)p, len)) >= 0) {
+                     fprintf(stderr, "    " PROGNAME " warning:  character code"
+                       " %u is %sdiscouraged by the PNG\n    specification "
+                       "[first occurrence was at character position #%d]\n",
+                       (unsigned)p[result], (p[result] == 27)? "strongly " : "",
+                       result+1);
+                     fflush(stderr);
+ #ifdef FORBID_LATIN1_CTRL
+                     wpng_info.have_text &= ~TEXT_URL;
+                     valid = FALSE;
+ #else
+                     if (p[result] == 27) {    /* escape character */
+                         wpng_info.have_text &= ~TEXT_URL;
+                         valid = FALSE;
+                     }
+ #endif
+                 }
+             }
+         } while (!valid);
+ 
+ #ifndef DOS_OS2_W32
+         fclose(keybd);
+ #endif
+ 
+     } else if (text) {
+         fprintf(stderr, PROGNAME ":  unable to allocate memory for text\n");
+         text = FALSE;
+         wpng_info.have_text = 0;
+     }
+ 
+ 
+     /* allocate libpng stuff, initialize transformations, write pre-IDAT data */
+ 
+     if ((rc = writepng_init(&wpng_info)) != 0) {
+         switch (rc) {
+             case 2:
+                 fprintf(stderr, PROGNAME
+                   ":  libpng initialization problem (longjmp)\n");
+                 break;
+             case 4:
+                 fprintf(stderr, PROGNAME ":  insufficient memory\n");
+                 break;
+             case 11:
+                 fprintf(stderr, PROGNAME
+                   ":  internal logic error (unexpected PNM type)\n");
+                 break;
+             default:
+                 fprintf(stderr, PROGNAME
+                   ":  unknown writepng_init() error\n");
+                 break;
+         }
+         exit(rc);
+     }
+ 
+ 
+     /* free textbuf, since it's a completely local variable and all text info
+      * has just been written to the PNG file */
+ 
+     if (text && textbuf) {
+         free(textbuf);
+         textbuf = NULL;
+     }
+ 
+ 
+     /* calculate rowbytes on basis of image type; note that this becomes much
+      * more complicated if we choose to support PBM type, ASCII PNM types, or
+      * 16-bit-per-sample binary data [currently not an official NetPBM type] */
+ 
+     if (wpng_info.pnmtype == 5)
+         rowbytes = wpng_info.width;
+     else if (wpng_info.pnmtype == 6)
+         rowbytes = wpng_info.width * 3;
+     else /* if (wpng_info.pnmtype == 8) */
+         rowbytes = wpng_info.width * 4;
+ 
+ 
+     /* read and write the image, either in its entirety (if writing interlaced
+      * PNG) or row by row (if non-interlaced) */
+ 
+     fprintf(stderr, "Encoding image data...\n");
+     fflush(stderr);
+ 
+     if (wpng_info.interlaced) {
+         long i;
+         ulg bytes;
+         ulg image_bytes = rowbytes * wpng_info.height;   /* overflow? */
+ 
+         wpng_info.image_data = (uch *)malloc(image_bytes);
+         wpng_info.row_pointers = (uch **)malloc(wpng_info.height*sizeof(uch *));
+         if (wpng_info.image_data == NULL || wpng_info.row_pointers == NULL) {
+             fprintf(stderr, PROGNAME ":  insufficient memory for image data\n");
+             writepng_cleanup(&wpng_info);
+             wpng_cleanup();
+             exit(5);
+         }
+         for (i = 0;  i < wpng_info.height;  ++i)
+             wpng_info.row_pointers[i] = wpng_info.image_data + i*rowbytes;
+         bytes = fread(wpng_info.image_data, 1, image_bytes, wpng_info.infile);
+         if (bytes != image_bytes) {
+             fprintf(stderr, PROGNAME ":  expected %lu bytes, got %lu bytes\n",
+               image_bytes, bytes);
+             fprintf(stderr, "  (continuing anyway)\n");
+         }
+         if (writepng_encode_image(&wpng_info) != 0) {
+             fprintf(stderr, PROGNAME
+               ":  libpng problem (longjmp) while writing image data\n");
+             writepng_cleanup(&wpng_info);
+             wpng_cleanup();
+             exit(2);
+         }
+ 
+     } else /* not interlaced:  write progressively (row by row) */ {
+         long j;
+         ulg bytes;
+ 
+         wpng_info.image_data = (uch *)malloc(rowbytes);
+         if (wpng_info.image_data == NULL) {
+             fprintf(stderr, PROGNAME ":  insufficient memory for row data\n");
+             writepng_cleanup(&wpng_info);
+             wpng_cleanup();
+             exit(5);
+         }
+         error = 0;
+         for (j = wpng_info.height;  j > 0L;  --j) {
+             bytes = fread(wpng_info.image_data, 1, rowbytes, wpng_info.infile);
+             if (bytes != rowbytes) {
+                 fprintf(stderr, PROGNAME
+                   ":  expected %lu bytes, got %lu bytes (row %ld)\n", rowbytes,
+                   bytes, wpng_info.height-j);
+                 ++error;
+                 break;
+             }
+             if (writepng_encode_row(&wpng_info) != 0) {
+                 fprintf(stderr, PROGNAME
+                   ":  libpng problem (longjmp) while writing row %ld\n",
+                   wpng_info.height-j);
+                 ++error;
+                 break;
+             }
+         }
+         if (error) {
+             writepng_cleanup(&wpng_info);
+             wpng_cleanup();
+             exit(2);
+         }
+         if (writepng_encode_finish(&wpng_info) != 0) {
+             fprintf(stderr, PROGNAME ":  error on final libpng call\n");
+             writepng_cleanup(&wpng_info);
+             wpng_cleanup();
+             exit(2);
+         }
+     }
+ 
+ 
+     /* OK, we're done (successfully):  clean up all resources and quit */
+ 
+     fprintf(stderr, "Done.\n");
+     fflush(stderr);
+ 
+     writepng_cleanup(&wpng_info);
+     wpng_cleanup();
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ 
+ static int wpng_isvalid_latin1(uch *p, int len)
+ {
+     int i, result = -1;
+ 
+     for (i = 0;  i < len;  ++i) {
+         if (p[i] == 10 || (p[i] > 31 && p[i] < 127) || p[i] > 160)
+             continue;           /* character is completely OK */
+         if (result < 0 || (p[result] != 27 && p[i] == 27))
+             result = i;         /* mark location of first questionable one */
+     }                           /*  or of first escape character (bad) */
+ 
+     return result;
+ }
+ 
+ 
+ 
+ 
+ 
+ static void wpng_cleanup(void)
+ {
+     if (wpng_info.outfile) {
+         fclose(wpng_info.outfile);
+         wpng_info.outfile = NULL;
+     }
+ 
+     if (wpng_info.infile) {
+         fclose(wpng_info.infile);
+         wpng_info.infile = NULL;
+     }
+ 
+     if (wpng_info.image_data) {
+         free(wpng_info.image_data);
+         wpng_info.image_data = NULL;
+     }
+ 
+     if (wpng_info.row_pointers) {
+         free(wpng_info.row_pointers);
+         wpng_info.row_pointers = NULL;
+     }
+ }
+ 
+ 
+ 
+ 
+ #ifdef DOS_OS2_W32
+ 
+ static char *dos_kbd_gets(char *buf, int len)
+ {
+     int ch, count=0;
+ 
+     do {
+         buf[count++] = ch = getche();
+     } while (ch != '\r' && count < len-1);
+ 
+     buf[count--] = '\0';        /* terminate string */
+     if (buf[count] == '\r')     /* Enter key makes CR, so change to newline */
+         buf[count] = '\n';
+ 
+     fprintf(stderr, "\n");      /* Enter key does *not* cause a newline */
+     fflush(stderr);
+ 
+     return buf;
+ }
+ 
+ #endif /* DOS_OS2_W32 */


Index: llvm/runtime/libpng/contrib/gregbook/writepng.c
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/writepng.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:56 2004
--- llvm/runtime/libpng/contrib/gregbook/writepng.c	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,368 ----
+ /*---------------------------------------------------------------------------
+ 
+    wpng - simple PNG-writing program                             writepng.c
+ 
+   ---------------------------------------------------------------------------
+ 
+       Copyright (c) 1998-2000 Greg Roelofs.  All rights reserved.
+ 
+       This software is provided "as is," without warranty of any kind,
+       express or implied.  In no event shall the author or contributors
+       be held liable for any damages arising in any way from the use of
+       this software.
+ 
+       Permission is granted to anyone to use this software for any purpose,
+       including commercial applications, and to alter it and redistribute
+       it freely, subject to the following restrictions:
+ 
+       1. Redistributions of source code must retain the above copyright
+          notice, disclaimer, and this list of conditions.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, disclaimer, and this list of conditions in the documenta-
+          tion and/or other materials provided with the distribution.
+       3. All advertising materials mentioning features or use of this
+          software must display the following acknowledgment:
+ 
+             This product includes software developed by Greg Roelofs
+             and contributors for the book, "PNG: The Definitive Guide,"
+             published by O'Reilly and Associates.
+ 
+   ---------------------------------------------------------------------------*/
+ 
+ 
+ #include <stdlib.h>     /* for exit() prototype */
+ 
+ #include "png.h"        /* libpng header; includes zlib.h and setjmp.h */
+ #include "writepng.h"   /* typedefs, common macros, public prototypes */
+ 
+ 
+ /* local prototype */
+ 
+ static void writepng_error_handler(png_structp png_ptr, png_const_charp msg);
+ 
+ 
+ 
+ void writepng_version_info(void)
+ {
+   fprintf(stderr, "   Compiled with libpng %s; using libpng %s.\n",
+     PNG_LIBPNG_VER_STRING, png_libpng_ver);
+   fprintf(stderr, "   Compiled with zlib %s; using zlib %s.\n",
+     ZLIB_VERSION, zlib_version);
+ }
+ 
+ 
+ 
+ 
+ /* returns 0 for success, 2 for libpng problem, 4 for out of memory, 11 for
+  *  unexpected pnmtype; note that outfile might be stdout */
+ 
+ int writepng_init(mainprog_info *mainprog_ptr)
+ {
+     png_structp  png_ptr;       /* note:  temporary variables! */
+     png_infop  info_ptr;
+     int color_type, interlace_type;
+ 
+ 
+     /* could also replace libpng warning-handler (final NULL), but no need: */
+ 
+     png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr,
+       writepng_error_handler, NULL);
+     if (!png_ptr)
+         return 4;   /* out of memory */
+ 
+     info_ptr = png_create_info_struct(png_ptr);
+     if (!info_ptr) {
+         png_destroy_write_struct(&png_ptr, NULL);
+         return 4;   /* out of memory */
+     }
+ 
+ 
+     /* setjmp() must be called in every function that calls a PNG-writing
+      * libpng function, unless an alternate error handler was installed--
+      * but compatible error handlers must either use longjmp() themselves
+      * (as in this program) or exit immediately, so here we go: */
+ 
+     if (setjmp(mainprog_ptr->jmpbuf)) {
+         png_destroy_write_struct(&png_ptr, &info_ptr);
+         return 2;
+     }
+ 
+ 
+     /* make sure outfile is (re)opened in BINARY mode */
+ 
+     png_init_io(png_ptr, mainprog_ptr->outfile);
+ 
+ 
+     /* set the compression levels--in general, always want to leave filtering
+      * turned on (except for palette images) and allow all of the filters,
+      * which is the default; want 32K zlib window, unless entire image buffer
+      * is 16K or smaller (unknown here)--also the default; usually want max
+      * compression (NOT the default); and remaining compression flags should
+      * be left alone */
+ 
+     png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
+ /*
+     >> this is default for no filtering; Z_FILTERED is default otherwise:
+     png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
+     >> these are all defaults:
+     png_set_compression_mem_level(png_ptr, 8);
+     png_set_compression_window_bits(png_ptr, 15);
+     png_set_compression_method(png_ptr, 8);
+  */
+ 
+ 
+     /* set the image parameters appropriately */
+ 
+     if (mainprog_ptr->pnmtype == 5)
+         color_type = PNG_COLOR_TYPE_GRAY;
+     else if (mainprog_ptr->pnmtype == 6)
+         color_type = PNG_COLOR_TYPE_RGB;
+     else if (mainprog_ptr->pnmtype == 8)
+         color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+     else {
+         png_destroy_write_struct(&png_ptr, &info_ptr);
+         return 11;
+     }
+ 
+     interlace_type = mainprog_ptr->interlaced? PNG_INTERLACE_ADAM7 :
+                                                PNG_INTERLACE_NONE;
+ 
+     png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height,
+       mainprog_ptr->sample_depth, color_type, interlace_type,
+       PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+ 
+     if (mainprog_ptr->gamma > 0.0)
+         png_set_gAMA(png_ptr, info_ptr, mainprog_ptr->gamma);
+ 
+     if (mainprog_ptr->have_bg) {   /* we know it's RGBA, not gray+alpha */
+         png_color_16  background;
+ 
+         background.red = mainprog_ptr->bg_red;
+         background.green = mainprog_ptr->bg_green;
+         background.blue = mainprog_ptr->bg_blue;
+         png_set_bKGD(png_ptr, info_ptr, &background);
+     }
+ 
+     if (mainprog_ptr->have_time) {
+         png_time  modtime;
+ 
+         png_convert_from_time_t(&modtime, mainprog_ptr->modtime);
+         png_set_tIME(png_ptr, info_ptr, &modtime);
+     }
+ 
+     if (mainprog_ptr->have_text) {
+         png_text  text[6];
+         int  num_text = 0;
+ 
+         if (mainprog_ptr->have_text & TEXT_TITLE) {
+             text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
+             text[num_text].key = "Title";
+             text[num_text].text = mainprog_ptr->title;
+             ++num_text;
+         }
+         if (mainprog_ptr->have_text & TEXT_AUTHOR) {
+             text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
+             text[num_text].key = "Author";
+             text[num_text].text = mainprog_ptr->author;
+             ++num_text;
+         }
+         if (mainprog_ptr->have_text & TEXT_DESC) {
+             text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
+             text[num_text].key = "Description";
+             text[num_text].text = mainprog_ptr->desc;
+             ++num_text;
+         }
+         if (mainprog_ptr->have_text & TEXT_COPY) {
+             text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
+             text[num_text].key = "Copyright";
+             text[num_text].text = mainprog_ptr->copyright;
+             ++num_text;
+         }
+         if (mainprog_ptr->have_text & TEXT_EMAIL) {
+             text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
+             text[num_text].key = "E-mail";
+             text[num_text].text = mainprog_ptr->email;
+             ++num_text;
+         }
+         if (mainprog_ptr->have_text & TEXT_URL) {
+             text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
+             text[num_text].key = "URL";
+             text[num_text].text = mainprog_ptr->url;
+             ++num_text;
+         }
+         png_set_text(png_ptr, info_ptr, text, num_text);
+     }
+ 
+ 
+     /* write all chunks up to (but not including) first IDAT */
+ 
+     png_write_info(png_ptr, info_ptr);
+ 
+ 
+     /* if we wanted to write any more text info *after* the image data, we
+      * would set up text struct(s) here and call png_set_text() again, with
+      * just the new data; png_set_tIME() could also go here, but it would
+      * have no effect since we already called it above (only one tIME chunk
+      * allowed) */
+ 
+ 
+     /* set up the transformations:  for now, just pack low-bit-depth pixels
+      * into bytes (one, two or four pixels per byte) */
+ 
+     png_set_packing(png_ptr);
+ /*  png_set_shift(png_ptr, &sig_bit);  to scale low-bit-depth values */
+ 
+ 
+     /* make sure we save our pointers for use in writepng_encode_image() */
+ 
+     mainprog_ptr->png_ptr = png_ptr;
+     mainprog_ptr->info_ptr = info_ptr;
+ 
+ 
+     /* OK, that's all we need to do for now; return happy */
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ 
+ /* returns 0 for success, 2 for libpng (longjmp) problem */
+ 
+ int writepng_encode_image(mainprog_info *mainprog_ptr)
+ {
+     png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
+     png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
+ 
+ 
+     /* as always, setjmp() must be called in every function that calls a
+      * PNG-writing libpng function */
+ 
+     if (setjmp(mainprog_ptr->jmpbuf)) {
+         png_destroy_write_struct(&png_ptr, &info_ptr);
+         mainprog_ptr->png_ptr = NULL;
+         mainprog_ptr->info_ptr = NULL;
+         return 2;
+     }
+ 
+ 
+     /* and now we just write the whole image; libpng takes care of interlacing
+      * for us */
+ 
+     png_write_image(png_ptr, mainprog_ptr->row_pointers);
+ 
+ 
+     /* since that's it, we also close out the end of the PNG file now--if we
+      * had any text or time info to write after the IDATs, second argument
+      * would be info_ptr, but we optimize slightly by sending NULL pointer: */
+ 
+     png_write_end(png_ptr, NULL);
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ 
+ /* returns 0 if succeeds, 2 if libpng problem */
+ 
+ int writepng_encode_row(mainprog_info *mainprog_ptr)  /* NON-interlaced only! */
+ {
+     png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
+     png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
+ 
+ 
+     /* as always, setjmp() must be called in every function that calls a
+      * PNG-writing libpng function */
+ 
+     if (setjmp(mainprog_ptr->jmpbuf)) {
+         png_destroy_write_struct(&png_ptr, &info_ptr);
+         mainprog_ptr->png_ptr = NULL;
+         mainprog_ptr->info_ptr = NULL;
+         return 2;
+     }
+ 
+ 
+     /* image_data points at our one row of image data */
+ 
+     png_write_row(png_ptr, mainprog_ptr->image_data);
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ 
+ /* returns 0 if succeeds, 2 if libpng problem */
+ 
+ int writepng_encode_finish(mainprog_info *mainprog_ptr)   /* NON-interlaced! */
+ {
+     png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
+     png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
+ 
+ 
+     /* as always, setjmp() must be called in every function that calls a
+      * PNG-writing libpng function */
+ 
+     if (setjmp(mainprog_ptr->jmpbuf)) {
+         png_destroy_write_struct(&png_ptr, &info_ptr);
+         mainprog_ptr->png_ptr = NULL;
+         mainprog_ptr->info_ptr = NULL;
+         return 2;
+     }
+ 
+ 
+     /* close out PNG file; if we had any text or time info to write after
+      * the IDATs, second argument would be info_ptr: */
+ 
+     png_write_end(png_ptr, NULL);
+ 
+     return 0;
+ }
+ 
+ 
+ 
+ 
+ 
+ void writepng_cleanup(mainprog_info *mainprog_ptr)
+ {
+     png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
+     png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
+ 
+     if (png_ptr && info_ptr)
+         png_destroy_write_struct(&png_ptr, &info_ptr);
+ }
+ 
+ 
+ 
+ 
+ 
+ static void writepng_error_handler(png_structp png_ptr, png_const_charp msg)
+ {
+     mainprog_info  *mainprog_ptr;
+ 
+     /* This function, aside from the extra step of retrieving the "error
+      * pointer" (below) and the fact that it exists within the application
+      * rather than within libpng, is essentially identical to libpng's
+      * default error handler.  The second point is critical:  since both
+      * setjmp() and longjmp() are called from the same code, they are
+      * guaranteed to have compatible notions of how big a jmp_buf is,
+      * regardless of whether _BSD_SOURCE or anything else has (or has not)
+      * been defined. */
+ 
+     fprintf(stderr, "writepng libpng error: %s\n", msg);
+     fflush(stderr);
+ 
+     mainprog_ptr = png_get_error_ptr(png_ptr);
+     if (mainprog_ptr == NULL) {         /* we are completely hosed now */
+         fprintf(stderr,
+           "writepng severe error:  jmpbuf not recoverable; terminating.\n");
+         fflush(stderr);
+         exit(99);
+     }
+ 
+     longjmp(mainprog_ptr->jmpbuf, 1);
+ }


Index: llvm/runtime/libpng/contrib/gregbook/writepng.h
diff -c /dev/null llvm/runtime/libpng/contrib/gregbook/writepng.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:56 2004
--- llvm/runtime/libpng/contrib/gregbook/writepng.h	Mon Mar  1 17:58:45 2004
***************
*** 0 ****
--- 1,109 ----
+ /*---------------------------------------------------------------------------
+ 
+    wpng - simple PNG-writing program                             writepng.h
+ 
+   ---------------------------------------------------------------------------
+ 
+       Copyright (c) 1998-2000 Greg Roelofs.  All rights reserved.
+ 
+       This software is provided "as is," without warranty of any kind,
+       express or implied.  In no event shall the author or contributors
+       be held liable for any damages arising in any way from the use of
+       this software.
+ 
+       Permission is granted to anyone to use this software for any purpose,
+       including commercial applications, and to alter it and redistribute
+       it freely, subject to the following restrictions:
+ 
+       1. Redistributions of source code must retain the above copyright
+          notice, disclaimer, and this list of conditions.
+       2. Redistributions in binary form must reproduce the above copyright
+          notice, disclaimer, and this list of conditions in the documenta-
+          tion and/or other materials provided with the distribution.
+       3. All advertising materials mentioning features or use of this
+          software must display the following acknowledgment:
+ 
+             This product includes software developed by Greg Roelofs
+             and contributors for the book, "PNG: The Definitive Guide,"
+             published by O'Reilly and Associates.
+ 
+   ---------------------------------------------------------------------------*/
+ 
+ #ifndef TRUE
+ #  define TRUE 1
+ #  define FALSE 0
+ #endif
+ 
+ #ifndef MAX
+ #  define MAX(a,b)  ((a) > (b)? (a) : (b))
+ #  define MIN(a,b)  ((a) < (b)? (a) : (b))
+ #endif
+ 
+ #ifdef DEBUG
+ #  define Trace(x)  {fprintf x ; fflush(stderr); fflush(stdout);}
+ #else
+ #  define Trace(x)  ;
+ #endif
+ 
+ #define TEXT_TITLE    0x01
+ #define TEXT_AUTHOR   0x02
+ #define TEXT_DESC     0x04
+ #define TEXT_COPY     0x08
+ #define TEXT_EMAIL    0x10
+ #define TEXT_URL      0x20
+ 
+ #define TEXT_TITLE_OFFSET        0
+ #define TEXT_AUTHOR_OFFSET      72
+ #define TEXT_COPY_OFFSET     (2*72)
+ #define TEXT_EMAIL_OFFSET    (3*72)
+ #define TEXT_URL_OFFSET      (4*72)
+ #define TEXT_DESC_OFFSET     (5*72)
+ 
+ typedef unsigned char   uch;
+ typedef unsigned short  ush;
+ typedef unsigned long   ulg;
+ 
+ typedef struct _mainprog_info {
+     double gamma;
+     long width;
+     long height;
+     time_t modtime;
+     FILE *infile;
+     FILE *outfile;
+     void *png_ptr;
+     void *info_ptr;
+     uch *image_data;
+     uch **row_pointers;
+     char *title;
+     char *author;
+     char *desc;
+     char *copyright;
+     char *email;
+     char *url;
+     int filter;    /* command-line-filter flag, not PNG row filter! */
+     int pnmtype;
+     int sample_depth;
+     int interlaced;
+     int have_bg;
+     int have_time;
+     int have_text;
+     jmp_buf jmpbuf;
+     uch bg_red;
+     uch bg_green;
+     uch bg_blue;
+ } mainprog_info;
+ 
+ 
+ /* prototypes for public functions in writepng.c */
+ 
+ void writepng_version_info(void);
+ 
+ int writepng_init(mainprog_info *mainprog_ptr);
+ 
+ int writepng_encode_image(mainprog_info *mainprog_ptr);
+ 
+ int writepng_encode_row(mainprog_info *mainprog_ptr);
+ 
+ int writepng_encode_finish(mainprog_info *mainprog_ptr);
+ 
+ void writepng_cleanup(mainprog_info *mainprog_ptr);





More information about the llvm-commits mailing list