From 373dc625f82b47096893add42c4472e4a57ab7eb Mon Sep 17 00:00:00 2001 From: Aki Date: Wed, 9 Feb 2022 22:23:03 +0100 Subject: Moved third-party libraries to a separate subdirectory --- contrib/CMakeLists.txt | 5 + contrib/Opcode/CMakeLists.txt | 55 + contrib/Opcode/Doc/OpcodeUserManual.pdf | Bin 0 -> 39653 bytes contrib/Opcode/Ice/IceAABB.cpp | 405 + contrib/Opcode/Ice/IceAABB.h | 505 + contrib/Opcode/Ice/IceAxes.h | 54 + contrib/Opcode/Ice/IceBoundingSphere.h | 142 + contrib/Opcode/Ice/IceContainer.cpp | 357 + contrib/Opcode/Ice/IceContainer.h | 212 + contrib/Opcode/Ice/IceFPU.h | 237 + contrib/Opcode/Ice/IceHPoint.cpp | 70 + contrib/Opcode/Ice/IceHPoint.h | 157 + contrib/Opcode/Ice/IceIndexedTriangle.cpp | 548 + contrib/Opcode/Ice/IceIndexedTriangle.h | 64 + contrib/Opcode/Ice/IceLSS.h | 75 + contrib/Opcode/Ice/IceMatrix3x3.cpp | 48 + contrib/Opcode/Ice/IceMatrix3x3.h | 496 + contrib/Opcode/Ice/IceMatrix4x4.cpp | 135 + contrib/Opcode/Ice/IceMatrix4x4.h | 455 + contrib/Opcode/Ice/IceMemoryMacros.h | 89 + contrib/Opcode/Ice/IceOBB.cpp | 323 + contrib/Opcode/Ice/IceOBB.h | 177 + contrib/Opcode/Ice/IcePairs.h | 45 + contrib/Opcode/Ice/IcePlane.cpp | 45 + contrib/Opcode/Ice/IcePlane.h | 113 + contrib/Opcode/Ice/IcePoint.cpp | 193 + contrib/Opcode/Ice/IcePoint.h | 528 + contrib/Opcode/Ice/IcePreprocessor.h | 128 + contrib/Opcode/Ice/IceRandom.cpp | 35 + contrib/Opcode/Ice/IceRandom.h | 42 + contrib/Opcode/Ice/IceRay.cpp | 84 + contrib/Opcode/Ice/IceRay.h | 98 + contrib/Opcode/Ice/IceRevisitedRadix.cpp | 520 + contrib/Opcode/Ice/IceRevisitedRadix.h | 65 + contrib/Opcode/Ice/IceSegment.cpp | 57 + contrib/Opcode/Ice/IceSegment.h | 55 + contrib/Opcode/Ice/IceTriangle.cpp | 286 + contrib/Opcode/Ice/IceTriangle.h | 68 + contrib/Opcode/Ice/IceTrilist.h | 61 + contrib/Opcode/Ice/IceTypes.h | 157 + contrib/Opcode/Ice/IceUtils.cpp | 39 + contrib/Opcode/Ice/IceUtils.h | 256 + contrib/Opcode/OPC_AABBCollider.cpp | 696 + contrib/Opcode/OPC_AABBCollider.h | 97 + contrib/Opcode/OPC_AABBTree.cpp | 573 + contrib/Opcode/OPC_AABBTree.h | 137 + contrib/Opcode/OPC_BaseModel.cpp | 138 + contrib/Opcode/OPC_BaseModel.h | 175 + contrib/Opcode/OPC_BoxBoxOverlap.h | 122 + contrib/Opcode/OPC_BoxPruning.cpp | 367 + contrib/Opcode/OPC_BoxPruning.h | 31 + contrib/Opcode/OPC_Collider.cpp | 54 + contrib/Opcode/OPC_Collider.h | 176 + contrib/Opcode/OPC_Common.cpp | 48 + contrib/Opcode/OPC_Common.h | 101 + contrib/Opcode/OPC_HybridModel.cpp | 466 + contrib/Opcode/OPC_HybridModel.h | 106 + contrib/Opcode/OPC_IceHook.h | 70 + contrib/Opcode/OPC_LSSAABBOverlap.h | 523 + contrib/Opcode/OPC_LSSCollider.cpp | 725 + contrib/Opcode/OPC_LSSCollider.h | 99 + contrib/Opcode/OPC_LSSTriOverlap.h | 679 + contrib/Opcode/OPC_MeshInterface.cpp | 299 + contrib/Opcode/OPC_MeshInterface.h | 182 + contrib/Opcode/OPC_Model.cpp | 222 + contrib/Opcode/OPC_Model.h | 65 + contrib/Opcode/OPC_OBBCollider.cpp | 767 + contrib/Opcode/OPC_OBBCollider.h | 142 + contrib/Opcode/OPC_OptimizedTree.cpp | 782 + contrib/Opcode/OPC_OptimizedTree.h | 206 + contrib/Opcode/OPC_Picking.cpp | 182 + contrib/Opcode/OPC_Picking.h | 45 + contrib/Opcode/OPC_PlanesAABBOverlap.h | 50 + contrib/Opcode/OPC_PlanesCollider.cpp | 653 + contrib/Opcode/OPC_PlanesCollider.h | 121 + contrib/Opcode/OPC_PlanesTriOverlap.h | 40 + contrib/Opcode/OPC_RayAABBOverlap.h | 63 + contrib/Opcode/OPC_RayCollider.cpp | 762 + contrib/Opcode/OPC_RayCollider.h | 225 + contrib/Opcode/OPC_RayTriOverlap.h | 89 + contrib/Opcode/OPC_Settings.h | 49 + contrib/Opcode/OPC_SphereAABBOverlap.h | 128 + contrib/Opcode/OPC_SphereCollider.cpp | 726 + contrib/Opcode/OPC_SphereCollider.h | 96 + contrib/Opcode/OPC_SphereTriOverlap.h | 187 + contrib/Opcode/OPC_SweepAndPrune.cpp | 664 + contrib/Opcode/OPC_SweepAndPrune.h | 86 + contrib/Opcode/OPC_TreeBuilders.cpp | 255 + contrib/Opcode/OPC_TreeBuilders.h | 173 + contrib/Opcode/OPC_TreeCollider.cpp | 943 ++ contrib/Opcode/OPC_TreeCollider.h | 244 + contrib/Opcode/OPC_TriBoxOverlap.h | 339 + contrib/Opcode/OPC_TriTriOverlap.h | 279 + contrib/Opcode/OPC_VolumeCollider.cpp | 103 + contrib/Opcode/OPC_VolumeCollider.h | 138 + contrib/Opcode/Opcode.cpp | 65 + contrib/Opcode/Opcode.h | 68 + contrib/Opcode/ReadMe.txt | 171 + contrib/Opcode/StdAfx.cpp | 10 + contrib/Opcode/StdAfx.h | 24 + contrib/Opcode/TemporalCoherence.txt | 32 + contrib/libpng/ANNOUNCE | 96 + contrib/libpng/CHANGES | 3253 ++++ contrib/libpng/CMakeLists.txt | 303 + contrib/libpng/INSTALL | 135 + contrib/libpng/LICENSE | 111 + contrib/libpng/Makefile.am | 211 + contrib/libpng/Makefile.in | 1375 ++ contrib/libpng/README | 205 + contrib/libpng/TODO | 27 + contrib/libpng/aclocal.m4 | 9430 +++++++++++ contrib/libpng/autogen.sh | 34 + contrib/libpng/config.guess | 1501 ++ contrib/libpng/config.h.in | 86 + contrib/libpng/config.sub | 1705 ++ contrib/libpng/configure | 14885 +++++++++++++++++ contrib/libpng/configure.ac | 167 + contrib/libpng/contrib/gregbook/COPYING | 340 + contrib/libpng/contrib/gregbook/LICENSE | 50 + contrib/libpng/contrib/gregbook/Makefile.mingw32 | 130 + contrib/libpng/contrib/gregbook/Makefile.sgi | 104 + contrib/libpng/contrib/gregbook/Makefile.unx | 132 + contrib/libpng/contrib/gregbook/Makefile.w32 | 113 + contrib/libpng/contrib/gregbook/README | 186 + contrib/libpng/contrib/gregbook/makevms.com | 132 + contrib/libpng/contrib/gregbook/readpng.c | 305 + contrib/libpng/contrib/gregbook/readpng.h | 88 + contrib/libpng/contrib/gregbook/readpng2.c | 505 + contrib/libpng/contrib/gregbook/readpng2.h | 116 + contrib/libpng/contrib/gregbook/readppm.c | 179 + contrib/libpng/contrib/gregbook/rpng-win.c | 728 + contrib/libpng/contrib/gregbook/rpng-x.c | 904 ++ contrib/libpng/contrib/gregbook/rpng2-win.c | 1253 ++ contrib/libpng/contrib/gregbook/rpng2-x.c | 2107 +++ contrib/libpng/contrib/gregbook/toucan.png | Bin 0 -> 12901 bytes contrib/libpng/contrib/gregbook/wpng.c | 853 + contrib/libpng/contrib/gregbook/writepng.c | 400 + contrib/libpng/contrib/gregbook/writepng.h | 133 + contrib/libpng/contrib/pngminim/README | 4 + contrib/libpng/contrib/pngminim/decoder/README | 10 + contrib/libpng/contrib/pngminim/decoder/makefile | 149 + contrib/libpng/contrib/pngminim/decoder/pngusr.dfa | 39 + contrib/libpng/contrib/pngminim/decoder/pngusr.h | 23 + contrib/libpng/contrib/pngminim/encoder/README | 10 + contrib/libpng/contrib/pngminim/encoder/makefile | 148 + contrib/libpng/contrib/pngminim/encoder/pngusr.dfa | 35 + contrib/libpng/contrib/pngminim/encoder/pngusr.h | 23 + contrib/libpng/contrib/pngminim/preader/README | 15 + contrib/libpng/contrib/pngminim/preader/makefile | 164 + contrib/libpng/contrib/pngminim/preader/pngusr.dfa | 40 + contrib/libpng/contrib/pngminim/preader/pngusr.h | 23 + contrib/libpng/contrib/pngminus/README | 153 + contrib/libpng/contrib/pngminus/makefile.std | 65 + contrib/libpng/contrib/pngminus/makefile.tc3 | 38 + contrib/libpng/contrib/pngminus/makevms.com | 92 + contrib/libpng/contrib/pngminus/png2pnm.bat | 41 + contrib/libpng/contrib/pngminus/png2pnm.c | 430 + contrib/libpng/contrib/pngminus/png2pnm.sh | 42 + contrib/libpng/contrib/pngminus/pngminus.bat | 4 + contrib/libpng/contrib/pngminus/pngminus.sh | 5 + contrib/libpng/contrib/pngminus/pnm2png.bat | 41 + contrib/libpng/contrib/pngminus/pnm2png.c | 533 + contrib/libpng/contrib/pngminus/pnm2png.sh | 42 + contrib/libpng/contrib/pngsuite/README | 102 + contrib/libpng/contrib/pngsuite/basn0g01.png | Bin 0 -> 164 bytes contrib/libpng/contrib/pngsuite/basn0g02.png | Bin 0 -> 104 bytes contrib/libpng/contrib/pngsuite/basn0g04.png | Bin 0 -> 145 bytes contrib/libpng/contrib/pngsuite/basn0g08.png | Bin 0 -> 138 bytes contrib/libpng/contrib/pngsuite/basn0g16.png | Bin 0 -> 167 bytes contrib/libpng/contrib/pngsuite/basn2c08.png | Bin 0 -> 145 bytes contrib/libpng/contrib/pngsuite/basn2c16.png | Bin 0 -> 302 bytes contrib/libpng/contrib/pngsuite/basn3p01.png | Bin 0 -> 112 bytes contrib/libpng/contrib/pngsuite/basn3p02.png | Bin 0 -> 146 bytes contrib/libpng/contrib/pngsuite/basn3p04.png | Bin 0 -> 216 bytes contrib/libpng/contrib/pngsuite/basn3p08.png | Bin 0 -> 1286 bytes contrib/libpng/contrib/pngsuite/basn4a08.png | Bin 0 -> 126 bytes contrib/libpng/contrib/pngsuite/basn4a16.png | Bin 0 -> 2206 bytes contrib/libpng/contrib/pngsuite/basn6a08.png | Bin 0 -> 184 bytes contrib/libpng/contrib/pngsuite/basn6a16.png | Bin 0 -> 3435 bytes contrib/libpng/contrib/pngsuite/ftbbn1g04.png | Bin 0 -> 429 bytes contrib/libpng/contrib/pngsuite/ftbbn2c16.png | Bin 0 -> 2041 bytes contrib/libpng/contrib/pngsuite/ftbbn3p08.png | Bin 0 -> 1499 bytes contrib/libpng/contrib/pngsuite/ftbgn2c16.png | Bin 0 -> 2041 bytes contrib/libpng/contrib/pngsuite/ftbgn3p08.png | Bin 0 -> 1499 bytes contrib/libpng/contrib/pngsuite/ftbrn2c08.png | Bin 0 -> 1633 bytes contrib/libpng/contrib/pngsuite/ftbwn1g16.png | Bin 0 -> 1313 bytes contrib/libpng/contrib/pngsuite/ftbwn3p08.png | Bin 0 -> 1496 bytes contrib/libpng/contrib/pngsuite/ftbyn3p08.png | Bin 0 -> 1499 bytes contrib/libpng/contrib/pngsuite/ftp0n1g08.png | Bin 0 -> 719 bytes contrib/libpng/contrib/pngsuite/ftp0n2c08.png | Bin 0 -> 1594 bytes contrib/libpng/contrib/pngsuite/ftp0n3p08.png | Bin 0 -> 1476 bytes contrib/libpng/contrib/pngsuite/ftp1n3p08.png | Bin 0 -> 1483 bytes contrib/libpng/contrib/visupng/PngFile.c | 442 + contrib/libpng/contrib/visupng/PngFile.h | 30 + contrib/libpng/contrib/visupng/README.txt | 61 + contrib/libpng/contrib/visupng/VisualPng.c | 964 ++ contrib/libpng/contrib/visupng/VisualPng.dsp | 147 + contrib/libpng/contrib/visupng/VisualPng.dsw | 29 + contrib/libpng/contrib/visupng/VisualPng.ico | Bin 0 -> 766 bytes contrib/libpng/contrib/visupng/VisualPng.png | Bin 0 -> 208 bytes contrib/libpng/contrib/visupng/VisualPng.rc | 152 + contrib/libpng/contrib/visupng/cexcept.h | 248 + contrib/libpng/contrib/visupng/resource.h | 23 + contrib/libpng/depcomp | 630 + contrib/libpng/example.c | 843 + contrib/libpng/install-sh | 520 + contrib/libpng/libpng-config.in | 127 + contrib/libpng/libpng-manual.txt | 4136 +++++ contrib/libpng/libpng.3 | 5376 +++++++ contrib/libpng/libpng.pc.in | 11 + contrib/libpng/libpngpf.3 | 30 + contrib/libpng/ltmain.sh | 9636 +++++++++++ contrib/libpng/missing | 376 + contrib/libpng/png.5 | 74 + contrib/libpng/png.c | 2362 +++ contrib/libpng/png.h | 2280 +++ contrib/libpng/pngbar.jpg | Bin 0 -> 2498 bytes contrib/libpng/pngbar.png | Bin 0 -> 2399 bytes contrib/libpng/pngconf.h | 632 + contrib/libpng/pngdebug.h | 157 + contrib/libpng/pngerror.c | 447 + contrib/libpng/pngget.c | 1032 ++ contrib/libpng/pnginfo.h | 270 + contrib/libpng/pngmem.c | 658 + contrib/libpng/pngnow.png | Bin 0 -> 2069 bytes contrib/libpng/pngpread.c | 1854 +++ contrib/libpng/pngpriv.h | 1239 ++ contrib/libpng/pngread.c | 1466 ++ contrib/libpng/pngrio.c | 176 + contrib/libpng/pngrtran.c | 4224 +++++ contrib/libpng/pngrutil.c | 3616 +++++ contrib/libpng/pngset.c | 1225 ++ contrib/libpng/pngstruct.h | 308 + contrib/libpng/pngtest.c | 1787 +++ contrib/libpng/pngtest.png | Bin 0 -> 8665 bytes contrib/libpng/pngtrans.c | 723 + contrib/libpng/pngvalid.c | 6658 ++++++++ contrib/libpng/pngwio.c | 254 + contrib/libpng/pngwrite.c | 1605 ++ contrib/libpng/pngwtran.c | 631 + contrib/libpng/pngwutil.c | 2948 ++++ contrib/libpng/projects/visualc71/PRJ0041.mak | 21 + contrib/libpng/projects/visualc71/README.txt | 58 + contrib/libpng/projects/visualc71/README_zlib.txt | 44 + contrib/libpng/projects/visualc71/libpng.sln | 60 + contrib/libpng/projects/visualc71/libpng.vcproj | 419 + contrib/libpng/projects/visualc71/pngtest.vcproj | 267 + contrib/libpng/projects/visualc71/zlib.vcproj | 391 + .../libpng/projects/vstudio/libpng/libpng.vcxproj | 233 + .../projects/vstudio/pnglibconf/pnglibconf.vcxproj | 60 + .../projects/vstudio/pngtest/pngtest.vcxproj | 219 + .../projects/vstudio/pngvalid/pngvalid.vcxproj | 219 + contrib/libpng/projects/vstudio/readme.txt | 64 + contrib/libpng/projects/vstudio/vstudio.sln | 79 + contrib/libpng/projects/vstudio/zlib.props | 30 + contrib/libpng/projects/vstudio/zlib/zlib.vcxproj | 174 + contrib/libpng/scripts/README.txt | 77 + contrib/libpng/scripts/SCOPTIONS.ppc | 7 + contrib/libpng/scripts/checksym.awk | 161 + contrib/libpng/scripts/chkfmt | 137 + contrib/libpng/scripts/def.dfn | 38 + contrib/libpng/scripts/descrip.mms | 52 + contrib/libpng/scripts/libpng-config-body.in | 96 + contrib/libpng/scripts/libpng-config-head.in | 24 + contrib/libpng/scripts/libpng.pc.in | 10 + contrib/libpng/scripts/makefile.32sunu | 241 + contrib/libpng/scripts/makefile.64sunu | 241 + contrib/libpng/scripts/makefile.acorn | 57 + contrib/libpng/scripts/makefile.aix | 121 + contrib/libpng/scripts/makefile.amiga | 56 + contrib/libpng/scripts/makefile.atari | 63 + contrib/libpng/scripts/makefile.bc32 | 151 + contrib/libpng/scripts/makefile.beos | 215 + contrib/libpng/scripts/makefile.bor | 161 + contrib/libpng/scripts/makefile.cegcc | 116 + contrib/libpng/scripts/makefile.darwin | 219 + contrib/libpng/scripts/makefile.dec | 202 + contrib/libpng/scripts/makefile.dj2 | 62 + contrib/libpng/scripts/makefile.elf | 263 + contrib/libpng/scripts/makefile.freebsd | 53 + contrib/libpng/scripts/makefile.gcc | 87 + contrib/libpng/scripts/makefile.hp64 | 224 + contrib/libpng/scripts/makefile.hpgcc | 230 + contrib/libpng/scripts/makefile.hpux | 221 + contrib/libpng/scripts/makefile.ibmc | 82 + contrib/libpng/scripts/makefile.intel | 110 + contrib/libpng/scripts/makefile.knr | 109 + contrib/libpng/scripts/makefile.linux | 239 + contrib/libpng/scripts/makefile.mips | 94 + contrib/libpng/scripts/makefile.msc | 95 + contrib/libpng/scripts/makefile.ne12bsd | 50 + contrib/libpng/scripts/makefile.netbsd | 50 + contrib/libpng/scripts/makefile.openbsd | 82 + contrib/libpng/scripts/makefile.sco | 218 + contrib/libpng/scripts/makefile.sggcc | 228 + contrib/libpng/scripts/makefile.sgi | 229 + contrib/libpng/scripts/makefile.so9 | 239 + contrib/libpng/scripts/makefile.solaris | 236 + contrib/libpng/scripts/makefile.solaris-x86 | 236 + contrib/libpng/scripts/makefile.std | 123 + contrib/libpng/scripts/makefile.sunos | 107 + contrib/libpng/scripts/makefile.tc3 | 93 + contrib/libpng/scripts/makefile.vcwin32 | 108 + contrib/libpng/scripts/makefile.watcom | 122 + contrib/libpng/scripts/makevms.com | 142 + contrib/libpng/scripts/options.awk | 734 + contrib/libpng/scripts/pnglibconf.dfa | 549 + contrib/libpng/scripts/pnglibconf.h.prebuilt | 176 + contrib/libpng/scripts/pnglibconf.mak | 55 + contrib/libpng/scripts/pngwin.rc | 112 + contrib/libpng/scripts/smakefile.ppc | 34 + contrib/libpng/scripts/sym.dfn | 15 + contrib/libpng/scripts/symbols.def | 228 + contrib/libpng/scripts/symbols.dfn | 57 + contrib/libpng/scripts/vers.dfn | 26 + contrib/libpng/test-pngtest.sh | 8 + contrib/libpng/test-pngvalid-full.sh | 23 + contrib/libpng/test-pngvalid-simple.sh | 30 + contrib/ogg/.gitignore | 33 + contrib/ogg/.travis.yml | 17 + contrib/ogg/AUTHORS | 7 + contrib/ogg/CHANGES | 94 + contrib/ogg/CMakeLists.txt | 107 + contrib/ogg/COPYING | 28 + contrib/ogg/Makefile.am | 32 + contrib/ogg/README.md | 131 + contrib/ogg/appveyor.yml | 19 + contrib/ogg/autogen.sh | 12 + contrib/ogg/configure.ac | 185 + contrib/ogg/doc/Makefile.am | 9 + contrib/ogg/doc/fish_xiph_org.png | Bin 0 -> 2536 bytes contrib/ogg/doc/framing.html | 429 + contrib/ogg/doc/index.html | 105 + contrib/ogg/doc/libogg/Makefile.am | 39 + contrib/ogg/doc/libogg/bitpacking.html | 103 + contrib/ogg/doc/libogg/datastructures.html | 59 + contrib/ogg/doc/libogg/decoding.html | 104 + contrib/ogg/doc/libogg/encoding.html | 76 + contrib/ogg/doc/libogg/general.html | 109 + contrib/ogg/doc/libogg/index.html | 39 + contrib/ogg/doc/libogg/ogg_iovec_t.html | 62 + contrib/ogg/doc/libogg/ogg_packet.html | 75 + contrib/ogg/doc/libogg/ogg_packet_clear.html | 64 + contrib/ogg/doc/libogg/ogg_page.html | 75 + contrib/ogg/doc/libogg/ogg_page_bos.html | 65 + contrib/ogg/doc/libogg/ogg_page_checksum_set.html | 62 + contrib/ogg/doc/libogg/ogg_page_continued.html | 64 + contrib/ogg/doc/libogg/ogg_page_eos.html | 65 + contrib/ogg/doc/libogg/ogg_page_granulepos.html | 65 + contrib/ogg/doc/libogg/ogg_page_packets.html | 75 + contrib/ogg/doc/libogg/ogg_page_pageno.html | 63 + contrib/ogg/doc/libogg/ogg_page_serialno.html | 63 + contrib/ogg/doc/libogg/ogg_page_version.html | 63 + contrib/ogg/doc/libogg/ogg_stream_check.html | 71 + contrib/ogg/doc/libogg/ogg_stream_clear.html | 61 + contrib/ogg/doc/libogg/ogg_stream_destroy.html | 71 + contrib/ogg/doc/libogg/ogg_stream_eos.html | 62 + contrib/ogg/doc/libogg/ogg_stream_flush.html | 67 + contrib/ogg/doc/libogg/ogg_stream_flush_fill.html | 74 + contrib/ogg/doc/libogg/ogg_stream_init.html | 66 + contrib/ogg/doc/libogg/ogg_stream_iovecin.html | 80 + contrib/ogg/doc/libogg/ogg_stream_packetin.html | 72 + contrib/ogg/doc/libogg/ogg_stream_packetout.html | 85 + contrib/ogg/doc/libogg/ogg_stream_packetpeek.html | 85 + contrib/ogg/doc/libogg/ogg_stream_pagein.html | 67 + contrib/ogg/doc/libogg/ogg_stream_pageout.html | 84 + .../ogg/doc/libogg/ogg_stream_pageout_fill.html | 89 + contrib/ogg/doc/libogg/ogg_stream_reset.html | 61 + .../ogg/doc/libogg/ogg_stream_reset_serialno.html | 67 + contrib/ogg/doc/libogg/ogg_stream_state.html | 121 + contrib/ogg/doc/libogg/ogg_sync_buffer.html | 67 + contrib/ogg/doc/libogg/ogg_sync_check.html | 71 + contrib/ogg/doc/libogg/ogg_sync_clear.html | 62 + contrib/ogg/doc/libogg/ogg_sync_destroy.html | 68 + contrib/ogg/doc/libogg/ogg_sync_init.html | 63 + contrib/ogg/doc/libogg/ogg_sync_pageout.html | 77 + contrib/ogg/doc/libogg/ogg_sync_pageseek.html | 68 + contrib/ogg/doc/libogg/ogg_sync_reset.html | 63 + contrib/ogg/doc/libogg/ogg_sync_state.html | 77 + contrib/ogg/doc/libogg/ogg_sync_wrote.html | 73 + contrib/ogg/doc/libogg/oggpack_adv.html | 64 + contrib/ogg/doc/libogg/oggpack_adv1.html | 62 + contrib/ogg/doc/libogg/oggpack_bits.html | 62 + contrib/ogg/doc/libogg/oggpack_buffer.html | 66 + contrib/ogg/doc/libogg/oggpack_bytes.html | 67 + contrib/ogg/doc/libogg/oggpack_get_buffer.html | 62 + contrib/ogg/doc/libogg/oggpack_look.html | 66 + contrib/ogg/doc/libogg/oggpack_look1.html | 63 + contrib/ogg/doc/libogg/oggpack_read.html | 65 + contrib/ogg/doc/libogg/oggpack_read1.html | 63 + contrib/ogg/doc/libogg/oggpack_readinit.html | 64 + contrib/ogg/doc/libogg/oggpack_reset.html | 62 + contrib/ogg/doc/libogg/oggpack_write.html | 68 + contrib/ogg/doc/libogg/oggpack_writealign.html | 65 + contrib/ogg/doc/libogg/oggpack_writecheck.html | 81 + contrib/ogg/doc/libogg/oggpack_writeclear.html | 62 + contrib/ogg/doc/libogg/oggpack_writecopy.html | 69 + contrib/ogg/doc/libogg/oggpack_writeinit.html | 62 + contrib/ogg/doc/libogg/oggpack_writetrunc.html | 65 + contrib/ogg/doc/libogg/overview.html | 44 + contrib/ogg/doc/libogg/reference.html | 98 + contrib/ogg/doc/libogg/style.css | 7 + contrib/ogg/doc/multiplex1.png | Bin 0 -> 54409 bytes contrib/ogg/doc/multiplex1.svg | 632 + contrib/ogg/doc/ogg-multiplex.html | 446 + contrib/ogg/doc/oggstream.html | 594 + contrib/ogg/doc/packets.png | Bin 0 -> 19776 bytes contrib/ogg/doc/packets.svg | 876 + contrib/ogg/doc/pages.png | Bin 0 -> 43547 bytes contrib/ogg/doc/pages.svg | 1219 ++ contrib/ogg/doc/rfc3533.txt | 843 + contrib/ogg/doc/rfc3534.txt | 339 + contrib/ogg/doc/rfc5334.txt | 787 + contrib/ogg/doc/skeleton.html | 222 + contrib/ogg/doc/stream.png | Bin 0 -> 2254 bytes contrib/ogg/doc/vorbisword2.png | Bin 0 -> 1394 bytes contrib/ogg/doc/white-ogg.png | Bin 0 -> 2652 bytes contrib/ogg/doc/white-xifish.png | Bin 0 -> 965 bytes contrib/ogg/include/Makefile.am | 3 + contrib/ogg/include/ogg/Makefile.am | 6 + contrib/ogg/include/ogg/config_types.h.in | 25 + contrib/ogg/include/ogg/ogg.h | 210 + contrib/ogg/include/ogg/os_types.h | 148 + contrib/ogg/libogg.spec.in | 109 + contrib/ogg/macosx/English.lproj/InfoPlist.strings | Bin 0 -> 136 bytes contrib/ogg/macosx/Info.plist | 30 + contrib/ogg/macosx/Ogg.xcodeproj/project.pbxproj | 363 + contrib/ogg/macosx/Ogg_Prefix.pch | 5 + contrib/ogg/ogg-uninstalled.pc.in | 14 + contrib/ogg/ogg.m4 | 116 + contrib/ogg/ogg.pc.in | 14 + contrib/ogg/releases.sha2 | 34 + contrib/ogg/src/Makefile.am | 28 + contrib/ogg/src/bitwise.c | 1088 ++ contrib/ogg/src/framing.c | 2140 +++ contrib/ogg/symbian/bld.inf | 35 + contrib/ogg/symbian/ogg.mmp | 39 + contrib/ogg/win32/.gitignore | 21 + contrib/ogg/win32/VS2015/libogg_dynamic.sln | 26 + contrib/ogg/win32/VS2015/libogg_dynamic.vcxproj | 187 + contrib/ogg/win32/VS2015/libogg_static.sln | 26 + contrib/ogg/win32/VS2015/libogg_static.vcxproj | 174 + contrib/ogg/win32/ogg.def | 80 + contrib/vorbis/.gitignore | 40 + contrib/vorbis/.travis.yml | 24 + contrib/vorbis/.ycm_extra_conf.py | 8 + contrib/vorbis/AUTHORS | 3 + contrib/vorbis/CHANGES | 165 + contrib/vorbis/CMakeLists.txt | 59 + contrib/vorbis/COPYING | 28 + contrib/vorbis/Makefile.am | 47 + contrib/vorbis/README.md | 149 + contrib/vorbis/appveyor.yml | 32 + contrib/vorbis/autogen.sh | 12 + contrib/vorbis/configure.ac | 304 + contrib/vorbis/debian/changelog | 208 + contrib/vorbis/debian/control | 60 + contrib/vorbis/debian/copyright | 38 + contrib/vorbis/debian/libvorbis-dev.docs | 1 + contrib/vorbis/debian/libvorbis-dev.examples | 2 + contrib/vorbis/debian/libvorbis-dev.install | 16 + contrib/vorbis/debian/libvorbis0a.install | 1 + contrib/vorbis/debian/libvorbisenc2.install | 1 + contrib/vorbis/debian/libvorbisfile3.install | 1 + contrib/vorbis/debian/rules | 154 + contrib/vorbis/debian/watch | 3 + contrib/vorbis/doc/01-introduction.tex | 528 + contrib/vorbis/doc/02-bitpacking.tex | 246 + contrib/vorbis/doc/03-codebook.tex | 456 + contrib/vorbis/doc/04-codec.tex | 660 + contrib/vorbis/doc/05-comment.tex | 239 + contrib/vorbis/doc/06-floor0.tex | 201 + contrib/vorbis/doc/07-floor1.tex | 404 + contrib/vorbis/doc/08-residue.tex | 451 + contrib/vorbis/doc/09-helper.tex | 180 + contrib/vorbis/doc/10-tables.tex | 76 + contrib/vorbis/doc/Doxyfile.in | 1142 ++ contrib/vorbis/doc/Makefile.am | 148 + contrib/vorbis/doc/Vorbis_I_spec.cfg | 4 + contrib/vorbis/doc/Vorbis_I_spec.css | 144 + contrib/vorbis/doc/Vorbis_I_spec.html | 13243 ++++++++++++++++ contrib/vorbis/doc/Vorbis_I_spec.pdf | Bin 0 -> 418532 bytes contrib/vorbis/doc/Vorbis_I_spec.tex | 141 + contrib/vorbis/doc/Vorbis_I_spec0x.png | Bin 0 -> 1341 bytes contrib/vorbis/doc/Vorbis_I_spec10x.png | Bin 0 -> 3781 bytes contrib/vorbis/doc/Vorbis_I_spec11x.png | Bin 0 -> 3825 bytes contrib/vorbis/doc/Vorbis_I_spec12x.png | Bin 0 -> 3371 bytes contrib/vorbis/doc/Vorbis_I_spec13x.png | Bin 0 -> 1768 bytes contrib/vorbis/doc/Vorbis_I_spec14x.png | Bin 0 -> 1792 bytes contrib/vorbis/doc/Vorbis_I_spec1x.png | Bin 0 -> 556 bytes contrib/vorbis/doc/Vorbis_I_spec2x.png | Bin 0 -> 556 bytes contrib/vorbis/doc/Vorbis_I_spec3x.png | Bin 0 -> 556 bytes contrib/vorbis/doc/Vorbis_I_spec4x.png | Bin 0 -> 556 bytes contrib/vorbis/doc/Vorbis_I_spec5x.png | Bin 0 -> 556 bytes contrib/vorbis/doc/Vorbis_I_spec6x.png | Bin 0 -> 557 bytes contrib/vorbis/doc/Vorbis_I_spec7x.png | Bin 0 -> 2436 bytes contrib/vorbis/doc/Vorbis_I_spec8x.png | Bin 0 -> 2569 bytes contrib/vorbis/doc/Vorbis_I_spec9x.png | Bin 0 -> 1819 bytes contrib/vorbis/doc/a1-encapsulation-ogg.tex | 184 + contrib/vorbis/doc/a2-encapsulation-rtp.tex | 8 + contrib/vorbis/doc/components.png | Bin 0 -> 9741 bytes contrib/vorbis/doc/eightphase.png | Bin 0 -> 11130 bytes contrib/vorbis/doc/fish_xiph_org.png | Bin 0 -> 2503 bytes contrib/vorbis/doc/floor1-1.png | Bin 0 -> 3420 bytes contrib/vorbis/doc/floor1-2.png | Bin 0 -> 3752 bytes contrib/vorbis/doc/floor1-3.png | Bin 0 -> 4627 bytes contrib/vorbis/doc/floor1-4.png | Bin 0 -> 4163 bytes contrib/vorbis/doc/floor1_inverse_dB_table.html | 154 + contrib/vorbis/doc/floorval.png | Bin 0 -> 2545 bytes contrib/vorbis/doc/footer.tex | 31 + contrib/vorbis/doc/fourphase.png | Bin 0 -> 9992 bytes contrib/vorbis/doc/framing.html | 431 + contrib/vorbis/doc/helper.html | 239 + contrib/vorbis/doc/hufftree-under.png | Bin 0 -> 1206 bytes contrib/vorbis/doc/hufftree.png | Bin 0 -> 1228 bytes contrib/vorbis/doc/index.html | 114 + contrib/vorbis/doc/libvorbis/Makefile.am | 24 + contrib/vorbis/doc/libvorbis/index.html | 44 + contrib/vorbis/doc/libvorbis/overview.html | 136 + contrib/vorbis/doc/libvorbis/reference.html | 86 + contrib/vorbis/doc/libvorbis/return.html | 79 + contrib/vorbis/doc/libvorbis/style.css | 7 + contrib/vorbis/doc/libvorbis/vorbis_analysis.html | 86 + .../doc/libvorbis/vorbis_analysis_blockout.html | 79 + .../doc/libvorbis/vorbis_analysis_buffer.html | 74 + .../doc/libvorbis/vorbis_analysis_headerout.html | 83 + .../vorbis/doc/libvorbis/vorbis_analysis_init.html | 66 + .../doc/libvorbis/vorbis_analysis_wrote.html | 80 + .../doc/libvorbis/vorbis_bitrate_addblock.html | 74 + .../doc/libvorbis/vorbis_bitrate_flushpacket.html | 80 + contrib/vorbis/doc/libvorbis/vorbis_block.html | 60 + .../vorbis/doc/libvorbis/vorbis_block_clear.html | 61 + .../vorbis/doc/libvorbis/vorbis_block_init.html | 66 + contrib/vorbis/doc/libvorbis/vorbis_comment.html | 80 + .../vorbis/doc/libvorbis/vorbis_comment_add.html | 70 + .../doc/libvorbis/vorbis_comment_add_tag.html | 74 + .../vorbis/doc/libvorbis/vorbis_comment_clear.html | 69 + .../vorbis/doc/libvorbis/vorbis_comment_init.html | 72 + .../vorbis/doc/libvorbis/vorbis_comment_query.html | 72 + .../doc/libvorbis/vorbis_comment_query_count.html | 66 + .../doc/libvorbis/vorbis_commentheader_out.html | 65 + contrib/vorbis/doc/libvorbis/vorbis_dsp_clear.html | 63 + contrib/vorbis/doc/libvorbis/vorbis_dsp_state.html | 57 + .../vorbis/doc/libvorbis/vorbis_granule_time.html | 65 + contrib/vorbis/doc/libvorbis/vorbis_info.html | 80 + .../doc/libvorbis/vorbis_info_blocksize.html | 66 + .../vorbis/doc/libvorbis/vorbis_info_clear.html | 61 + contrib/vorbis/doc/libvorbis/vorbis_info_init.html | 62 + .../doc/libvorbis/vorbis_packet_blocksize.html | 66 + contrib/vorbis/doc/libvorbis/vorbis_synthesis.html | 70 + .../doc/libvorbis/vorbis_synthesis_blockin.html | 69 + .../doc/libvorbis/vorbis_synthesis_halfrate.html | 68 + .../doc/libvorbis/vorbis_synthesis_halfrate_p.html | 64 + .../doc/libvorbis/vorbis_synthesis_headerin.html | 80 + .../doc/libvorbis/vorbis_synthesis_idheader.html | 63 + .../doc/libvorbis/vorbis_synthesis_init.html | 69 + .../doc/libvorbis/vorbis_synthesis_lapout.html | 74 + .../doc/libvorbis/vorbis_synthesis_pcmout.html | 75 + .../doc/libvorbis/vorbis_synthesis_read.html | 67 + .../doc/libvorbis/vorbis_synthesis_restart.html | 64 + .../doc/libvorbis/vorbis_synthesis_trackonly.html | 71 + .../doc/libvorbis/vorbis_version_string.html | 56 + contrib/vorbis/doc/oggstream.html | 234 + contrib/vorbis/doc/programming.html | 554 + contrib/vorbis/doc/release.txt | 16 + contrib/vorbis/doc/residue-pack.png | Bin 0 -> 32318 bytes contrib/vorbis/doc/residue2.png | Bin 0 -> 20427 bytes contrib/vorbis/doc/rfc5215.txt | 1459 ++ contrib/vorbis/doc/rfc5215.xml | 1176 ++ contrib/vorbis/doc/squarepolar.png | Bin 0 -> 8406 bytes contrib/vorbis/doc/stereo.html | 419 + contrib/vorbis/doc/stream.png | Bin 0 -> 2171 bytes contrib/vorbis/doc/v-comment.html | 285 + contrib/vorbis/doc/vorbis-clip.txt | 139 + contrib/vorbis/doc/vorbis-errors.txt | 103 + contrib/vorbis/doc/vorbis-fidelity.html | 180 + contrib/vorbis/doc/vorbisenc/Makefile.am | 11 + contrib/vorbis/doc/vorbisenc/changes.html | 104 + contrib/vorbis/doc/vorbisenc/examples.html | 133 + contrib/vorbis/doc/vorbisenc/index.html | 40 + .../doc/vorbisenc/ovectl_ratemanage2_arg.html | 92 + .../doc/vorbisenc/ovectl_ratemanage_arg.html | 92 + contrib/vorbis/doc/vorbisenc/overview.html | 382 + contrib/vorbis/doc/vorbisenc/reference.html | 54 + contrib/vorbis/doc/vorbisenc/style.css | 7 + .../vorbis/doc/vorbisenc/vorbis_encode_ctl.html | 183 + .../vorbis/doc/vorbisenc/vorbis_encode_init.html | 88 + .../doc/vorbisenc/vorbis_encode_init_vbr.html | 81 + .../doc/vorbisenc/vorbis_encode_setup_init.html | 88 + .../doc/vorbisenc/vorbis_encode_setup_managed.html | 102 + .../doc/vorbisenc/vorbis_encode_setup_vbr.html | 90 + contrib/vorbis/doc/vorbisfile/Makefile.am | 25 + contrib/vorbis/doc/vorbisfile/OggVorbis_File.html | 137 + contrib/vorbis/doc/vorbisfile/callbacks.html | 121 + .../vorbis/doc/vorbisfile/chaining_example_c.html | 90 + contrib/vorbis/doc/vorbisfile/chainingexample.html | 175 + contrib/vorbis/doc/vorbisfile/crosslap.html | 121 + contrib/vorbis/doc/vorbisfile/datastructures.html | 61 + contrib/vorbis/doc/vorbisfile/decoding.html | 92 + contrib/vorbis/doc/vorbisfile/example.html | 208 + contrib/vorbis/doc/vorbisfile/exampleindex.html | 39 + contrib/vorbis/doc/vorbisfile/fileinfo.html | 95 + contrib/vorbis/doc/vorbisfile/index.html | 49 + contrib/vorbis/doc/vorbisfile/initialization.html | 118 + contrib/vorbis/doc/vorbisfile/ov_bitrate.html | 72 + .../vorbis/doc/vorbisfile/ov_bitrate_instant.html | 65 + contrib/vorbis/doc/vorbisfile/ov_callbacks.html | 117 + contrib/vorbis/doc/vorbisfile/ov_clear.html | 64 + contrib/vorbis/doc/vorbisfile/ov_comment.html | 66 + contrib/vorbis/doc/vorbisfile/ov_crosslap.html | 100 + contrib/vorbis/doc/vorbisfile/ov_fopen.html | 124 + contrib/vorbis/doc/vorbisfile/ov_info.html | 64 + contrib/vorbis/doc/vorbisfile/ov_open.html | 183 + .../vorbis/doc/vorbisfile/ov_open_callbacks.html | 147 + contrib/vorbis/doc/vorbisfile/ov_pcm_seek.html | 83 + contrib/vorbis/doc/vorbisfile/ov_pcm_seek_lap.html | 103 + .../vorbis/doc/vorbisfile/ov_pcm_seek_page.html | 84 + .../doc/vorbisfile/ov_pcm_seek_page_lap.html | 112 + contrib/vorbis/doc/vorbisfile/ov_pcm_tell.html | 63 + contrib/vorbis/doc/vorbisfile/ov_pcm_total.html | 67 + contrib/vorbis/doc/vorbisfile/ov_raw_seek.html | 83 + contrib/vorbis/doc/vorbisfile/ov_raw_seek_lap.html | 110 + contrib/vorbis/doc/vorbisfile/ov_raw_tell.html | 65 + contrib/vorbis/doc/vorbisfile/ov_raw_total.html | 68 + contrib/vorbis/doc/vorbisfile/ov_read.html | 148 + contrib/vorbis/doc/vorbisfile/ov_read_filter.html | 114 + contrib/vorbis/doc/vorbisfile/ov_read_float.html | 105 + contrib/vorbis/doc/vorbisfile/ov_seekable.html | 63 + contrib/vorbis/doc/vorbisfile/ov_serialnumber.html | 67 + contrib/vorbis/doc/vorbisfile/ov_streams.html | 64 + contrib/vorbis/doc/vorbisfile/ov_test.html | 104 + .../vorbis/doc/vorbisfile/ov_test_callbacks.html | 111 + contrib/vorbis/doc/vorbisfile/ov_test_open.html | 82 + contrib/vorbis/doc/vorbisfile/ov_time_seek.html | 82 + .../vorbis/doc/vorbisfile/ov_time_seek_lap.html | 105 + .../vorbis/doc/vorbisfile/ov_time_seek_page.html | 83 + .../doc/vorbisfile/ov_time_seek_page_lap.html | 112 + contrib/vorbis/doc/vorbisfile/ov_time_tell.html | 63 + contrib/vorbis/doc/vorbisfile/ov_time_total.html | 67 + contrib/vorbis/doc/vorbisfile/overview.html | 61 + contrib/vorbis/doc/vorbisfile/reference.html | 86 + contrib/vorbis/doc/vorbisfile/seekexample.html | 152 + contrib/vorbis/doc/vorbisfile/seeking.html | 107 + .../vorbis/doc/vorbisfile/seeking_example_c.html | 86 + contrib/vorbis/doc/vorbisfile/seeking_test_c.html | 86 + contrib/vorbis/doc/vorbisfile/seekingexample.html | 203 + contrib/vorbis/doc/vorbisfile/style.css | 7 + contrib/vorbis/doc/vorbisfile/threads.html | 50 + .../doc/vorbisfile/vorbisfile_example_c.html | 106 + contrib/vorbis/doc/window1.png | Bin 0 -> 1703 bytes contrib/vorbis/doc/window2.png | Bin 0 -> 1601 bytes contrib/vorbis/examples/Makefile.am | 34 + contrib/vorbis/examples/chaining_example.c | 71 + contrib/vorbis/examples/decoder_example.c | 313 + contrib/vorbis/examples/encoder_example.c | 251 + contrib/vorbis/examples/frameview.pl | 630 + contrib/vorbis/examples/seeking_example.c | 277 + contrib/vorbis/examples/vorbisfile_example.c | 91 + contrib/vorbis/include/Makefile.am | 3 + contrib/vorbis/include/vorbis/Makefile.am | 7 + contrib/vorbis/include/vorbis/codec.h | 242 + contrib/vorbis/include/vorbis/vorbisenc.h | 435 + contrib/vorbis/include/vorbis/vorbisfile.h | 205 + contrib/vorbis/lib/CMakeLists.txt | 109 + contrib/vorbis/lib/Makefile.am | 63 + contrib/vorbis/lib/analysis.c | 119 + contrib/vorbis/lib/backends.h | 143 + contrib/vorbis/lib/barkmel.c | 63 + contrib/vorbis/lib/bitrate.c | 252 + contrib/vorbis/lib/bitrate.h | 58 + contrib/vorbis/lib/block.c | 1046 ++ contrib/vorbis/lib/books/Makefile.am | 3 + contrib/vorbis/lib/books/coupled/Makefile.am | 3 + contrib/vorbis/lib/books/coupled/res_books_51.h | 12273 ++++++++++++++ .../vorbis/lib/books/coupled/res_books_stereo.h | 15782 +++++++++++++++++++ contrib/vorbis/lib/books/floor/Makefile.am | 3 + contrib/vorbis/lib/books/floor/floor_books.h | 1546 ++ contrib/vorbis/lib/books/uncoupled/Makefile.am | 3 + .../lib/books/uncoupled/res_books_uncoupled.h | 7757 +++++++++ contrib/vorbis/lib/codebook.c | 461 + contrib/vorbis/lib/codebook.h | 117 + contrib/vorbis/lib/codec_internal.h | 166 + contrib/vorbis/lib/envelope.c | 374 + contrib/vorbis/lib/envelope.h | 79 + contrib/vorbis/lib/floor0.c | 223 + contrib/vorbis/lib/floor1.c | 1086 ++ contrib/vorbis/lib/highlevel.h | 57 + contrib/vorbis/lib/info.c | 679 + contrib/vorbis/lib/lookup.c | 93 + contrib/vorbis/lib/lookup.h | 31 + contrib/vorbis/lib/lookup_data.h | 191 + contrib/vorbis/lib/lookups.pl | 141 + contrib/vorbis/lib/lpc.c | 159 + contrib/vorbis/lib/lpc.h | 28 + contrib/vorbis/lib/lsp.c | 453 + contrib/vorbis/lib/lsp.h | 27 + contrib/vorbis/lib/mapping0.c | 808 + contrib/vorbis/lib/masking.h | 784 + contrib/vorbis/lib/mdct.c | 562 + contrib/vorbis/lib/mdct.h | 70 + contrib/vorbis/lib/misc.c | 216 + contrib/vorbis/lib/misc.h | 57 + contrib/vorbis/lib/modes/Makefile.am | 6 + contrib/vorbis/lib/modes/floor_all.h | 259 + contrib/vorbis/lib/modes/psych_11.h | 50 + contrib/vorbis/lib/modes/psych_16.h | 132 + contrib/vorbis/lib/modes/psych_44.h | 641 + contrib/vorbis/lib/modes/psych_8.h | 100 + contrib/vorbis/lib/modes/residue_16.h | 162 + contrib/vorbis/lib/modes/residue_44.h | 291 + contrib/vorbis/lib/modes/residue_44p51.h | 450 + contrib/vorbis/lib/modes/residue_44u.h | 317 + contrib/vorbis/lib/modes/residue_8.h | 108 + contrib/vorbis/lib/modes/setup_11.h | 142 + contrib/vorbis/lib/modes/setup_16.h | 152 + contrib/vorbis/lib/modes/setup_22.h | 127 + contrib/vorbis/lib/modes/setup_32.h | 131 + contrib/vorbis/lib/modes/setup_44.h | 116 + contrib/vorbis/lib/modes/setup_44p51.h | 73 + contrib/vorbis/lib/modes/setup_44u.h | 73 + contrib/vorbis/lib/modes/setup_8.h | 148 + contrib/vorbis/lib/modes/setup_X.h | 224 + contrib/vorbis/lib/os.h | 190 + contrib/vorbis/lib/psy.c | 1205 ++ contrib/vorbis/lib/psy.h | 153 + contrib/vorbis/lib/psytune.c | 523 + contrib/vorbis/lib/registry.c | 44 + contrib/vorbis/lib/registry.h | 31 + contrib/vorbis/lib/res0.c | 889 ++ contrib/vorbis/lib/scales.h | 89 + contrib/vorbis/lib/sharedbook.c | 595 + contrib/vorbis/lib/smallft.c | 1254 ++ contrib/vorbis/lib/smallft.h | 33 + contrib/vorbis/lib/synthesis.c | 179 + contrib/vorbis/lib/tone.c | 54 + contrib/vorbis/lib/vorbisenc.c | 1223 ++ contrib/vorbis/lib/vorbisfile.c | 2424 +++ contrib/vorbis/lib/window.c | 2135 +++ contrib/vorbis/lib/window.h | 25 + contrib/vorbis/libvorbis.spec.in | 121 + contrib/vorbis/m4/Makefile.am | 4 + contrib/vorbis/m4/add_cflags.m4 | 15 + contrib/vorbis/m4/ogg.m4 | 116 + contrib/vorbis/m4/pkg.m4 | 157 + .../vorbis/macosx/English.lproj/InfoPlist.strings | Bin 0 -> 142 bytes contrib/vorbis/macosx/Info.plist | 30 + .../vorbis/macosx/Vorbis.xcodeproj/project.pbxproj | 891 ++ contrib/vorbis/symbian/bld.inf | 35 + contrib/vorbis/symbian/config.h | 54 + contrib/vorbis/symbian/vorbis.mmp | 43 + contrib/vorbis/test/Makefile.am | 19 + contrib/vorbis/test/test.c | 99 + contrib/vorbis/test/util.c | 52 + contrib/vorbis/test/util.h | 23 + contrib/vorbis/test/write_read.c | 297 + contrib/vorbis/test/write_read.h | 27 + contrib/vorbis/vorbis-uninstalled.pc.in | 14 + contrib/vorbis/vorbis.m4 | 136 + contrib/vorbis/vorbis.pc.in | 15 + contrib/vorbis/vorbisenc-uninstalled.pc.in | 14 + contrib/vorbis/vorbisenc.pc.in | 14 + contrib/vorbis/vorbisfile-uninstalled.pc.in | 14 + contrib/vorbis/vorbisfile.pc.in | 14 + contrib/vorbis/vq/16.vqs | 74 + contrib/vorbis/vq/16u.vqs | 69 + contrib/vorbis/vq/44c-1.vqs | 63 + contrib/vorbis/vq/44c0.vqs | 65 + contrib/vorbis/vq/44c1.vqs | 66 + contrib/vorbis/vq/44c2.vqs | 37 + contrib/vorbis/vq/44c3.vqs | 36 + contrib/vorbis/vq/44c4.vqs | 36 + contrib/vorbis/vq/44c5.vqs | 37 + contrib/vorbis/vq/44c6.vqs | 37 + contrib/vorbis/vq/44c7.vqs | 38 + contrib/vorbis/vq/44c8.vqs | 39 + contrib/vorbis/vq/44c9.vqs | 37 + contrib/vorbis/vq/44p-1.vqs | 49 + contrib/vorbis/vq/44p0.vqs | 49 + contrib/vorbis/vq/44p1.vqs | 49 + contrib/vorbis/vq/44p2.vqs | 52 + contrib/vorbis/vq/44p3.vqs | 52 + contrib/vorbis/vq/44p4.vqs | 52 + contrib/vorbis/vq/44p5.vqs | 52 + contrib/vorbis/vq/44p6.vqs | 52 + contrib/vorbis/vq/44p7.vqs | 52 + contrib/vorbis/vq/44p8.vqs | 52 + contrib/vorbis/vq/44p9.vqs | 52 + contrib/vorbis/vq/44u0.vqs | 33 + contrib/vorbis/vq/44u1.vqs | 33 + contrib/vorbis/vq/44u2.vqs | 32 + contrib/vorbis/vq/44u3.vqs | 33 + contrib/vorbis/vq/44u4.vqs | 33 + contrib/vorbis/vq/44u5.vqs | 35 + contrib/vorbis/vq/44u6.vqs | 35 + contrib/vorbis/vq/44u7.vqs | 34 + contrib/vorbis/vq/44u8.vqs | 35 + contrib/vorbis/vq/44u9.vqs | 36 + contrib/vorbis/vq/8.vqs | 43 + contrib/vorbis/vq/8u.vqs | 41 + contrib/vorbis/vq/Makefile.am | 36 + contrib/vorbis/vq/bookutil.c | 476 + contrib/vorbis/vq/bookutil.h | 42 + contrib/vorbis/vq/distribution.c | 247 + contrib/vorbis/vq/floor_11.vqs | 10 + contrib/vorbis/vq/floor_22.vqs | 27 + contrib/vorbis/vq/floor_44.vqs | 83 + contrib/vorbis/vq/huffbuild.c | 197 + contrib/vorbis/vq/latticebuild.c | 176 + contrib/vorbis/vq/latticetune.c | 163 + contrib/vorbis/vq/localcodebook.h | 120 + contrib/vorbis/vq/make_floor_books.pl | 108 + contrib/vorbis/vq/make_residue_books.pl | 177 + contrib/vorbis/vq/metrics.c | 294 + contrib/vorbis/vq/vqgen.c | 566 + contrib/vorbis/vq/vqgen.h | 84 + contrib/vorbis/win32/VS2005/README | 16 + contrib/vorbis/win32/VS2005/libogg.vsprops | 19 + .../VS2005/libvorbis/libvorbis_dynamic.vcproj | 1200 ++ .../win32/VS2005/libvorbis/libvorbis_static.vcproj | 1062 ++ .../libvorbisfile/libvorbisfile_dynamic.vcproj | 108 + .../libvorbisfile/libvorbisfile_static.vcproj | 96 + contrib/vorbis/win32/VS2005/vorbis_dynamic.sln | 56 + contrib/vorbis/win32/VS2005/vorbis_static.sln | 56 + .../VS2005/vorbisdec/vorbisdec_dynamic.vcproj | 106 + .../win32/VS2005/vorbisdec/vorbisdec_static.vcproj | 106 + .../VS2005/vorbisenc/vorbisenc_dynamic.vcproj | 106 + .../win32/VS2005/vorbisenc/vorbisenc_static.vcproj | 106 + contrib/vorbis/win32/VS2008/README | 16 + contrib/vorbis/win32/VS2008/libogg.vsprops | 19 + .../VS2008/libvorbis/libvorbis_dynamic.vcproj | 348 + .../win32/VS2008/libvorbis/libvorbis_static.vcproj | 1069 ++ .../libvorbisfile/libvorbisfile_dynamic.vcproj | 108 + .../libvorbisfile/libvorbisfile_static.vcproj | 96 + contrib/vorbis/win32/VS2008/vorbis_dynamic.sln | 92 + contrib/vorbis/win32/VS2008/vorbis_static.sln | 92 + .../VS2008/vorbisdec/vorbisdec_dynamic.vcproj | 106 + .../win32/VS2008/vorbisdec/vorbisdec_static.vcproj | 106 + .../VS2008/vorbisenc/vorbisenc_dynamic.vcproj | 106 + .../win32/VS2008/vorbisenc/vorbisenc_static.vcproj | 106 + contrib/vorbis/win32/VS2010/README | 16 + contrib/vorbis/win32/VS2010/libogg.props | 22 + .../VS2010/libvorbis/libvorbis_dynamic.vcxproj | 286 + .../VS2010/libvorbis/libvorbis_static.vcxproj | 235 + .../libvorbisfile/libvorbisfile_dynamic.vcxproj | 203 + .../libvorbisfile/libvorbisfile_static.vcxproj | 165 + contrib/vorbis/win32/VS2010/vorbis_dynamic.sln | 56 + contrib/vorbis/win32/VS2010/vorbis_static.sln | 56 + .../VS2010/vorbisdec/vorbisdec_dynamic.vcxproj | 213 + .../VS2010/vorbisdec/vorbisdec_static.vcxproj | 213 + .../VS2010/vorbisenc/vorbisenc_dynamic.vcxproj | 217 + .../VS2010/vorbisenc/vorbisenc_static.vcxproj | 217 + contrib/vorbis/win32/vorbis.def | 58 + contrib/vorbis/win32/vorbisenc.def | 12 + contrib/vorbis/win32/vorbisfile.def | 39 + contrib/zlib/.gitignore | 26 + contrib/zlib/CMakeLists.txt | 231 + contrib/zlib/ChangeLog | 1515 ++ contrib/zlib/FAQ | 368 + contrib/zlib/INDEX | 68 + contrib/zlib/Makefile | 5 + contrib/zlib/Makefile.in | 410 + contrib/zlib/README | 115 + contrib/zlib/adler32.c | 186 + contrib/zlib/amiga/Makefile.pup | 69 + contrib/zlib/amiga/Makefile.sas | 68 + contrib/zlib/compress.c | 86 + contrib/zlib/configure | 921 ++ contrib/zlib/contrib/README.contrib | 78 + contrib/zlib/contrib/ada/buffer_demo.adb | 106 + contrib/zlib/contrib/ada/mtest.adb | 156 + contrib/zlib/contrib/ada/read.adb | 156 + contrib/zlib/contrib/ada/readme.txt | 65 + contrib/zlib/contrib/ada/test.adb | 463 + contrib/zlib/contrib/ada/zlib-streams.adb | 225 + contrib/zlib/contrib/ada/zlib-streams.ads | 114 + contrib/zlib/contrib/ada/zlib-thin.adb | 141 + contrib/zlib/contrib/ada/zlib-thin.ads | 450 + contrib/zlib/contrib/ada/zlib.adb | 701 + contrib/zlib/contrib/ada/zlib.ads | 328 + contrib/zlib/contrib/ada/zlib.gpr | 20 + contrib/zlib/contrib/amd64/amd64-match.S | 452 + contrib/zlib/contrib/asm686/README.686 | 51 + contrib/zlib/contrib/asm686/match.S | 357 + contrib/zlib/contrib/blast/Makefile | 8 + contrib/zlib/contrib/blast/README | 4 + contrib/zlib/contrib/blast/blast.c | 466 + contrib/zlib/contrib/blast/blast.h | 83 + contrib/zlib/contrib/blast/test.pk | Bin 0 -> 8 bytes contrib/zlib/contrib/blast/test.txt | 1 + contrib/zlib/contrib/delphi/ZLib.pas | 557 + contrib/zlib/contrib/delphi/ZLibConst.pas | 11 + contrib/zlib/contrib/delphi/readme.txt | 76 + contrib/zlib/contrib/delphi/zlibd32.mak | 99 + contrib/zlib/contrib/dotzlib/DotZLib.build | 33 + contrib/zlib/contrib/dotzlib/DotZLib.chm | Bin 0 -> 72726 bytes contrib/zlib/contrib/dotzlib/DotZLib.sln | 21 + .../zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs | 58 + .../zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs | 202 + .../zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs | 83 + contrib/zlib/contrib/dotzlib/DotZLib/CodecBase.cs | 198 + contrib/zlib/contrib/dotzlib/DotZLib/Deflater.cs | 106 + contrib/zlib/contrib/dotzlib/DotZLib/DotZLib.cs | 288 + .../zlib/contrib/dotzlib/DotZLib/DotZLib.csproj | 141 + contrib/zlib/contrib/dotzlib/DotZLib/GZipStream.cs | 301 + contrib/zlib/contrib/dotzlib/DotZLib/Inflater.cs | 105 + contrib/zlib/contrib/dotzlib/DotZLib/UnitTests.cs | 274 + contrib/zlib/contrib/dotzlib/LICENSE_1_0.txt | 23 + contrib/zlib/contrib/dotzlib/readme.txt | 58 + contrib/zlib/contrib/gcc_gvmat64/gvmat64.S | 574 + contrib/zlib/contrib/infback9/README | 1 + contrib/zlib/contrib/infback9/infback9.c | 615 + contrib/zlib/contrib/infback9/infback9.h | 37 + contrib/zlib/contrib/infback9/inffix9.h | 107 + contrib/zlib/contrib/infback9/inflate9.h | 47 + contrib/zlib/contrib/infback9/inftree9.c | 324 + contrib/zlib/contrib/infback9/inftree9.h | 61 + contrib/zlib/contrib/inflate86/inffas86.c | 1157 ++ contrib/zlib/contrib/inflate86/inffast.S | 1368 ++ contrib/zlib/contrib/iostream/test.cpp | 24 + contrib/zlib/contrib/iostream/zfstream.cpp | 329 + contrib/zlib/contrib/iostream/zfstream.h | 128 + contrib/zlib/contrib/iostream2/zstream.h | 307 + contrib/zlib/contrib/iostream2/zstream_test.cpp | 25 + contrib/zlib/contrib/iostream3/README | 35 + contrib/zlib/contrib/iostream3/TODO | 17 + contrib/zlib/contrib/iostream3/test.cc | 50 + contrib/zlib/contrib/iostream3/zfstream.cc | 479 + contrib/zlib/contrib/iostream3/zfstream.h | 466 + contrib/zlib/contrib/masmx64/bld_ml64.bat | 2 + contrib/zlib/contrib/masmx64/gvmat64.asm | 553 + contrib/zlib/contrib/masmx64/inffas8664.c | 186 + contrib/zlib/contrib/masmx64/inffasx64.asm | 396 + contrib/zlib/contrib/masmx64/readme.txt | 31 + contrib/zlib/contrib/masmx86/bld_ml32.bat | 2 + contrib/zlib/contrib/masmx86/inffas32.asm | 1080 ++ contrib/zlib/contrib/masmx86/match686.asm | 479 + contrib/zlib/contrib/masmx86/readme.txt | 27 + contrib/zlib/contrib/minizip/Makefile | 25 + contrib/zlib/contrib/minizip/Makefile.am | 45 + contrib/zlib/contrib/minizip/MiniZip64_Changes.txt | 6 + contrib/zlib/contrib/minizip/MiniZip64_info.txt | 74 + contrib/zlib/contrib/minizip/configure.ac | 32 + contrib/zlib/contrib/minizip/crypt.h | 131 + contrib/zlib/contrib/minizip/ioapi.c | 247 + contrib/zlib/contrib/minizip/ioapi.h | 208 + contrib/zlib/contrib/minizip/iowin32.c | 462 + contrib/zlib/contrib/minizip/iowin32.h | 28 + contrib/zlib/contrib/minizip/make_vms.com | 25 + contrib/zlib/contrib/minizip/miniunz.c | 660 + contrib/zlib/contrib/minizip/miniunzip.1 | 63 + contrib/zlib/contrib/minizip/minizip.1 | 46 + contrib/zlib/contrib/minizip/minizip.c | 520 + contrib/zlib/contrib/minizip/minizip.pc.in | 12 + contrib/zlib/contrib/minizip/mztools.c | 291 + contrib/zlib/contrib/minizip/mztools.h | 37 + contrib/zlib/contrib/minizip/unzip.c | 2125 +++ contrib/zlib/contrib/minizip/unzip.h | 437 + contrib/zlib/contrib/minizip/zip.c | 2007 +++ contrib/zlib/contrib/minizip/zip.h | 362 + contrib/zlib/contrib/pascal/example.pas | 599 + contrib/zlib/contrib/pascal/readme.txt | 76 + contrib/zlib/contrib/pascal/zlibd32.mak | 99 + contrib/zlib/contrib/pascal/zlibpas.pas | 276 + contrib/zlib/contrib/puff/Makefile | 42 + contrib/zlib/contrib/puff/README | 63 + contrib/zlib/contrib/puff/puff.c | 840 + contrib/zlib/contrib/puff/puff.h | 35 + contrib/zlib/contrib/puff/pufftest.c | 165 + contrib/zlib/contrib/puff/zeros.raw | Bin 0 -> 2517 bytes contrib/zlib/contrib/testzlib/testzlib.c | 275 + contrib/zlib/contrib/testzlib/testzlib.txt | 10 + contrib/zlib/contrib/untgz/Makefile | 14 + contrib/zlib/contrib/untgz/Makefile.msc | 17 + contrib/zlib/contrib/untgz/untgz.c | 674 + contrib/zlib/contrib/vstudio/readme.txt | 78 + contrib/zlib/contrib/vstudio/vc10/miniunz.vcxproj | 310 + .../contrib/vstudio/vc10/miniunz.vcxproj.filters | 22 + contrib/zlib/contrib/vstudio/vc10/minizip.vcxproj | 307 + .../contrib/vstudio/vc10/minizip.vcxproj.filters | 22 + contrib/zlib/contrib/vstudio/vc10/testzlib.vcxproj | 420 + .../contrib/vstudio/vc10/testzlib.vcxproj.filters | 58 + .../zlib/contrib/vstudio/vc10/testzlibdll.vcxproj | 310 + .../vstudio/vc10/testzlibdll.vcxproj.filters | 22 + contrib/zlib/contrib/vstudio/vc10/zlib.rc | 32 + contrib/zlib/contrib/vstudio/vc10/zlibstat.vcxproj | 473 + .../contrib/vstudio/vc10/zlibstat.vcxproj.filters | 77 + contrib/zlib/contrib/vstudio/vc10/zlibvc.def | 153 + contrib/zlib/contrib/vstudio/vc10/zlibvc.sln | 135 + contrib/zlib/contrib/vstudio/vc10/zlibvc.vcxproj | 657 + .../contrib/vstudio/vc10/zlibvc.vcxproj.filters | 118 + contrib/zlib/contrib/vstudio/vc11/miniunz.vcxproj | 314 + contrib/zlib/contrib/vstudio/vc11/minizip.vcxproj | 311 + contrib/zlib/contrib/vstudio/vc11/testzlib.vcxproj | 426 + .../zlib/contrib/vstudio/vc11/testzlibdll.vcxproj | 314 + contrib/zlib/contrib/vstudio/vc11/zlib.rc | 32 + contrib/zlib/contrib/vstudio/vc11/zlibstat.vcxproj | 464 + contrib/zlib/contrib/vstudio/vc11/zlibvc.def | 153 + contrib/zlib/contrib/vstudio/vc11/zlibvc.sln | 117 + contrib/zlib/contrib/vstudio/vc11/zlibvc.vcxproj | 688 + contrib/zlib/contrib/vstudio/vc12/miniunz.vcxproj | 316 + contrib/zlib/contrib/vstudio/vc12/minizip.vcxproj | 313 + contrib/zlib/contrib/vstudio/vc12/testzlib.vcxproj | 430 + .../zlib/contrib/vstudio/vc12/testzlibdll.vcxproj | 316 + contrib/zlib/contrib/vstudio/vc12/zlib.rc | 32 + contrib/zlib/contrib/vstudio/vc12/zlibstat.vcxproj | 467 + contrib/zlib/contrib/vstudio/vc12/zlibvc.def | 153 + contrib/zlib/contrib/vstudio/vc12/zlibvc.sln | 119 + contrib/zlib/contrib/vstudio/vc12/zlibvc.vcxproj | 692 + contrib/zlib/contrib/vstudio/vc14/miniunz.vcxproj | 316 + contrib/zlib/contrib/vstudio/vc14/minizip.vcxproj | 313 + contrib/zlib/contrib/vstudio/vc14/testzlib.vcxproj | 430 + .../zlib/contrib/vstudio/vc14/testzlibdll.vcxproj | 316 + contrib/zlib/contrib/vstudio/vc14/zlib.rc | 32 + contrib/zlib/contrib/vstudio/vc14/zlibstat.vcxproj | 467 + contrib/zlib/contrib/vstudio/vc14/zlibvc.def | 153 + contrib/zlib/contrib/vstudio/vc14/zlibvc.sln | 119 + contrib/zlib/contrib/vstudio/vc14/zlibvc.vcxproj | 692 + contrib/zlib/contrib/vstudio/vc9/miniunz.vcproj | 565 + contrib/zlib/contrib/vstudio/vc9/minizip.vcproj | 562 + contrib/zlib/contrib/vstudio/vc9/testzlib.vcproj | 852 + .../zlib/contrib/vstudio/vc9/testzlibdll.vcproj | 565 + contrib/zlib/contrib/vstudio/vc9/zlib.rc | 32 + contrib/zlib/contrib/vstudio/vc9/zlibstat.vcproj | 835 + contrib/zlib/contrib/vstudio/vc9/zlibvc.def | 153 + contrib/zlib/contrib/vstudio/vc9/zlibvc.sln | 144 + contrib/zlib/contrib/vstudio/vc9/zlibvc.vcproj | 1156 ++ contrib/zlib/crc32.c | 442 + contrib/zlib/crc32.h | 441 + contrib/zlib/deflate.c | 2163 +++ contrib/zlib/deflate.h | 349 + contrib/zlib/doc/algorithm.txt | 209 + contrib/zlib/doc/rfc1950.txt | 619 + contrib/zlib/doc/rfc1951.txt | 955 ++ contrib/zlib/doc/rfc1952.txt | 675 + contrib/zlib/doc/txtvsbin.txt | 107 + contrib/zlib/examples/README.examples | 49 + contrib/zlib/examples/enough.c | 572 + contrib/zlib/examples/fitblk.c | 233 + contrib/zlib/examples/gun.c | 702 + contrib/zlib/examples/gzappend.c | 504 + contrib/zlib/examples/gzjoin.c | 449 + contrib/zlib/examples/gzlog.c | 1059 ++ contrib/zlib/examples/gzlog.h | 91 + contrib/zlib/examples/zlib_how.html | 545 + contrib/zlib/examples/zpipe.c | 205 + contrib/zlib/examples/zran.c | 409 + contrib/zlib/gzclose.c | 25 + contrib/zlib/gzguts.h | 218 + contrib/zlib/gzlib.c | 637 + contrib/zlib/gzread.c | 654 + contrib/zlib/gzwrite.c | 665 + contrib/zlib/infback.c | 640 + contrib/zlib/inffast.c | 323 + contrib/zlib/inffast.h | 11 + contrib/zlib/inffixed.h | 94 + contrib/zlib/inflate.c | 1561 ++ contrib/zlib/inflate.h | 125 + contrib/zlib/inftrees.c | 304 + contrib/zlib/inftrees.h | 62 + contrib/zlib/make_vms.com | 867 + contrib/zlib/msdos/Makefile.bor | 115 + contrib/zlib/msdos/Makefile.dj2 | 104 + contrib/zlib/msdos/Makefile.emx | 69 + contrib/zlib/msdos/Makefile.msc | 112 + contrib/zlib/msdos/Makefile.tc | 100 + contrib/zlib/nintendods/Makefile | 126 + contrib/zlib/nintendods/README | 5 + contrib/zlib/old/Makefile.emx | 69 + contrib/zlib/old/Makefile.riscos | 151 + contrib/zlib/old/README | 3 + contrib/zlib/old/descrip.mms | 48 + contrib/zlib/old/os2/Makefile.os2 | 136 + contrib/zlib/old/os2/zlib.def | 51 + contrib/zlib/old/visual-basic.txt | 160 + contrib/zlib/os400/README400 | 48 + contrib/zlib/os400/bndsrc | 119 + contrib/zlib/os400/make.sh | 366 + contrib/zlib/os400/zlib.inc | 527 + contrib/zlib/qnx/package.qpg | 141 + contrib/zlib/test/example.c | 602 + contrib/zlib/test/infcover.c | 671 + contrib/zlib/test/minigzip.c | 651 + contrib/zlib/treebuild.xml | 116 + contrib/zlib/trees.c | 1203 ++ contrib/zlib/trees.h | 128 + contrib/zlib/uncompr.c | 93 + contrib/zlib/watcom/watcom_f.mak | 43 + contrib/zlib/watcom/watcom_l.mak | 43 + contrib/zlib/win32/DLL_FAQ.txt | 397 + contrib/zlib/win32/Makefile.bor | 110 + contrib/zlib/win32/Makefile.gcc | 182 + contrib/zlib/win32/Makefile.msc | 163 + contrib/zlib/win32/README-WIN32.txt | 103 + contrib/zlib/win32/VisualC.txt | 3 + contrib/zlib/win32/zlib.def | 94 + contrib/zlib/win32/zlib1.rc | 40 + contrib/zlib/zconf.h | 534 + contrib/zlib/zconf.h.cmakein | 536 + contrib/zlib/zconf.h.in | 534 + contrib/zlib/zlib.3 | 149 + contrib/zlib/zlib.3.pdf | Bin 0 -> 19318 bytes contrib/zlib/zlib.h | 1912 +++ contrib/zlib/zlib.map | 94 + contrib/zlib/zlib.pc.cmakein | 13 + contrib/zlib/zlib.pc.in | 13 + contrib/zlib/zlib2ansi | 152 + contrib/zlib/zutil.c | 325 + contrib/zlib/zutil.h | 271 + 1108 files changed, 344375 insertions(+) create mode 100644 contrib/CMakeLists.txt create mode 100644 contrib/Opcode/CMakeLists.txt create mode 100644 contrib/Opcode/Doc/OpcodeUserManual.pdf create mode 100644 contrib/Opcode/Ice/IceAABB.cpp create mode 100644 contrib/Opcode/Ice/IceAABB.h create mode 100644 contrib/Opcode/Ice/IceAxes.h create mode 100644 contrib/Opcode/Ice/IceBoundingSphere.h create mode 100644 contrib/Opcode/Ice/IceContainer.cpp create mode 100644 contrib/Opcode/Ice/IceContainer.h create mode 100644 contrib/Opcode/Ice/IceFPU.h create mode 100644 contrib/Opcode/Ice/IceHPoint.cpp create mode 100644 contrib/Opcode/Ice/IceHPoint.h create mode 100644 contrib/Opcode/Ice/IceIndexedTriangle.cpp create mode 100644 contrib/Opcode/Ice/IceIndexedTriangle.h create mode 100644 contrib/Opcode/Ice/IceLSS.h create mode 100644 contrib/Opcode/Ice/IceMatrix3x3.cpp create mode 100644 contrib/Opcode/Ice/IceMatrix3x3.h create mode 100644 contrib/Opcode/Ice/IceMatrix4x4.cpp create mode 100644 contrib/Opcode/Ice/IceMatrix4x4.h create mode 100644 contrib/Opcode/Ice/IceMemoryMacros.h create mode 100644 contrib/Opcode/Ice/IceOBB.cpp create mode 100644 contrib/Opcode/Ice/IceOBB.h create mode 100644 contrib/Opcode/Ice/IcePairs.h create mode 100644 contrib/Opcode/Ice/IcePlane.cpp create mode 100644 contrib/Opcode/Ice/IcePlane.h create mode 100644 contrib/Opcode/Ice/IcePoint.cpp create mode 100644 contrib/Opcode/Ice/IcePoint.h create mode 100644 contrib/Opcode/Ice/IcePreprocessor.h create mode 100644 contrib/Opcode/Ice/IceRandom.cpp create mode 100644 contrib/Opcode/Ice/IceRandom.h create mode 100644 contrib/Opcode/Ice/IceRay.cpp create mode 100644 contrib/Opcode/Ice/IceRay.h create mode 100644 contrib/Opcode/Ice/IceRevisitedRadix.cpp create mode 100644 contrib/Opcode/Ice/IceRevisitedRadix.h create mode 100644 contrib/Opcode/Ice/IceSegment.cpp create mode 100644 contrib/Opcode/Ice/IceSegment.h create mode 100644 contrib/Opcode/Ice/IceTriangle.cpp create mode 100644 contrib/Opcode/Ice/IceTriangle.h create mode 100644 contrib/Opcode/Ice/IceTrilist.h create mode 100644 contrib/Opcode/Ice/IceTypes.h create mode 100644 contrib/Opcode/Ice/IceUtils.cpp create mode 100644 contrib/Opcode/Ice/IceUtils.h create mode 100644 contrib/Opcode/OPC_AABBCollider.cpp create mode 100644 contrib/Opcode/OPC_AABBCollider.h create mode 100644 contrib/Opcode/OPC_AABBTree.cpp create mode 100644 contrib/Opcode/OPC_AABBTree.h create mode 100644 contrib/Opcode/OPC_BaseModel.cpp create mode 100644 contrib/Opcode/OPC_BaseModel.h create mode 100644 contrib/Opcode/OPC_BoxBoxOverlap.h create mode 100644 contrib/Opcode/OPC_BoxPruning.cpp create mode 100644 contrib/Opcode/OPC_BoxPruning.h create mode 100644 contrib/Opcode/OPC_Collider.cpp create mode 100644 contrib/Opcode/OPC_Collider.h create mode 100644 contrib/Opcode/OPC_Common.cpp create mode 100644 contrib/Opcode/OPC_Common.h create mode 100644 contrib/Opcode/OPC_HybridModel.cpp create mode 100644 contrib/Opcode/OPC_HybridModel.h create mode 100644 contrib/Opcode/OPC_IceHook.h create mode 100644 contrib/Opcode/OPC_LSSAABBOverlap.h create mode 100644 contrib/Opcode/OPC_LSSCollider.cpp create mode 100644 contrib/Opcode/OPC_LSSCollider.h create mode 100644 contrib/Opcode/OPC_LSSTriOverlap.h create mode 100644 contrib/Opcode/OPC_MeshInterface.cpp create mode 100644 contrib/Opcode/OPC_MeshInterface.h create mode 100644 contrib/Opcode/OPC_Model.cpp create mode 100644 contrib/Opcode/OPC_Model.h create mode 100644 contrib/Opcode/OPC_OBBCollider.cpp create mode 100644 contrib/Opcode/OPC_OBBCollider.h create mode 100644 contrib/Opcode/OPC_OptimizedTree.cpp create mode 100644 contrib/Opcode/OPC_OptimizedTree.h create mode 100644 contrib/Opcode/OPC_Picking.cpp create mode 100644 contrib/Opcode/OPC_Picking.h create mode 100644 contrib/Opcode/OPC_PlanesAABBOverlap.h create mode 100644 contrib/Opcode/OPC_PlanesCollider.cpp create mode 100644 contrib/Opcode/OPC_PlanesCollider.h create mode 100644 contrib/Opcode/OPC_PlanesTriOverlap.h create mode 100644 contrib/Opcode/OPC_RayAABBOverlap.h create mode 100644 contrib/Opcode/OPC_RayCollider.cpp create mode 100644 contrib/Opcode/OPC_RayCollider.h create mode 100644 contrib/Opcode/OPC_RayTriOverlap.h create mode 100644 contrib/Opcode/OPC_Settings.h create mode 100644 contrib/Opcode/OPC_SphereAABBOverlap.h create mode 100644 contrib/Opcode/OPC_SphereCollider.cpp create mode 100644 contrib/Opcode/OPC_SphereCollider.h create mode 100644 contrib/Opcode/OPC_SphereTriOverlap.h create mode 100644 contrib/Opcode/OPC_SweepAndPrune.cpp create mode 100644 contrib/Opcode/OPC_SweepAndPrune.h create mode 100644 contrib/Opcode/OPC_TreeBuilders.cpp create mode 100644 contrib/Opcode/OPC_TreeBuilders.h create mode 100644 contrib/Opcode/OPC_TreeCollider.cpp create mode 100644 contrib/Opcode/OPC_TreeCollider.h create mode 100644 contrib/Opcode/OPC_TriBoxOverlap.h create mode 100644 contrib/Opcode/OPC_TriTriOverlap.h create mode 100644 contrib/Opcode/OPC_VolumeCollider.cpp create mode 100644 contrib/Opcode/OPC_VolumeCollider.h create mode 100644 contrib/Opcode/Opcode.cpp create mode 100644 contrib/Opcode/Opcode.h create mode 100644 contrib/Opcode/ReadMe.txt create mode 100644 contrib/Opcode/StdAfx.cpp create mode 100644 contrib/Opcode/StdAfx.h create mode 100644 contrib/Opcode/TemporalCoherence.txt create mode 100644 contrib/libpng/ANNOUNCE create mode 100644 contrib/libpng/CHANGES create mode 100644 contrib/libpng/CMakeLists.txt create mode 100644 contrib/libpng/INSTALL create mode 100644 contrib/libpng/LICENSE create mode 100644 contrib/libpng/Makefile.am create mode 100644 contrib/libpng/Makefile.in create mode 100644 contrib/libpng/README create mode 100644 contrib/libpng/TODO create mode 100644 contrib/libpng/aclocal.m4 create mode 100755 contrib/libpng/autogen.sh create mode 100644 contrib/libpng/config.guess create mode 100644 contrib/libpng/config.h.in create mode 100644 contrib/libpng/config.sub create mode 100755 contrib/libpng/configure create mode 100644 contrib/libpng/configure.ac create mode 100644 contrib/libpng/contrib/gregbook/COPYING create mode 100644 contrib/libpng/contrib/gregbook/LICENSE create mode 100644 contrib/libpng/contrib/gregbook/Makefile.mingw32 create mode 100644 contrib/libpng/contrib/gregbook/Makefile.sgi create mode 100644 contrib/libpng/contrib/gregbook/Makefile.unx create mode 100644 contrib/libpng/contrib/gregbook/Makefile.w32 create mode 100644 contrib/libpng/contrib/gregbook/README create mode 100644 contrib/libpng/contrib/gregbook/makevms.com create mode 100644 contrib/libpng/contrib/gregbook/readpng.c create mode 100644 contrib/libpng/contrib/gregbook/readpng.h create mode 100644 contrib/libpng/contrib/gregbook/readpng2.c create mode 100644 contrib/libpng/contrib/gregbook/readpng2.h create mode 100644 contrib/libpng/contrib/gregbook/readppm.c create mode 100644 contrib/libpng/contrib/gregbook/rpng-win.c create mode 100644 contrib/libpng/contrib/gregbook/rpng-x.c create mode 100644 contrib/libpng/contrib/gregbook/rpng2-win.c create mode 100644 contrib/libpng/contrib/gregbook/rpng2-x.c create mode 100644 contrib/libpng/contrib/gregbook/toucan.png create mode 100644 contrib/libpng/contrib/gregbook/wpng.c create mode 100644 contrib/libpng/contrib/gregbook/writepng.c create mode 100644 contrib/libpng/contrib/gregbook/writepng.h create mode 100644 contrib/libpng/contrib/pngminim/README create mode 100644 contrib/libpng/contrib/pngminim/decoder/README create mode 100644 contrib/libpng/contrib/pngminim/decoder/makefile create mode 100644 contrib/libpng/contrib/pngminim/decoder/pngusr.dfa create mode 100644 contrib/libpng/contrib/pngminim/decoder/pngusr.h create mode 100644 contrib/libpng/contrib/pngminim/encoder/README create mode 100644 contrib/libpng/contrib/pngminim/encoder/makefile create mode 100644 contrib/libpng/contrib/pngminim/encoder/pngusr.dfa create mode 100644 contrib/libpng/contrib/pngminim/encoder/pngusr.h create mode 100644 contrib/libpng/contrib/pngminim/preader/README create mode 100644 contrib/libpng/contrib/pngminim/preader/makefile create mode 100644 contrib/libpng/contrib/pngminim/preader/pngusr.dfa create mode 100644 contrib/libpng/contrib/pngminim/preader/pngusr.h create mode 100644 contrib/libpng/contrib/pngminus/README create mode 100644 contrib/libpng/contrib/pngminus/makefile.std create mode 100644 contrib/libpng/contrib/pngminus/makefile.tc3 create mode 100644 contrib/libpng/contrib/pngminus/makevms.com create mode 100644 contrib/libpng/contrib/pngminus/png2pnm.bat create mode 100644 contrib/libpng/contrib/pngminus/png2pnm.c create mode 100644 contrib/libpng/contrib/pngminus/png2pnm.sh create mode 100644 contrib/libpng/contrib/pngminus/pngminus.bat create mode 100644 contrib/libpng/contrib/pngminus/pngminus.sh create mode 100644 contrib/libpng/contrib/pngminus/pnm2png.bat create mode 100644 contrib/libpng/contrib/pngminus/pnm2png.c create mode 100644 contrib/libpng/contrib/pngminus/pnm2png.sh create mode 100644 contrib/libpng/contrib/pngsuite/README create mode 100644 contrib/libpng/contrib/pngsuite/basn0g01.png create mode 100644 contrib/libpng/contrib/pngsuite/basn0g02.png create mode 100644 contrib/libpng/contrib/pngsuite/basn0g04.png create mode 100644 contrib/libpng/contrib/pngsuite/basn0g08.png create mode 100644 contrib/libpng/contrib/pngsuite/basn0g16.png create mode 100644 contrib/libpng/contrib/pngsuite/basn2c08.png create mode 100644 contrib/libpng/contrib/pngsuite/basn2c16.png create mode 100644 contrib/libpng/contrib/pngsuite/basn3p01.png create mode 100644 contrib/libpng/contrib/pngsuite/basn3p02.png create mode 100644 contrib/libpng/contrib/pngsuite/basn3p04.png create mode 100644 contrib/libpng/contrib/pngsuite/basn3p08.png create mode 100644 contrib/libpng/contrib/pngsuite/basn4a08.png create mode 100644 contrib/libpng/contrib/pngsuite/basn4a16.png create mode 100644 contrib/libpng/contrib/pngsuite/basn6a08.png create mode 100644 contrib/libpng/contrib/pngsuite/basn6a16.png create mode 100644 contrib/libpng/contrib/pngsuite/ftbbn1g04.png create mode 100644 contrib/libpng/contrib/pngsuite/ftbbn2c16.png create mode 100644 contrib/libpng/contrib/pngsuite/ftbbn3p08.png create mode 100644 contrib/libpng/contrib/pngsuite/ftbgn2c16.png create mode 100644 contrib/libpng/contrib/pngsuite/ftbgn3p08.png create mode 100644 contrib/libpng/contrib/pngsuite/ftbrn2c08.png create mode 100644 contrib/libpng/contrib/pngsuite/ftbwn1g16.png create mode 100644 contrib/libpng/contrib/pngsuite/ftbwn3p08.png create mode 100644 contrib/libpng/contrib/pngsuite/ftbyn3p08.png create mode 100644 contrib/libpng/contrib/pngsuite/ftp0n1g08.png create mode 100644 contrib/libpng/contrib/pngsuite/ftp0n2c08.png create mode 100644 contrib/libpng/contrib/pngsuite/ftp0n3p08.png create mode 100644 contrib/libpng/contrib/pngsuite/ftp1n3p08.png create mode 100644 contrib/libpng/contrib/visupng/PngFile.c create mode 100644 contrib/libpng/contrib/visupng/PngFile.h create mode 100644 contrib/libpng/contrib/visupng/README.txt create mode 100644 contrib/libpng/contrib/visupng/VisualPng.c create mode 100644 contrib/libpng/contrib/visupng/VisualPng.dsp create mode 100644 contrib/libpng/contrib/visupng/VisualPng.dsw create mode 100644 contrib/libpng/contrib/visupng/VisualPng.ico create mode 100644 contrib/libpng/contrib/visupng/VisualPng.png create mode 100644 contrib/libpng/contrib/visupng/VisualPng.rc create mode 100644 contrib/libpng/contrib/visupng/cexcept.h create mode 100644 contrib/libpng/contrib/visupng/resource.h create mode 100755 contrib/libpng/depcomp create mode 100644 contrib/libpng/example.c create mode 100755 contrib/libpng/install-sh create mode 100755 contrib/libpng/libpng-config.in create mode 100644 contrib/libpng/libpng-manual.txt create mode 100644 contrib/libpng/libpng.3 create mode 100644 contrib/libpng/libpng.pc.in create mode 100644 contrib/libpng/libpngpf.3 create mode 100755 contrib/libpng/ltmain.sh create mode 100755 contrib/libpng/missing create mode 100644 contrib/libpng/png.5 create mode 100644 contrib/libpng/png.c create mode 100644 contrib/libpng/png.h create mode 100644 contrib/libpng/pngbar.jpg create mode 100644 contrib/libpng/pngbar.png create mode 100644 contrib/libpng/pngconf.h create mode 100644 contrib/libpng/pngdebug.h create mode 100644 contrib/libpng/pngerror.c create mode 100644 contrib/libpng/pngget.c create mode 100644 contrib/libpng/pnginfo.h create mode 100644 contrib/libpng/pngmem.c create mode 100644 contrib/libpng/pngnow.png create mode 100644 contrib/libpng/pngpread.c create mode 100644 contrib/libpng/pngpriv.h create mode 100644 contrib/libpng/pngread.c create mode 100644 contrib/libpng/pngrio.c create mode 100644 contrib/libpng/pngrtran.c create mode 100644 contrib/libpng/pngrutil.c create mode 100644 contrib/libpng/pngset.c create mode 100644 contrib/libpng/pngstruct.h create mode 100644 contrib/libpng/pngtest.c create mode 100644 contrib/libpng/pngtest.png create mode 100644 contrib/libpng/pngtrans.c create mode 100644 contrib/libpng/pngvalid.c create mode 100644 contrib/libpng/pngwio.c create mode 100644 contrib/libpng/pngwrite.c create mode 100644 contrib/libpng/pngwtran.c create mode 100644 contrib/libpng/pngwutil.c create mode 100644 contrib/libpng/projects/visualc71/PRJ0041.mak create mode 100644 contrib/libpng/projects/visualc71/README.txt create mode 100644 contrib/libpng/projects/visualc71/README_zlib.txt create mode 100644 contrib/libpng/projects/visualc71/libpng.sln create mode 100644 contrib/libpng/projects/visualc71/libpng.vcproj create mode 100644 contrib/libpng/projects/visualc71/pngtest.vcproj create mode 100644 contrib/libpng/projects/visualc71/zlib.vcproj create mode 100644 contrib/libpng/projects/vstudio/libpng/libpng.vcxproj create mode 100644 contrib/libpng/projects/vstudio/pnglibconf/pnglibconf.vcxproj create mode 100644 contrib/libpng/projects/vstudio/pngtest/pngtest.vcxproj create mode 100644 contrib/libpng/projects/vstudio/pngvalid/pngvalid.vcxproj create mode 100644 contrib/libpng/projects/vstudio/readme.txt create mode 100644 contrib/libpng/projects/vstudio/vstudio.sln create mode 100644 contrib/libpng/projects/vstudio/zlib.props create mode 100644 contrib/libpng/projects/vstudio/zlib/zlib.vcxproj create mode 100644 contrib/libpng/scripts/README.txt create mode 100644 contrib/libpng/scripts/SCOPTIONS.ppc create mode 100755 contrib/libpng/scripts/checksym.awk create mode 100755 contrib/libpng/scripts/chkfmt create mode 100644 contrib/libpng/scripts/def.dfn create mode 100644 contrib/libpng/scripts/descrip.mms create mode 100755 contrib/libpng/scripts/libpng-config-body.in create mode 100755 contrib/libpng/scripts/libpng-config-head.in create mode 100644 contrib/libpng/scripts/libpng.pc.in create mode 100644 contrib/libpng/scripts/makefile.32sunu create mode 100644 contrib/libpng/scripts/makefile.64sunu create mode 100644 contrib/libpng/scripts/makefile.acorn create mode 100644 contrib/libpng/scripts/makefile.aix create mode 100644 contrib/libpng/scripts/makefile.amiga create mode 100644 contrib/libpng/scripts/makefile.atari create mode 100644 contrib/libpng/scripts/makefile.bc32 create mode 100644 contrib/libpng/scripts/makefile.beos create mode 100644 contrib/libpng/scripts/makefile.bor create mode 100644 contrib/libpng/scripts/makefile.cegcc create mode 100644 contrib/libpng/scripts/makefile.darwin create mode 100644 contrib/libpng/scripts/makefile.dec create mode 100644 contrib/libpng/scripts/makefile.dj2 create mode 100644 contrib/libpng/scripts/makefile.elf create mode 100644 contrib/libpng/scripts/makefile.freebsd create mode 100644 contrib/libpng/scripts/makefile.gcc create mode 100644 contrib/libpng/scripts/makefile.hp64 create mode 100644 contrib/libpng/scripts/makefile.hpgcc create mode 100644 contrib/libpng/scripts/makefile.hpux create mode 100644 contrib/libpng/scripts/makefile.ibmc create mode 100644 contrib/libpng/scripts/makefile.intel create mode 100644 contrib/libpng/scripts/makefile.knr create mode 100644 contrib/libpng/scripts/makefile.linux create mode 100644 contrib/libpng/scripts/makefile.mips create mode 100644 contrib/libpng/scripts/makefile.msc create mode 100644 contrib/libpng/scripts/makefile.ne12bsd create mode 100644 contrib/libpng/scripts/makefile.netbsd create mode 100644 contrib/libpng/scripts/makefile.openbsd create mode 100644 contrib/libpng/scripts/makefile.sco create mode 100644 contrib/libpng/scripts/makefile.sggcc create mode 100644 contrib/libpng/scripts/makefile.sgi create mode 100644 contrib/libpng/scripts/makefile.so9 create mode 100644 contrib/libpng/scripts/makefile.solaris create mode 100644 contrib/libpng/scripts/makefile.solaris-x86 create mode 100644 contrib/libpng/scripts/makefile.std create mode 100644 contrib/libpng/scripts/makefile.sunos create mode 100644 contrib/libpng/scripts/makefile.tc3 create mode 100644 contrib/libpng/scripts/makefile.vcwin32 create mode 100644 contrib/libpng/scripts/makefile.watcom create mode 100644 contrib/libpng/scripts/makevms.com create mode 100755 contrib/libpng/scripts/options.awk create mode 100644 contrib/libpng/scripts/pnglibconf.dfa create mode 100644 contrib/libpng/scripts/pnglibconf.h.prebuilt create mode 100755 contrib/libpng/scripts/pnglibconf.mak create mode 100644 contrib/libpng/scripts/pngwin.rc create mode 100644 contrib/libpng/scripts/smakefile.ppc create mode 100644 contrib/libpng/scripts/sym.dfn create mode 100644 contrib/libpng/scripts/symbols.def create mode 100644 contrib/libpng/scripts/symbols.dfn create mode 100644 contrib/libpng/scripts/vers.dfn create mode 100755 contrib/libpng/test-pngtest.sh create mode 100755 contrib/libpng/test-pngvalid-full.sh create mode 100755 contrib/libpng/test-pngvalid-simple.sh create mode 100644 contrib/ogg/.gitignore create mode 100644 contrib/ogg/.travis.yml create mode 100644 contrib/ogg/AUTHORS create mode 100644 contrib/ogg/CHANGES create mode 100644 contrib/ogg/CMakeLists.txt create mode 100644 contrib/ogg/COPYING create mode 100644 contrib/ogg/Makefile.am create mode 100644 contrib/ogg/README.md create mode 100644 contrib/ogg/appveyor.yml create mode 100755 contrib/ogg/autogen.sh create mode 100644 contrib/ogg/configure.ac create mode 100644 contrib/ogg/doc/Makefile.am create mode 100644 contrib/ogg/doc/fish_xiph_org.png create mode 100644 contrib/ogg/doc/framing.html create mode 100644 contrib/ogg/doc/index.html create mode 100644 contrib/ogg/doc/libogg/Makefile.am create mode 100644 contrib/ogg/doc/libogg/bitpacking.html create mode 100644 contrib/ogg/doc/libogg/datastructures.html create mode 100644 contrib/ogg/doc/libogg/decoding.html create mode 100644 contrib/ogg/doc/libogg/encoding.html create mode 100644 contrib/ogg/doc/libogg/general.html create mode 100644 contrib/ogg/doc/libogg/index.html create mode 100644 contrib/ogg/doc/libogg/ogg_iovec_t.html create mode 100644 contrib/ogg/doc/libogg/ogg_packet.html create mode 100644 contrib/ogg/doc/libogg/ogg_packet_clear.html create mode 100644 contrib/ogg/doc/libogg/ogg_page.html create mode 100644 contrib/ogg/doc/libogg/ogg_page_bos.html create mode 100644 contrib/ogg/doc/libogg/ogg_page_checksum_set.html create mode 100644 contrib/ogg/doc/libogg/ogg_page_continued.html create mode 100644 contrib/ogg/doc/libogg/ogg_page_eos.html create mode 100644 contrib/ogg/doc/libogg/ogg_page_granulepos.html create mode 100644 contrib/ogg/doc/libogg/ogg_page_packets.html create mode 100644 contrib/ogg/doc/libogg/ogg_page_pageno.html create mode 100644 contrib/ogg/doc/libogg/ogg_page_serialno.html create mode 100644 contrib/ogg/doc/libogg/ogg_page_version.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_check.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_clear.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_destroy.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_eos.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_flush.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_flush_fill.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_init.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_iovecin.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_packetin.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_packetout.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_packetpeek.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_pagein.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_pageout.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_pageout_fill.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_reset.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_reset_serialno.html create mode 100644 contrib/ogg/doc/libogg/ogg_stream_state.html create mode 100644 contrib/ogg/doc/libogg/ogg_sync_buffer.html create mode 100644 contrib/ogg/doc/libogg/ogg_sync_check.html create mode 100644 contrib/ogg/doc/libogg/ogg_sync_clear.html create mode 100644 contrib/ogg/doc/libogg/ogg_sync_destroy.html create mode 100644 contrib/ogg/doc/libogg/ogg_sync_init.html create mode 100644 contrib/ogg/doc/libogg/ogg_sync_pageout.html create mode 100644 contrib/ogg/doc/libogg/ogg_sync_pageseek.html create mode 100644 contrib/ogg/doc/libogg/ogg_sync_reset.html create mode 100644 contrib/ogg/doc/libogg/ogg_sync_state.html create mode 100644 contrib/ogg/doc/libogg/ogg_sync_wrote.html create mode 100644 contrib/ogg/doc/libogg/oggpack_adv.html create mode 100644 contrib/ogg/doc/libogg/oggpack_adv1.html create mode 100644 contrib/ogg/doc/libogg/oggpack_bits.html create mode 100644 contrib/ogg/doc/libogg/oggpack_buffer.html create mode 100644 contrib/ogg/doc/libogg/oggpack_bytes.html create mode 100644 contrib/ogg/doc/libogg/oggpack_get_buffer.html create mode 100644 contrib/ogg/doc/libogg/oggpack_look.html create mode 100644 contrib/ogg/doc/libogg/oggpack_look1.html create mode 100644 contrib/ogg/doc/libogg/oggpack_read.html create mode 100644 contrib/ogg/doc/libogg/oggpack_read1.html create mode 100644 contrib/ogg/doc/libogg/oggpack_readinit.html create mode 100644 contrib/ogg/doc/libogg/oggpack_reset.html create mode 100644 contrib/ogg/doc/libogg/oggpack_write.html create mode 100644 contrib/ogg/doc/libogg/oggpack_writealign.html create mode 100644 contrib/ogg/doc/libogg/oggpack_writecheck.html create mode 100644 contrib/ogg/doc/libogg/oggpack_writeclear.html create mode 100644 contrib/ogg/doc/libogg/oggpack_writecopy.html create mode 100644 contrib/ogg/doc/libogg/oggpack_writeinit.html create mode 100644 contrib/ogg/doc/libogg/oggpack_writetrunc.html create mode 100644 contrib/ogg/doc/libogg/overview.html create mode 100644 contrib/ogg/doc/libogg/reference.html create mode 100644 contrib/ogg/doc/libogg/style.css create mode 100644 contrib/ogg/doc/multiplex1.png create mode 100644 contrib/ogg/doc/multiplex1.svg create mode 100644 contrib/ogg/doc/ogg-multiplex.html create mode 100644 contrib/ogg/doc/oggstream.html create mode 100644 contrib/ogg/doc/packets.png create mode 100644 contrib/ogg/doc/packets.svg create mode 100644 contrib/ogg/doc/pages.png create mode 100644 contrib/ogg/doc/pages.svg create mode 100644 contrib/ogg/doc/rfc3533.txt create mode 100644 contrib/ogg/doc/rfc3534.txt create mode 100644 contrib/ogg/doc/rfc5334.txt create mode 100755 contrib/ogg/doc/skeleton.html create mode 100644 contrib/ogg/doc/stream.png create mode 100644 contrib/ogg/doc/vorbisword2.png create mode 100644 contrib/ogg/doc/white-ogg.png create mode 100644 contrib/ogg/doc/white-xifish.png create mode 100644 contrib/ogg/include/Makefile.am create mode 100644 contrib/ogg/include/ogg/Makefile.am create mode 100644 contrib/ogg/include/ogg/config_types.h.in create mode 100644 contrib/ogg/include/ogg/ogg.h create mode 100644 contrib/ogg/include/ogg/os_types.h create mode 100644 contrib/ogg/libogg.spec.in create mode 100644 contrib/ogg/macosx/English.lproj/InfoPlist.strings create mode 100644 contrib/ogg/macosx/Info.plist create mode 100644 contrib/ogg/macosx/Ogg.xcodeproj/project.pbxproj create mode 100644 contrib/ogg/macosx/Ogg_Prefix.pch create mode 100644 contrib/ogg/ogg-uninstalled.pc.in create mode 100644 contrib/ogg/ogg.m4 create mode 100644 contrib/ogg/ogg.pc.in create mode 100644 contrib/ogg/releases.sha2 create mode 100644 contrib/ogg/src/Makefile.am create mode 100644 contrib/ogg/src/bitwise.c create mode 100644 contrib/ogg/src/framing.c create mode 100644 contrib/ogg/symbian/bld.inf create mode 100644 contrib/ogg/symbian/ogg.mmp create mode 100644 contrib/ogg/win32/.gitignore create mode 100644 contrib/ogg/win32/VS2015/libogg_dynamic.sln create mode 100644 contrib/ogg/win32/VS2015/libogg_dynamic.vcxproj create mode 100644 contrib/ogg/win32/VS2015/libogg_static.sln create mode 100644 contrib/ogg/win32/VS2015/libogg_static.vcxproj create mode 100644 contrib/ogg/win32/ogg.def create mode 100644 contrib/vorbis/.gitignore create mode 100644 contrib/vorbis/.travis.yml create mode 100644 contrib/vorbis/.ycm_extra_conf.py create mode 100644 contrib/vorbis/AUTHORS create mode 100644 contrib/vorbis/CHANGES create mode 100644 contrib/vorbis/CMakeLists.txt create mode 100644 contrib/vorbis/COPYING create mode 100644 contrib/vorbis/Makefile.am create mode 100644 contrib/vorbis/README.md create mode 100644 contrib/vorbis/appveyor.yml create mode 100755 contrib/vorbis/autogen.sh create mode 100644 contrib/vorbis/configure.ac create mode 100644 contrib/vorbis/debian/changelog create mode 100644 contrib/vorbis/debian/control create mode 100644 contrib/vorbis/debian/copyright create mode 100644 contrib/vorbis/debian/libvorbis-dev.docs create mode 100644 contrib/vorbis/debian/libvorbis-dev.examples create mode 100644 contrib/vorbis/debian/libvorbis-dev.install create mode 100644 contrib/vorbis/debian/libvorbis0a.install create mode 100644 contrib/vorbis/debian/libvorbisenc2.install create mode 100644 contrib/vorbis/debian/libvorbisfile3.install create mode 100755 contrib/vorbis/debian/rules create mode 100644 contrib/vorbis/debian/watch create mode 100644 contrib/vorbis/doc/01-introduction.tex create mode 100644 contrib/vorbis/doc/02-bitpacking.tex create mode 100644 contrib/vorbis/doc/03-codebook.tex create mode 100644 contrib/vorbis/doc/04-codec.tex create mode 100644 contrib/vorbis/doc/05-comment.tex create mode 100644 contrib/vorbis/doc/06-floor0.tex create mode 100644 contrib/vorbis/doc/07-floor1.tex create mode 100644 contrib/vorbis/doc/08-residue.tex create mode 100644 contrib/vorbis/doc/09-helper.tex create mode 100644 contrib/vorbis/doc/10-tables.tex create mode 100644 contrib/vorbis/doc/Doxyfile.in create mode 100644 contrib/vorbis/doc/Makefile.am create mode 100644 contrib/vorbis/doc/Vorbis_I_spec.cfg create mode 100644 contrib/vorbis/doc/Vorbis_I_spec.css create mode 100644 contrib/vorbis/doc/Vorbis_I_spec.html create mode 100644 contrib/vorbis/doc/Vorbis_I_spec.pdf create mode 100644 contrib/vorbis/doc/Vorbis_I_spec.tex create mode 100644 contrib/vorbis/doc/Vorbis_I_spec0x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec10x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec11x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec12x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec13x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec14x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec1x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec2x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec3x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec4x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec5x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec6x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec7x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec8x.png create mode 100644 contrib/vorbis/doc/Vorbis_I_spec9x.png create mode 100644 contrib/vorbis/doc/a1-encapsulation-ogg.tex create mode 100644 contrib/vorbis/doc/a2-encapsulation-rtp.tex create mode 100644 contrib/vorbis/doc/components.png create mode 100644 contrib/vorbis/doc/eightphase.png create mode 100644 contrib/vorbis/doc/fish_xiph_org.png create mode 100644 contrib/vorbis/doc/floor1-1.png create mode 100644 contrib/vorbis/doc/floor1-2.png create mode 100644 contrib/vorbis/doc/floor1-3.png create mode 100644 contrib/vorbis/doc/floor1-4.png create mode 100644 contrib/vorbis/doc/floor1_inverse_dB_table.html create mode 100644 contrib/vorbis/doc/floorval.png create mode 100644 contrib/vorbis/doc/footer.tex create mode 100644 contrib/vorbis/doc/fourphase.png create mode 100644 contrib/vorbis/doc/framing.html create mode 100644 contrib/vorbis/doc/helper.html create mode 100644 contrib/vorbis/doc/hufftree-under.png create mode 100644 contrib/vorbis/doc/hufftree.png create mode 100644 contrib/vorbis/doc/index.html create mode 100644 contrib/vorbis/doc/libvorbis/Makefile.am create mode 100644 contrib/vorbis/doc/libvorbis/index.html create mode 100644 contrib/vorbis/doc/libvorbis/overview.html create mode 100644 contrib/vorbis/doc/libvorbis/reference.html create mode 100644 contrib/vorbis/doc/libvorbis/return.html create mode 100644 contrib/vorbis/doc/libvorbis/style.css create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_analysis.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_analysis_blockout.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_analysis_buffer.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_analysis_headerout.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_analysis_init.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_analysis_wrote.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_bitrate_addblock.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_bitrate_flushpacket.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_block.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_block_clear.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_block_init.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_comment.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_comment_add.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_comment_add_tag.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_comment_clear.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_comment_init.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_comment_query.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_comment_query_count.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_commentheader_out.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_dsp_clear.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_dsp_state.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_granule_time.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_info.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_info_blocksize.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_info_clear.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_info_init.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_packet_blocksize.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_synthesis.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_synthesis_blockin.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_synthesis_halfrate.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_synthesis_halfrate_p.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_synthesis_headerin.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_synthesis_idheader.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_synthesis_init.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_synthesis_lapout.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_synthesis_pcmout.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_synthesis_read.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_synthesis_restart.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_synthesis_trackonly.html create mode 100644 contrib/vorbis/doc/libvorbis/vorbis_version_string.html create mode 100644 contrib/vorbis/doc/oggstream.html create mode 100644 contrib/vorbis/doc/programming.html create mode 100644 contrib/vorbis/doc/release.txt create mode 100644 contrib/vorbis/doc/residue-pack.png create mode 100644 contrib/vorbis/doc/residue2.png create mode 100755 contrib/vorbis/doc/rfc5215.txt create mode 100755 contrib/vorbis/doc/rfc5215.xml create mode 100644 contrib/vorbis/doc/squarepolar.png create mode 100644 contrib/vorbis/doc/stereo.html create mode 100644 contrib/vorbis/doc/stream.png create mode 100644 contrib/vorbis/doc/v-comment.html create mode 100644 contrib/vorbis/doc/vorbis-clip.txt create mode 100644 contrib/vorbis/doc/vorbis-errors.txt create mode 100644 contrib/vorbis/doc/vorbis-fidelity.html create mode 100644 contrib/vorbis/doc/vorbisenc/Makefile.am create mode 100644 contrib/vorbis/doc/vorbisenc/changes.html create mode 100644 contrib/vorbis/doc/vorbisenc/examples.html create mode 100644 contrib/vorbis/doc/vorbisenc/index.html create mode 100644 contrib/vorbis/doc/vorbisenc/ovectl_ratemanage2_arg.html create mode 100644 contrib/vorbis/doc/vorbisenc/ovectl_ratemanage_arg.html create mode 100644 contrib/vorbis/doc/vorbisenc/overview.html create mode 100644 contrib/vorbis/doc/vorbisenc/reference.html create mode 100644 contrib/vorbis/doc/vorbisenc/style.css create mode 100644 contrib/vorbis/doc/vorbisenc/vorbis_encode_ctl.html create mode 100644 contrib/vorbis/doc/vorbisenc/vorbis_encode_init.html create mode 100644 contrib/vorbis/doc/vorbisenc/vorbis_encode_init_vbr.html create mode 100644 contrib/vorbis/doc/vorbisenc/vorbis_encode_setup_init.html create mode 100644 contrib/vorbis/doc/vorbisenc/vorbis_encode_setup_managed.html create mode 100644 contrib/vorbis/doc/vorbisenc/vorbis_encode_setup_vbr.html create mode 100644 contrib/vorbis/doc/vorbisfile/Makefile.am create mode 100644 contrib/vorbis/doc/vorbisfile/OggVorbis_File.html create mode 100644 contrib/vorbis/doc/vorbisfile/callbacks.html create mode 100644 contrib/vorbis/doc/vorbisfile/chaining_example_c.html create mode 100644 contrib/vorbis/doc/vorbisfile/chainingexample.html create mode 100644 contrib/vorbis/doc/vorbisfile/crosslap.html create mode 100644 contrib/vorbis/doc/vorbisfile/datastructures.html create mode 100644 contrib/vorbis/doc/vorbisfile/decoding.html create mode 100644 contrib/vorbis/doc/vorbisfile/example.html create mode 100644 contrib/vorbis/doc/vorbisfile/exampleindex.html create mode 100644 contrib/vorbis/doc/vorbisfile/fileinfo.html create mode 100644 contrib/vorbis/doc/vorbisfile/index.html create mode 100644 contrib/vorbis/doc/vorbisfile/initialization.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_bitrate.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_bitrate_instant.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_callbacks.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_clear.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_comment.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_crosslap.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_fopen.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_info.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_open.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_open_callbacks.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_pcm_seek.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_pcm_seek_lap.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_pcm_seek_page.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_pcm_seek_page_lap.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_pcm_tell.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_pcm_total.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_raw_seek.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_raw_seek_lap.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_raw_tell.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_raw_total.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_read.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_read_filter.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_read_float.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_seekable.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_serialnumber.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_streams.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_test.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_test_callbacks.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_test_open.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_time_seek.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_time_seek_lap.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_time_seek_page.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_time_seek_page_lap.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_time_tell.html create mode 100644 contrib/vorbis/doc/vorbisfile/ov_time_total.html create mode 100644 contrib/vorbis/doc/vorbisfile/overview.html create mode 100644 contrib/vorbis/doc/vorbisfile/reference.html create mode 100644 contrib/vorbis/doc/vorbisfile/seekexample.html create mode 100644 contrib/vorbis/doc/vorbisfile/seeking.html create mode 100644 contrib/vorbis/doc/vorbisfile/seeking_example_c.html create mode 100644 contrib/vorbis/doc/vorbisfile/seeking_test_c.html create mode 100644 contrib/vorbis/doc/vorbisfile/seekingexample.html create mode 100644 contrib/vorbis/doc/vorbisfile/style.css create mode 100644 contrib/vorbis/doc/vorbisfile/threads.html create mode 100644 contrib/vorbis/doc/vorbisfile/vorbisfile_example_c.html create mode 100644 contrib/vorbis/doc/window1.png create mode 100644 contrib/vorbis/doc/window2.png create mode 100644 contrib/vorbis/examples/Makefile.am create mode 100644 contrib/vorbis/examples/chaining_example.c create mode 100644 contrib/vorbis/examples/decoder_example.c create mode 100644 contrib/vorbis/examples/encoder_example.c create mode 100755 contrib/vorbis/examples/frameview.pl create mode 100644 contrib/vorbis/examples/seeking_example.c create mode 100644 contrib/vorbis/examples/vorbisfile_example.c create mode 100644 contrib/vorbis/include/Makefile.am create mode 100644 contrib/vorbis/include/vorbis/Makefile.am create mode 100644 contrib/vorbis/include/vorbis/codec.h create mode 100644 contrib/vorbis/include/vorbis/vorbisenc.h create mode 100644 contrib/vorbis/include/vorbis/vorbisfile.h create mode 100644 contrib/vorbis/lib/CMakeLists.txt create mode 100644 contrib/vorbis/lib/Makefile.am create mode 100644 contrib/vorbis/lib/analysis.c create mode 100644 contrib/vorbis/lib/backends.h create mode 100644 contrib/vorbis/lib/barkmel.c create mode 100644 contrib/vorbis/lib/bitrate.c create mode 100644 contrib/vorbis/lib/bitrate.h create mode 100644 contrib/vorbis/lib/block.c create mode 100644 contrib/vorbis/lib/books/Makefile.am create mode 100644 contrib/vorbis/lib/books/coupled/Makefile.am create mode 100644 contrib/vorbis/lib/books/coupled/res_books_51.h create mode 100644 contrib/vorbis/lib/books/coupled/res_books_stereo.h create mode 100644 contrib/vorbis/lib/books/floor/Makefile.am create mode 100644 contrib/vorbis/lib/books/floor/floor_books.h create mode 100644 contrib/vorbis/lib/books/uncoupled/Makefile.am create mode 100644 contrib/vorbis/lib/books/uncoupled/res_books_uncoupled.h create mode 100644 contrib/vorbis/lib/codebook.c create mode 100644 contrib/vorbis/lib/codebook.h create mode 100644 contrib/vorbis/lib/codec_internal.h create mode 100644 contrib/vorbis/lib/envelope.c create mode 100644 contrib/vorbis/lib/envelope.h create mode 100644 contrib/vorbis/lib/floor0.c create mode 100644 contrib/vorbis/lib/floor1.c create mode 100644 contrib/vorbis/lib/highlevel.h create mode 100644 contrib/vorbis/lib/info.c create mode 100644 contrib/vorbis/lib/lookup.c create mode 100644 contrib/vorbis/lib/lookup.h create mode 100644 contrib/vorbis/lib/lookup_data.h create mode 100755 contrib/vorbis/lib/lookups.pl create mode 100644 contrib/vorbis/lib/lpc.c create mode 100644 contrib/vorbis/lib/lpc.h create mode 100644 contrib/vorbis/lib/lsp.c create mode 100644 contrib/vorbis/lib/lsp.h create mode 100644 contrib/vorbis/lib/mapping0.c create mode 100644 contrib/vorbis/lib/masking.h create mode 100644 contrib/vorbis/lib/mdct.c create mode 100644 contrib/vorbis/lib/mdct.h create mode 100644 contrib/vorbis/lib/misc.c create mode 100644 contrib/vorbis/lib/misc.h create mode 100644 contrib/vorbis/lib/modes/Makefile.am create mode 100644 contrib/vorbis/lib/modes/floor_all.h create mode 100644 contrib/vorbis/lib/modes/psych_11.h create mode 100644 contrib/vorbis/lib/modes/psych_16.h create mode 100644 contrib/vorbis/lib/modes/psych_44.h create mode 100644 contrib/vorbis/lib/modes/psych_8.h create mode 100644 contrib/vorbis/lib/modes/residue_16.h create mode 100644 contrib/vorbis/lib/modes/residue_44.h create mode 100644 contrib/vorbis/lib/modes/residue_44p51.h create mode 100644 contrib/vorbis/lib/modes/residue_44u.h create mode 100644 contrib/vorbis/lib/modes/residue_8.h create mode 100644 contrib/vorbis/lib/modes/setup_11.h create mode 100644 contrib/vorbis/lib/modes/setup_16.h create mode 100644 contrib/vorbis/lib/modes/setup_22.h create mode 100644 contrib/vorbis/lib/modes/setup_32.h create mode 100644 contrib/vorbis/lib/modes/setup_44.h create mode 100644 contrib/vorbis/lib/modes/setup_44p51.h create mode 100644 contrib/vorbis/lib/modes/setup_44u.h create mode 100644 contrib/vorbis/lib/modes/setup_8.h create mode 100644 contrib/vorbis/lib/modes/setup_X.h create mode 100644 contrib/vorbis/lib/os.h create mode 100644 contrib/vorbis/lib/psy.c create mode 100644 contrib/vorbis/lib/psy.h create mode 100644 contrib/vorbis/lib/psytune.c create mode 100644 contrib/vorbis/lib/registry.c create mode 100644 contrib/vorbis/lib/registry.h create mode 100644 contrib/vorbis/lib/res0.c create mode 100644 contrib/vorbis/lib/scales.h create mode 100644 contrib/vorbis/lib/sharedbook.c create mode 100644 contrib/vorbis/lib/smallft.c create mode 100644 contrib/vorbis/lib/smallft.h create mode 100644 contrib/vorbis/lib/synthesis.c create mode 100644 contrib/vorbis/lib/tone.c create mode 100644 contrib/vorbis/lib/vorbisenc.c create mode 100644 contrib/vorbis/lib/vorbisfile.c create mode 100644 contrib/vorbis/lib/window.c create mode 100644 contrib/vorbis/lib/window.h create mode 100644 contrib/vorbis/libvorbis.spec.in create mode 100644 contrib/vorbis/m4/Makefile.am create mode 100644 contrib/vorbis/m4/add_cflags.m4 create mode 100644 contrib/vorbis/m4/ogg.m4 create mode 100644 contrib/vorbis/m4/pkg.m4 create mode 100644 contrib/vorbis/macosx/English.lproj/InfoPlist.strings create mode 100644 contrib/vorbis/macosx/Info.plist create mode 100644 contrib/vorbis/macosx/Vorbis.xcodeproj/project.pbxproj create mode 100644 contrib/vorbis/symbian/bld.inf create mode 100644 contrib/vorbis/symbian/config.h create mode 100644 contrib/vorbis/symbian/vorbis.mmp create mode 100644 contrib/vorbis/test/Makefile.am create mode 100644 contrib/vorbis/test/test.c create mode 100644 contrib/vorbis/test/util.c create mode 100644 contrib/vorbis/test/util.h create mode 100644 contrib/vorbis/test/write_read.c create mode 100644 contrib/vorbis/test/write_read.h create mode 100644 contrib/vorbis/vorbis-uninstalled.pc.in create mode 100644 contrib/vorbis/vorbis.m4 create mode 100644 contrib/vorbis/vorbis.pc.in create mode 100644 contrib/vorbis/vorbisenc-uninstalled.pc.in create mode 100644 contrib/vorbis/vorbisenc.pc.in create mode 100644 contrib/vorbis/vorbisfile-uninstalled.pc.in create mode 100644 contrib/vorbis/vorbisfile.pc.in create mode 100644 contrib/vorbis/vq/16.vqs create mode 100644 contrib/vorbis/vq/16u.vqs create mode 100644 contrib/vorbis/vq/44c-1.vqs create mode 100644 contrib/vorbis/vq/44c0.vqs create mode 100644 contrib/vorbis/vq/44c1.vqs create mode 100644 contrib/vorbis/vq/44c2.vqs create mode 100644 contrib/vorbis/vq/44c3.vqs create mode 100644 contrib/vorbis/vq/44c4.vqs create mode 100644 contrib/vorbis/vq/44c5.vqs create mode 100644 contrib/vorbis/vq/44c6.vqs create mode 100644 contrib/vorbis/vq/44c7.vqs create mode 100644 contrib/vorbis/vq/44c8.vqs create mode 100644 contrib/vorbis/vq/44c9.vqs create mode 100644 contrib/vorbis/vq/44p-1.vqs create mode 100644 contrib/vorbis/vq/44p0.vqs create mode 100644 contrib/vorbis/vq/44p1.vqs create mode 100644 contrib/vorbis/vq/44p2.vqs create mode 100644 contrib/vorbis/vq/44p3.vqs create mode 100644 contrib/vorbis/vq/44p4.vqs create mode 100644 contrib/vorbis/vq/44p5.vqs create mode 100644 contrib/vorbis/vq/44p6.vqs create mode 100644 contrib/vorbis/vq/44p7.vqs create mode 100644 contrib/vorbis/vq/44p8.vqs create mode 100644 contrib/vorbis/vq/44p9.vqs create mode 100644 contrib/vorbis/vq/44u0.vqs create mode 100644 contrib/vorbis/vq/44u1.vqs create mode 100644 contrib/vorbis/vq/44u2.vqs create mode 100644 contrib/vorbis/vq/44u3.vqs create mode 100644 contrib/vorbis/vq/44u4.vqs create mode 100644 contrib/vorbis/vq/44u5.vqs create mode 100644 contrib/vorbis/vq/44u6.vqs create mode 100644 contrib/vorbis/vq/44u7.vqs create mode 100644 contrib/vorbis/vq/44u8.vqs create mode 100644 contrib/vorbis/vq/44u9.vqs create mode 100644 contrib/vorbis/vq/8.vqs create mode 100644 contrib/vorbis/vq/8u.vqs create mode 100644 contrib/vorbis/vq/Makefile.am create mode 100644 contrib/vorbis/vq/bookutil.c create mode 100644 contrib/vorbis/vq/bookutil.h create mode 100644 contrib/vorbis/vq/distribution.c create mode 100644 contrib/vorbis/vq/floor_11.vqs create mode 100644 contrib/vorbis/vq/floor_22.vqs create mode 100644 contrib/vorbis/vq/floor_44.vqs create mode 100644 contrib/vorbis/vq/huffbuild.c create mode 100644 contrib/vorbis/vq/latticebuild.c create mode 100644 contrib/vorbis/vq/latticetune.c create mode 100644 contrib/vorbis/vq/localcodebook.h create mode 100755 contrib/vorbis/vq/make_floor_books.pl create mode 100755 contrib/vorbis/vq/make_residue_books.pl create mode 100644 contrib/vorbis/vq/metrics.c create mode 100644 contrib/vorbis/vq/vqgen.c create mode 100644 contrib/vorbis/vq/vqgen.h create mode 100644 contrib/vorbis/win32/VS2005/README create mode 100644 contrib/vorbis/win32/VS2005/libogg.vsprops create mode 100644 contrib/vorbis/win32/VS2005/libvorbis/libvorbis_dynamic.vcproj create mode 100644 contrib/vorbis/win32/VS2005/libvorbis/libvorbis_static.vcproj create mode 100644 contrib/vorbis/win32/VS2005/libvorbisfile/libvorbisfile_dynamic.vcproj create mode 100644 contrib/vorbis/win32/VS2005/libvorbisfile/libvorbisfile_static.vcproj create mode 100644 contrib/vorbis/win32/VS2005/vorbis_dynamic.sln create mode 100644 contrib/vorbis/win32/VS2005/vorbis_static.sln create mode 100644 contrib/vorbis/win32/VS2005/vorbisdec/vorbisdec_dynamic.vcproj create mode 100644 contrib/vorbis/win32/VS2005/vorbisdec/vorbisdec_static.vcproj create mode 100644 contrib/vorbis/win32/VS2005/vorbisenc/vorbisenc_dynamic.vcproj create mode 100644 contrib/vorbis/win32/VS2005/vorbisenc/vorbisenc_static.vcproj create mode 100644 contrib/vorbis/win32/VS2008/README create mode 100644 contrib/vorbis/win32/VS2008/libogg.vsprops create mode 100644 contrib/vorbis/win32/VS2008/libvorbis/libvorbis_dynamic.vcproj create mode 100644 contrib/vorbis/win32/VS2008/libvorbis/libvorbis_static.vcproj create mode 100644 contrib/vorbis/win32/VS2008/libvorbisfile/libvorbisfile_dynamic.vcproj create mode 100644 contrib/vorbis/win32/VS2008/libvorbisfile/libvorbisfile_static.vcproj create mode 100644 contrib/vorbis/win32/VS2008/vorbis_dynamic.sln create mode 100644 contrib/vorbis/win32/VS2008/vorbis_static.sln create mode 100644 contrib/vorbis/win32/VS2008/vorbisdec/vorbisdec_dynamic.vcproj create mode 100644 contrib/vorbis/win32/VS2008/vorbisdec/vorbisdec_static.vcproj create mode 100644 contrib/vorbis/win32/VS2008/vorbisenc/vorbisenc_dynamic.vcproj create mode 100644 contrib/vorbis/win32/VS2008/vorbisenc/vorbisenc_static.vcproj create mode 100644 contrib/vorbis/win32/VS2010/README create mode 100644 contrib/vorbis/win32/VS2010/libogg.props create mode 100644 contrib/vorbis/win32/VS2010/libvorbis/libvorbis_dynamic.vcxproj create mode 100644 contrib/vorbis/win32/VS2010/libvorbis/libvorbis_static.vcxproj create mode 100644 contrib/vorbis/win32/VS2010/libvorbisfile/libvorbisfile_dynamic.vcxproj create mode 100644 contrib/vorbis/win32/VS2010/libvorbisfile/libvorbisfile_static.vcxproj create mode 100644 contrib/vorbis/win32/VS2010/vorbis_dynamic.sln create mode 100644 contrib/vorbis/win32/VS2010/vorbis_static.sln create mode 100644 contrib/vorbis/win32/VS2010/vorbisdec/vorbisdec_dynamic.vcxproj create mode 100644 contrib/vorbis/win32/VS2010/vorbisdec/vorbisdec_static.vcxproj create mode 100644 contrib/vorbis/win32/VS2010/vorbisenc/vorbisenc_dynamic.vcxproj create mode 100644 contrib/vorbis/win32/VS2010/vorbisenc/vorbisenc_static.vcxproj create mode 100644 contrib/vorbis/win32/vorbis.def create mode 100644 contrib/vorbis/win32/vorbisenc.def create mode 100644 contrib/vorbis/win32/vorbisfile.def create mode 100644 contrib/zlib/.gitignore create mode 100644 contrib/zlib/CMakeLists.txt create mode 100644 contrib/zlib/ChangeLog create mode 100644 contrib/zlib/FAQ create mode 100644 contrib/zlib/INDEX create mode 100644 contrib/zlib/Makefile create mode 100644 contrib/zlib/Makefile.in create mode 100644 contrib/zlib/README create mode 100644 contrib/zlib/adler32.c create mode 100644 contrib/zlib/amiga/Makefile.pup create mode 100644 contrib/zlib/amiga/Makefile.sas create mode 100644 contrib/zlib/compress.c create mode 100755 contrib/zlib/configure create mode 100644 contrib/zlib/contrib/README.contrib create mode 100644 contrib/zlib/contrib/ada/buffer_demo.adb create mode 100644 contrib/zlib/contrib/ada/mtest.adb create mode 100644 contrib/zlib/contrib/ada/read.adb create mode 100644 contrib/zlib/contrib/ada/readme.txt create mode 100644 contrib/zlib/contrib/ada/test.adb create mode 100644 contrib/zlib/contrib/ada/zlib-streams.adb create mode 100644 contrib/zlib/contrib/ada/zlib-streams.ads create mode 100644 contrib/zlib/contrib/ada/zlib-thin.adb create mode 100644 contrib/zlib/contrib/ada/zlib-thin.ads create mode 100644 contrib/zlib/contrib/ada/zlib.adb create mode 100644 contrib/zlib/contrib/ada/zlib.ads create mode 100644 contrib/zlib/contrib/ada/zlib.gpr create mode 100644 contrib/zlib/contrib/amd64/amd64-match.S create mode 100644 contrib/zlib/contrib/asm686/README.686 create mode 100644 contrib/zlib/contrib/asm686/match.S create mode 100644 contrib/zlib/contrib/blast/Makefile create mode 100644 contrib/zlib/contrib/blast/README create mode 100644 contrib/zlib/contrib/blast/blast.c create mode 100644 contrib/zlib/contrib/blast/blast.h create mode 100644 contrib/zlib/contrib/blast/test.pk create mode 100644 contrib/zlib/contrib/blast/test.txt create mode 100644 contrib/zlib/contrib/delphi/ZLib.pas create mode 100644 contrib/zlib/contrib/delphi/ZLibConst.pas create mode 100644 contrib/zlib/contrib/delphi/readme.txt create mode 100644 contrib/zlib/contrib/delphi/zlibd32.mak create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib.build create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib.chm create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib.sln create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib/AssemblyInfo.cs create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib/ChecksumImpl.cs create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib/CircularBuffer.cs create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib/CodecBase.cs create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib/Deflater.cs create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib/DotZLib.cs create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib/DotZLib.csproj create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib/GZipStream.cs create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib/Inflater.cs create mode 100644 contrib/zlib/contrib/dotzlib/DotZLib/UnitTests.cs create mode 100644 contrib/zlib/contrib/dotzlib/LICENSE_1_0.txt create mode 100644 contrib/zlib/contrib/dotzlib/readme.txt create mode 100644 contrib/zlib/contrib/gcc_gvmat64/gvmat64.S create mode 100644 contrib/zlib/contrib/infback9/README create mode 100644 contrib/zlib/contrib/infback9/infback9.c create mode 100644 contrib/zlib/contrib/infback9/infback9.h create mode 100644 contrib/zlib/contrib/infback9/inffix9.h create mode 100644 contrib/zlib/contrib/infback9/inflate9.h create mode 100644 contrib/zlib/contrib/infback9/inftree9.c create mode 100644 contrib/zlib/contrib/infback9/inftree9.h create mode 100644 contrib/zlib/contrib/inflate86/inffas86.c create mode 100644 contrib/zlib/contrib/inflate86/inffast.S create mode 100644 contrib/zlib/contrib/iostream/test.cpp create mode 100644 contrib/zlib/contrib/iostream/zfstream.cpp create mode 100644 contrib/zlib/contrib/iostream/zfstream.h create mode 100644 contrib/zlib/contrib/iostream2/zstream.h create mode 100644 contrib/zlib/contrib/iostream2/zstream_test.cpp create mode 100644 contrib/zlib/contrib/iostream3/README create mode 100644 contrib/zlib/contrib/iostream3/TODO create mode 100644 contrib/zlib/contrib/iostream3/test.cc create mode 100644 contrib/zlib/contrib/iostream3/zfstream.cc create mode 100644 contrib/zlib/contrib/iostream3/zfstream.h create mode 100644 contrib/zlib/contrib/masmx64/bld_ml64.bat create mode 100644 contrib/zlib/contrib/masmx64/gvmat64.asm create mode 100644 contrib/zlib/contrib/masmx64/inffas8664.c create mode 100644 contrib/zlib/contrib/masmx64/inffasx64.asm create mode 100644 contrib/zlib/contrib/masmx64/readme.txt create mode 100644 contrib/zlib/contrib/masmx86/bld_ml32.bat create mode 100644 contrib/zlib/contrib/masmx86/inffas32.asm create mode 100644 contrib/zlib/contrib/masmx86/match686.asm create mode 100644 contrib/zlib/contrib/masmx86/readme.txt create mode 100644 contrib/zlib/contrib/minizip/Makefile create mode 100644 contrib/zlib/contrib/minizip/Makefile.am create mode 100644 contrib/zlib/contrib/minizip/MiniZip64_Changes.txt create mode 100644 contrib/zlib/contrib/minizip/MiniZip64_info.txt create mode 100644 contrib/zlib/contrib/minizip/configure.ac create mode 100644 contrib/zlib/contrib/minizip/crypt.h create mode 100644 contrib/zlib/contrib/minizip/ioapi.c create mode 100644 contrib/zlib/contrib/minizip/ioapi.h create mode 100644 contrib/zlib/contrib/minizip/iowin32.c create mode 100644 contrib/zlib/contrib/minizip/iowin32.h create mode 100644 contrib/zlib/contrib/minizip/make_vms.com create mode 100644 contrib/zlib/contrib/minizip/miniunz.c create mode 100644 contrib/zlib/contrib/minizip/miniunzip.1 create mode 100644 contrib/zlib/contrib/minizip/minizip.1 create mode 100644 contrib/zlib/contrib/minizip/minizip.c create mode 100644 contrib/zlib/contrib/minizip/minizip.pc.in create mode 100644 contrib/zlib/contrib/minizip/mztools.c create mode 100644 contrib/zlib/contrib/minizip/mztools.h create mode 100644 contrib/zlib/contrib/minizip/unzip.c create mode 100644 contrib/zlib/contrib/minizip/unzip.h create mode 100644 contrib/zlib/contrib/minizip/zip.c create mode 100644 contrib/zlib/contrib/minizip/zip.h create mode 100644 contrib/zlib/contrib/pascal/example.pas create mode 100644 contrib/zlib/contrib/pascal/readme.txt create mode 100644 contrib/zlib/contrib/pascal/zlibd32.mak create mode 100644 contrib/zlib/contrib/pascal/zlibpas.pas create mode 100644 contrib/zlib/contrib/puff/Makefile create mode 100644 contrib/zlib/contrib/puff/README create mode 100644 contrib/zlib/contrib/puff/puff.c create mode 100644 contrib/zlib/contrib/puff/puff.h create mode 100644 contrib/zlib/contrib/puff/pufftest.c create mode 100644 contrib/zlib/contrib/puff/zeros.raw create mode 100644 contrib/zlib/contrib/testzlib/testzlib.c create mode 100644 contrib/zlib/contrib/testzlib/testzlib.txt create mode 100644 contrib/zlib/contrib/untgz/Makefile create mode 100644 contrib/zlib/contrib/untgz/Makefile.msc create mode 100644 contrib/zlib/contrib/untgz/untgz.c create mode 100644 contrib/zlib/contrib/vstudio/readme.txt create mode 100644 contrib/zlib/contrib/vstudio/vc10/miniunz.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc10/miniunz.vcxproj.filters create mode 100644 contrib/zlib/contrib/vstudio/vc10/minizip.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc10/minizip.vcxproj.filters create mode 100644 contrib/zlib/contrib/vstudio/vc10/testzlib.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc10/testzlib.vcxproj.filters create mode 100644 contrib/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc10/testzlibdll.vcxproj.filters create mode 100644 contrib/zlib/contrib/vstudio/vc10/zlib.rc create mode 100644 contrib/zlib/contrib/vstudio/vc10/zlibstat.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc10/zlibstat.vcxproj.filters create mode 100644 contrib/zlib/contrib/vstudio/vc10/zlibvc.def create mode 100644 contrib/zlib/contrib/vstudio/vc10/zlibvc.sln create mode 100644 contrib/zlib/contrib/vstudio/vc10/zlibvc.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc10/zlibvc.vcxproj.filters create mode 100644 contrib/zlib/contrib/vstudio/vc11/miniunz.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc11/minizip.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc11/testzlib.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc11/zlib.rc create mode 100644 contrib/zlib/contrib/vstudio/vc11/zlibstat.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc11/zlibvc.def create mode 100644 contrib/zlib/contrib/vstudio/vc11/zlibvc.sln create mode 100644 contrib/zlib/contrib/vstudio/vc11/zlibvc.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc12/miniunz.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc12/minizip.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc12/testzlib.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc12/zlib.rc create mode 100644 contrib/zlib/contrib/vstudio/vc12/zlibstat.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc12/zlibvc.def create mode 100644 contrib/zlib/contrib/vstudio/vc12/zlibvc.sln create mode 100644 contrib/zlib/contrib/vstudio/vc12/zlibvc.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc14/miniunz.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc14/minizip.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc14/testzlib.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc14/zlib.rc create mode 100644 contrib/zlib/contrib/vstudio/vc14/zlibstat.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc14/zlibvc.def create mode 100644 contrib/zlib/contrib/vstudio/vc14/zlibvc.sln create mode 100644 contrib/zlib/contrib/vstudio/vc14/zlibvc.vcxproj create mode 100644 contrib/zlib/contrib/vstudio/vc9/miniunz.vcproj create mode 100644 contrib/zlib/contrib/vstudio/vc9/minizip.vcproj create mode 100644 contrib/zlib/contrib/vstudio/vc9/testzlib.vcproj create mode 100644 contrib/zlib/contrib/vstudio/vc9/testzlibdll.vcproj create mode 100644 contrib/zlib/contrib/vstudio/vc9/zlib.rc create mode 100644 contrib/zlib/contrib/vstudio/vc9/zlibstat.vcproj create mode 100644 contrib/zlib/contrib/vstudio/vc9/zlibvc.def create mode 100644 contrib/zlib/contrib/vstudio/vc9/zlibvc.sln create mode 100644 contrib/zlib/contrib/vstudio/vc9/zlibvc.vcproj create mode 100644 contrib/zlib/crc32.c create mode 100644 contrib/zlib/crc32.h create mode 100644 contrib/zlib/deflate.c create mode 100644 contrib/zlib/deflate.h create mode 100644 contrib/zlib/doc/algorithm.txt create mode 100644 contrib/zlib/doc/rfc1950.txt create mode 100644 contrib/zlib/doc/rfc1951.txt create mode 100644 contrib/zlib/doc/rfc1952.txt create mode 100644 contrib/zlib/doc/txtvsbin.txt create mode 100644 contrib/zlib/examples/README.examples create mode 100644 contrib/zlib/examples/enough.c create mode 100644 contrib/zlib/examples/fitblk.c create mode 100644 contrib/zlib/examples/gun.c create mode 100644 contrib/zlib/examples/gzappend.c create mode 100644 contrib/zlib/examples/gzjoin.c create mode 100644 contrib/zlib/examples/gzlog.c create mode 100644 contrib/zlib/examples/gzlog.h create mode 100644 contrib/zlib/examples/zlib_how.html create mode 100644 contrib/zlib/examples/zpipe.c create mode 100644 contrib/zlib/examples/zran.c create mode 100644 contrib/zlib/gzclose.c create mode 100644 contrib/zlib/gzguts.h create mode 100644 contrib/zlib/gzlib.c create mode 100644 contrib/zlib/gzread.c create mode 100644 contrib/zlib/gzwrite.c create mode 100644 contrib/zlib/infback.c create mode 100644 contrib/zlib/inffast.c create mode 100644 contrib/zlib/inffast.h create mode 100644 contrib/zlib/inffixed.h create mode 100644 contrib/zlib/inflate.c create mode 100644 contrib/zlib/inflate.h create mode 100644 contrib/zlib/inftrees.c create mode 100644 contrib/zlib/inftrees.h create mode 100644 contrib/zlib/make_vms.com create mode 100644 contrib/zlib/msdos/Makefile.bor create mode 100644 contrib/zlib/msdos/Makefile.dj2 create mode 100644 contrib/zlib/msdos/Makefile.emx create mode 100644 contrib/zlib/msdos/Makefile.msc create mode 100644 contrib/zlib/msdos/Makefile.tc create mode 100644 contrib/zlib/nintendods/Makefile create mode 100644 contrib/zlib/nintendods/README create mode 100644 contrib/zlib/old/Makefile.emx create mode 100644 contrib/zlib/old/Makefile.riscos create mode 100644 contrib/zlib/old/README create mode 100644 contrib/zlib/old/descrip.mms create mode 100644 contrib/zlib/old/os2/Makefile.os2 create mode 100644 contrib/zlib/old/os2/zlib.def create mode 100644 contrib/zlib/old/visual-basic.txt create mode 100644 contrib/zlib/os400/README400 create mode 100644 contrib/zlib/os400/bndsrc create mode 100644 contrib/zlib/os400/make.sh create mode 100644 contrib/zlib/os400/zlib.inc create mode 100644 contrib/zlib/qnx/package.qpg create mode 100644 contrib/zlib/test/example.c create mode 100644 contrib/zlib/test/infcover.c create mode 100644 contrib/zlib/test/minigzip.c create mode 100644 contrib/zlib/treebuild.xml create mode 100644 contrib/zlib/trees.c create mode 100644 contrib/zlib/trees.h create mode 100644 contrib/zlib/uncompr.c create mode 100644 contrib/zlib/watcom/watcom_f.mak create mode 100644 contrib/zlib/watcom/watcom_l.mak create mode 100644 contrib/zlib/win32/DLL_FAQ.txt create mode 100644 contrib/zlib/win32/Makefile.bor create mode 100644 contrib/zlib/win32/Makefile.gcc create mode 100644 contrib/zlib/win32/Makefile.msc create mode 100644 contrib/zlib/win32/README-WIN32.txt create mode 100644 contrib/zlib/win32/VisualC.txt create mode 100644 contrib/zlib/win32/zlib.def create mode 100644 contrib/zlib/win32/zlib1.rc create mode 100644 contrib/zlib/zconf.h create mode 100644 contrib/zlib/zconf.h.cmakein create mode 100644 contrib/zlib/zconf.h.in create mode 100644 contrib/zlib/zlib.3 create mode 100644 contrib/zlib/zlib.3.pdf create mode 100644 contrib/zlib/zlib.h create mode 100644 contrib/zlib/zlib.map create mode 100644 contrib/zlib/zlib.pc.cmakein create mode 100644 contrib/zlib/zlib.pc.in create mode 100755 contrib/zlib/zlib2ansi create mode 100644 contrib/zlib/zutil.c create mode 100644 contrib/zlib/zutil.h (limited to 'contrib') diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt new file mode 100644 index 0000000..ea23799 --- /dev/null +++ b/contrib/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(libpng) +add_subdirectory(ogg) +add_subdirectory(Opcode) +add_subdirectory(vorbis) +add_subdirectory(zlib) diff --git a/contrib/Opcode/CMakeLists.txt b/contrib/Opcode/CMakeLists.txt new file mode 100644 index 0000000..6010c50 --- /dev/null +++ b/contrib/Opcode/CMakeLists.txt @@ -0,0 +1,55 @@ +project(Opcode) +add_library( + Opcode + SHARED + OPC_AABBCollider.cpp + OPC_AABBTree.cpp + OPC_BaseModel.cpp + OPC_BoxPruning.cpp + OPC_Collider.cpp + OPC_Common.cpp + OPC_HybridModel.cpp + OPC_LSSCollider.cpp + OPC_MeshInterface.cpp + OPC_Model.cpp + OPC_OBBCollider.cpp + OPC_OptimizedTree.cpp + OPC_Picking.cpp + OPC_PlanesCollider.cpp + OPC_RayCollider.cpp + OPC_SphereCollider.cpp + OPC_SweepAndPrune.cpp + OPC_TreeBuilders.cpp + OPC_TreeCollider.cpp + OPC_VolumeCollider.cpp + Opcode.cpp + StdAfx.cpp + Ice/IceAABB.cpp + Ice/IceContainer.cpp + Ice/IceHPoint.cpp + Ice/IceIndexedTriangle.cpp + Ice/IceMatrix3x3.cpp + Ice/IceMatrix4x4.cpp + Ice/IceOBB.cpp + Ice/IcePlane.cpp + Ice/IcePoint.cpp + Ice/IceRandom.cpp + Ice/IceRay.cpp + Ice/IceRevisitedRadix.cpp + Ice/IceSegment.cpp + Ice/IceTriangle.cpp + Ice/IceUtils.cpp + ) +target_include_directories( + Opcode + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + ) +target_precompile_headers( + Opcode + PUBLIC StdAfx.h + ) +target_compile_definitions( + Opcode + PRIVATE OPCODE_EXPORTS + PUBLIC _ALLOW_KEYWORD_MACROS + ) diff --git a/contrib/Opcode/Doc/OpcodeUserManual.pdf b/contrib/Opcode/Doc/OpcodeUserManual.pdf new file mode 100644 index 0000000..4ca3f12 Binary files /dev/null and b/contrib/Opcode/Doc/OpcodeUserManual.pdf differ diff --git a/contrib/Opcode/Ice/IceAABB.cpp b/contrib/Opcode/Ice/IceAABB.cpp new file mode 100644 index 0000000..03bca6c --- /dev/null +++ b/contrib/Opcode/Ice/IceAABB.cpp @@ -0,0 +1,405 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains AABB-related code. + * \file IceAABB.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * AABB class. + * \class AABB + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the sum of two AABBs. + * \param aabb [in] the other AABB + * \return Self-Reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABB& AABB::Add(const AABB& aabb) +{ + // Compute new min & max values + IcePoint Min; GetMin(Min); + IcePoint Tmp; aabb.GetMin(Tmp); + Min.Min(Tmp); + + IcePoint Max; GetMax(Max); + aabb.GetMax(Tmp); + Max.Max(Tmp); + + // Update this + SetMinMax(Min, Max); + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Makes a cube from the AABB. + * \param cube [out] the cube AABB + * \return cube edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float AABB::MakeCube(AABB& cube) const +{ + IcePoint Ext; GetExtents(Ext); + float Max = Ext.Max(); + + IcePoint Cnt; GetCenter(Cnt); + cube.SetCenterExtents(Cnt, IcePoint(Max, Max, Max)); + return Max; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Makes a sphere from the AABB. + * \param sphere [out] sphere containing the AABB + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABB::MakeSphere(Sphere& sphere) const +{ + GetExtents(sphere.mCenter); + sphere.mRadius = sphere.mCenter.Magnitude() * 1.00001f; // To make sure sphere::Contains(*this) succeeds + GetCenter(sphere.mCenter); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks a box is inside another box. + * \param box [in] the other AABB + * \return true if current box is inside input box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABB::IsInside(const AABB& box) const +{ + if(box.GetMin(0)>GetMin(0)) return false; + if(box.GetMin(1)>GetMin(1)) return false; + if(box.GetMin(2)>GetMin(2)) return false; + if(box.GetMax(0) max.x) ? 2 : 0) // 2 = right + + ((local_eye.y < min.y) ? 4 : 0) // 4 = bottom + + ((local_eye.y > max.y) ? 8 : 0) // 8 = top + + ((local_eye.z < min.z) ? 16 : 0) // 16 = front + + ((local_eye.z > max.z) ? 32 : 0); // 32 = back + + // Look up number of vertices in outline + num = (sdword)gIndexList[pos][7]; + // Zero indicates invalid case + if(!num) return null; + + return &gIndexList[pos][0]; +} + +// calculateBoxArea: computes the screen-projected 2D area of an oriented 3D bounding box + +//const IcePoint& eye, //eye point (in bbox object coordinates) +//const AABB& box, //3d bbox +//const Matrix4x4& mat, //free transformation for bbox +//float width, float height, int& num) +float AABB::ComputeBoxArea(const IcePoint& eye, const Matrix4x4& mat, float width, float height, sdword& num) const +{ + const sbyte* Outline = ComputeOutline(eye, num); + if(!Outline) return -1.0f; + + // Compute box vertices + IcePoint vertexBox[8], dst[8]; + ComputePoints(vertexBox); + + // Transform all outline corners into 2D screen space + for(sdword i=0;i GetMax(0) || p.x < GetMin(0)) return FALSE; \ + if(p.y > GetMax(1) || p.y < GetMin(1)) return FALSE; \ + if(p.z > GetMax(2) || p.z < GetMin(2)) return FALSE; \ + return TRUE; \ + } + + enum AABBType + { + AABB_RENDER = 0, //!< AABB used for rendering. Not visible == not rendered. + AABB_UPDATE = 1, //!< AABB used for dynamic updates. Not visible == not updated. + + AABB_FORCE_DWORD = 0x7fffffff, + }; + +#ifdef USE_MINMAX + + struct ICEMATHS_API ShadowAABB + { + Point mMin; + Point mMax; + }; + + class ICEMATHS_API AABB + { + public: + //! Constructor + inline_ AABB() {} + //! Destructor + inline_ ~AABB() {} + + //! Type-independent methods + AABB_COMMON_METHODS; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from min & max vectors. + * \param min [in] the min point + * \param max [in] the max point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetMinMax(const Point& min, const Point& max) { mMin = min; mMax = max; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from center & extents vectors. + * \param c [in] the center point + * \param e [in] the extents vector + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetCenterExtents(const Point& c, const Point& e) { mMin = c - e; mMax = c + e; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an empty AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetEmpty() { Point p(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); mMin = -p; mMax = p;} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups a point AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetPoint(const Point& pt) { mMin = mMax = pt; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the size of the AABB. The size is defined as the longest extent. + * \return the size of the AABB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + float GetSize() const { Point e; GetExtents(e); return e.Max(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Extends the AABB. + * \param p [in] the next point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Extend(const Point& p) + { + if(p.x > mMax.x) mMax.x = p.x; + if(p.x < mMin.x) mMin.x = p.x; + + if(p.y > mMax.y) mMax.y = p.y; + if(p.y < mMin.y) mMin.y = p.y; + + if(p.z > mMax.z) mMax.z = p.z; + if(p.z < mMin.z) mMin.z = p.z; + } + // Data access + + //! Get min point of the box + inline_ void GetMin(Point& min) const { min = mMin; } + //! Get max point of the box + inline_ void GetMax(Point& max) const { max = mMax; } + + //! Get component of the box's min point along a given axis + inline_ float GetMin(udword axis) const { return mMin[axis]; } + //! Get component of the box's max point along a given axis + inline_ float GetMax(udword axis) const { return mMax[axis]; } + + //! Get box center + inline_ void GetCenter(Point& center) const { center = (mMax + mMin)*0.5f; } + //! Get box extents + inline_ void GetExtents(Point& extents) const { extents = (mMax - mMin)*0.5f; } + + //! Get component of the box's center along a given axis + inline_ float GetCenter(udword axis) const { return (mMax[axis] + mMin[axis])*0.5f; } + //! Get component of the box's extents along a given axis + inline_ float GetExtents(udword axis) const { return (mMax[axis] - mMin[axis])*0.5f; } + + //! Get box diagonal + inline_ void GetDiagonal(Point& diagonal) const { diagonal = mMax - mMin; } + inline_ float GetWidth() const { return mMax.x - mMin.x; } + inline_ float GetHeight() const { return mMax.y - mMin.y; } + inline_ float GetDepth() const { return mMax.z - mMin.z; } + + //! Volume + inline_ float GetVolume() const { return GetWidth() * GetHeight() * GetDepth(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the intersection between two AABBs. + * \param a [in] the other AABB + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a) const + { + if(mMax.x < a.mMin.x + || a.mMax.x < mMin.x + || mMax.y < a.mMin.y + || a.mMax.y < mMin.y + || mMax.z < a.mMin.z + || a.mMax.z < mMin.z) return FALSE; + + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the 1D-intersection between two AABBs, on a given axis. + * \param a [in] the other AABB + * \param axis [in] the axis (0, 1, 2) + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a, udword axis) const + { + if(mMax[axis] < a.mMin[axis] || a.mMax[axis] < mMin[axis]) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Recomputes the AABB after an arbitrary transform by a 4x4 matrix. + * Original code by Charles Bloom on the GD-Algorithm list. (I slightly modified it) + * \param mtx [in] the transform matrix + * \param aabb [out] the transformed AABB [can be *this] + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const + { + // The three edges transformed: you can efficiently transform an X-only vector + // by just getting the "X" column of the matrix + Point vx,vy,vz; + mtx.GetRow(0, vx); vx *= (mMax.x - mMin.x); + mtx.GetRow(1, vy); vy *= (mMax.y - mMin.y); + mtx.GetRow(2, vz); vz *= (mMax.z - mMin.z); + + // Transform the min point + aabb.mMin = aabb.mMax = mMin * mtx; + + // Take the transformed min & axes and find new extents + // Using CPU code in the right place is faster... + if(IS_NEGATIVE_FLOAT(vx.x)) aabb.mMin.x += vx.x; else aabb.mMax.x += vx.x; + if(IS_NEGATIVE_FLOAT(vx.y)) aabb.mMin.y += vx.y; else aabb.mMax.y += vx.y; + if(IS_NEGATIVE_FLOAT(vx.z)) aabb.mMin.z += vx.z; else aabb.mMax.z += vx.z; + if(IS_NEGATIVE_FLOAT(vy.x)) aabb.mMin.x += vy.x; else aabb.mMax.x += vy.x; + if(IS_NEGATIVE_FLOAT(vy.y)) aabb.mMin.y += vy.y; else aabb.mMax.y += vy.y; + if(IS_NEGATIVE_FLOAT(vy.z)) aabb.mMin.z += vy.z; else aabb.mMax.z += vy.z; + if(IS_NEGATIVE_FLOAT(vz.x)) aabb.mMin.x += vz.x; else aabb.mMax.x += vz.x; + if(IS_NEGATIVE_FLOAT(vz.y)) aabb.mMin.y += vz.y; else aabb.mMax.y += vz.y; + if(IS_NEGATIVE_FLOAT(vz.z)) aabb.mMin.z += vz.z; else aabb.mMax.z += vz.z; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the AABB is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for (Min, Max) boxes: min < max + if(mMin.x > mMax.x) return FALSE; + if(mMin.y > mMax.y) return FALSE; + if(mMin.z > mMax.z) return FALSE; + return TRUE; + } + + //! Operator for AABB *= float. Scales the extents, keeps same center. + inline_ AABB& operator*=(float s) + { + Point Center; GetCenter(Center); + Point Extents; GetExtents(Extents); + SetCenterExtents(Center, Extents * s); + return *this; + } + + //! Operator for AABB /= float. Scales the extents, keeps same center. + inline_ AABB& operator/=(float s) + { + Point Center; GetCenter(Center); + Point Extents; GetExtents(Extents); + SetCenterExtents(Center, Extents / s); + return *this; + } + + //! Operator for AABB += Point. Translates the box. + inline_ AABB& operator+=(const Point& trans) + { + mMin+=trans; + mMax+=trans; + return *this; + } + private: + Point mMin; //!< Min point + Point mMax; //!< Max point + }; + +#else + + class ICEMATHS_API AABB + { + public: + //! Constructor + inline_ AABB() {} + //! Destructor + inline_ ~AABB() {} + + //! Type-independent methods + AABB_COMMON_METHODS; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from min & max vectors. + * \param min [in] the min point + * \param max [in] the max point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetMinMax(const IcePoint& min, const IcePoint& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from center & extents vectors. + * \param c [in] the center point + * \param e [in] the extents vector + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetCenterExtents(const IcePoint& c, const IcePoint& e) { mCenter = c; mExtents = e; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an empty AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetEmpty() { mCenter.Zero(); mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups a point AABB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetPoint(const IcePoint& pt) { mCenter = pt; mExtents.Zero(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the size of the AABB. The size is defined as the longest extent. + * \return the size of the AABB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + float GetSize() const { return mExtents.Max(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Extends the AABB. + * \param p [in] the next point + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Extend(const IcePoint& p) + { + IcePoint Max = mCenter + mExtents; + IcePoint Min = mCenter - mExtents; + + if(p.x > Max.x) Max.x = p.x; + if(p.x < Min.x) Min.x = p.x; + + if(p.y > Max.y) Max.y = p.y; + if(p.y < Min.y) Min.y = p.y; + + if(p.z > Max.z) Max.z = p.z; + if(p.z < Min.z) Min.z = p.z; + + SetMinMax(Min, Max); + } + // Data access + + //! Get min point of the box + inline_ void GetMin(IcePoint& min) const { min = mCenter - mExtents; } + //! Get max point of the box + inline_ void GetMax(IcePoint& max) const { max = mCenter + mExtents; } + + //! Get component of the box's min point along a given axis + inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; } + //! Get component of the box's max point along a given axis + inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; } + + //! Get box center + inline_ void GetCenter(IcePoint& center) const { center = mCenter; } + //! Get box extents + inline_ void GetExtents(IcePoint& extents) const { extents = mExtents; } + + //! Get component of the box's center along a given axis + inline_ float GetCenter(udword axis) const { return mCenter[axis]; } + //! Get component of the box's extents along a given axis + inline_ float GetExtents(udword axis) const { return mExtents[axis]; } + + //! Get box diagonal + inline_ void GetDiagonal(IcePoint& diagonal) const { diagonal = mExtents * 2.0f; } + inline_ float GetWidth() const { return mExtents.x * 2.0f; } + inline_ float GetHeight() const { return mExtents.y * 2.0f; } + inline_ float GetDepth() const { return mExtents.z * 2.0f; } + + //! Volume + inline_ float GetVolume() const { return mExtents.x * mExtents.y * mExtents.z * 8.0f; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the intersection between two AABBs. + * \param a [in] the other AABB + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a) const + { + float tx = mCenter.x - a.mCenter.x; float ex = a.mExtents.x + mExtents.x; if(AIR(tx) > IR(ex)) return FALSE; + float ty = mCenter.y - a.mCenter.y; float ey = a.mExtents.y + mExtents.y; if(AIR(ty) > IR(ey)) return FALSE; + float tz = mCenter.z - a.mCenter.z; float ez = a.mExtents.z + mExtents.z; if(AIR(tz) > IR(ez)) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * The standard intersection method from Gamasutra. Just here to check its speed against the one above. + * \param a [in] the other AABB + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool GomezIntersect(const AABB& a) + { + IcePoint T = mCenter - a.mCenter; // Vector from A to B + return ((fabsf(T.x) <= (a.mExtents.x + mExtents.x)) + && (fabsf(T.y) <= (a.mExtents.y + mExtents.y)) + && (fabsf(T.z) <= (a.mExtents.z + mExtents.z))); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the 1D-intersection between two AABBs, on a given axis. + * \param a [in] the other AABB + * \param axis [in] the axis (0, 1, 2) + * \return true on intersection + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Intersect(const AABB& a, udword axis) const + { + float t = mCenter[axis] - a.mCenter[axis]; + float e = a.mExtents[axis] + mExtents[axis]; + if(AIR(t) > IR(e)) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Recomputes the AABB after an arbitrary transform by a 4x4 matrix. + * \param mtx [in] the transform matrix + * \param aabb [out] the transformed AABB [can be *this] + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Rotate(const Matrix4x4& mtx, AABB& aabb) const + { + // Compute new center + aabb.mCenter = mCenter * mtx; + + // Compute new extents. FPU code & CPU code have been interleaved for improved performance. + IcePoint Ex(mtx.m[0][0] * mExtents.x, mtx.m[0][1] * mExtents.x, mtx.m[0][2] * mExtents.x); + IR(Ex.x)&=0x7fffffff; IR(Ex.y)&=0x7fffffff; IR(Ex.z)&=0x7fffffff; + + IcePoint Ey(mtx.m[1][0] * mExtents.y, mtx.m[1][1] * mExtents.y, mtx.m[1][2] * mExtents.y); + IR(Ey.x)&=0x7fffffff; IR(Ey.y)&=0x7fffffff; IR(Ey.z)&=0x7fffffff; + + IcePoint Ez(mtx.m[2][0] * mExtents.z, mtx.m[2][1] * mExtents.z, mtx.m[2][2] * mExtents.z); + IR(Ez.x)&=0x7fffffff; IR(Ez.y)&=0x7fffffff; IR(Ez.z)&=0x7fffffff; + + aabb.mExtents.x = Ex.x + Ey.x + Ez.x; + aabb.mExtents.y = Ex.y + Ey.y + Ez.y; + aabb.mExtents.z = Ex.z + Ey.z + Ez.z; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the AABB is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for (Center, Extents) boxes: Extents >= 0 + if(IS_NEGATIVE_FLOAT(mExtents.x)) return FALSE; + if(IS_NEGATIVE_FLOAT(mExtents.y)) return FALSE; + if(IS_NEGATIVE_FLOAT(mExtents.z)) return FALSE; + return TRUE; + } + + //! Operator for AABB *= float. Scales the extents, keeps same center. + inline_ AABB& operator*=(float s) { mExtents*=s; return *this; } + + //! Operator for AABB /= float. Scales the extents, keeps same center. + inline_ AABB& operator/=(float s) { mExtents/=s; return *this; } + + //! Operator for AABB += Point. Translates the box. + inline_ AABB& operator+=(const IcePoint& trans) + { + mCenter+=trans; + return *this; + } + private: + IcePoint mCenter; //!< AABB Center + IcePoint mExtents; //!< x, y and z extents + }; + +#endif + + inline_ void ComputeMinMax(const IcePoint& p, IcePoint& min, IcePoint& max) + { + if(p.x > max.x) max.x = p.x; + if(p.x < min.x) min.x = p.x; + + if(p.y > max.y) max.y = p.y; + if(p.y < min.y) min.y = p.y; + + if(p.z > max.z) max.z = p.z; + if(p.z < min.z) min.z = p.z; + } + + inline_ void ComputeAABB(AABB& aabb, const IcePoint* list, udword nb_pts) + { + if(list) + { + IcePoint Maxi(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); + IcePoint Mini(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT); + while(nb_pts--) + { +// _prefetch(list+1); // off by one ? + ComputeMinMax(*list++, Mini, Maxi); + } + aabb.SetMinMax(Mini, Maxi); + } + } + +#endif // __ICEAABB_H__ diff --git a/contrib/Opcode/Ice/IceAxes.h b/contrib/Opcode/Ice/IceAxes.h new file mode 100644 index 0000000..842b55e --- /dev/null +++ b/contrib/Opcode/Ice/IceAxes.h @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains axes definition. + * \file IceAxes.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEAXES_H__ +#define __ICEAXES_H__ + + enum PointComponent + { + _X = 0, + _Y = 1, + _Z = 2, + _W = 3, + + _FORCE_DWORD = 0x7fffffff + }; + + enum AxisOrder + { + AXES_XYZ = (_X)|(_Y<<2)|(_Z<<4), + AXES_XZY = (_X)|(_Z<<2)|(_Y<<4), + AXES_YXZ = (_Y)|(_X<<2)|(_Z<<4), + AXES_YZX = (_Y)|(_Z<<2)|(_X<<4), + AXES_ZXY = (_Z)|(_X<<2)|(_Y<<4), + AXES_ZYX = (_Z)|(_Y<<2)|(_X<<4), + + AXES_FORCE_DWORD = 0x7fffffff + }; + + class ICEMATHS_API Axes + { + public: + + inline_ Axes(AxisOrder order) + { + mAxis0 = (order ) & 3; + mAxis1 = (order>>2) & 3; + mAxis2 = (order>>4) & 3; + } + inline_ ~Axes() {} + + udword mAxis0; + udword mAxis1; + udword mAxis2; + }; + +#endif // __ICEAXES_H__ diff --git a/contrib/Opcode/Ice/IceBoundingSphere.h b/contrib/Opcode/Ice/IceBoundingSphere.h new file mode 100644 index 0000000..df2861d --- /dev/null +++ b/contrib/Opcode/Ice/IceBoundingSphere.h @@ -0,0 +1,142 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code to compute the minimal bounding sphere. + * \file IceBoundingSphere.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEBOUNDINGSPHERE_H__ +#define __ICEBOUNDINGSPHERE_H__ + + enum BSphereMethod + { + BS_NONE, + BS_GEMS, + BS_MINIBALL, + + BS_FORCE_DWORD = 0x7fffffff + }; + + class ICEMATHS_API Sphere + { + public: + //! Constructor + inline_ Sphere() {} + //! Constructor + inline_ Sphere(const IcePoint& center, float radius) : mCenter(center), mRadius(radius) {} + //! Constructor + Sphere(udword nb_verts, const IcePoint* verts); + //! Copy constructor + inline_ Sphere(const Sphere& sphere) : mCenter(sphere.mCenter), mRadius(sphere.mRadius) {} + //! Destructor + inline_ ~Sphere() {} + + BSphereMethod Compute(udword nb_verts, const IcePoint* verts); + bool FastCompute(udword nb_verts, const IcePoint* verts); + + // Access methods + inline_ const IcePoint& GetCenter() const { return mCenter; } + inline_ float GetRadius() const { return mRadius; } + + inline_ const IcePoint& Center() const { return mCenter; } + inline_ float Radius() const { return mRadius; } + + inline_ Sphere& Set(const IcePoint& center, float radius) { mCenter = center; mRadius = radius; return *this; } + inline_ Sphere& SetCenter(const IcePoint& center) { mCenter = center; return *this; } + inline_ Sphere& SetRadius(float radius) { mRadius = radius; return *this; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a IcePoint is contained within the sphere. + * \param p [in] the IcePoint to test + * \return true if inside the sphere + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const IcePoint& p) const + { + return mCenter.SquareDistance(p) <= mRadius*mRadius; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a sphere is contained within the sphere. + * \param sphere [in] the sphere to test + * \return true if inside the sphere + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const Sphere& sphere) const + { + // If our radius is the smallest, we can't possibly contain the other sphere + if(mRadius < sphere.mRadius) return false; + // So r is always positive or null now + float r = mRadius - sphere.mRadius; + return mCenter.SquareDistance(sphere.mCenter) <= r*r; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a box is contained within the sphere. + * \param aabb [in] the box to test + * \return true if inside the sphere + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Contains(const AABB& aabb) const + { + // I assume if all 8 box vertices are inside the sphere, so does the whole box. + // Sounds ok but maybe there's a better way? + float R2 = mRadius * mRadius; +#ifdef USE_MIN_MAX + const IcePoint& Max = ((ShadowAABB&)&aabb).mMax; + const IcePoint& Min = ((ShadowAABB&)&aabb).mMin; +#else + IcePoint Max; aabb.GetMax(Max); + IcePoint Min; aabb.GetMin(Min); +#endif + IcePoint p; + p.x=Max.x; p.y=Max.y; p.z=Max.z; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Max.x; p.y=Max.y; p.z=Min.z; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Max.x; p.y=Min.y; if(mCenter.SquareDistance(p)>=R2) return FALSE; + p.x=Min.x; if(mCenter.SquareDistance(p)>=R2) return FALSE; + + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if the sphere intersects another sphere + * \param sphere [in] the other sphere + * \return true if spheres overlap + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Intersect(const Sphere& sphere) const + { + float r = mRadius + sphere.mRadius; + return mCenter.SquareDistance(sphere.mCenter) <= r*r; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the sphere is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for spheres: Radius >= 0.0f + if(mRadius < 0.0f) return FALSE; + return TRUE; + } + public: + IcePoint mCenter; //!< Sphere center + float mRadius; //!< Sphere radius + }; + +#endif // __ICEBOUNDINGSPHERE_H__ diff --git a/contrib/Opcode/Ice/IceContainer.cpp b/contrib/Opcode/Ice/IceContainer.cpp new file mode 100644 index 0000000..dc59602 --- /dev/null +++ b/contrib/Opcode/Ice/IceContainer.cpp @@ -0,0 +1,357 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a simple container class. + * \file IceContainer.cpp + * \author Pierre Terdiman + * \date February, 5, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a list of 32-bits values. + * Use this class when you need to store an unknown number of values. The list is automatically + * resized and can contains 32-bits entities (dwords or floats) + * + * \class Container + * \author Pierre Terdiman + * \version 1.0 + * \date 08.15.98 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceCore; + +// Static members +#ifdef CONTAINER_STATS +#ifdef OPCODE_EXPORTS +udword Container::mNbContainers = 0; +udword Container::mUsedRam = 0; +#endif +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. No entries allocated there. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f) +{ +#ifdef CONTAINER_STATS + mNbContainers++; + mUsedRam+=sizeof(Container); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. Also allocates a given number of entries. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(growth_factor) +{ +#ifdef CONTAINER_STATS + mNbContainers++; + mUsedRam+=sizeof(Container); +#endif + SetSize(size); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Copy constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::Container(const Container& object) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f) +{ +#ifdef CONTAINER_STATS + mNbContainers++; + mUsedRam+=sizeof(Container); +#endif + *this = object; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. Frees everything and leaves. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container::~Container() +{ + Empty(); +#ifdef CONTAINER_STATS + mNbContainers--; + mUsedRam-=GetUsedRam(); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Clears the container. All stored values are deleted, and it frees used ram. + * \see Reset() + * \return Self-Reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Container& Container::Empty() +{ +#ifdef CONTAINER_STATS + mUsedRam-=mMaxNbEntries*sizeof(udword); +#endif + DELETEARRAY(mEntries); + mCurNbEntries = mMaxNbEntries = 0; + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Resizes the container. + * \param needed [in] assume the container can be added at least "needed" values + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Container::Resize(udword needed) +{ +#ifdef CONTAINER_STATS + // Subtract previous amount of bytes + mUsedRam-=mMaxNbEntries*sizeof(udword); +#endif + + // Get more entries + mMaxNbEntries = mMaxNbEntries ? udword(float(mMaxNbEntries)*mGrowthFactor) : 2; // Default nb Entries = 2 + if(mMaxNbEntriesmMaxNbEntries) Resize(nb); + + // Add new entry + CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword)); + mCurNbEntries+=nb; + return *this; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * A O(1) method to add a value in the container. The container is automatically resized if needed. + * The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation + * costs a lot more than the call overhead... + * + * \param entry [in] a float to store in the container + * \see Add(udword entry) + * \see Empty() + * \see Contains(udword entry) + * \return Self-Reference + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ Container& Add(float entry) + { + // Resize if needed + if(mCurNbEntries==mMaxNbEntries) Resize(); + + // Add new entry + mEntries[mCurNbEntries++] = IR(entry); + return *this; + } + + inline_ Container& Add(const float* entries, udword nb) + { + // Resize if needed + if(mCurNbEntries+nb>mMaxNbEntries) Resize(nb); + + // Add new entry + CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float)); + mCurNbEntries+=nb; + return *this; + } + + //! Add unique [slow] + inline_ Container& AddUnique(udword entry) + { + if(!Contains(entry)) Add(entry); + return *this; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Clears the container. All stored values are deleted, and it frees used ram. + * \see Reset() + * \return Self-Reference + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Container& Empty(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again. + * That's a kind of temporal coherence. + * \see Empty() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Reset() + { + // Avoid the write if possible + // ### CMOV + if(mCurNbEntries) mCurNbEntries = 0; + } + + // HANDLE WITH CARE + inline_ void ForceSize(udword size) + { + mCurNbEntries = size; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Sets the initial size of the container. If it already contains something, it's discarded. + * \param nb [in] Number of entries + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetSize(udword nb); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the container and get rid of unused bytes. + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Refit(); + + // Checks whether the container already contains a given value. + bool Contains(udword entry, udword* location=null) const; + // Deletes an entry - doesn't preserve insertion order. + bool Delete(udword entry); + // Deletes an entry - does preserve insertion order. + bool DeleteKeepingOrder(udword entry); + //! Deletes the very last entry. + inline_ void DeleteLastEntry() { if(mCurNbEntries) mCurNbEntries--; } + //! Deletes the entry whose index is given + inline_ void DeleteIndex(udword index) { mEntries[index] = mEntries[--mCurNbEntries]; } + + // Helpers + Container& FindNext(udword& entry, FindMode find_mode=FIND_CLAMP); + Container& FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP); + // Data access. + inline_ udword GetNbEntries() const { return mCurNbEntries; } //!< Returns the current number of entries. + inline_ udword GetEntry(udword i) const { return mEntries[i]; } //!< Returns ith entry + inline_ udword* GetEntries() const { return mEntries; } //!< Returns the list of entries. + + inline_ udword GetFirst() const { return mEntries[0]; } + inline_ udword GetLast() const { return mEntries[mCurNbEntries-1]; } + + // Growth control + inline_ float GetGrowthFactor() const { return mGrowthFactor; } //!< Returns the growth factor + inline_ void SetGrowthFactor(float growth) { mGrowthFactor = growth; } //!< Sets the growth factor + inline_ bool IsFull() const { return mCurNbEntries==mMaxNbEntries; } //!< Checks the container is full + inline_ BOOL IsNotEmpty() const { return mCurNbEntries; } //!< Checks the container is empty + + //! Read-access as an array + inline_ udword operator[](udword i) const { ASSERT(i>=0 && i=0 && i + #include + + #define SIGN_BITMASK 0x80000000 + + //! Integer representation of a floating-point value. + #define IR(x) ((udword&)(x)) + + //! Signed integer representation of a floating-point value. + #define SIR(x) ((sdword&)(x)) + + //! Absolute integer representation of a floating-point value + #define AIR(x) (IR(x)&0x7fffffff) + + //! Floating-point representation of an integer value. + #define FR(x) ((float&)(x)) + + //! Integer-based comparison of a floating point value. + //! Don't use it blindly, it can be faster or slower than the FPU comparison, depends on the context. + #define IS_NEGATIVE_FLOAT(x) (IR(x)&0x80000000) + + //! Fast fabs for floating-point values. It just clears the sign bit. + //! Don't use it blindy, it can be faster or slower than the FPU comparison, depends on the context. + inline_ float FastFabs(float x) + { + udword FloatBits = IR(x)&0x7fffffff; + return FR(FloatBits); + } + + //! Fast square root for floating-point values. + inline_ float FastSqrt(float square) + { + return std::sqrt(square); + } + + //! Saturates positive to zero. + inline_ float fsat(float f) + { + udword y = (udword&)f & ~((sdword&)f >>31); + return (float&)y; + } + + //! Computes 1.0f / sqrtf(x). + inline_ float frsqrt(float f) + { + float x = f * 0.5f; + udword y = 0x5f3759df - ((udword&)f >> 1); + // Iteration... + (float&)y = (float&)y * ( 1.5f - ( x * (float&)y * (float&)y ) ); + // Result + return (float&)y; + } + + //! Computes 1.0f / sqrtf(x). Comes from NVIDIA. + inline_ float InvSqrt(const float& x) + { + udword tmp = (udword(IEEE_1_0 << 1) + IEEE_1_0 - *(udword*)&x) >> 1; + float y = *(float*)&tmp; + return y * (1.47f - 0.47f * x * y * y); + } + + //! Computes 1.0f / sqrtf(x). Comes from Quake3. Looks like the first one I had above. + //! See http://www.magic-software.com/3DGEDInvSqrt.html + inline_ float RSqrt(float number) + { + long i; + float x2, y; + const float threehalfs = 1.5f; + + x2 = number * 0.5f; + y = number; + i = * (long *) &y; + i = 0x5f3759df - (i >> 1); + y = * (float *) &i; + y = y * (threehalfs - (x2 * y * y)); + + return y; + } + + //! TO BE DOCUMENTED + inline_ float fsqrt(float f) + { + udword y = ( ( (sdword&)f - 0x3f800000 ) >> 1 ) + 0x3f800000; + // Iteration...? + // (float&)y = (3.0f - ((float&)y * (float&)y) / f) * (float&)y * 0.5f; + // Result + return (float&)y; + } + + //! Returns the float ranged espilon value. + inline_ float fepsilon(float f) + { + udword b = (udword&)f & 0xff800000; + udword a = b | 0x00000001; + (float&)a -= (float&)b; + // Result + return (float&)a; + } + + //! Is the float valid ? + inline_ bool IsNAN(float value) { return (IR(value)&0x7f800000) == 0x7f800000; } + inline_ bool IsIndeterminate(float value) { return IR(value) == 0xffc00000; } + inline_ bool IsPlusInf(float value) { return IR(value) == 0x7f800000; } + inline_ bool IsMinusInf(float value) { return IR(value) == 0xff800000; } + + inline_ bool IsValidFloat(float value) + { + if(IsNAN(value)) return false; + if(IsIndeterminate(value)) return false; + if(IsPlusInf(value)) return false; + if(IsMinusInf(value)) return false; + return true; + } + + #define CHECK_VALID_FLOAT(x) ASSERT(IsValidFloat(x)); + +/* + //! FPU precision setting function. + inline_ void SetFPU() + { + // This function evaluates whether the floating-point + // control word is set to single precision/round to nearest/ + // exceptions disabled. If these conditions don't hold, the + // function changes the control word to set them and returns + // TRUE, putting the old control word value in the passback + // location pointed to by pwOldCW. + { + uword wTemp, wSave; + + __asm fstcw wSave + if (wSave & 0x300 || // Not single mode + 0x3f != (wSave & 0x3f) || // Exceptions enabled + wSave & 0xC00) // Not round to nearest mode + { + __asm + { + mov ax, wSave + and ax, not 300h ;; single mode + or ax, 3fh ;; disable all exceptions + and ax, not 0xC00 ;; round to nearest mode + mov wTemp, ax + fldcw wTemp + } + } + } + } +*/ + //! This function computes the slowest possible floating-point value (you can also directly use FLT_EPSILON) + inline_ float ComputeFloatEpsilon() + { + float f = 1.0f; + ((udword&)f)^=1; + return f - 1.0f; // You can check it's the same as FLT_EPSILON + } + + inline_ bool IsFloatZero(float x, float epsilon=1e-6f) + { + return x*x < epsilon; + } + + //! A global function to find MAX(a,b) using FCOMI/FCMOV + inline_ float FCMax2(float a, float b) + { + return std::max(a, b); + } + + //! A global function to find MIN(a,b) using FCOMI/FCMOV + inline_ float FCMin2(float a, float b) + { + return std::min(a, b); + } + + //! A global function to find MAX(a,b,c) using FCOMI/FCMOV + inline_ float FCMax3(float a, float b, float c) + { + return std::max(std::max(a, b), c); + } + + //! A global function to find MIN(a,b,c) using FCOMI/FCMOV + inline_ float FCMin3(float a, float b, float c) + { + return std::min(std::min(a, b), c); + } + + inline_ int ConvertToSortable(float f) + { + int& Fi = (int&)f; + int Fmask = (Fi>>31); + Fi ^= Fmask; + Fmask &= ~(1<<31); + Fi -= Fmask; + return Fi; + } + + enum FPUMode + { + FPU_FLOOR = 0, + FPU_CEIL = 1, + FPU_BEST = 2, + + FPU_FORCE_DWORD = 0x7fffffff + }; + + FUNCTION ICECORE_API FPUMode GetFPUMode(); + FUNCTION ICECORE_API void SaveFPU(); + FUNCTION ICECORE_API void RestoreFPU(); + FUNCTION ICECORE_API void SetFPUFloorMode(); + FUNCTION ICECORE_API void SetFPUCeilMode(); + FUNCTION ICECORE_API void SetFPUBestMode(); + + FUNCTION ICECORE_API void SetFPUPrecision24(); + FUNCTION ICECORE_API void SetFPUPrecision53(); + FUNCTION ICECORE_API void SetFPUPrecision64(); + FUNCTION ICECORE_API void SetFPURoundingChop(); + FUNCTION ICECORE_API void SetFPURoundingUp(); + FUNCTION ICECORE_API void SetFPURoundingDown(); + FUNCTION ICECORE_API void SetFPURoundingNear(); + + FUNCTION ICECORE_API int intChop(const float& f); + FUNCTION ICECORE_API int intFloor(const float& f); + FUNCTION ICECORE_API int intCeil(const float& f); + +#endif // __ICEFPU_H__ diff --git a/contrib/Opcode/Ice/IceHPoint.cpp b/contrib/Opcode/Ice/IceHPoint.cpp new file mode 100644 index 0000000..daa7038 --- /dev/null +++ b/contrib/Opcode/Ice/IceHPoint.cpp @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for homogeneous points. + * \file IceHPoint.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Homogeneous point. + * + * Use it: + * - for clipping in homogeneous space (standard way) + * - to differentiate between points (w=1) and vectors (w=0). + * - in some cases you can also use it instead of IcePoint for padding reasons. + * + * \class HPoint + * \author Pierre Terdiman + * \version 1.0 + * \warning No cross-product in 4D. + * \warning HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// IcePoint Mul = HPoint * Matrix3x3; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +IcePoint HPoint::operator*(const Matrix3x3& mat) const +{ + return IcePoint( + x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0], + x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1], + x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] ); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// HPoint Mul = HPoint * Matrix4x4; +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HPoint HPoint::operator*(const Matrix4x4& mat) const +{ + return HPoint( + x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0], + x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1], + x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2], + x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// HPoint *= Matrix4x4 +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HPoint& HPoint::operator*=(const Matrix4x4& mat) +{ + float xp = x * mat.m[0][0] + y * mat.m[1][0] + z * mat.m[2][0] + w * mat.m[3][0]; + float yp = x * mat.m[0][1] + y * mat.m[1][1] + z * mat.m[2][1] + w * mat.m[3][1]; + float zp = x * mat.m[0][2] + y * mat.m[1][2] + z * mat.m[2][2] + w * mat.m[3][2]; + float wp = x * mat.m[0][3] + y * mat.m[1][3] + z * mat.m[2][3] + w * mat.m[3][3]; + + x = xp; y = yp; z = zp; w = wp; + + return *this; +} + diff --git a/contrib/Opcode/Ice/IceHPoint.h b/contrib/Opcode/Ice/IceHPoint.h new file mode 100644 index 0000000..f7d0d16 --- /dev/null +++ b/contrib/Opcode/Ice/IceHPoint.h @@ -0,0 +1,157 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for homogeneous points. + * \file IceHPoint.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEHPOINT_H__ +#define __ICEHPOINT_H__ + + class ICEMATHS_API HPoint : public IcePoint + { + public: + + //! Empty constructor + inline_ HPoint() {} + //! Constructor from floats + inline_ HPoint(float _x, float _y, float _z, float _w=0.0f) : IcePoint(_x, _y, _z), w(_w) {} + //! Constructor from array + inline_ HPoint(const float f[4]) : IcePoint(f), w(f[3]) {} + //! Constructor from a Point + inline_ HPoint(const IcePoint& p, float _w=0.0f) : IcePoint(p), w(_w) {} + //! Destructor + inline_ ~HPoint() {} + + //! Clear the point + inline_ HPoint& Zero() { x = y = z = w = 0.0f; return *this; } + + //! Assignment from values + inline_ HPoint& Set(float _x, float _y, float _z, float _w ) { x = _x; y = _y; z = _z; w = _w; return *this; } + //! Assignment from array + inline_ HPoint& Set(const float f[4]) { x = f[_X]; y = f[_Y]; z = f[_Z]; w = f[_W]; return *this; } + //! Assignment from another h-point + inline_ HPoint& Set(const HPoint& src) { x = src.x; y = src.y; z = src.z; w = src.w; return *this; } + + //! Add a vector + inline_ HPoint& Add(float _x, float _y, float _z, float _w ) { x += _x; y += _y; z += _z; w += _w; return *this; } + //! Add a vector + inline_ HPoint& Add(const float f[4]) { x += f[_X]; y += f[_Y]; z += f[_Z]; w += f[_W]; return *this; } + + //! Subtract a vector + inline_ HPoint& Sub(float _x, float _y, float _z, float _w ) { x -= _x; y -= _y; z -= _z; w -= _w; return *this; } + //! Subtract a vector + inline_ HPoint& Sub(const float f[4]) { x -= f[_X]; y -= f[_Y]; z -= f[_Z]; w -= f[_W]; return *this; } + + //! Multiplies by a scalar + inline_ HPoint& Mul(float s) { x *= s; y *= s; z *= s; w *= s; return *this; } + + //! Returns MIN(x, y, z, w); + float Min() const { return MIN(x, MIN(y, MIN(z, w))); } + //! Returns MAX(x, y, z, w); + float Max() const { return MAX(x, MAX(y, MAX(z, w))); } + //! Sets each element to be componentwise minimum + HPoint& Min(const HPoint& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); w = MIN(w, p.w); return *this; } + //! Sets each element to be componentwise maximum + HPoint& Max(const HPoint& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); w = MAX(w, p.w); return *this; } + + //! Computes square magnitude + inline_ float SquareMagnitude() const { return x*x + y*y + z*z + w*w; } + //! Computes magnitude + inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z + w*w); } + + //! Normalize the vector + inline_ HPoint& Normalize() + { + float M = Magnitude(); + if(M) + { + M = 1.0f / M; + x *= M; + y *= M; + z *= M; + w *= M; + } + return *this; + } + + // Arithmetic operators + //! Operator for HPoint Negate = - HPoint; + inline_ HPoint operator-() const { return HPoint(-x, -y, -z, -w); } + + //! Operator for HPoint Plus = HPoint + HPoint; + inline_ HPoint operator+(const HPoint& p) const { return HPoint(x + p.x, y + p.y, z + p.z, w + p.w); } + //! Operator for HPoint Minus = HPoint - HPoint; + inline_ HPoint operator-(const HPoint& p) const { return HPoint(x - p.x, y - p.y, z - p.z, w - p.w); } + + //! Operator for HPoint Mul = HPoint * HPoint; + inline_ HPoint operator*(const HPoint& p) const { return HPoint(x * p.x, y * p.y, z * p.z, w * p.w); } + //! Operator for HPoint Scale = HPoint * float; + inline_ HPoint operator*(float s) const { return HPoint(x * s, y * s, z * s, w * s); } + //! Operator for HPoint Scale = float * HPoint; + inline_ friend HPoint operator*(float s, const HPoint& p) { return HPoint(s * p.x, s * p.y, s * p.z, s * p.w); } + + //! Operator for HPoint Div = HPoint / HPoint; + inline_ HPoint operator/(const HPoint& p) const { return HPoint(x / p.x, y / p.y, z / p.z, w / p.w); } + //! Operator for HPoint Scale = HPoint / float; + inline_ HPoint operator/(float s) const { s = 1.0f / s; return HPoint(x * s, y * s, z * s, w * s); } + //! Operator for HPoint Scale = float / HPoint; + inline_ friend HPoint operator/(float s, const HPoint& p) { return HPoint(s / p.x, s / p.y, s / p.z, s / p.w); } + + //! Operator for float DotProd = HPoint | HPoint; + inline_ float operator|(const HPoint& p) const { return x*p.x + y*p.y + z*p.z + w*p.w; } + // No cross-product in 4D + + //! Operator for HPoint += HPoint; + inline_ HPoint& operator+=(const HPoint& p) { x += p.x; y += p.y; z += p.z; w += p.w; return *this; } + //! Operator for HPoint += float; + inline_ HPoint& operator+=(float s) { x += s; y += s; z += s; w += s; return *this; } + + //! Operator for HPoint -= HPoint; + inline_ HPoint& operator-=(const HPoint& p) { x -= p.x; y -= p.y; z -= p.z; w -= p.w; return *this; } + //! Operator for HPoint -= float; + inline_ HPoint& operator-=(float s) { x -= s; y -= s; z -= s; w -= s; return *this; } + + //! Operator for HPoint *= HPoint; + inline_ HPoint& operator*=(const HPoint& p) { x *= p.x; y *= p.y; z *= p.z; w *= p.w; return *this; } + //! Operator for HPoint *= float; + inline_ HPoint& operator*=(float s) { x*=s; y*=s; z*=s; w*=s; return *this; } + + //! Operator for HPoint /= HPoint; + inline_ HPoint& operator/=(const HPoint& p) { x /= p.x; y /= p.y; z /= p.z; w /= p.w; return *this; } + //! Operator for HPoint /= float; + inline_ HPoint& operator/=(float s) { s = 1.0f / s; x*=s; y*=s; z*=s; w*=s; return *this; } + + // Arithmetic operators + + //! Operator for Point Mul = HPoint * Matrix3x3; + IcePoint operator*(const Matrix3x3& mat) const; + //! Operator for HPoint Mul = HPoint * Matrix4x4; + HPoint operator*(const Matrix4x4& mat) const; + + // HPoint *= Matrix3x3 doesn't exist, the matrix is first casted to a 4x4 + //! Operator for HPoint *= Matrix4x4 + HPoint& operator*=(const Matrix4x4& mat); + + // Logical operators + + //! Operator for "if(HPoint==HPoint)" + inline_ bool operator==(const HPoint& p) const { return ( (x==p.x)&&(y==p.y)&&(z==p.z)&&(w==p.w)); } + //! Operator for "if(HPoint!=HPoint)" + inline_ bool operator!=(const HPoint& p) const { return ( (x!=p.x)||(y!=p.y)||(z!=p.z)||(w!=p.w)); } + + // Cast operators + + //! Cast a HPoint to a Point. w is discarded. + inline_ operator HPoint() const { return IcePoint(x, y, z); } + + public: + float w; + }; + +#endif // __ICEHPOINT_H__ + diff --git a/contrib/Opcode/Ice/IceIndexedTriangle.cpp b/contrib/Opcode/Ice/IceIndexedTriangle.cpp new file mode 100644 index 0000000..3e74cbb --- /dev/null +++ b/contrib/Opcode/Ice/IceIndexedTriangle.cpp @@ -0,0 +1,548 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a handy indexed triangle class. + * \file IceIndexedTriangle.cpp + * \author Pierre Terdiman + * \date January, 17, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an indexed triangle class. + * + * \class Triangle + * \author Pierre Terdiman + * \version 1.0 + * \date 08.15.98 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Flips the winding order. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::Flip() +{ + Swap(mVRef[1], mVRef[2]); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle area. + * \param verts [in] the list of indexed vertices + * \return the area + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::Area(const IcePoint* verts) const +{ + if(!verts) return 0.0f; + const IcePoint& p0 = verts[0]; + const IcePoint& p1 = verts[1]; + const IcePoint& p2 = verts[2]; + return ((p0-p1)^(p0-p2)).Magnitude() * 0.5f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle perimeter. + * \param verts [in] the list of indexed vertices + * \return the perimeter + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::Perimeter(const IcePoint* verts) const +{ + if(!verts) return 0.0f; + const IcePoint& p0 = verts[0]; + const IcePoint& p1 = verts[1]; + const IcePoint& p2 = verts[2]; + return p0.Distance(p1) + + p0.Distance(p2) + + p1.Distance(p2); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle compacity. + * \param verts [in] the list of indexed vertices + * \return the compacity + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::Compacity(const IcePoint* verts) const +{ + if(!verts) return 0.0f; + float P = Perimeter(verts); + if(P==0.0f) return 0.0f; + return (4.0f*PI*Area(verts)/(P*P)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle normal. + * \param verts [in] the list of indexed vertices + * \param normal [out] the computed normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::Normal(const IcePoint* verts, IcePoint& normal) const +{ + if(!verts) return; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + normal = ((p2-p1)^(p0-p1)).Normalize(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle denormalized normal. + * \param verts [in] the list of indexed vertices + * \param normal [out] the computed normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::DenormalizedNormal(const IcePoint* verts, IcePoint& normal) const +{ + if(!verts) return; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + normal = ((p2-p1)^(p0-p1)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle center. + * \param verts [in] the list of indexed vertices + * \param center [out] the computed center + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::Center(const IcePoint* verts, IcePoint& center) const +{ + if(!verts) return; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + center = (p0+p1+p2)*INV3; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the centered normal + * \param verts [in] the list of indexed vertices + * \param normal [out] the computed centered normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::CenteredNormal(const IcePoint* verts, IcePoint& normal) const +{ + if(!verts) return; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + IcePoint Center = (p0+p1+p2)*INV3; + normal = Center + ((p2-p1)^(p0-p1)).Normalize(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a random point within the triangle. + * \param verts [in] the list of indexed vertices + * \param normal [out] the computed centered normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::RandomPoint(const IcePoint* verts, IcePoint& random) const +{ + if(!verts) return; + + // Random barycentric coords + float Alpha = UnitRandomFloat(); + float Beta = UnitRandomFloat(); + float Gamma = UnitRandomFloat(); + float OneOverTotal = 1.0f / (Alpha + Beta + Gamma); + Alpha *= OneOverTotal; + Beta *= OneOverTotal; + Gamma *= OneOverTotal; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + random = Alpha*p0 + Beta*p1 + Gamma*p2; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes backface culling. + * \param verts [in] the list of indexed vertices + * \param source [in] source point (in local space) from which culling must be computed + * \return true if the triangle is visible from the source point + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::IsVisible(const IcePoint* verts, const IcePoint& source) const +{ + // Checkings + if(!verts) return false; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + + // Compute denormalized normal + IcePoint Normal = (p2 - p1)^(p0 - p1); + + // Backface culling + return (Normal | source) >= 0.0f; + +// Same as: +// IcePlane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); +// return PL.Distance(source) > PL.d; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes backface culling. + * \param verts [in] the list of indexed vertices + * \param source [in] source point (in local space) from which culling must be computed + * \return true if the triangle is visible from the source point + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::BackfaceCulling(const IcePoint* verts, const IcePoint& source) const +{ + // Checkings + if(!verts) return false; + + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + + // Compute base +// IcePoint Base = (p0 + p1 + p2)*INV3; + + // Compute denormalized normal + IcePoint Normal = (p2 - p1)^(p0 - p1); + + // Backface culling +// return (Normal | (source - Base)) >= 0.0f; + return (Normal | (source - p0)) >= 0.0f; + +// Same as: (but a bit faster) +// IcePlane PL(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); +// return PL.Distance(source)>0.0f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the occlusion potential of the triangle. + * \param verts [in] the list of indexed vertices + * \param source [in] source point (in local space) from which occlusion potential must be computed + * \return the occlusion potential + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::ComputeOcclusionPotential(const IcePoint* verts, const IcePoint& view) const +{ + if(!verts) return 0.0f; + // Occlusion potential: -(A * (N|V) / d^2) + // A = polygon area + // N = polygon normal + // V = view vector + // d = distance viewpoint-center of polygon + + float A = Area(verts); + IcePoint N; Normal(verts, N); + IcePoint C; Center(verts, C); + float d = view.Distance(C); + return -(A*(N|view))/(d*d); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Replaces a vertex reference with another one. + * \param oldref [in] the vertex reference to replace + * \param newref [in] the new vertex reference + * \return true if success, else false if the input vertex reference doesn't belong to the triangle + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::ReplaceVertex(udword oldref, udword newref) +{ + if(mVRef[0]==oldref) { mVRef[0] = newref; return true; } + else if(mVRef[1]==oldref) { mVRef[1] = newref; return true; } + else if(mVRef[2]==oldref) { mVRef[2] = newref; return true; } + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks whether the triangle is degenerate or not. A degenerate triangle has two common vertex references. This is a zero-area triangle. + * \return true if the triangle is degenerate + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::IsDegenerate() const +{ + if(mVRef[0]==mVRef[1]) return true; + if(mVRef[1]==mVRef[2]) return true; + if(mVRef[2]==mVRef[0]) return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks whether the input vertex reference belongs to the triangle or not. + * \param ref [in] the vertex reference to look for + * \return true if the triangle contains the vertex reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::HasVertex(udword ref) const +{ + if(mVRef[0]==ref) return true; + if(mVRef[1]==ref) return true; + if(mVRef[2]==ref) return true; + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks whether the input vertex reference belongs to the triangle or not. + * \param ref [in] the vertex reference to look for + * \param index [out] the corresponding index in the triangle + * \return true if the triangle contains the vertex reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::HasVertex(udword ref, udword* index) const +{ + if(mVRef[0]==ref) { *index = 0; return true; } + if(mVRef[1]==ref) { *index = 1; return true; } + if(mVRef[2]==ref) { *index = 2; return true; } + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Finds an edge in a tri, given two vertex references. + * \param vref0 [in] the edge's first vertex reference + * \param vref1 [in] the edge's second vertex reference + * \return the edge number between 0 and 2, or 0xff if input refs are wrong. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ubyte IndexedTriangle::FindEdge(udword vref0, udword vref1) const +{ + if(mVRef[0]==vref0 && mVRef[1]==vref1) return 0; + else if(mVRef[0]==vref1 && mVRef[1]==vref0) return 0; + else if(mVRef[0]==vref0 && mVRef[2]==vref1) return 1; + else if(mVRef[0]==vref1 && mVRef[2]==vref0) return 1; + else if(mVRef[1]==vref0 && mVRef[2]==vref1) return 2; + else if(mVRef[1]==vref1 && mVRef[2]==vref0) return 2; + return 0xff; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the last reference given the first two. + * \param vref0 [in] the first vertex reference + * \param vref1 [in] the second vertex reference + * \return the last reference, or INVALID_ID if input refs are wrong. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword IndexedTriangle::OppositeVertex(udword vref0, udword vref1) const +{ + if(mVRef[0]==vref0 && mVRef[1]==vref1) return mVRef[2]; + else if(mVRef[0]==vref1 && mVRef[1]==vref0) return mVRef[2]; + else if(mVRef[0]==vref0 && mVRef[2]==vref1) return mVRef[1]; + else if(mVRef[0]==vref1 && mVRef[2]==vref0) return mVRef[1]; + else if(mVRef[1]==vref0 && mVRef[2]==vref1) return mVRef[0]; + else if(mVRef[1]==vref1 && mVRef[2]==vref0) return mVRef[0]; + return INVALID_ID; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the three sorted vertex references according to an edge number. + * edgenb = 0 => edge 0-1, returns references 0, 1, 2 + * edgenb = 1 => edge 0-2, returns references 0, 2, 1 + * edgenb = 2 => edge 1-2, returns references 1, 2, 0 + * + * \param edgenb [in] the edge number, 0, 1 or 2 + * \param vref0 [out] the returned first vertex reference + * \param vref1 [out] the returned second vertex reference + * \param vref2 [out] the returned third vertex reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const +{ + if(edgenb==0) + { + vref0 = mVRef[0]; + vref1 = mVRef[1]; + vref2 = mVRef[2]; + } + else if(edgenb==1) + { + vref0 = mVRef[0]; + vref1 = mVRef[2]; + vref2 = mVRef[1]; + } + else if(edgenb==2) + { + vref0 = mVRef[1]; + vref1 = mVRef[2]; + vref2 = mVRef[0]; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle's smallest edge length. + * \param verts [in] the list of indexed vertices + * \return the smallest edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::MinEdgeLength(const IcePoint* verts) const +{ + if(!verts) return 0.0f; + + float Min = MAX_FLOAT; + float Length01 = verts[0].Distance(verts[1]); + float Length02 = verts[0].Distance(verts[2]); + float Length12 = verts[1].Distance(verts[2]); + if(Length01 < Min) Min = Length01; + if(Length02 < Min) Min = Length02; + if(Length12 < Min) Min = Length12; + return Min; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle's largest edge length. + * \param verts [in] the list of indexed vertices + * \return the largest edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::MaxEdgeLength(const IcePoint* verts) const +{ + if(!verts) return 0.0f; + + float Max = MIN_FLOAT; + float Length01 = verts[0].Distance(verts[1]); + float Length02 = verts[0].Distance(verts[2]); + float Length12 = verts[1].Distance(verts[2]); + if(Length01 > Max) Max = Length01; + if(Length02 > Max) Max = Length02; + if(Length12 > Max) Max = Length12; + return Max; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a point on the triangle according to the stabbing information. + * \param verts [in] the list of indexed vertices + * \param u,v [in] point's barycentric coordinates + * \param pt [out] point on triangle + * \param nearvtx [out] index of nearest vertex + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void IndexedTriangle::ComputePoint(const IcePoint* verts, float u, float v, IcePoint& pt, udword* nearvtx) const +{ + // Checkings + if(!verts) return; + + // Get face in local or global space + const IcePoint& p0 = verts[mVRef[0]]; + const IcePoint& p1 = verts[mVRef[1]]; + const IcePoint& p2 = verts[mVRef[2]]; + + // Compute point coordinates + pt = (1.0f - u - v)*p0 + u*p1 + v*p2; + + // Compute nearest vertex if needed + if(nearvtx) + { + // Compute distance vector + IcePoint d(p0.SquareDistance(pt), // Distance^2 from vertex 0 to point on the face + p1.SquareDistance(pt), // Distance^2 from vertex 1 to point on the face + p2.SquareDistance(pt)); // Distance^2 from vertex 2 to point on the face + + // Get smallest distance + *nearvtx = mVRef[d.SmallestAxis()]; + } +} + + //************************************** + // Angle between two vectors (in radians) + // we use this formula + // uv = |u||v| cos(u,v) + // u ^ v = w + // |w| = |u||v| |sin(u,v)| + //************************************** + float Angle(const IcePoint& u, const IcePoint& v) + { + float NormU = u.Magnitude(); // |u| + float NormV = v.Magnitude(); // |v| + float Product = NormU*NormV; // |u||v| + if(Product==0.0f) return 0.0f; + float OneOverProduct = 1.0f / Product; + + // Cosinus + float Cosinus = (u|v) * OneOverProduct; + + // Sinus + IcePoint w = u^v; + float NormW = w.Magnitude(); + + float AbsSinus = NormW * OneOverProduct; + + // Remove degeneracy + if(AbsSinus > 1.0f) AbsSinus = 1.0f; + if(AbsSinus < -1.0f) AbsSinus = -1.0f; + + if(Cosinus>=0.0f) return asinf(AbsSinus); + else return (PI-asinf(AbsSinus)); + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the angle between two triangles. + * \param tri [in] the other triangle + * \param verts [in] the list of indexed vertices + * \return the angle in radians + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float IndexedTriangle::Angle(const IndexedTriangle& tri, const IcePoint* verts) const +{ + // Checkings + if(!verts) return 0.0f; + + // Compute face normals + IcePoint n0, n1; + Normal(verts, n0); + tri.Normal(verts, n1); + + // Compute angle + float dp = n0|n1; + if(dp>1.0f) return 0.0f; + if(dp<-1.0f) return PI; + return acosf(dp); + +// return ::Angle(n0,n1); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks a triangle is the same as another one. + * \param tri [in] the other triangle + * \return true if same triangle + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool IndexedTriangle::Equal(const IndexedTriangle& tri) const +{ + // Test all vertex references + return (HasVertex(tri.mVRef[0]) && + HasVertex(tri.mVRef[1]) && + HasVertex(tri.mVRef[2])); +} diff --git a/contrib/Opcode/Ice/IceIndexedTriangle.h b/contrib/Opcode/Ice/IceIndexedTriangle.h new file mode 100644 index 0000000..ef279c2 --- /dev/null +++ b/contrib/Opcode/Ice/IceIndexedTriangle.h @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a handy indexed triangle class. + * \file IceIndexedTriangle.h + * \author Pierre Terdiman + * \date January, 17, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEINDEXEDTRIANGLE_H__ +#define __ICEINDEXEDTRIANGLE_H__ + + // An indexed triangle class. + class ICEMATHS_API IndexedTriangle + { + public: + //! Constructor + inline_ IndexedTriangle() {} + //! Constructor + inline_ IndexedTriangle(udword r0, udword r1, udword r2) { mVRef[0]=r0; mVRef[1]=r1; mVRef[2]=r2; } + //! Copy constructor + inline_ IndexedTriangle(const IndexedTriangle& triangle) + { + mVRef[0] = triangle.mVRef[0]; + mVRef[1] = triangle.mVRef[1]; + mVRef[2] = triangle.mVRef[2]; + } + //! Destructor + inline_ ~IndexedTriangle() {} + //! Vertex-references + udword mVRef[3]; + + // Methods + void Flip(); + float Area(const IcePoint* verts) const; + float Perimeter(const IcePoint* verts) const; + float Compacity(const IcePoint* verts) const; + void Normal(const IcePoint* verts, IcePoint& normal) const; + void DenormalizedNormal(const IcePoint* verts, IcePoint& normal) const; + void Center(const IcePoint* verts, IcePoint& center) const; + void CenteredNormal(const IcePoint* verts, IcePoint& normal) const; + void RandomPoint(const IcePoint* verts, IcePoint& random) const; + bool IsVisible(const IcePoint* verts, const IcePoint& source) const; + bool BackfaceCulling(const IcePoint* verts, const IcePoint& source) const; + float ComputeOcclusionPotential(const IcePoint* verts, const IcePoint& view) const; + bool ReplaceVertex(udword oldref, udword newref); + bool IsDegenerate() const; + bool HasVertex(udword ref) const; + bool HasVertex(udword ref, udword* index) const; + ubyte FindEdge(udword vref0, udword vref1) const; + udword OppositeVertex(udword vref0, udword vref1) const; + inline_ udword OppositeVertex(ubyte edgenb) const { return mVRef[2-edgenb]; } + void GetVRefs(ubyte edgenb, udword& vref0, udword& vref1, udword& vref2) const; + float MinEdgeLength(const IcePoint* verts) const; + float MaxEdgeLength(const IcePoint* verts) const; + void ComputePoint(const IcePoint* verts, float u, float v, IcePoint& pt, udword* nearvtx=null) const; + float Angle(const IndexedTriangle& tri, const IcePoint* verts) const; + inline_ IcePlane PlaneEquation(const IcePoint* verts) const { return IcePlane(verts[mVRef[0]], verts[mVRef[1]], verts[mVRef[2]]); } + bool Equal(const IndexedTriangle& tri) const; + }; + +#endif // __ICEINDEXEDTRIANGLE_H__ diff --git a/contrib/Opcode/Ice/IceLSS.h b/contrib/Opcode/Ice/IceLSS.h new file mode 100644 index 0000000..e4c9ef8 --- /dev/null +++ b/contrib/Opcode/Ice/IceLSS.h @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for line-swept spheres. + * \file IceLSS.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICELSS_H__ +#define __ICELSS_H__ + + class ICEMATHS_API LSS : public IceSegment + { + public: + //! Constructor + inline_ LSS() {} + //! Constructor + inline_ LSS(const IceSegment& seg, float radius) : IceSegment(seg), mRadius(radius) {} + //! Destructor + inline_ ~LSS() {} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes an OBB surrounding the LSS. + * \param box [out] the OBB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void ComputeOBB(OBB& box); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a IcePoint is contained within the LSS. + * \param pt [in] the IcePoint to test + * \return true if inside the LSS + * \warning IcePoint and LSS must be in same space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const IcePoint& pt) const { return SquareDistance(pt) <= mRadius*mRadius; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a sphere is contained within the LSS. + * \param sphere [in] the sphere to test + * \return true if inside the LSS + * \warning sphere and LSS must be in same space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const Sphere& sphere) + { + float d = mRadius - sphere.mRadius; + if(d>=0.0f) return SquareDistance(sphere.mCenter) <= d*d; + else return false; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if an LSS is contained within the LSS. + * \param lss [in] the LSS to test + * \return true if inside the LSS + * \warning both LSS must be in same space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ bool Contains(const LSS& lss) + { + // We check the LSS contains the two spheres at the start and end of the sweep + return Contains(Sphere(lss.mP0, lss.mRadius)) && Contains(Sphere(lss.mP0, lss.mRadius)); + } + + float mRadius; //!< Sphere radius + }; + +#endif // __ICELSS_H__ diff --git a/contrib/Opcode/Ice/IceMatrix3x3.cpp b/contrib/Opcode/Ice/IceMatrix3x3.cpp new file mode 100644 index 0000000..c856366 --- /dev/null +++ b/contrib/Opcode/Ice/IceMatrix3x3.cpp @@ -0,0 +1,48 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 3x3 matrices. + * \file IceMatrix3x3.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * 3x3 matrix. + * DirectX-compliant, ie row-column order, ie m[Row][Col]. + * Same as: + * m11 m12 m13 first row. + * m21 m22 m23 second row. + * m31 m32 m33 third row. + * Stored in memory as m11 m12 m13 m21... + * + * Multiplication rules: + * + * [x'y'z'] = [xyz][M] + * + * x' = x*m11 + y*m21 + z*m31 + * y' = x*m12 + y*m22 + z*m32 + * z' = x*m13 + y*m23 + z*m33 + * + * \class Matrix3x3 + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +// Cast operator +Matrix3x3::operator Matrix4x4() const +{ + return Matrix4x4( + m[0][0], m[0][1], m[0][2], 0.0f, + m[1][0], m[1][1], m[1][2], 0.0f, + m[2][0], m[2][1], m[2][2], 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); +} diff --git a/contrib/Opcode/Ice/IceMatrix3x3.h b/contrib/Opcode/Ice/IceMatrix3x3.h new file mode 100644 index 0000000..3356103 --- /dev/null +++ b/contrib/Opcode/Ice/IceMatrix3x3.h @@ -0,0 +1,496 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 3x3 matrices. + * \file IceMatrix3x3.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEMATRIX3X3_H__ +#define __ICEMATRIX3X3_H__ + + // Forward declarations + class Quat; + + #define MATRIX3X3_EPSILON (1.0e-7f) + + class ICEMATHS_API Matrix3x3 + { + public: + //! Empty constructor + inline_ Matrix3x3() {} + //! Constructor from 9 values + inline_ Matrix3x3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; + } + //! Copy constructor + inline_ Matrix3x3(const Matrix3x3& mat) { CopyMemory(m, &mat.m, 9*sizeof(float)); } + //! Destructor + inline_ ~Matrix3x3() {} + + //! Assign values + inline_ void Set(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; + } + + //! Sets the scale from a Point. The point is put on the diagonal. + inline_ void SetScale(const IcePoint& p) { m[0][0] = p.x; m[1][1] = p.y; m[2][2] = p.z; } + + //! Sets the scale from floats. Values are put on the diagonal. + inline_ void SetScale(float sx, float sy, float sz) { m[0][0] = sx; m[1][1] = sy; m[2][2] = sz; } + + //! Scales from a Point. Each row is multiplied by a component. + inline_ void Scale(const IcePoint& p) + { + m[0][0] *= p.x; m[0][1] *= p.x; m[0][2] *= p.x; + m[1][0] *= p.y; m[1][1] *= p.y; m[1][2] *= p.y; + m[2][0] *= p.z; m[2][1] *= p.z; m[2][2] *= p.z; + } + + //! Scales from floats. Each row is multiplied by a value. + inline_ void Scale(float sx, float sy, float sz) + { + m[0][0] *= sx; m[0][1] *= sx; m[0][2] *= sx; + m[1][0] *= sy; m[1][1] *= sy; m[1][2] *= sy; + m[2][0] *= sz; m[2][1] *= sz; m[2][2] *= sz; + } + + //! Copy from a Matrix3x3 + inline_ void Copy(const Matrix3x3& source) { CopyMemory(m, source.m, 9*sizeof(float)); } + + // Row-column access + //! Returns a row. + inline_ void GetRow(const udword r, IcePoint& p) const { p.x = m[r][0]; p.y = m[r][1]; p.z = m[r][2]; } + //! Returns a row. + inline_ const IcePoint& GetRow(const udword r) const { return *(const IcePoint*)&m[r][0]; } + //! Returns a row. + inline_ IcePoint& GetRow(const udword r) { return *(IcePoint*)&m[r][0]; } + //! Sets a row. + inline_ void SetRow(const udword r, const IcePoint& p) { m[r][0] = p.x; m[r][1] = p.y; m[r][2] = p.z; } + //! Returns a column. + inline_ void GetCol(const udword c, IcePoint& p) const { p.x = m[0][c]; p.y = m[1][c]; p.z = m[2][c]; } + //! Sets a column. + inline_ void SetCol(const udword c, const IcePoint& p) { m[0][c] = p.x; m[1][c] = p.y; m[2][c] = p.z; } + + //! Computes the trace. The trace is the sum of the 3 diagonal components. + inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2]; } + //! Clears the matrix. + inline_ void Zero() { ZeroMemory(&m, sizeof(m)); } + //! Sets the identity matrix. + inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = 1.0f; } + //! Checks for identity + inline_ bool IsIdentity() const + { + if(IR(m[0][0])!=IEEE_1_0) return false; + if(IR(m[0][1])!=0) return false; + if(IR(m[0][2])!=0) return false; + + if(IR(m[1][0])!=0) return false; + if(IR(m[1][1])!=IEEE_1_0) return false; + if(IR(m[1][2])!=0) return false; + + if(IR(m[2][0])!=0) return false; + if(IR(m[2][1])!=0) return false; + if(IR(m[2][2])!=IEEE_1_0) return false; + + return true; + } + + //! Checks matrix validity + inline_ BOOL IsValid() const + { + for(udword j=0;j<3;j++) + { + for(udword i=0;i<3;i++) + { + if(!IsValidFloat(m[j][i])) return FALSE; + } + } + return TRUE; + } + + //! Makes a skew-symmetric matrix (a.k.a. Star(*) Matrix) + //! [ 0.0 -a.z a.y ] + //! [ a.z 0.0 -a.x ] + //! [ -a.y a.x 0.0 ] + //! This is also called a "cross matrix" since for any vectors A and B, + //! A^B = Skew(A) * B = - B * Skew(A); + inline_ void SkewSymmetric(const IcePoint& a) + { + m[0][0] = 0.0f; + m[0][1] = -a.z; + m[0][2] = a.y; + + m[1][0] = a.z; + m[1][1] = 0.0f; + m[1][2] = -a.x; + + m[2][0] = -a.y; + m[2][1] = a.x; + m[2][2] = 0.0f; + } + + //! Negates the matrix + inline_ void Neg() + { + m[0][0] = -m[0][0]; m[0][1] = -m[0][1]; m[0][2] = -m[0][2]; + m[1][0] = -m[1][0]; m[1][1] = -m[1][1]; m[1][2] = -m[1][2]; + m[2][0] = -m[2][0]; m[2][1] = -m[2][1]; m[2][2] = -m[2][2]; + } + + //! Neg from another matrix + inline_ void Neg(const Matrix3x3& mat) + { + m[0][0] = -mat.m[0][0]; m[0][1] = -mat.m[0][1]; m[0][2] = -mat.m[0][2]; + m[1][0] = -mat.m[1][0]; m[1][1] = -mat.m[1][1]; m[1][2] = -mat.m[1][2]; + m[2][0] = -mat.m[2][0]; m[2][1] = -mat.m[2][1]; m[2][2] = -mat.m[2][2]; + } + + //! Add another matrix + inline_ void Add(const Matrix3x3& mat) + { + m[0][0] += mat.m[0][0]; m[0][1] += mat.m[0][1]; m[0][2] += mat.m[0][2]; + m[1][0] += mat.m[1][0]; m[1][1] += mat.m[1][1]; m[1][2] += mat.m[1][2]; + m[2][0] += mat.m[2][0]; m[2][1] += mat.m[2][1]; m[2][2] += mat.m[2][2]; + } + + //! Sub another matrix + inline_ void Sub(const Matrix3x3& mat) + { + m[0][0] -= mat.m[0][0]; m[0][1] -= mat.m[0][1]; m[0][2] -= mat.m[0][2]; + m[1][0] -= mat.m[1][0]; m[1][1] -= mat.m[1][1]; m[1][2] -= mat.m[1][2]; + m[2][0] -= mat.m[2][0]; m[2][1] -= mat.m[2][1]; m[2][2] -= mat.m[2][2]; + } + //! Mac + inline_ void Mac(const Matrix3x3& a, const Matrix3x3& b, float s) + { + m[0][0] = a.m[0][0] + b.m[0][0] * s; + m[0][1] = a.m[0][1] + b.m[0][1] * s; + m[0][2] = a.m[0][2] + b.m[0][2] * s; + + m[1][0] = a.m[1][0] + b.m[1][0] * s; + m[1][1] = a.m[1][1] + b.m[1][1] * s; + m[1][2] = a.m[1][2] + b.m[1][2] * s; + + m[2][0] = a.m[2][0] + b.m[2][0] * s; + m[2][1] = a.m[2][1] + b.m[2][1] * s; + m[2][2] = a.m[2][2] + b.m[2][2] * s; + } + //! Mac + inline_ void Mac(const Matrix3x3& a, float s) + { + m[0][0] += a.m[0][0] * s; m[0][1] += a.m[0][1] * s; m[0][2] += a.m[0][2] * s; + m[1][0] += a.m[1][0] * s; m[1][1] += a.m[1][1] * s; m[1][2] += a.m[1][2] * s; + m[2][0] += a.m[2][0] * s; m[2][1] += a.m[2][1] * s; m[2][2] += a.m[2][2] * s; + } + + //! this = A * s + inline_ void Mult(const Matrix3x3& a, float s) + { + m[0][0] = a.m[0][0] * s; m[0][1] = a.m[0][1] * s; m[0][2] = a.m[0][2] * s; + m[1][0] = a.m[1][0] * s; m[1][1] = a.m[1][1] * s; m[1][2] = a.m[1][2] * s; + m[2][0] = a.m[2][0] * s; m[2][1] = a.m[2][1] * s; m[2][2] = a.m[2][2] * s; + } + + inline_ void Add(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] + b.m[0][0]; m[0][1] = a.m[0][1] + b.m[0][1]; m[0][2] = a.m[0][2] + b.m[0][2]; + m[1][0] = a.m[1][0] + b.m[1][0]; m[1][1] = a.m[1][1] + b.m[1][1]; m[1][2] = a.m[1][2] + b.m[1][2]; + m[2][0] = a.m[2][0] + b.m[2][0]; m[2][1] = a.m[2][1] + b.m[2][1]; m[2][2] = a.m[2][2] + b.m[2][2]; + } + + inline_ void Sub(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] - b.m[0][0]; m[0][1] = a.m[0][1] - b.m[0][1]; m[0][2] = a.m[0][2] - b.m[0][2]; + m[1][0] = a.m[1][0] - b.m[1][0]; m[1][1] = a.m[1][1] - b.m[1][1]; m[1][2] = a.m[1][2] - b.m[1][2]; + m[2][0] = a.m[2][0] - b.m[2][0]; m[2][1] = a.m[2][1] - b.m[2][1]; m[2][2] = a.m[2][2] - b.m[2][2]; + } + + //! this = a * b + inline_ void Mult(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[1][0] + a.m[0][2] * b.m[2][0]; + m[0][1] = a.m[0][0] * b.m[0][1] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[2][1]; + m[0][2] = a.m[0][0] * b.m[0][2] + a.m[0][1] * b.m[1][2] + a.m[0][2] * b.m[2][2]; + m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[1][2] * b.m[2][0]; + m[1][1] = a.m[1][0] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[2][1]; + m[1][2] = a.m[1][0] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[1][2] * b.m[2][2]; + m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[1][0] + a.m[2][2] * b.m[2][0]; + m[2][1] = a.m[2][0] * b.m[0][1] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[2][1]; + m[2][2] = a.m[2][0] * b.m[0][2] + a.m[2][1] * b.m[1][2] + a.m[2][2] * b.m[2][2]; + } + + //! this = transpose(a) * b + inline_ void MultAtB(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] * b.m[0][0] + a.m[1][0] * b.m[1][0] + a.m[2][0] * b.m[2][0]; + m[0][1] = a.m[0][0] * b.m[0][1] + a.m[1][0] * b.m[1][1] + a.m[2][0] * b.m[2][1]; + m[0][2] = a.m[0][0] * b.m[0][2] + a.m[1][0] * b.m[1][2] + a.m[2][0] * b.m[2][2]; + m[1][0] = a.m[0][1] * b.m[0][0] + a.m[1][1] * b.m[1][0] + a.m[2][1] * b.m[2][0]; + m[1][1] = a.m[0][1] * b.m[0][1] + a.m[1][1] * b.m[1][1] + a.m[2][1] * b.m[2][1]; + m[1][2] = a.m[0][1] * b.m[0][2] + a.m[1][1] * b.m[1][2] + a.m[2][1] * b.m[2][2]; + m[2][0] = a.m[0][2] * b.m[0][0] + a.m[1][2] * b.m[1][0] + a.m[2][2] * b.m[2][0]; + m[2][1] = a.m[0][2] * b.m[0][1] + a.m[1][2] * b.m[1][1] + a.m[2][2] * b.m[2][1]; + m[2][2] = a.m[0][2] * b.m[0][2] + a.m[1][2] * b.m[1][2] + a.m[2][2] * b.m[2][2]; + } + + //! this = a * transpose(b) + inline_ void MultABt(const Matrix3x3& a, const Matrix3x3& b) + { + m[0][0] = a.m[0][0] * b.m[0][0] + a.m[0][1] * b.m[0][1] + a.m[0][2] * b.m[0][2]; + m[0][1] = a.m[0][0] * b.m[1][0] + a.m[0][1] * b.m[1][1] + a.m[0][2] * b.m[1][2]; + m[0][2] = a.m[0][0] * b.m[2][0] + a.m[0][1] * b.m[2][1] + a.m[0][2] * b.m[2][2]; + m[1][0] = a.m[1][0] * b.m[0][0] + a.m[1][1] * b.m[0][1] + a.m[1][2] * b.m[0][2]; + m[1][1] = a.m[1][0] * b.m[1][0] + a.m[1][1] * b.m[1][1] + a.m[1][2] * b.m[1][2]; + m[1][2] = a.m[1][0] * b.m[2][0] + a.m[1][1] * b.m[2][1] + a.m[1][2] * b.m[2][2]; + m[2][0] = a.m[2][0] * b.m[0][0] + a.m[2][1] * b.m[0][1] + a.m[2][2] * b.m[0][2]; + m[2][1] = a.m[2][0] * b.m[1][0] + a.m[2][1] * b.m[1][1] + a.m[2][2] * b.m[1][2]; + m[2][2] = a.m[2][0] * b.m[2][0] + a.m[2][1] * b.m[2][1] + a.m[2][2] * b.m[2][2]; + } + + //! Makes a rotation matrix mapping vector "from" to vector "to". + Matrix3x3& FromTo(const IcePoint& from, const IcePoint& to); + + //! Set a rotation matrix around the X axis. + //! 1 0 0 + //! RX = 0 cx sx + //! 0 -sx cx + void RotX(float angle); + //! Set a rotation matrix around the Y axis. + //! cy 0 -sy + //! RY = 0 1 0 + //! sy 0 cy + void RotY(float angle); + //! Set a rotation matrix around the Z axis. + //! cz sz 0 + //! RZ = -sz cz 0 + //! 0 0 1 + void RotZ(float angle); + //! cy sx.sy -sy.cx + //! RY.RX 0 cx sx + //! sy -sx.cy cx.cy + void RotYX(float y, float x); + + //! Make a rotation matrix about an arbitrary axis + Matrix3x3& Rot(float angle, const IcePoint& axis); + + //! Transpose the matrix. + void Transpose() + { + IR(m[1][0]) ^= IR(m[0][1]); IR(m[0][1]) ^= IR(m[1][0]); IR(m[1][0]) ^= IR(m[0][1]); + IR(m[2][0]) ^= IR(m[0][2]); IR(m[0][2]) ^= IR(m[2][0]); IR(m[2][0]) ^= IR(m[0][2]); + IR(m[2][1]) ^= IR(m[1][2]); IR(m[1][2]) ^= IR(m[2][1]); IR(m[2][1]) ^= IR(m[1][2]); + } + + //! this = Transpose(a) + void Transpose(const Matrix3x3& a) + { + m[0][0] = a.m[0][0]; m[0][1] = a.m[1][0]; m[0][2] = a.m[2][0]; + m[1][0] = a.m[0][1]; m[1][1] = a.m[1][1]; m[1][2] = a.m[2][1]; + m[2][0] = a.m[0][2]; m[2][1] = a.m[1][2]; m[2][2] = a.m[2][2]; + } + + //! Compute the determinant of the matrix. We use the rule of Sarrus. + float Determinant() const + { + return (m[0][0]*m[1][1]*m[2][2] + m[0][1]*m[1][2]*m[2][0] + m[0][2]*m[1][0]*m[2][1]) + - (m[2][0]*m[1][1]*m[0][2] + m[2][1]*m[1][2]*m[0][0] + m[2][2]*m[1][0]*m[0][1]); + } +/* + //! Compute a cofactor. Used for matrix inversion. + float CoFactor(ubyte row, ubyte column) const + { + static sdword gIndex[3+2] = { 0, 1, 2, 0, 1 }; + return (m[gIndex[row+1]][gIndex[column+1]]*m[gIndex[row+2]][gIndex[column+2]] - m[gIndex[row+2]][gIndex[column+1]]*m[gIndex[row+1]][gIndex[column+2]]); + } +*/ + //! Invert the matrix. Determinant must be different from zero, else matrix can't be inverted. + Matrix3x3& Invert() + { + float Det = Determinant(); // Must be !=0 + float OneOverDet = 1.0f / Det; + + Matrix3x3 Temp; + Temp.m[0][0] = +(m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDet; + Temp.m[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDet; + Temp.m[2][0] = +(m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDet; + Temp.m[0][1] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDet; + Temp.m[1][1] = +(m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDet; + Temp.m[2][1] = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDet; + Temp.m[0][2] = +(m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDet; + Temp.m[1][2] = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDet; + Temp.m[2][2] = +(m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDet; + + *this = Temp; + + return *this; + } + + Matrix3x3& Normalize(); + + //! this = exp(a) + Matrix3x3& Exp(const Matrix3x3& a); + +void FromQuat(const Quat &q); +void FromQuatL2(const Quat &q, float l2); + + // Arithmetic operators + //! Operator for Matrix3x3 Plus = Matrix3x3 + Matrix3x3; + inline_ Matrix3x3 operator+(const Matrix3x3& mat) const + { + return Matrix3x3( + m[0][0] + mat.m[0][0], m[0][1] + mat.m[0][1], m[0][2] + mat.m[0][2], + m[1][0] + mat.m[1][0], m[1][1] + mat.m[1][1], m[1][2] + mat.m[1][2], + m[2][0] + mat.m[2][0], m[2][1] + mat.m[2][1], m[2][2] + mat.m[2][2]); + } + + //! Operator for Matrix3x3 Minus = Matrix3x3 - Matrix3x3; + inline_ Matrix3x3 operator-(const Matrix3x3& mat) const + { + return Matrix3x3( + m[0][0] - mat.m[0][0], m[0][1] - mat.m[0][1], m[0][2] - mat.m[0][2], + m[1][0] - mat.m[1][0], m[1][1] - mat.m[1][1], m[1][2] - mat.m[1][2], + m[2][0] - mat.m[2][0], m[2][1] - mat.m[2][1], m[2][2] - mat.m[2][2]); + } + + //! Operator for Matrix3x3 Mul = Matrix3x3 * Matrix3x3; + inline_ Matrix3x3 operator*(const Matrix3x3& mat) const + { + return Matrix3x3( + m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0], + m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1], + m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2], + + m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0], + m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1], + m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2], + + m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0], + m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1], + m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2]); + } + + //! Operator for Point Mul = Matrix3x3 * Point; + inline_ IcePoint operator*(const IcePoint& v) const { return IcePoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v); } + + //! Operator for Matrix3x3 Mul = Matrix3x3 * float; + inline_ Matrix3x3 operator*(float s) const + { + return Matrix3x3( + m[0][0]*s, m[0][1]*s, m[0][2]*s, + m[1][0]*s, m[1][1]*s, m[1][2]*s, + m[2][0]*s, m[2][1]*s, m[2][2]*s); + } + + //! Operator for Matrix3x3 Mul = float * Matrix3x3; + inline_ friend Matrix3x3 operator*(float s, const Matrix3x3& mat) + { + return Matrix3x3( + s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], + s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], + s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2]); + } + + //! Operator for Matrix3x3 Div = Matrix3x3 / float; + inline_ Matrix3x3 operator/(float s) const + { + if (s) s = 1.0f / s; + return Matrix3x3( + m[0][0]*s, m[0][1]*s, m[0][2]*s, + m[1][0]*s, m[1][1]*s, m[1][2]*s, + m[2][0]*s, m[2][1]*s, m[2][2]*s); + } + + //! Operator for Matrix3x3 Div = float / Matrix3x3; + inline_ friend Matrix3x3 operator/(float s, const Matrix3x3& mat) + { + return Matrix3x3( + s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], + s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], + s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2]); + } + + //! Operator for Matrix3x3 += Matrix3x3 + inline_ Matrix3x3& operator+=(const Matrix3x3& mat) + { + m[0][0] += mat.m[0][0]; m[0][1] += mat.m[0][1]; m[0][2] += mat.m[0][2]; + m[1][0] += mat.m[1][0]; m[1][1] += mat.m[1][1]; m[1][2] += mat.m[1][2]; + m[2][0] += mat.m[2][0]; m[2][1] += mat.m[2][1]; m[2][2] += mat.m[2][2]; + return *this; + } + + //! Operator for Matrix3x3 -= Matrix3x3 + inline_ Matrix3x3& operator-=(const Matrix3x3& mat) + { + m[0][0] -= mat.m[0][0]; m[0][1] -= mat.m[0][1]; m[0][2] -= mat.m[0][2]; + m[1][0] -= mat.m[1][0]; m[1][1] -= mat.m[1][1]; m[1][2] -= mat.m[1][2]; + m[2][0] -= mat.m[2][0]; m[2][1] -= mat.m[2][1]; m[2][2] -= mat.m[2][2]; + return *this; + } + + //! Operator for Matrix3x3 *= Matrix3x3 + inline_ Matrix3x3& operator*=(const Matrix3x3& mat) + { + IcePoint TempRow; + + GetRow(0, TempRow); + m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; + m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; + m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; + + GetRow(1, TempRow); + m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; + m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; + m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; + + GetRow(2, TempRow); + m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0]; + m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1]; + m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2]; + return *this; + } + + //! Operator for Matrix3x3 *= float + inline_ Matrix3x3& operator*=(float s) + { + m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; + m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; + m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; + return *this; + } + + //! Operator for Matrix3x3 /= float + inline_ Matrix3x3& operator/=(float s) + { + if (s) s = 1.0f / s; + m[0][0] *= s; m[0][1] *= s; m[0][2] *= s; + m[1][0] *= s; m[1][1] *= s; m[1][2] *= s; + m[2][0] *= s; m[2][1] *= s; m[2][2] *= s; + return *this; + } + + // Cast operators + //! Cast a Matrix3x3 to a Matrix4x4. + operator Matrix4x4() const; + //! Cast a Matrix3x3 to a Quat. + operator Quat() const; + + inline_ const IcePoint& operator[](int row) const { return *(const IcePoint*)&m[row][0]; } + inline_ IcePoint& operator[](int row) { return *(IcePoint*)&m[row][0]; } + + public: + + float m[3][3]; + }; + +#endif // __ICEMATRIX3X3_H__ + diff --git a/contrib/Opcode/Ice/IceMatrix4x4.cpp b/contrib/Opcode/Ice/IceMatrix4x4.cpp new file mode 100644 index 0000000..f9d8997 --- /dev/null +++ b/contrib/Opcode/Ice/IceMatrix4x4.cpp @@ -0,0 +1,135 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 4x4 matrices. + * \file IceMatrix4x4.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * 4x4 matrix. + * DirectX-compliant, ie row-column order, ie m[Row][Col]. + * Same as: + * m11 m12 m13 m14 first row. + * m21 m22 m23 m24 second row. + * m31 m32 m33 m34 third row. + * m41 m42 m43 m44 fourth row. + * Translation is (m41, m42, m43), (m14, m24, m34, m44) = (0, 0, 0, 1). + * Stored in memory as m11 m12 m13 m14 m21... + * + * Multiplication rules: + * + * [x'y'z'1] = [xyz1][M] + * + * x' = x*m11 + y*m21 + z*m31 + m41 + * y' = x*m12 + y*m22 + z*m32 + m42 + * z' = x*m13 + y*m23 + z*m33 + m43 + * 1' = 0 + 0 + 0 + m44 + * + * \class Matrix4x4 + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Inverts a PR matrix. (which only contains a rotation and a translation) + * This is faster and less subject to FPU errors than the generic inversion code. + * + * \relates Matrix4x4 + * \fn InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src) + * \param dest [out] destination matrix + * \param src [in] source matrix + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +ICEMATHS_API void IceMaths::InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src) +{ + dest.m[0][0] = src.m[0][0]; + dest.m[1][0] = src.m[0][1]; + dest.m[2][0] = src.m[0][2]; + dest.m[3][0] = -(src.m[3][0]*src.m[0][0] + src.m[3][1]*src.m[0][1] + src.m[3][2]*src.m[0][2]); + + dest.m[0][1] = src.m[1][0]; + dest.m[1][1] = src.m[1][1]; + dest.m[2][1] = src.m[1][2]; + dest.m[3][1] = -(src.m[3][0]*src.m[1][0] + src.m[3][1]*src.m[1][1] + src.m[3][2]*src.m[1][2]); + + dest.m[0][2] = src.m[2][0]; + dest.m[1][2] = src.m[2][1]; + dest.m[2][2] = src.m[2][2]; + dest.m[3][2] = -(src.m[3][0]*src.m[2][0] + src.m[3][1]*src.m[2][1] + src.m[3][2]*src.m[2][2]); + + dest.m[0][3] = 0.0f; + dest.m[1][3] = 0.0f; + dest.m[2][3] = 0.0f; + dest.m[3][3] = 1.0f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Compute the cofactor of the Matrix at a specified location +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Matrix4x4::CoFactor(udword row, udword col) const +{ + return (( m[(row+1)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+3)&3][(col+3)&3] + + m[(row+1)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+3)&3][(col+1)&3] + + m[(row+1)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+3)&3][(col+2)&3]) + - (m[(row+3)&3][(col+1)&3]*m[(row+2)&3][(col+2)&3]*m[(row+1)&3][(col+3)&3] + + m[(row+3)&3][(col+2)&3]*m[(row+2)&3][(col+3)&3]*m[(row+1)&3][(col+1)&3] + + m[(row+3)&3][(col+3)&3]*m[(row+2)&3][(col+1)&3]*m[(row+1)&3][(col+2)&3])) * ((row + col) & 1 ? -1.0f : +1.0f); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Compute the determinant of the Matrix +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Matrix4x4::Determinant() const +{ + return m[0][0] * CoFactor(0, 0) + + m[0][1] * CoFactor(0, 1) + + m[0][2] * CoFactor(0, 2) + + m[0][3] * CoFactor(0, 3); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Compute the inverse of the matrix +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Matrix4x4& Matrix4x4::Invert() +{ + float Det = Determinant(); + Matrix4x4 Temp; + + if(fabsf(Det) < MATRIX4X4_EPSILON) + return *this; // The matrix is not invertible! Singular case! + + float IDet = 1.0f / Det; + + Temp.m[0][0] = CoFactor(0,0) * IDet; + Temp.m[1][0] = CoFactor(0,1) * IDet; + Temp.m[2][0] = CoFactor(0,2) * IDet; + Temp.m[3][0] = CoFactor(0,3) * IDet; + Temp.m[0][1] = CoFactor(1,0) * IDet; + Temp.m[1][1] = CoFactor(1,1) * IDet; + Temp.m[2][1] = CoFactor(1,2) * IDet; + Temp.m[3][1] = CoFactor(1,3) * IDet; + Temp.m[0][2] = CoFactor(2,0) * IDet; + Temp.m[1][2] = CoFactor(2,1) * IDet; + Temp.m[2][2] = CoFactor(2,2) * IDet; + Temp.m[3][2] = CoFactor(2,3) * IDet; + Temp.m[0][3] = CoFactor(3,0) * IDet; + Temp.m[1][3] = CoFactor(3,1) * IDet; + Temp.m[2][3] = CoFactor(3,2) * IDet; + Temp.m[3][3] = CoFactor(3,3) * IDet; + + *this = Temp; + + return *this; +} + diff --git a/contrib/Opcode/Ice/IceMatrix4x4.h b/contrib/Opcode/Ice/IceMatrix4x4.h new file mode 100644 index 0000000..82ebc05 --- /dev/null +++ b/contrib/Opcode/Ice/IceMatrix4x4.h @@ -0,0 +1,455 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 4x4 matrices. + * \file IceMatrix4x4.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEMATRIX4X4_H__ +#define __ICEMATRIX4X4_H__ + + // Forward declarations + class PRS; + class PR; + + #define MATRIX4X4_EPSILON (1.0e-7f) + + class ICEMATHS_API Matrix4x4 + { +// void LUBackwardSubstitution( sdword *indx, float* b ); +// void LUDecomposition( sdword* indx, float* d ); + + public: + //! Empty constructor. + inline_ Matrix4x4() {} + //! Constructor from 16 values + inline_ Matrix4x4( float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; + m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; + } + //! Copy constructor + inline_ Matrix4x4(const Matrix4x4& mat) { CopyMemory(m, &mat.m, 16*sizeof(float)); } + //! Destructor. + inline_ ~Matrix4x4() {} + + //! Assign values (rotation only) + inline_ Matrix4x4& Set( float m00, float m01, float m02, + float m10, float m11, float m12, + float m20, float m21, float m22) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; + return *this; + } + //! Assign values + inline_ Matrix4x4& Set( float m00, float m01, float m02, float m03, + float m10, float m11, float m12, float m13, + float m20, float m21, float m22, float m23, + float m30, float m31, float m32, float m33) + { + m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03; + m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13; + m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23; + m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33; + return *this; + } + + //! Copy from a Matrix4x4 + inline_ void Copy(const Matrix4x4& source) { CopyMemory(m, source.m, 16*sizeof(float)); } + + // Row-column access + //! Returns a row. + inline_ void GetRow(const udword r, HPoint& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; p.w=m[r][3]; } + //! Returns a row. + inline_ void GetRow(const udword r, IcePoint& p) const { p.x=m[r][0]; p.y=m[r][1]; p.z=m[r][2]; } + //! Returns a row. + inline_ const HPoint& GetRow(const udword r) const { return *(const HPoint*)&m[r][0]; } + //! Returns a row. + inline_ HPoint& GetRow(const udword r) { return *(HPoint*)&m[r][0]; } + //! Sets a row. + inline_ void SetRow(const udword r, const HPoint& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]=p.w; } + //! Sets a row. + inline_ void SetRow(const udword r, const IcePoint& p) { m[r][0]=p.x; m[r][1]=p.y; m[r][2]=p.z; m[r][3]= (r!=3) ? 0.0f : 1.0f; } + //! Returns a column. + inline_ void GetCol(const udword c, HPoint& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; p.w=m[3][c]; } + //! Returns a column. + inline_ void GetCol(const udword c, IcePoint& p) const { p.x=m[0][c]; p.y=m[1][c]; p.z=m[2][c]; } + //! Sets a column. + inline_ void SetCol(const udword c, const HPoint& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]=p.w; } + //! Sets a column. + inline_ void SetCol(const udword c, const IcePoint& p) { m[0][c]=p.x; m[1][c]=p.y; m[2][c]=p.z; m[3][c]= (c!=3) ? 0.0f : 1.0f; } + + // Translation + //! Returns the translation part of the matrix. + inline_ const HPoint& GetTrans() const { return GetRow(3); } + //! Gets the translation part of the matrix + inline_ void GetTrans(IcePoint& p) const { p.x=m[3][0]; p.y=m[3][1]; p.z=m[3][2]; } + //! Sets the translation part of the matrix, from a Point. + inline_ void SetTrans(const IcePoint& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; } + //! Sets the translation part of the matrix, from a HPoint. + inline_ void SetTrans(const HPoint& p) { m[3][0]=p.x; m[3][1]=p.y; m[3][2]=p.z; m[3][3]=p.w; } + //! Sets the translation part of the matrix, from floats. + inline_ void SetTrans(float tx, float ty, float tz) { m[3][0]=tx; m[3][1]=ty; m[3][2]=tz; } + + // Scale + //! Sets the scale from a Point. The point is put on the diagonal. + inline_ void SetScale(const IcePoint& p) { m[0][0]=p.x; m[1][1]=p.y; m[2][2]=p.z; } + //! Sets the scale from floats. Values are put on the diagonal. + inline_ void SetScale(float sx, float sy, float sz) { m[0][0]=sx; m[1][1]=sy; m[2][2]=sz; } + //! Scales from a Point. Each row is multiplied by a component. + void Scale(const IcePoint& p) + { + m[0][0] *= p.x; m[1][0] *= p.y; m[2][0] *= p.z; + m[0][1] *= p.x; m[1][1] *= p.y; m[2][1] *= p.z; + m[0][2] *= p.x; m[1][2] *= p.y; m[2][2] *= p.z; + } + //! Scales from floats. Each row is multiplied by a value. + void Scale(float sx, float sy, float sz) + { + m[0][0] *= sx; m[1][0] *= sy; m[2][0] *= sz; + m[0][1] *= sx; m[1][1] *= sy; m[2][1] *= sz; + m[0][2] *= sx; m[1][2] *= sy; m[2][2] *= sz; + } +/* + //! Returns a row. + inline_ HPoint GetRow(const udword row) const { return mRow[row]; } + //! Sets a row. + inline_ Matrix4x4& SetRow(const udword row, const HPoint& p) { mRow[row] = p; return *this; } + //! Sets a row. + Matrix4x4& SetRow(const udword row, const Point& p) + { + m[row][0] = p.x; + m[row][1] = p.y; + m[row][2] = p.z; + m[row][3] = (row != 3) ? 0.0f : 1.0f; + return *this; + } + //! Returns a column. + HPoint GetCol(const udword col) const + { + HPoint Res; + Res.x = m[0][col]; + Res.y = m[1][col]; + Res.z = m[2][col]; + Res.w = m[3][col]; + return Res; + } + //! Sets a column. + Matrix4x4& SetCol(const udword col, const HPoint& p) + { + m[0][col] = p.x; + m[1][col] = p.y; + m[2][col] = p.z; + m[3][col] = p.w; + return *this; + } + //! Sets a column. + Matrix4x4& SetCol(const udword col, const Point& p) + { + m[0][col] = p.x; + m[1][col] = p.y; + m[2][col] = p.z; + m[3][col] = (col != 3) ? 0.0f : 1.0f; + return *this; + } +*/ + //! Computes the trace. The trace is the sum of the 4 diagonal components. + inline_ float Trace() const { return m[0][0] + m[1][1] + m[2][2] + m[3][3]; } + //! Computes the trace of the upper 3x3 matrix. + inline_ float Trace3x3() const { return m[0][0] + m[1][1] + m[2][2]; } + //! Clears the matrix. + inline_ void Zero() { ZeroMemory(&m, sizeof(m)); } + //! Sets the identity matrix. + inline_ void Identity() { Zero(); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; } + //! Checks for identity + inline_ bool IsIdentity() const + { + if(IR(m[0][0])!=IEEE_1_0) return false; + if(IR(m[0][1])!=0) return false; + if(IR(m[0][2])!=0) return false; + if(IR(m[0][3])!=0) return false; + + if(IR(m[1][0])!=0) return false; + if(IR(m[1][1])!=IEEE_1_0) return false; + if(IR(m[1][2])!=0) return false; + if(IR(m[1][3])!=0) return false; + + if(IR(m[2][0])!=0) return false; + if(IR(m[2][1])!=0) return false; + if(IR(m[2][2])!=IEEE_1_0) return false; + if(IR(m[2][3])!=0) return false; + + if(IR(m[3][0])!=0) return false; + if(IR(m[3][1])!=0) return false; + if(IR(m[3][2])!=0) return false; + if(IR(m[3][3])!=IEEE_1_0) return false; + return true; + } + + //! Checks matrix validity + inline_ BOOL IsValid() const + { + for(udword j=0;j<4;j++) + { + for(udword i=0;i<4;i++) + { + if(!IsValidFloat(m[j][i])) return FALSE; + } + } + return TRUE; + } + + //! Sets a rotation matrix around the X axis. + void RotX(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[1][1] = m[2][2] = Cos; m[2][1] = -Sin; m[1][2] = Sin; } + //! Sets a rotation matrix around the Y axis. + void RotY(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[2][2] = Cos; m[2][0] = Sin; m[0][2] = -Sin; } + //! Sets a rotation matrix around the Z axis. + void RotZ(float angle) { float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[1][1] = Cos; m[1][0] = -Sin; m[0][1] = Sin; } + + //! Makes a rotation matrix about an arbitrary axis + Matrix4x4& Rot(float angle, IcePoint& p1, IcePoint& p2); + + //! Transposes the matrix. + void Transpose() + { + IR(m[1][0]) ^= IR(m[0][1]); IR(m[0][1]) ^= IR(m[1][0]); IR(m[1][0]) ^= IR(m[0][1]); + IR(m[2][0]) ^= IR(m[0][2]); IR(m[0][2]) ^= IR(m[2][0]); IR(m[2][0]) ^= IR(m[0][2]); + IR(m[3][0]) ^= IR(m[0][3]); IR(m[0][3]) ^= IR(m[3][0]); IR(m[3][0]) ^= IR(m[0][3]); + IR(m[1][2]) ^= IR(m[2][1]); IR(m[2][1]) ^= IR(m[1][2]); IR(m[1][2]) ^= IR(m[2][1]); + IR(m[1][3]) ^= IR(m[3][1]); IR(m[3][1]) ^= IR(m[1][3]); IR(m[1][3]) ^= IR(m[3][1]); + IR(m[2][3]) ^= IR(m[3][2]); IR(m[3][2]) ^= IR(m[2][3]); IR(m[2][3]) ^= IR(m[3][2]); + } + + //! Computes a cofactor. Used for matrix inversion. + float CoFactor(udword row, udword col) const; + //! Computes the determinant of the matrix. + float Determinant() const; + //! Inverts the matrix. Determinant must be different from zero, else matrix can't be inverted. + Matrix4x4& Invert(); +// Matrix& ComputeAxisMatrix(Point& axis, float angle); + + // Cast operators + //! Casts a Matrix4x4 to a Matrix3x3. + inline_ operator Matrix3x3() const + { + return Matrix3x3( + m[0][0], m[0][1], m[0][2], + m[1][0], m[1][1], m[1][2], + m[2][0], m[2][1], m[2][2]); + } + //! Casts a Matrix4x4 to a Quat. + operator Quat() const; + //! Casts a Matrix4x4 to a PR. + operator PR() const; + + // Arithmetic operators + //! Operator for Matrix4x4 Plus = Matrix4x4 + Matrix4x4; + inline_ Matrix4x4 operator+(const Matrix4x4& mat) const + { + return Matrix4x4( + m[0][0]+mat.m[0][0], m[0][1]+mat.m[0][1], m[0][2]+mat.m[0][2], m[0][3]+mat.m[0][3], + m[1][0]+mat.m[1][0], m[1][1]+mat.m[1][1], m[1][2]+mat.m[1][2], m[1][3]+mat.m[1][3], + m[2][0]+mat.m[2][0], m[2][1]+mat.m[2][1], m[2][2]+mat.m[2][2], m[2][3]+mat.m[2][3], + m[3][0]+mat.m[3][0], m[3][1]+mat.m[3][1], m[3][2]+mat.m[3][2], m[3][3]+mat.m[3][3]); + } + + //! Operator for Matrix4x4 Minus = Matrix4x4 - Matrix4x4; + inline_ Matrix4x4 operator-(const Matrix4x4& mat) const + { + return Matrix4x4( + m[0][0]-mat.m[0][0], m[0][1]-mat.m[0][1], m[0][2]-mat.m[0][2], m[0][3]-mat.m[0][3], + m[1][0]-mat.m[1][0], m[1][1]-mat.m[1][1], m[1][2]-mat.m[1][2], m[1][3]-mat.m[1][3], + m[2][0]-mat.m[2][0], m[2][1]-mat.m[2][1], m[2][2]-mat.m[2][2], m[2][3]-mat.m[2][3], + m[3][0]-mat.m[3][0], m[3][1]-mat.m[3][1], m[3][2]-mat.m[3][2], m[3][3]-mat.m[3][3]); + } + + //! Operator for Matrix4x4 Mul = Matrix4x4 * Matrix4x4; + inline_ Matrix4x4 operator*(const Matrix4x4& mat) const + { + return Matrix4x4( + m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0] + m[0][3]*mat.m[3][0], + m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1] + m[0][3]*mat.m[3][1], + m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2] + m[0][3]*mat.m[3][2], + m[0][0]*mat.m[0][3] + m[0][1]*mat.m[1][3] + m[0][2]*mat.m[2][3] + m[0][3]*mat.m[3][3], + + m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0] + m[1][3]*mat.m[3][0], + m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1] + m[1][3]*mat.m[3][1], + m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2] + m[1][3]*mat.m[3][2], + m[1][0]*mat.m[0][3] + m[1][1]*mat.m[1][3] + m[1][2]*mat.m[2][3] + m[1][3]*mat.m[3][3], + + m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0] + m[2][3]*mat.m[3][0], + m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1] + m[2][3]*mat.m[3][1], + m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2] + m[2][3]*mat.m[3][2], + m[2][0]*mat.m[0][3] + m[2][1]*mat.m[1][3] + m[2][2]*mat.m[2][3] + m[2][3]*mat.m[3][3], + + m[3][0]*mat.m[0][0] + m[3][1]*mat.m[1][0] + m[3][2]*mat.m[2][0] + m[3][3]*mat.m[3][0], + m[3][0]*mat.m[0][1] + m[3][1]*mat.m[1][1] + m[3][2]*mat.m[2][1] + m[3][3]*mat.m[3][1], + m[3][0]*mat.m[0][2] + m[3][1]*mat.m[1][2] + m[3][2]*mat.m[2][2] + m[3][3]*mat.m[3][2], + m[3][0]*mat.m[0][3] + m[3][1]*mat.m[1][3] + m[3][2]*mat.m[2][3] + m[3][3]*mat.m[3][3]); + } + + //! Operator for HPoint Mul = Matrix4x4 * HPoint; + inline_ HPoint operator*(const HPoint& v) const { return HPoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v, GetRow(3)|v); } + + //! Operator for Point Mul = Matrix4x4 * Point; + inline_ IcePoint operator*(const IcePoint& v) const + { + return IcePoint( m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3], + m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3], + m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3] ); + } + + //! Operator for Matrix4x4 Scale = Matrix4x4 * float; + inline_ Matrix4x4 operator*(float s) const + { + return Matrix4x4( + m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s, + m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s, + m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s, + m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s); + } + + //! Operator for Matrix4x4 Scale = float * Matrix4x4; + inline_ friend Matrix4x4 operator*(float s, const Matrix4x4& mat) + { + return Matrix4x4( + s*mat.m[0][0], s*mat.m[0][1], s*mat.m[0][2], s*mat.m[0][3], + s*mat.m[1][0], s*mat.m[1][1], s*mat.m[1][2], s*mat.m[1][3], + s*mat.m[2][0], s*mat.m[2][1], s*mat.m[2][2], s*mat.m[2][3], + s*mat.m[3][0], s*mat.m[3][1], s*mat.m[3][2], s*mat.m[3][3]); + } + + //! Operator for Matrix4x4 Div = Matrix4x4 / float; + inline_ Matrix4x4 operator/(float s) const + { + if(s) s = 1.0f / s; + + return Matrix4x4( + m[0][0]*s, m[0][1]*s, m[0][2]*s, m[0][3]*s, + m[1][0]*s, m[1][1]*s, m[1][2]*s, m[1][3]*s, + m[2][0]*s, m[2][1]*s, m[2][2]*s, m[2][3]*s, + m[3][0]*s, m[3][1]*s, m[3][2]*s, m[3][3]*s); + } + + //! Operator for Matrix4x4 Div = float / Matrix4x4; + inline_ friend Matrix4x4 operator/(float s, const Matrix4x4& mat) + { + return Matrix4x4( + s/mat.m[0][0], s/mat.m[0][1], s/mat.m[0][2], s/mat.m[0][3], + s/mat.m[1][0], s/mat.m[1][1], s/mat.m[1][2], s/mat.m[1][3], + s/mat.m[2][0], s/mat.m[2][1], s/mat.m[2][2], s/mat.m[2][3], + s/mat.m[3][0], s/mat.m[3][1], s/mat.m[3][2], s/mat.m[3][3]); + } + + //! Operator for Matrix4x4 += Matrix4x4; + inline_ Matrix4x4& operator+=(const Matrix4x4& mat) + { + m[0][0]+=mat.m[0][0]; m[0][1]+=mat.m[0][1]; m[0][2]+=mat.m[0][2]; m[0][3]+=mat.m[0][3]; + m[1][0]+=mat.m[1][0]; m[1][1]+=mat.m[1][1]; m[1][2]+=mat.m[1][2]; m[1][3]+=mat.m[1][3]; + m[2][0]+=mat.m[2][0]; m[2][1]+=mat.m[2][1]; m[2][2]+=mat.m[2][2]; m[2][3]+=mat.m[2][3]; + m[3][0]+=mat.m[3][0]; m[3][1]+=mat.m[3][1]; m[3][2]+=mat.m[3][2]; m[3][3]+=mat.m[3][3]; + return *this; + } + + //! Operator for Matrix4x4 -= Matrix4x4; + inline_ Matrix4x4& operator-=(const Matrix4x4& mat) + { + m[0][0]-=mat.m[0][0]; m[0][1]-=mat.m[0][1]; m[0][2]-=mat.m[0][2]; m[0][3]-=mat.m[0][3]; + m[1][0]-=mat.m[1][0]; m[1][1]-=mat.m[1][1]; m[1][2]-=mat.m[1][2]; m[1][3]-=mat.m[1][3]; + m[2][0]-=mat.m[2][0]; m[2][1]-=mat.m[2][1]; m[2][2]-=mat.m[2][2]; m[2][3]-=mat.m[2][3]; + m[3][0]-=mat.m[3][0]; m[3][1]-=mat.m[3][1]; m[3][2]-=mat.m[3][2]; m[3][3]-=mat.m[3][3]; + return *this; + } + + //! Operator for Matrix4x4 *= Matrix4x4; + Matrix4x4& operator*=(const Matrix4x4& mat) + { + HPoint TempRow; + + GetRow(0, TempRow); + m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; + m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; + m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; + m[0][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; + + GetRow(1, TempRow); + m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; + m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; + m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; + m[1][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; + + GetRow(2, TempRow); + m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; + m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; + m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; + m[2][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; + + GetRow(3, TempRow); + m[3][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0]; + m[3][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1]; + m[3][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2]; + m[3][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3]; + + return *this; + } + + //! Operator for Matrix4x4 *= float; + inline_ Matrix4x4& operator*=(float s) + { + m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s; + m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s; + m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s; + m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s; + return *this; + } + + //! Operator for Matrix4x4 /= float; + inline_ Matrix4x4& operator/=(float s) + { + if(s) s = 1.0f / s; + m[0][0]*=s; m[0][1]*=s; m[0][2]*=s; m[0][3]*=s; + m[1][0]*=s; m[1][1]*=s; m[1][2]*=s; m[1][3]*=s; + m[2][0]*=s; m[2][1]*=s; m[2][2]*=s; m[2][3]*=s; + m[3][0]*=s; m[3][1]*=s; m[3][2]*=s; m[3][3]*=s; + return *this; + } + + inline_ const HPoint& operator[](int row) const { return *(const HPoint*)&m[row][0]; } + inline_ HPoint& operator[](int row) { return *(HPoint*)&m[row][0]; } + + public: + + float m[4][4]; + }; + + //! Quickly rotates & translates a vector, using the 4x3 part of a 4x4 matrix + inline_ void TransformPoint4x3(IcePoint& dest, const IcePoint& source, const Matrix4x4& rot) + { + dest.x = rot.m[3][0] + source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0]; + dest.y = rot.m[3][1] + source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1]; + dest.z = rot.m[3][2] + source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2]; + } + + //! Quickly rotates a vector, using the 3x3 part of a 4x4 matrix + inline_ void TransformPoint3x3(IcePoint& dest, const IcePoint& source, const Matrix4x4& rot) + { + dest.x = source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0]; + dest.y = source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1]; + dest.z = source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2]; + } + + ICEMATHS_API void InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src); + +#endif // __ICEMATRIX4X4_H__ + diff --git a/contrib/Opcode/Ice/IceMemoryMacros.h b/contrib/Opcode/Ice/IceMemoryMacros.h new file mode 100644 index 0000000..0987e11 --- /dev/null +++ b/contrib/Opcode/Ice/IceMemoryMacros.h @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains all memory macros. + * \file IceMemoryMacros.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEMEMORYMACROS_H__ +#define __ICEMEMORYMACROS_H__ + +#undef ZeroMemory +#undef CopyMemory +#undef MoveMemory +#undef FillMemory + + //! Clears a buffer. + //! \param addr [in] buffer address + //! \param size [in] buffer length + //! \see FillMemory + //! \see StoreDwords + //! \see CopyMemory + //! \see MoveMemory + inline_ void ZeroMemory(void* addr, udword size) { memset(addr, 0, size); } + + //! Fills a buffer with a given byte. + //! \param addr [in] buffer address + //! \param size [in] buffer length + //! \param val [in] the byte value + //! \see StoreDwords + //! \see ZeroMemory + //! \see CopyMemory + //! \see MoveMemory + inline_ void FillMemory(void* dest, udword size, ubyte val) { memset(dest, val, size); } + + //! Fills a buffer with a given dword. + //! \param addr [in] buffer address + //! \param nb [in] number of dwords to write + //! \param value [in] the dword value + //! \see FillMemory + //! \see ZeroMemory + //! \see CopyMemory + //! \see MoveMemory + //! \warning writes nb*4 bytes ! + inline_ void StoreDwords(udword* dest, udword nb, udword value) + { + while (nb--) *dest++ = value; + } + + //! Copies a buffer. + //! \param addr [in] destination buffer address + //! \param addr [in] source buffer address + //! \param size [in] buffer length + //! \see ZeroMemory + //! \see FillMemory + //! \see StoreDwords + //! \see MoveMemory + inline_ void CopyMemory(void* dest, const void* src, udword size) { memcpy(dest, src, size); } + + //! Moves a buffer. + //! \param addr [in] destination buffer address + //! \param addr [in] source buffer address + //! \param size [in] buffer length + //! \see ZeroMemory + //! \see FillMemory + //! \see StoreDwords + //! \see CopyMemory + inline_ void MoveMemory(void* dest, const void* src, udword size) { memmove(dest, src, size); } + + #define SIZEOFOBJECT sizeof(*this) //!< Gives the size of current object. Avoid some mistakes (e.g. "sizeof(this)"). + //#define CLEAROBJECT { memset(this, 0, SIZEOFOBJECT); } //!< Clears current object. Laziness is my business. HANDLE WITH CARE. + #define DELETESINGLE(x) if (x) { delete x; x = null; } //!< Deletes an instance of a class. + #define DELETEARRAY(x) if (x) { delete []x; x = null; } //!< Deletes an array. + #define SAFE_RELEASE(x) if (x) { (x)->Release(); (x) = null; } //!< Safe D3D-style release + #define SAFE_DESTRUCT(x) if (x) { (x)->SelfDestruct(); (x) = null; } //!< Safe ICE-style release + +#ifdef __ICEERROR_H__ + #define CHECKALLOC(x) if(!x) return SetIceError;; // ("Out of memory.", EC_OUT_OF_MEMORY); //!< Standard alloc checking. HANDLE WITH CARE. +#else + #define CHECKALLOC(x) if(!x) return false; +#endif + + //! Standard allocation cycle + #define SAFE_ALLOC(ptr, type, count) DELETEARRAY(ptr); ptr = new type[count]; CHECKALLOC(ptr); + +#endif // __ICEMEMORYMACROS_H__ diff --git a/contrib/Opcode/Ice/IceOBB.cpp b/contrib/Opcode/Ice/IceOBB.cpp new file mode 100644 index 0000000..ac9dbf7 --- /dev/null +++ b/contrib/Opcode/Ice/IceOBB.cpp @@ -0,0 +1,323 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains OBB-related code. + * \file IceOBB.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * An Oriented Bounding Box (OBB). + * \class OBB + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Tests if a point is contained within the OBB. + * \param p [in] the world point to test + * \return true if inside the OBB + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBB::ContainsPoint(const IcePoint& p) const +{ + // IcePoint in OBB test using lazy evaluation and early exits + + // Translate to box space + IcePoint RelPoint = p - mCenter; + + // IcePoint * mRot maps from box space to world space + // mRot * IcePoint maps from world space to box space (what we need here) + + float f = mRot.m[0][0] * RelPoint.x + mRot.m[0][1] * RelPoint.y + mRot.m[0][2] * RelPoint.z; + if(f >= mExtents.x || f <= -mExtents.x) return false; + + f = mRot.m[1][0] * RelPoint.x + mRot.m[1][1] * RelPoint.y + mRot.m[1][2] * RelPoint.z; + if(f >= mExtents.y || f <= -mExtents.y) return false; + + f = mRot.m[2][0] * RelPoint.x + mRot.m[2][1] * RelPoint.y + mRot.m[2][2] * RelPoint.z; + if(f >= mExtents.z || f <= -mExtents.z) return false; + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds an OBB from an AABB and a world transform. + * \param aabb [in] the aabb + * \param mat [in] the world transform + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBB::Create(const AABB& aabb, const Matrix4x4& mat) +{ + // Note: must be coherent with Rotate() + + aabb.GetCenter(mCenter); + aabb.GetExtents(mExtents); + // Here we have the same as OBB::Rotate(mat) where the obb is (mCenter, mExtents, Identity). + + // So following what's done in Rotate: + // - x-form the center + mCenter *= mat; + // - combine rotation with identity, i.e. just use given matrix + mRot = mat; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the obb planes. + * \param planes [out] 6 box planes + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBB::ComputePlanes(IcePlane* planes) const +{ + // Checkings + if(!planes) return false; + + IcePoint Axis0 = mRot[0]; + IcePoint Axis1 = mRot[1]; + IcePoint Axis2 = mRot[2]; + + // Writes normals + planes[0].n = Axis0; + planes[1].n = -Axis0; + planes[2].n = Axis1; + planes[3].n = -Axis1; + planes[4].n = Axis2; + planes[5].n = -Axis2; + + // Compute a point on each plane + IcePoint p0 = mCenter + Axis0 * mExtents.x; + IcePoint p1 = mCenter - Axis0 * mExtents.x; + IcePoint p2 = mCenter + Axis1 * mExtents.y; + IcePoint p3 = mCenter - Axis1 * mExtents.y; + IcePoint p4 = mCenter + Axis2 * mExtents.z; + IcePoint p5 = mCenter - Axis2 * mExtents.z; + + // Compute d + planes[0].d = -(planes[0].n|p0); + planes[1].d = -(planes[1].n|p1); + planes[2].d = -(planes[2].n|p2); + planes[3].d = -(planes[3].n|p3); + planes[4].d = -(planes[4].n|p4); + planes[5].d = -(planes[5].n|p5); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the obb points. + * \param pts [out] 8 box points + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBB::ComputePoints(IcePoint* pts) const +{ + // Checkings + if(!pts) return false; + + IcePoint Axis0 = mRot[0]; + IcePoint Axis1 = mRot[1]; + IcePoint Axis2 = mRot[2]; + + Axis0 *= mExtents.x; + Axis1 *= mExtents.y; + Axis2 *= mExtents.z; + + // 7+------+6 0 = --- + // /| /| 1 = +-- + // / | / | 2 = ++- + // / 4+---/--+5 3 = -+- + // 3+------+2 / y z 4 = --+ + // | / | / | / 5 = +-+ + // |/ |/ |/ 6 = +++ + // 0+------+1 *---x 7 = -++ + + pts[0] = mCenter - Axis0 - Axis1 - Axis2; + pts[1] = mCenter + Axis0 - Axis1 - Axis2; + pts[2] = mCenter + Axis0 + Axis1 - Axis2; + pts[3] = mCenter - Axis0 + Axis1 - Axis2; + pts[4] = mCenter - Axis0 - Axis1 + Axis2; + pts[5] = mCenter + Axis0 - Axis1 + Axis2; + pts[6] = mCenter + Axis0 + Axis1 + Axis2; + pts[7] = mCenter - Axis0 + Axis1 + Axis2; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes vertex normals. + * \param pts [out] 8 box points + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBB::ComputeVertexNormals(IcePoint* pts) const +{ + static float VertexNormals[] = + { + -INVSQRT3, -INVSQRT3, -INVSQRT3, + INVSQRT3, -INVSQRT3, -INVSQRT3, + INVSQRT3, INVSQRT3, -INVSQRT3, + -INVSQRT3, INVSQRT3, -INVSQRT3, + -INVSQRT3, -INVSQRT3, INVSQRT3, + INVSQRT3, -INVSQRT3, INVSQRT3, + INVSQRT3, INVSQRT3, INVSQRT3, + -INVSQRT3, INVSQRT3, INVSQRT3 + }; + + if(!pts) return false; + + const IcePoint* VN = (const IcePoint*)VertexNormals; + for(udword i=0;i<8;i++) + { + pts[i] = VN[i] * mRot; + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Returns edges. + * \return 24 indices (12 edges) indexing the list returned by ComputePoints() + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const udword* OBB::GetEdges() const +{ + static udword Indices[] = { + 0, 1, 1, 2, 2, 3, 3, 0, + 7, 6, 6, 5, 5, 4, 4, 7, + 1, 5, 6, 2, + 3, 7, 4, 0 + }; + return Indices; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Returns local edge normals. + * \return edge normals in local space + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const IcePoint* OBB::GetLocalEdgeNormals() const +{ + static float EdgeNormals[] = + { + 0, -INVSQRT2, -INVSQRT2, // 0-1 + INVSQRT2, 0, -INVSQRT2, // 1-2 + 0, INVSQRT2, -INVSQRT2, // 2-3 + -INVSQRT2, 0, -INVSQRT2, // 3-0 + + 0, INVSQRT2, INVSQRT2, // 7-6 + INVSQRT2, 0, INVSQRT2, // 6-5 + 0, -INVSQRT2, INVSQRT2, // 5-4 + -INVSQRT2, 0, INVSQRT2, // 4-7 + + INVSQRT2, -INVSQRT2, 0, // 1-5 + INVSQRT2, INVSQRT2, 0, // 6-2 + -INVSQRT2, INVSQRT2, 0, // 3-7 + -INVSQRT2, -INVSQRT2, 0 // 4-0 + }; + return (const IcePoint*)EdgeNormals; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Returns world edge normal + * \param edge_index [in] 0 <= edge index < 12 + * \param world_normal [out] edge normal in world space + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBB::ComputeWorldEdgeNormal(udword edge_index, IcePoint& world_normal) const +{ + ASSERT(edge_index<12); + world_normal = GetLocalEdgeNormals()[edge_index] * mRot; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes an LSS surrounding the OBB. + * \param lss [out] the LSS + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBB::ComputeLSS(LSS& lss) const +{ + IcePoint Axis0 = mRot[0]; + IcePoint Axis1 = mRot[1]; + IcePoint Axis2 = mRot[2]; + + switch(mExtents.LargestAxis()) + { + case 0: + lss.mRadius = (mExtents.y + mExtents.z)*0.5f; + lss.mP0 = mCenter + Axis0 * (mExtents.x - lss.mRadius); + lss.mP1 = mCenter - Axis0 * (mExtents.x - lss.mRadius); + break; + case 1: + lss.mRadius = (mExtents.x + mExtents.z)*0.5f; + lss.mP0 = mCenter + Axis1 * (mExtents.y - lss.mRadius); + lss.mP1 = mCenter - Axis1 * (mExtents.y - lss.mRadius); + break; + case 2: + lss.mRadius = (mExtents.x + mExtents.y)*0.5f; + lss.mP0 = mCenter + Axis2 * (mExtents.z - lss.mRadius); + lss.mP1 = mCenter - Axis2 * (mExtents.z - lss.mRadius); + break; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the OBB is inside another OBB. + * \param box [in] the other OBB + * \return TRUE if we're inside the other box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL OBB::IsInside(const OBB& box) const +{ + // Make a 4x4 from the box & inverse it + Matrix4x4 M0Inv; + { + Matrix4x4 M0 = box.mRot; + M0.SetTrans(box.mCenter); + InvertPRMatrix(M0Inv, M0); + } + + // With our inversed 4x4, create box1 in space of box0 + OBB _1in0; + Rotate(M0Inv, _1in0); + + // This should cancel out box0's rotation, i.e. it's now an AABB. + // => Center(0,0,0), Rot(identity) + + // The two boxes are in the same space so now we can compare them. + + // Create the AABB of (box1 in space of box0) + const Matrix3x3& mtx = _1in0.mRot; + + float f = fabsf(mtx.m[0][0] * mExtents.x) + fabsf(mtx.m[1][0] * mExtents.y) + fabsf(mtx.m[2][0] * mExtents.z) - box.mExtents.x; + if(f > _1in0.mCenter.x) return FALSE; + if(-f < _1in0.mCenter.x) return FALSE; + + f = fabsf(mtx.m[0][1] * mExtents.x) + fabsf(mtx.m[1][1] * mExtents.y) + fabsf(mtx.m[2][1] * mExtents.z) - box.mExtents.y; + if(f > _1in0.mCenter.y) return FALSE; + if(-f < _1in0.mCenter.y) return FALSE; + + f = fabsf(mtx.m[0][2] * mExtents.x) + fabsf(mtx.m[1][2] * mExtents.y) + fabsf(mtx.m[2][2] * mExtents.z) - box.mExtents.z; + if(f > _1in0.mCenter.z) return FALSE; + if(-f < _1in0.mCenter.z) return FALSE; + + return TRUE; +} diff --git a/contrib/Opcode/Ice/IceOBB.h b/contrib/Opcode/Ice/IceOBB.h new file mode 100644 index 0000000..c55c2d5 --- /dev/null +++ b/contrib/Opcode/Ice/IceOBB.h @@ -0,0 +1,177 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains OBB-related code. (oriented bounding box) + * \file IceOBB.h + * \author Pierre Terdiman + * \date January, 13, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEOBB_H__ +#define __ICEOBB_H__ + + // Forward declarations + class LSS; + + class ICEMATHS_API OBB + { + public: + //! Constructor + inline_ OBB() {} + //! Constructor + inline_ OBB(const IcePoint& center, const IcePoint& extents, const Matrix3x3& rot) : mCenter(center), mExtents(extents), mRot(rot) {} + //! Destructor + inline_ ~OBB() {} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an empty OBB. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void SetEmpty() + { + mCenter.Zero(); + mExtents.Set(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); + mRot.Identity(); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Tests if a IcePoint is contained within the OBB. + * \param p [in] the world IcePoint to test + * \return true if inside the OBB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool ContainsPoint(const IcePoint& p) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds an OBB from an AABB and a world transform. + * \param aabb [in] the aabb + * \param mat [in] the world transform + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void Create(const AABB& aabb, const Matrix4x4& mat); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Recomputes the OBB after an arbitrary transform by a 4x4 matrix. + * \param mtx [in] the transform matrix + * \param obb [out] the transformed OBB + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void Rotate(const Matrix4x4& mtx, OBB& obb) const + { + // The extents remain constant + obb.mExtents = mExtents; + // The center gets x-formed + obb.mCenter = mCenter * mtx; + // Combine rotations + obb.mRot = mRot * Matrix3x3(mtx); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the OBB is valid. + * \return true if the box is valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsValid() const + { + // Consistency condition for (Center, Extents) boxes: Extents >= 0.0f + if(mExtents.x < 0.0f) return FALSE; + if(mExtents.y < 0.0f) return FALSE; + if(mExtents.z < 0.0f) return FALSE; + return TRUE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the obb planes. + * \param planes [out] 6 box planes + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool ComputePlanes(IcePlane* planes) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes the obb points. + * \param pts [out] 8 box points + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool ComputePoints(IcePoint* pts) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes vertex normals. + * \param pts [out] 8 box points + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool ComputeVertexNormals(IcePoint* pts) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns edges. + * \return 24 indices (12 edges) indexing the list returned by ComputePoints() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const udword* GetEdges() const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns local edge normals. + * \return edge normals in local space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const IcePoint* GetLocalEdgeNormals() const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns world edge normal + * \param edge_index [in] 0 <= edge index < 12 + * \param world_normal [out] edge normal in world space + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void ComputeWorldEdgeNormal(udword edge_index, IcePoint& world_normal) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes an LSS surrounding the OBB. + * \param lss [out] the LSS + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + void ComputeLSS(LSS& lss) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the OBB is inside another OBB. + * \param box [in] the other OBB + * \return TRUE if we're inside the other box + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + BOOL IsInside(const OBB& box) const; + + inline_ const IcePoint& GetCenter() const { return mCenter; } + inline_ const IcePoint& GetExtents() const { return mExtents; } + inline_ const Matrix3x3& GetRot() const { return mRot; } + + inline_ void GetRotatedExtents(Matrix3x3& extents) const + { + extents = mRot; + extents.Scale(mExtents); + } + + IcePoint mCenter; //!< B for Box + IcePoint mExtents; //!< B for Bounding + Matrix3x3 mRot; //!< O for Oriented + + // Orientation is stored in row-major format, + // i.e. rows = eigen vectors of the covariance matrix + }; + +#endif // __ICEOBB_H__ diff --git a/contrib/Opcode/Ice/IcePairs.h b/contrib/Opcode/Ice/IcePairs.h new file mode 100644 index 0000000..2c09b92 --- /dev/null +++ b/contrib/Opcode/Ice/IcePairs.h @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a simple pair class. + * \file IcePairs.h + * \author Pierre Terdiman + * \date January, 13, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEPAIRS_H__ +#define __ICEPAIRS_H__ + + //! A generic couple structure + struct ICECORE_API Pair + { + inline_ Pair() {} + inline_ Pair(udword i0, udword i1) : id0(i0), id1(i1) {} + + udword id0; //!< First index of the pair + udword id1; //!< Second index of the pair + }; + + class ICECORE_API Pairs : private Container + { + public: + // Constructor / Destructor + Pairs() {} + ~Pairs() {} + + inline_ udword GetNbPairs() const { return GetNbEntries()>>1; } + inline_ const Pair* GetPairs() const { return (const Pair*)GetEntries(); } + inline_ const Pair* GetPair(udword i) const { return (const Pair*)&GetEntries()[i+i]; } + + inline_ BOOL HasPairs() const { return IsNotEmpty(); } + + inline_ void ResetPairs() { Reset(); } + inline_ void DeleteLastPair() { DeleteLastEntry(); DeleteLastEntry(); } + + inline_ void AddPair(const Pair& p) { Add(p.id0).Add(p.id1); } + inline_ void AddPair(udword id0, udword id1) { Add(id0).Add(id1); } + }; + +#endif // __ICEPAIRS_H__ diff --git a/contrib/Opcode/Ice/IcePlane.cpp b/contrib/Opcode/Ice/IcePlane.cpp new file mode 100644 index 0000000..f198843 --- /dev/null +++ b/contrib/Opcode/Ice/IcePlane.cpp @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for planes. + * \file IcePlane.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * IcePlane class. + * \class IcePlane + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the plane equation from 3 points. + * \param p0 [in] first IcePoint + * \param p1 [in] second IcePoint + * \param p2 [in] third IcePoint + * \return Self-reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +IcePlane& IcePlane::Set(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) +{ + IcePoint Edge0 = p1 - p0; + IcePoint Edge1 = p2 - p0; + + n = Edge0 ^ Edge1; + n.Normalize(); + + d = -(p0 | n); + + return *this; +} diff --git a/contrib/Opcode/Ice/IcePlane.h b/contrib/Opcode/Ice/IcePlane.h new file mode 100644 index 0000000..5c93b90 --- /dev/null +++ b/contrib/Opcode/Ice/IcePlane.h @@ -0,0 +1,113 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for planes. + * \file IcePlane.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEPLANE_H__ +#define __ICEPLANE_H__ + + #define PLANE_EPSILON (1.0e-7f) + + class ICEMATHS_API IcePlane + { + public: + //! Constructor + inline_ IcePlane() { } + //! Constructor from a normal and a distance + inline_ IcePlane(float nx, float ny, float nz, float d) { Set(nx, ny, nz, d); } + //! Constructor from a point on the plane and a normal + inline_ IcePlane(const IcePoint& p, const IcePoint& n) { Set(p, n); } + //! Constructor from three points + inline_ IcePlane(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) { Set(p0, p1, p2); } + //! Constructor from a normal and a distance + inline_ IcePlane(const IcePoint& _n, float _d) { n = _n; d = _d; } + //! Copy constructor + inline_ IcePlane(const IcePlane& plane) : n(plane.n), d(plane.d) { } + //! Destructor + inline_ ~IcePlane() { } + + inline_ IcePlane& Zero() { n.Zero(); d = 0.0f; return *this; } + inline_ IcePlane& Set(float nx, float ny, float nz, float _d) { n.Set(nx, ny, nz); d = _d; return *this; } + inline_ IcePlane& Set(const IcePoint& p, const IcePoint& _n) { n = _n; d = - p | _n; return *this; } + IcePlane& Set(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2); + + inline_ float Distance(const IcePoint& p) const { return (p | n) + d; } + inline_ bool Belongs(const IcePoint& p) const { return fabsf(Distance(p)) < PLANE_EPSILON; } + + inline_ void Normalize() + { + float Denom = 1.0f / n.Magnitude(); + n.x *= Denom; + n.y *= Denom; + n.z *= Denom; + d *= Denom; + } + public: + // Members + IcePoint n; //!< The normal to the plane + float d; //!< The distance from the origin + + // Cast operators + inline_ operator IcePoint() const { return n; } + inline_ operator HPoint() const { return HPoint(n, d); } + + // Arithmetic operators + inline_ IcePlane operator*(const Matrix4x4& m) const + { + // Old code from Irion. Kept for reference. + IcePlane Ret(*this); + return Ret *= m; + } + + inline_ IcePlane& operator*=(const Matrix4x4& m) + { + // Old code from Irion. Kept for reference. + IcePoint n2 = HPoint(n, 0.0f) * m; + d = -((IcePoint) (HPoint( -d*n, 1.0f ) * m) | n2); + n = n2; + return *this; + } + }; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a plane by a 4x4 matrix. Same as IcePlane * Matrix4x4 operator, but faster. + * \param transformed [out] transformed plane + * \param plane [in] source plane + * \param transform [in] transform matrix + * \warning the plane normal must be unit-length + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void TransformPlane(IcePlane& transformed, const IcePlane& plane, const Matrix4x4& transform) + { + // Rotate the normal using the rotation part of the 4x4 matrix + transformed.n = plane.n * Matrix3x3(transform); + + // Compute new d + transformed.d = plane.d - (IcePoint(transform.GetTrans())|transformed.n); + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a plane by a 4x4 matrix. Same as IcePlane * Matrix4x4 operator, but faster. + * \param plane [in/out] source plane (transformed on return) + * \param transform [in] transform matrix + * \warning the plane normal must be unit-length + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void TransformPlane(IcePlane& plane, const Matrix4x4& transform) + { + // Rotate the normal using the rotation part of the 4x4 matrix + plane.n *= Matrix3x3(transform); + + // Compute new d + plane.d -= IcePoint(transform.GetTrans())|plane.n; + } + +#endif // __ICEPLANE_H__ diff --git a/contrib/Opcode/Ice/IcePoint.cpp b/contrib/Opcode/Ice/IcePoint.cpp new file mode 100644 index 0000000..616b08c --- /dev/null +++ b/contrib/Opcode/Ice/IcePoint.cpp @@ -0,0 +1,193 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 3D vectors. + * \file IcePoint.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * 3D point. + * + * The name is "Point" instead of "Vector" since a vector is N-dimensional, whereas a point is an implicit "vector of dimension 3". + * So the choice was between "Point" and "Vector3", the first one looked better (IMHO). + * + * Some people, then, use a typedef to handle both points & vectors using the same class: typedef Point Vector3; + * This is bad since it opens the door to a lot of confusion while reading the code. I know it may sounds weird but check this out: + * + * \code + * Point P0,P1 = some 3D points; + * Point Delta = P1 - P0; + * \endcode + * + * This compiles fine, although you should have written: + * + * \code + * Point P0,P1 = some 3D points; + * Vector3 Delta = P1 - P0; + * \endcode + * + * Subtle things like this are not caught at compile-time, and when you find one in the code, you never know whether it's a mistake + * from the author or something you don't get. + * + * One way to handle it at compile-time would be to use different classes for Point & Vector3, only overloading operator "-" for vectors. + * But then, you get a lot of redundant code in thoses classes, and basically it's really a lot of useless work. + * + * Another way would be to use homogeneous points: w=1 for points, w=0 for vectors. That's why the HPoint class exists. Now, to store + * your model's vertices and in most cases, you really want to use Points to save ram. + * + * \class Point + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Creates a positive unit random vector. + * \return Self-reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +IcePoint& IcePoint::PositiveUnitRandomVector() +{ + x = UnitRandomFloat(); + y = UnitRandomFloat(); + z = UnitRandomFloat(); + Normalize(); + return *this; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Creates a unit random vector. + * \return Self-reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +IcePoint& IcePoint::UnitRandomVector() +{ + x = UnitRandomFloat() - 0.5f; + y = UnitRandomFloat() - 0.5f; + z = UnitRandomFloat() - 0.5f; + Normalize(); + return *this; +} + +// Cast operator +// WARNING: not inlined +IcePoint::operator HPoint() const { return HPoint(x, y, z, 0.0f); } + +IcePoint& IcePoint::Refract(const IcePoint& eye, const IcePoint& n, float refractindex, IcePoint& refracted) +{ + // IcePoint EyePt = eye position + // IcePoint p = current vertex + // IcePoint n = vertex normal + // IcePoint rv = refracted vector + // Eye vector - doesn't need to be normalized + IcePoint Env; + Env.x = eye.x - x; + Env.y = eye.y - y; + Env.z = eye.z - z; + + float NDotE = n|Env; + float NDotN = n|n; + NDotE /= refractindex; + + // Refracted vector + refracted = n*NDotE - Env*NDotN; + + return *this; +} + +IcePoint& IcePoint::ProjectToPlane(const IcePlane& p) +{ + *this-= (p.d + (*this|p.n))*p.n; + return *this; +} + +void IcePoint::ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const +{ + projected = HPoint(x, y, z, 1.0f) * mat; + projected.w = 1.0f / projected.w; + + projected.x*=projected.w; + projected.y*=projected.w; + projected.z*=projected.w; + + projected.x *= halfrenderwidth; projected.x += halfrenderwidth; + projected.y *= -halfrenderheight; projected.y += halfrenderheight; +} + +void IcePoint::SetNotUsed() +{ + // We use a particular integer pattern : 0xffffffff everywhere. This is a NAN. + IR(x) = 0xffffffff; + IR(y) = 0xffffffff; + IR(z) = 0xffffffff; +} + +BOOL IcePoint::IsNotUsed() const +{ + if(IR(x)!=0xffffffff) return FALSE; + if(IR(y)!=0xffffffff) return FALSE; + if(IR(z)!=0xffffffff) return FALSE; + return TRUE; +} + +IcePoint& IcePoint::Mult(const Matrix3x3& mat, const IcePoint& a) +{ + x = a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2]; + y = a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2]; + z = a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2]; + return *this; +} + +IcePoint& IcePoint::Mult2(const Matrix3x3& mat1, const IcePoint& a1, const Matrix3x3& mat2, const IcePoint& a2) +{ + x = a1.x * mat1.m[0][0] + a1.y * mat1.m[0][1] + a1.z * mat1.m[0][2] + a2.x * mat2.m[0][0] + a2.y * mat2.m[0][1] + a2.z * mat2.m[0][2]; + y = a1.x * mat1.m[1][0] + a1.y * mat1.m[1][1] + a1.z * mat1.m[1][2] + a2.x * mat2.m[1][0] + a2.y * mat2.m[1][1] + a2.z * mat2.m[1][2]; + z = a1.x * mat1.m[2][0] + a1.y * mat1.m[2][1] + a1.z * mat1.m[2][2] + a2.x * mat2.m[2][0] + a2.y * mat2.m[2][1] + a2.z * mat2.m[2][2]; + return *this; +} + +IcePoint& IcePoint::Mac(const Matrix3x3& mat, const IcePoint& a) +{ + x += a.x * mat.m[0][0] + a.y * mat.m[0][1] + a.z * mat.m[0][2]; + y += a.x * mat.m[1][0] + a.y * mat.m[1][1] + a.z * mat.m[1][2]; + z += a.x * mat.m[2][0] + a.y * mat.m[2][1] + a.z * mat.m[2][2]; + return *this; +} + +IcePoint& IcePoint::TransMult(const Matrix3x3& mat, const IcePoint& a) +{ + x = a.x * mat.m[0][0] + a.y * mat.m[1][0] + a.z * mat.m[2][0]; + y = a.x * mat.m[0][1] + a.y * mat.m[1][1] + a.z * mat.m[2][1]; + z = a.x * mat.m[0][2] + a.y * mat.m[1][2] + a.z * mat.m[2][2]; + return *this; +} + +IcePoint& IcePoint::Transform(const IcePoint& r, const Matrix3x3& rotpos, const IcePoint& linpos) +{ + x = r.x * rotpos.m[0][0] + r.y * rotpos.m[0][1] + r.z * rotpos.m[0][2] + linpos.x; + y = r.x * rotpos.m[1][0] + r.y * rotpos.m[1][1] + r.z * rotpos.m[1][2] + linpos.y; + z = r.x * rotpos.m[2][0] + r.y * rotpos.m[2][1] + r.z * rotpos.m[2][2] + linpos.z; + return *this; +} + +IcePoint& IcePoint::InvTransform(const IcePoint& r, const Matrix3x3& rotpos, const IcePoint& linpos) +{ + float sx = r.x - linpos.x; + float sy = r.y - linpos.y; + float sz = r.z - linpos.z; + x = sx * rotpos.m[0][0] + sy * rotpos.m[1][0] + sz * rotpos.m[2][0]; + y = sx * rotpos.m[0][1] + sy * rotpos.m[1][1] + sz * rotpos.m[2][1]; + z = sx * rotpos.m[0][2] + sy * rotpos.m[1][2] + sz * rotpos.m[2][2]; + return *this; +} diff --git a/contrib/Opcode/Ice/IcePoint.h b/contrib/Opcode/Ice/IcePoint.h new file mode 100644 index 0000000..2ca1801 --- /dev/null +++ b/contrib/Opcode/Ice/IcePoint.h @@ -0,0 +1,528 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for 3D vectors. + * \file IcePoint.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEPOINT_H__ +#define __ICEPOINT_H__ + + // Forward declarations + class HPoint; + class IcePlane; + class Matrix3x3; + class Matrix4x4; + + #define CROSS2D(a, b) (a.x*b.y - b.x*a.y) + + const float EPSILON2 = 1.0e-20f; + + class ICEMATHS_API IcePoint + { + public: + + //! Empty constructor + inline_ IcePoint() {} + //! Constructor from a single float +// inline_ Point(float val) : x(val), y(val), z(val) {} +// Removed since it introduced the nasty "Point T = *Matrix4x4.GetTrans();" bug....... + //! Constructor from floats + inline_ IcePoint(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {} + //! Constructor from array + inline_ IcePoint(const float f[3]) : x(f[_X]), y(f[_Y]), z(f[_Z]) {} + //! Copy constructor + inline_ IcePoint(const IcePoint& p) : x(p.x), y(p.y), z(p.z) {} + //! Destructor + inline_ ~IcePoint() {} + + //! Clears the vector + inline_ IcePoint& Zero() { x = y = z = 0.0f; return *this; } + + //! + infinity + inline_ IcePoint& SetPlusInfinity() { x = y = z = MAX_FLOAT; return *this; } + //! - infinity + inline_ IcePoint& SetMinusInfinity() { x = y = z = MIN_FLOAT; return *this; } + + //! Sets positive unit random vector + IcePoint& PositiveUnitRandomVector(); + //! Sets unit random vector + IcePoint& UnitRandomVector(); + + //! Assignment from values + inline_ IcePoint& Set(float _x, float _y, float _z) { x = _x; y = _y; z = _z; return *this; } + //! Assignment from array + inline_ IcePoint& Set(const float f[3]) { x = f[_X]; y = f[_Y]; z = f[_Z]; return *this; } + //! Assignment from another point + inline_ IcePoint& Set(const IcePoint& src) { x = src.x; y = src.y; z = src.z; return *this; } + + //! Adds a vector + inline_ IcePoint& Add(const IcePoint& p) { x += p.x; y += p.y; z += p.z; return *this; } + //! Adds a vector + inline_ IcePoint& Add(float _x, float _y, float _z) { x += _x; y += _y; z += _z; return *this; } + //! Adds a vector + inline_ IcePoint& Add(const float f[3]) { x += f[_X]; y += f[_Y]; z += f[_Z]; return *this; } + //! Adds vectors + inline_ IcePoint& Add(const IcePoint& p, const IcePoint& q) { x = p.x+q.x; y = p.y+q.y; z = p.z+q.z; return *this; } + + //! Subtracts a vector + inline_ IcePoint& Sub(const IcePoint& p) { x -= p.x; y -= p.y; z -= p.z; return *this; } + //! Subtracts a vector + inline_ IcePoint& Sub(float _x, float _y, float _z) { x -= _x; y -= _y; z -= _z; return *this; } + //! Subtracts a vector + inline_ IcePoint& Sub(const float f[3]) { x -= f[_X]; y -= f[_Y]; z -= f[_Z]; return *this; } + //! Subtracts vectors + inline_ IcePoint& Sub(const IcePoint& p, const IcePoint& q) { x = p.x-q.x; y = p.y-q.y; z = p.z-q.z; return *this; } + + //! this = -this + inline_ IcePoint& Neg() { x = -x; y = -y; z = -z; return *this; } + //! this = -a + inline_ IcePoint& Neg(const IcePoint& a) { x = -a.x; y = -a.y; z = -a.z; return *this; } + + //! Multiplies by a scalar + inline_ IcePoint& Mult(float s) { x *= s; y *= s; z *= s; return *this; } + + //! this = a * scalar + inline_ IcePoint& Mult(const IcePoint& a, float scalar) + { + x = a.x * scalar; + y = a.y * scalar; + z = a.z * scalar; + return *this; + } + + //! this = a + b * scalar + inline_ IcePoint& Mac(const IcePoint& a, const IcePoint& b, float scalar) + { + x = a.x + b.x * scalar; + y = a.y + b.y * scalar; + z = a.z + b.z * scalar; + return *this; + } + + //! this = this + a * scalar + inline_ IcePoint& Mac(const IcePoint& a, float scalar) + { + x += a.x * scalar; + y += a.y * scalar; + z += a.z * scalar; + return *this; + } + + //! this = a - b * scalar + inline_ IcePoint& Msc(const IcePoint& a, const IcePoint& b, float scalar) + { + x = a.x - b.x * scalar; + y = a.y - b.y * scalar; + z = a.z - b.z * scalar; + return *this; + } + + //! this = this - a * scalar + inline_ IcePoint& Msc(const IcePoint& a, float scalar) + { + x -= a.x * scalar; + y -= a.y * scalar; + z -= a.z * scalar; + return *this; + } + + //! this = a + b * scalarb + c * scalarc + inline_ IcePoint& Mac2(const IcePoint& a, const IcePoint& b, float scalarb, const IcePoint& c, float scalarc) + { + x = a.x + b.x * scalarb + c.x * scalarc; + y = a.y + b.y * scalarb + c.y * scalarc; + z = a.z + b.z * scalarb + c.z * scalarc; + return *this; + } + + //! this = a - b * scalarb - c * scalarc + inline_ IcePoint& Msc2(const IcePoint& a, const IcePoint& b, float scalarb, const IcePoint& c, float scalarc) + { + x = a.x - b.x * scalarb - c.x * scalarc; + y = a.y - b.y * scalarb - c.y * scalarc; + z = a.z - b.z * scalarb - c.z * scalarc; + return *this; + } + + //! this = mat * a + inline_ IcePoint& Mult(const Matrix3x3& mat, const IcePoint& a); + + //! this = mat1 * a1 + mat2 * a2 + inline_ IcePoint& Mult2(const Matrix3x3& mat1, const IcePoint& a1, const Matrix3x3& mat2, const IcePoint& a2); + + //! this = this + mat * a + inline_ IcePoint& Mac(const Matrix3x3& mat, const IcePoint& a); + + //! this = transpose(mat) * a + inline_ IcePoint& TransMult(const Matrix3x3& mat, const IcePoint& a); + + //! Linear interpolate between two vectors: this = a + t * (b - a) + inline_ IcePoint& Lerp(const IcePoint& a, const IcePoint& b, float t) + { + x = a.x + t * (b.x - a.x); + y = a.y + t * (b.y - a.y); + z = a.z + t * (b.z - a.z); + return *this; + } + + //! Hermite interpolate between p1 and p2. p0 and p3 are used for finding gradient at p1 and p2. + //! this = p0 * (2t^2 - t^3 - t)/2 + //! + p1 * (3t^3 - 5t^2 + 2)/2 + //! + p2 * (4t^2 - 3t^3 + t)/2 + //! + p3 * (t^3 - t^2)/2 + inline_ IcePoint& Herp(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2, const IcePoint& p3, float t) + { + float t2 = t * t; + float t3 = t2 * t; + float kp0 = (2.0f * t2 - t3 - t) * 0.5f; + float kp1 = (3.0f * t3 - 5.0f * t2 + 2.0f) * 0.5f; + float kp2 = (4.0f * t2 - 3.0f * t3 + t) * 0.5f; + float kp3 = (t3 - t2) * 0.5f; + x = p0.x * kp0 + p1.x * kp1 + p2.x * kp2 + p3.x * kp3; + y = p0.y * kp0 + p1.y * kp1 + p2.y * kp2 + p3.y * kp3; + z = p0.z * kp0 + p1.z * kp1 + p2.z * kp2 + p3.z * kp3; + return *this; + } + + //! this = rotpos * r + linpos + inline_ IcePoint& Transform(const IcePoint& r, const Matrix3x3& rotpos, const IcePoint& linpos); + + //! this = trans(rotpos) * (r - linpos) + inline_ IcePoint& InvTransform(const IcePoint& r, const Matrix3x3& rotpos, const IcePoint& linpos); + + //! Returns MIN(x, y, z); + inline_ float Min() const { return MIN(x, MIN(y, z)); } + //! Returns MAX(x, y, z); + inline_ float Max() const { return MAX(x, MAX(y, z)); } + //! Sets each element to be componentwise minimum + inline_ IcePoint& Min(const IcePoint& p) { x = MIN(x, p.x); y = MIN(y, p.y); z = MIN(z, p.z); return *this; } + //! Sets each element to be componentwise maximum + inline_ IcePoint& Max(const IcePoint& p) { x = MAX(x, p.x); y = MAX(y, p.y); z = MAX(z, p.z); return *this; } + + //! Clamps each element + inline_ IcePoint& Clamp(float min, float max) + { + if(xmax) x=max; + if(ymax) y=max; + if(zmax) z=max; + return *this; + } + + //! Computes square magnitude + inline_ float SquareMagnitude() const { return x*x + y*y + z*z; } + //! Computes magnitude + inline_ float Magnitude() const { return sqrtf(x*x + y*y + z*z); } + //! Computes volume + inline_ float Volume() const { return x * y * z; } + + //! Checks the IcePoint is near zero + inline_ bool ApproxZero() const { return SquareMagnitude() < EPSILON2; } + + //! Tests for exact zero vector + inline_ BOOL IsZero() const + { + if(IR(x) || IR(y) || IR(z)) return FALSE; + return TRUE; + } + + //! Checks IcePoint validity + inline_ BOOL IsValid() const + { + if(!IsValidFloat(x)) return FALSE; + if(!IsValidFloat(y)) return FALSE; + if(!IsValidFloat(z)) return FALSE; + return TRUE; + } + + //! Slighty moves the IcePoint + void Tweak(udword coord_mask, udword tweak_mask) + { + if(coord_mask&1) { udword Dummy = IR(x); Dummy^=tweak_mask; x = FR(Dummy); } + if(coord_mask&2) { udword Dummy = IR(y); Dummy^=tweak_mask; y = FR(Dummy); } + if(coord_mask&4) { udword Dummy = IR(z); Dummy^=tweak_mask; z = FR(Dummy); } + } + + #define TWEAKMASK 0x3fffff + #define TWEAKNOTMASK ~TWEAKMASK + //! Slighty moves the IcePoint out + inline_ void TweakBigger() + { + udword Dummy = (IR(x)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(x)) Dummy+=TWEAKMASK+1; x = FR(Dummy); + Dummy = (IR(y)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(y)) Dummy+=TWEAKMASK+1; y = FR(Dummy); + Dummy = (IR(z)&TWEAKNOTMASK); if(!IS_NEGATIVE_FLOAT(z)) Dummy+=TWEAKMASK+1; z = FR(Dummy); + } + + //! Slighty moves the IcePoint in + inline_ void TweakSmaller() + { + udword Dummy = (IR(x)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(x)) Dummy+=TWEAKMASK+1; x = FR(Dummy); + Dummy = (IR(y)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(y)) Dummy+=TWEAKMASK+1; y = FR(Dummy); + Dummy = (IR(z)&TWEAKNOTMASK); if(IS_NEGATIVE_FLOAT(z)) Dummy+=TWEAKMASK+1; z = FR(Dummy); + } + + //! Normalizes the vector + inline_ IcePoint& Normalize() + { + float M = x*x + y*y + z*z; + if(M) + { + M = 1.0f / sqrtf(M); + x *= M; + y *= M; + z *= M; + } + return *this; + } + + //! Sets vector length + inline_ IcePoint& SetLength(float length) + { + float NewLength = length / Magnitude(); + x *= NewLength; + y *= NewLength; + z *= NewLength; + return *this; + } + + //! Clamps vector length + inline_ IcePoint& ClampLength(float limit_length) + { + if(limit_length>=0.0f) // Magnitude must be positive + { + float CurrentSquareLength = SquareMagnitude(); + + if(CurrentSquareLength > limit_length * limit_length) + { + float Coeff = limit_length / sqrtf(CurrentSquareLength); + x *= Coeff; + y *= Coeff; + z *= Coeff; + } + } + return *this; + } + + //! Computes distance to another IcePoint + inline_ float Distance(const IcePoint& b) const + { + return sqrtf((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z)); + } + + //! Computes square distance to another IcePoint + inline_ float SquareDistance(const IcePoint& b) const + { + return ((x - b.x)*(x - b.x) + (y - b.y)*(y - b.y) + (z - b.z)*(z - b.z)); + } + + //! Dot product dp = this|a + inline_ float Dot(const IcePoint& p) const { return p.x * x + p.y * y + p.z * z; } + + //! Cross product this = a x b + inline_ IcePoint& Cross(const IcePoint& a, const IcePoint& b) + { + x = a.y * b.z - a.z * b.y; + y = a.z * b.x - a.x * b.z; + z = a.x * b.y - a.y * b.x; + return *this; + } + + //! Vector code ( bitmask = sign(z) | sign(y) | sign(x) ) + inline_ udword VectorCode() const + { + return (IR(x)>>31) | ((IR(y)&SIGN_BITMASK)>>30) | ((IR(z)&SIGN_BITMASK)>>29); + } + + //! Returns largest axis + inline_ PointComponent LargestAxis() const + { + const float* Vals = &x; + PointComponent m = _X; + if(Vals[_Y] > Vals[m]) m = _Y; + if(Vals[_Z] > Vals[m]) m = _Z; + return m; + } + + //! Returns closest axis + inline_ PointComponent ClosestAxis() const + { + const float* Vals = &x; + PointComponent m = _X; + if(AIR(Vals[_Y]) > AIR(Vals[m])) m = _Y; + if(AIR(Vals[_Z]) > AIR(Vals[m])) m = _Z; + return m; + } + + //! Returns smallest axis + inline_ PointComponent SmallestAxis() const + { + const float* Vals = &x; + PointComponent m = _X; + if(Vals[_Y] < Vals[m]) m = _Y; + if(Vals[_Z] < Vals[m]) m = _Z; + return m; + } + + //! Refracts the IcePoint + IcePoint& Refract(const IcePoint& eye, const IcePoint& n, float refractindex, IcePoint& refracted); + + //! Projects the IcePoint onto a plane + IcePoint& ProjectToPlane(const IcePlane& p); + + //! Projects the IcePoint onto the screen + void ProjectToScreen(float halfrenderwidth, float halfrenderheight, const Matrix4x4& mat, HPoint& projected) const; + + //! Unfolds the IcePoint onto a plane according to edge(a,b) + IcePoint& Unfold(IcePlane& p, IcePoint& a, IcePoint& b); + + //! Hash function from Ville Miettinen + inline_ udword GetHashValue() const + { + const udword* h = (const udword*)(this); + udword f = (h[0]+h[1]*11-(h[2]*17)) & 0x7fffffff; // avoid problems with +-0 + return (f>>22)^(f>>12)^(f); + } + + //! Stuff magic values in the IcePoint, marking it as explicitely not used. + void SetNotUsed(); + //! Checks the IcePoint is marked as not used + BOOL IsNotUsed() const; + + // Arithmetic operators + + //! Unary operator for IcePoint Negate = - IcePoint + inline_ IcePoint operator-() const { return IcePoint(-x, -y, -z); } + + //! Operator for IcePoint Plus = IcePoint + IcePoint. + inline_ IcePoint operator+(const IcePoint& p) const { return IcePoint(x + p.x, y + p.y, z + p.z); } + //! Operator for IcePoint Minus = IcePoint - IcePoint. + inline_ IcePoint operator-(const IcePoint& p) const { return IcePoint(x - p.x, y - p.y, z - p.z); } + + //! Operator for IcePoint Mul = IcePoint * IcePoint. + inline_ IcePoint operator*(const IcePoint& p) const { return IcePoint(x * p.x, y * p.y, z * p.z); } + //! Operator for IcePoint Scale = IcePoint * float. + inline_ IcePoint operator*(float s) const { return IcePoint(x * s, y * s, z * s ); } + //! Operator for IcePoint Scale = float * IcePoint. + inline_ friend IcePoint operator*(float s, const IcePoint& p) { return IcePoint(s * p.x, s * p.y, s * p.z); } + + //! Operator for IcePoint Div = IcePoint / IcePoint. + inline_ IcePoint operator/(const IcePoint& p) const { return IcePoint(x / p.x, y / p.y, z / p.z); } + //! Operator for IcePoint Scale = IcePoint / float. + inline_ IcePoint operator/(float s) const { s = 1.0f / s; return IcePoint(x * s, y * s, z * s); } + //! Operator for IcePoint Scale = float / IcePoint. + inline_ friend IcePoint operator/(float s, const IcePoint& p) { return IcePoint(s / p.x, s / p.y, s / p.z); } + + //! Operator for float DotProd = IcePoint | IcePoint. + inline_ float operator|(const IcePoint& p) const { return x*p.x + y*p.y + z*p.z; } + //! Operator for IcePoint VecProd = IcePoint ^ IcePoint. + inline_ IcePoint operator^(const IcePoint& p) const + { + return IcePoint( + y * p.z - z * p.y, + z * p.x - x * p.z, + x * p.y - y * p.x ); + } + + //! Operator for IcePoint += IcePoint. + inline_ IcePoint& operator+=(const IcePoint& p) { x += p.x; y += p.y; z += p.z; return *this; } + //! Operator for IcePoint += float. + inline_ IcePoint& operator+=(float s) { x += s; y += s; z += s; return *this; } + + //! Operator for IcePoint -= IcePoint. + inline_ IcePoint& operator-=(const IcePoint& p) { x -= p.x; y -= p.y; z -= p.z; return *this; } + //! Operator for IcePoint -= float. + inline_ IcePoint& operator-=(float s) { x -= s; y -= s; z -= s; return *this; } + + //! Operator for IcePoint *= IcePoint. + inline_ IcePoint& operator*=(const IcePoint& p) { x *= p.x; y *= p.y; z *= p.z; return *this; } + //! Operator for IcePoint *= float. + inline_ IcePoint& operator*=(float s) { x *= s; y *= s; z *= s; return *this; } + + //! Operator for IcePoint /= IcePoint. + inline_ IcePoint& operator/=(const IcePoint& p) { x /= p.x; y /= p.y; z /= p.z; return *this; } + //! Operator for IcePoint /= float. + inline_ IcePoint& operator/=(float s) { s = 1.0f/s; x *= s; y *= s; z *= s; return *this; } + + // Logical operators + + //! Operator for "if(IcePoint==IcePoint)" + inline_ bool operator==(const IcePoint& p) const { return ( (IR(x)==IR(p.x))&&(IR(y)==IR(p.y))&&(IR(z)==IR(p.z))); } + //! Operator for "if(IcePoint!=IcePoint)" + inline_ bool operator!=(const IcePoint& p) const { return ( (IR(x)!=IR(p.x))||(IR(y)!=IR(p.y))||(IR(z)!=IR(p.z))); } + + // Arithmetic operators + + //! Operator for IcePoint Mul = IcePoint * Matrix3x3. + inline_ IcePoint operator*(const Matrix3x3& mat) const + { + class ShadowMatrix3x3{ public: float m[3][3]; }; // To allow inlining + const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat; + + return IcePoint( + x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0], + x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1], + x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] ); + } + + //! Operator for IcePoint Mul = IcePoint * Matrix4x4. + inline_ IcePoint operator*(const Matrix4x4& mat) const + { + class ShadowMatrix4x4{ public: float m[4][4]; }; // To allow inlining + const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat; + + return IcePoint( + x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0], + x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1], + x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2]); + } + + //! Operator for IcePoint *= Matrix3x3. + inline_ IcePoint& operator*=(const Matrix3x3& mat) + { + class ShadowMatrix3x3{ public: float m[3][3]; }; // To allow inlining + const ShadowMatrix3x3* Mat = (const ShadowMatrix3x3*)&mat; + + float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0]; + float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1]; + float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2]; + + x = xp; y = yp; z = zp; + + return *this; + } + + //! Operator for IcePoint *= Matrix4x4. + inline_ IcePoint& operator*=(const Matrix4x4& mat) + { + class ShadowMatrix4x4{ public: float m[4][4]; }; // To allow inlining + const ShadowMatrix4x4* Mat = (const ShadowMatrix4x4*)&mat; + + float xp = x * Mat->m[0][0] + y * Mat->m[1][0] + z * Mat->m[2][0] + Mat->m[3][0]; + float yp = x * Mat->m[0][1] + y * Mat->m[1][1] + z * Mat->m[2][1] + Mat->m[3][1]; + float zp = x * Mat->m[0][2] + y * Mat->m[1][2] + z * Mat->m[2][2] + Mat->m[3][2]; + + x = xp; y = yp; z = zp; + + return *this; + } + + // Cast operators + + //! Cast a IcePoint to a HPoint. w is set to zero. + operator HPoint() const; + + inline_ operator const float*() const { return &x; } + inline_ operator float*() { return &x; } + + public: + float x, y, z; + }; + + FUNCTION ICEMATHS_API void Normalize1(IcePoint& a); + FUNCTION ICEMATHS_API void Normalize2(IcePoint& a); + +#endif //__ICEPOINT_H__ diff --git a/contrib/Opcode/Ice/IcePreprocessor.h b/contrib/Opcode/Ice/IcePreprocessor.h new file mode 100644 index 0000000..0aaf8f1 --- /dev/null +++ b/contrib/Opcode/Ice/IcePreprocessor.h @@ -0,0 +1,128 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains preprocessor stuff. This should be the first included header. + * \file IcePreprocessor.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICEPREPROCESSOR_H__ +#define __ICEPREPROCESSOR_H__ + + // Check platform + #if defined( _WIN32 ) || defined( WIN32 ) + #pragma message("Compiling on Windows...") + #define PLATFORM_WINDOWS + #else + #pragma message("Compiling on unknown platform...") + #endif + + // Check compiler + #if defined(_MSC_VER) + #pragma message("Compiling with VC++...") + #define COMPILER_VISUAL_CPP + #else + #pragma message("Compiling with unknown compiler...") + #endif + + // Check compiler options. If this file is included in user-apps, this + // shouldn't be needed, so that they can use what they like best. + #ifndef ICE_DONT_CHECK_COMPILER_OPTIONS + #ifdef COMPILER_VISUAL_CPP + #if defined(_CHAR_UNSIGNED) + #endif + + #if defined(_CPPRTTI) + #error Please disable RTTI... + #endif + + #if defined(_CPPUNWIND) + #error Please disable exceptions... + #endif + + #if defined(_MT) + // Multithreading + #endif + #endif + #endif + + // Check debug mode + #ifdef DEBUG // May be defined instead of _DEBUG. Let's fix it. + #ifndef _DEBUG + #define _DEBUG + #endif + #endif + + #ifdef _DEBUG + // Here you may define items for debug builds + #endif + + #ifndef THIS_FILE + #define THIS_FILE __FILE__ + #endif + + #ifndef ICE_NO_DLL + #ifdef ICECORE_EXPORTS + #define ICECORE_API __declspec(dllexport) + #else + #define ICECORE_API __declspec(dllimport) + #endif + #else + #define ICECORE_API + #endif + + // Don't override new/delete +// #define DEFAULT_NEWDELETE + #define DONT_TRACK_MEMORY_LEAKS + + #define FUNCTION extern "C" + + // Cosmetic stuff [mainly useful with multiple inheritance] + #define override(base_class) virtual + + // Our own inline keyword, so that: + // - we can switch to __forceinline to check it's really better or not + // - we can remove __forceinline if the compiler doesn't support it +// #define inline_ __forceinline +// #define inline_ inline + + // Contributed by Bruce Mitchener + #if defined(COMPILER_VISUAL_CPP) + #define inline_ __forceinline +// #define inline_ inline + #elif defined(__GNUC__) && __GNUC__ < 3 + #define inline_ inline + #elif defined(__GNUC__) + #define inline_ inline __attribute__ ((always_inline)) + #else + #define inline_ inline + #endif + + // Down the hatch + #pragma inline_depth( 255 ) + + #ifdef COMPILER_VISUAL_CPP + #pragma intrinsic(memcmp) + #pragma intrinsic(memcpy) + #pragma intrinsic(memset) + #pragma intrinsic(strcat) + #pragma intrinsic(strcmp) + #pragma intrinsic(strcpy) + #pragma intrinsic(strlen) + #pragma intrinsic(abs) + #pragma intrinsic(labs) + #endif + + // ANSI compliance + #ifdef _DEBUG + // Remove painful warning in debug + inline_ bool __False__(){ return false; } + #define for if(__False__()){} else for + #else + #define for if(0){} else for + #endif + +#endif // __ICEPREPROCESSOR_H__ diff --git a/contrib/Opcode/Ice/IceRandom.cpp b/contrib/Opcode/Ice/IceRandom.cpp new file mode 100644 index 0000000..305721d --- /dev/null +++ b/contrib/Opcode/Ice/IceRandom.cpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for random generators. + * \file IceRandom.cpp + * \author Pierre Terdiman + * \date August, 9, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceCore; + +void IceCore:: SRand(udword seed) +{ + srand(seed); +} + +udword IceCore::Rand() +{ + return rand(); +} + + +static BasicRandom gRandomGenerator(42); + +udword IceCore::GetRandomIndex(udword max_index) +{ + // We don't use rand() since it's limited to RAND_MAX + udword Index = gRandomGenerator.Randomize(); + return Index % max_index; +} + diff --git a/contrib/Opcode/Ice/IceRandom.h b/contrib/Opcode/Ice/IceRandom.h new file mode 100644 index 0000000..3170b33 --- /dev/null +++ b/contrib/Opcode/Ice/IceRandom.h @@ -0,0 +1,42 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for random generators. + * \file IceRandom.h + * \author Pierre Terdiman + * \date August, 9, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICERANDOM_H__ +#define __ICERANDOM_H__ + + FUNCTION ICECORE_API void SRand(udword seed); + FUNCTION ICECORE_API udword Rand(); + + //! Returns a unit random floating-point value + inline_ float UnitRandomFloat() { return float(Rand()) * ONE_OVER_RAND_MAX; } + + //! Returns a random index so that 0<= index < max_index + ICECORE_API udword GetRandomIndex(udword max_index); + + class ICECORE_API BasicRandom + { + public: + + //! Constructor + inline_ BasicRandom(udword seed=0) : mRnd(seed) {} + //! Destructor + inline_ ~BasicRandom() {} + + inline_ void SetSeed(udword seed) { mRnd = seed; } + inline_ udword GetCurrentValue() const { return mRnd; } + inline_ udword Randomize() { mRnd = mRnd * 2147001325 + 715136305; return mRnd; } + + private: + udword mRnd; + }; + +#endif // __ICERANDOM_H__ + diff --git a/contrib/Opcode/Ice/IceRay.cpp b/contrib/Opcode/Ice/IceRay.cpp new file mode 100644 index 0000000..d7c617a --- /dev/null +++ b/contrib/Opcode/Ice/IceRay.cpp @@ -0,0 +1,84 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for rays. + * \file IceRay.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Ray class. + * A ray is a half-line P(t) = mOrig + mDir * t, with 0 <= t <= +infinity + * \class Ray + * \author Pierre Terdiman + * \version 1.0 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* + O = Origin = impact IcePoint + i = normalized vector along the x axis + j = normalized vector along the y axis = actually the normal vector in O + D = Direction vector, norm |D| = 1 + N = Projection of D on y axis, norm |N| = normal reaction + T = Projection of D on x axis, norm |T| = tangential reaction + R = Reflexion vector + + ^y + | + | + | + _ _ _| _ _ _ + * * *| + \ | / + \ |N / | + R\ | /D + \ | / | + \ | / + _________\|/______*_______>x + O T + + Let define theta = angle between D and N. Then cos(theta) = |N| / |D| = |N| since D is normalized. + + j|D = |j|*|D|*cos(theta) => |N| = j|D + + Then we simply have: + + D = N + T + + To compute tangential reaction : + + T = D - N + + To compute reflexion vector : + + R = N - T = N - (D-N) = 2*N - D +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +float Ray::SquareDistance(const IcePoint& Point, float* t) const +{ + IcePoint Diff = Point - mOrig; + float fT = Diff | mDir; + + if(fT<=0.0f) + { + fT = 0.0f; + } + else + { + fT /= mDir.SquareMagnitude(); + Diff -= fT*mDir; + } + + if(t) *t = fT; + + return Diff.SquareMagnitude(); +} diff --git a/contrib/Opcode/Ice/IceRay.h b/contrib/Opcode/Ice/IceRay.h new file mode 100644 index 0000000..4c0d6d9 --- /dev/null +++ b/contrib/Opcode/Ice/IceRay.h @@ -0,0 +1,98 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for rays. + * \file IceRay.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICERAY_H__ +#define __ICERAY_H__ + + class ICEMATHS_API Ray + { + public: + //! Constructor + inline_ Ray() {} + //! Constructor + inline_ Ray(const IcePoint& orig, const IcePoint& dir) : mOrig(orig), mDir(dir) {} + //! Copy constructor + inline_ Ray(const Ray& ray) : mOrig(ray.mOrig), mDir(ray.mDir) {} + //! Destructor + inline_ ~Ray() {} + + float SquareDistance(const IcePoint& point, float* t=null) const; + inline_ float Distance(const IcePoint& point, float* t=null) const { return sqrtf(SquareDistance(point, t)); } + + IcePoint mOrig; //!< Ray origin + IcePoint mDir; //!< Normalized direction + }; + + inline_ void ComputeReflexionVector(IcePoint& reflected, const IcePoint& incoming_dir, const IcePoint& outward_normal) + { + reflected = incoming_dir - outward_normal * 2.0f * (incoming_dir|outward_normal); + } + + inline_ void ComputeReflexionVector(IcePoint& reflected, const IcePoint& source, const IcePoint& impact, const IcePoint& normal) + { + IcePoint V = impact - source; + reflected = V - normal * 2.0f * (V|normal); + } + + inline_ void DecomposeVector(IcePoint& normal_compo, IcePoint& tangent_compo, const IcePoint& outward_dir, const IcePoint& outward_normal) + { + normal_compo = outward_normal * (outward_dir|outward_normal); + tangent_compo = outward_dir - normal_compo; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a direction vector from world space to local space + * \param local_dir [out] direction vector in local space + * \param world_dir [in] direction vector in world space + * \param world [in] world transform + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void ComputeLocalDirection(IcePoint& local_dir, const IcePoint& world_dir, const Matrix4x4& world) + { + // Get world direction back in local space +// Matrix3x3 InvWorld = world; +// local_dir = InvWorld * world_dir; + local_dir = Matrix3x3(world) * world_dir; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a position vector from world space to local space + * \param local_pt [out] position vector in local space + * \param world_pt [in] position vector in world space + * \param world [in] world transform + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void ComputeLocalPoint(IcePoint& local_pt, const IcePoint& world_pt, const Matrix4x4& world) + { + // Get world vertex back in local space + Matrix4x4 InvWorld = world; + InvWorld.Invert(); + local_pt = world_pt * InvWorld; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Transforms a ray from world space to local space + * \param local_ray [out] ray in local space + * \param world_ray [in] ray in world space + * \param world [in] world transform + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void ComputeLocalRay(Ray& local_ray, const Ray& world_ray, const Matrix4x4& world) + { + // Get world ray back in local space + ComputeLocalDirection(local_ray.mDir, world_ray.mDir, world); + ComputeLocalPoint(local_ray.mOrig, world_ray.mOrig, world); + } + +#endif // __ICERAY_H__ diff --git a/contrib/Opcode/Ice/IceRevisitedRadix.cpp b/contrib/Opcode/Ice/IceRevisitedRadix.cpp new file mode 100644 index 0000000..b654995 --- /dev/null +++ b/contrib/Opcode/Ice/IceRevisitedRadix.cpp @@ -0,0 +1,520 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains source code from the article "Radix Sort Revisited". + * \file IceRevisitedRadix.cpp + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Revisited Radix Sort. + * This is my new radix routine: + * - it uses indices and doesn't recopy the values anymore, hence wasting less ram + * - it creates all the histograms in one run instead of four + * - it sorts words faster than dwords and bytes faster than words + * - it correctly sorts negative floating-point values by patching the offsets + * - it automatically takes advantage of temporal coherence + * - multiple keys support is a side effect of temporal coherence + * - it may be worth recoding in asm... (mainly to use FCOMI, FCMOV, etc) [it's probably memory-bound anyway] + * + * History: + * - 08.15.98: very first version + * - 04.04.00: recoded for the radix article + * - 12.xx.00: code lifting + * - 09.18.01: faster CHECK_PASS_VALIDITY thanks to Mark D. Shattuck (who provided other tips, not included here) + * - 10.11.01: added local ram support + * - 01.20.02: bugfix! In very particular cases the last pass was skipped in the float code-path, leading to incorrect sorting...... + * - 01.02.02: - "mIndices" renamed => "mRanks". That's a rank sorter after all. + * - ranks are not "reset" anymore, but implicit on first calls + * - 07.05.02: - offsets rewritten with one less indirection. + * - 11.03.02: - "bool" replaced with RadixHint enum + * + * \class RadixSort + * \author Pierre Terdiman + * \version 1.4 + * \date August, 15, 1998 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* +To do: + - add an offset parameter between two input values (avoid some data recopy sometimes) + - unroll ? asm ? + - 11 bits trick & 3 passes as Michael did + - prefetch stuff the day I have a P3 + - make a version with 16-bits indices ? +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceCore; + +#define INVALIDATE_RANKS mCurrentSize|=0x80000000 +#define VALIDATE_RANKS mCurrentSize&=0x7fffffff +#define CURRENT_SIZE (mCurrentSize&0x7fffffff) +#define INVALID_RANKS (mCurrentSize&0x80000000) + +#define CHECK_RESIZE(n) \ + if(n!=mPreviousSize) \ + { \ + if(n>mCurrentSize) Resize(n); \ + else ResetRanks(); \ + mPreviousSize = n; \ + } + +#define CREATE_HISTOGRAMS(type, buffer) \ + /* Clear counters/histograms */ \ + ZeroMemory(mHistogram, 256*4*sizeof(udword)); \ + \ + /* Prepare to count */ \ + ubyte* p = (ubyte*)input; \ + ubyte* pe = &p[nb*4]; \ + udword* h0= &mHistogram[0]; /* Histogram for first pass (LSB) */ \ + udword* h1= &mHistogram[256]; /* Histogram for second pass */ \ + udword* h2= &mHistogram[512]; /* Histogram for third pass */ \ + udword* h3= &mHistogram[768]; /* Histogram for last pass (MSB) */ \ + \ + bool AlreadySorted = true; /* Optimism... */ \ + \ + if(INVALID_RANKS) \ + { \ + /* Prepare for temporal coherence */ \ + type* Running = (type*)buffer; \ + type PrevVal = *Running; \ + \ + while(p!=pe) \ + { \ + /* Read input buffer in previous sorted order */ \ + type Val = *Running++; \ + /* Check whether already sorted or not */ \ + if(ValCurSize) Resize(nb); + mCurrentSize = nb; + INVALIDATE_RANKS; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Main sort routine. + * This one is for integer values. After the call, mRanks contains a list of indices in sorted order, i.e. in the order you may process your data. + * \param input [in] a list of integer values to sort + * \param nb [in] number of values to sort, must be < 2^31 + * \param hint [in] RADIX_SIGNED to handle negative values, RADIX_UNSIGNED if you know your input buffer only contains positive values + * \return Self-Reference + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RadixSort& RadixSort::Sort(const udword* input, udword nb, RadixHint hint) +{ + // Checkings + if(!input || !nb || nb&0x80000000) return *this; + + // Stats + mTotalCalls++; + + // Resize lists if needed + CheckResize(nb); + +#ifdef RADIX_LOCAL_RAM + // Allocate histograms & offsets on the stack + udword mHistogram[256*4]; +// udword mOffset[256]; + udword* mLink[256]; +#endif + + // Create histograms (counters). Counters for all passes are created in one run. + // Pros: read input buffer once instead of four times + // Cons: mHistogram is 4Kb instead of 1Kb + // We must take care of signed/unsigned values for temporal coherence.... I just + // have 2 code paths even if just a single opcode changes. Self-modifying code, someone? + if(hint==RADIX_UNSIGNED) { CREATE_HISTOGRAMS(udword, input); } + else { CREATE_HISTOGRAMS(sdword, input); } + + // Compute #negative values involved if needed + udword NbNegativeValues = 0; + if(hint==RADIX_SIGNED) + { + // An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128 + // last values of the last histogram. Last histogram because that's the one for the Most Significant Byte, + // responsible for the sign. 128 last values because the 128 first ones are related to positive numbers. + udword* h3= &mHistogram[768]; + for(udword i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part + } + + // Radix sort, j is the pass number (0=LSB, 3=MSB) + for(udword j=0;j<4;j++) + { + CHECK_PASS_VALIDITY(j); + + // Sometimes the fourth (negative) pass is skipped because all numbers are negative and the MSB is 0xFF (for example). This is + // not a problem, numbers are correctly sorted anyway. + if(PerformPass) + { + // Should we care about negative values? + if(j!=3 || hint==RADIX_UNSIGNED) + { + // Here we deal with positive values only + + // Create offsets +// mOffset[0] = 0; +// for(udword i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; + mLink[0] = mRanks2; + for(udword i=1;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; + } + else + { + // This is a special case to correctly handle negative integers. They're sorted in the right order but at the wrong place. + + // Create biased offsets, in order for negative numbers to be sorted as well +// mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones + mLink[0] = &mRanks2[NbNegativeValues]; // First positive number takes place after the negative ones +// for(udword i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers + for(udword i=1;i<128;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers + + // Fixing the wrong place for negative values +// mOffset[128] = 0; + mLink[128] = mRanks2; +// for(i=129;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; + for(udword i=129;i<256;i++) mLink[i] = mLink[i-1] + CurCount[i-1]; + } + + // Perform Radix Sort + ubyte* InputBytes = (ubyte*)input; + InputBytes += j; + if(INVALID_RANKS) + { +// for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword). + // ### cmp to be killed. Not good. Later. +// if(Radix<128) mRanks2[mOffset[Radix]++] = i; // Number is positive, same as above +// else mRanks2[--mOffset[Radix]] = i; // Number is negative, flip the sorting order + if(Radix<128) *mLink[Radix]++ = i; // Number is positive, same as above + else *(--mLink[Radix]) = i; // Number is negative, flip the sorting order + } + VALIDATE_RANKS; + } + else + { + for(udword i=0;i>24; // Radix byte, same as above. AND is useless here (udword). + // ### cmp to be killed. Not good. Later. +// if(Radix<128) mRanks2[mOffset[Radix]++] = mRanks[i]; // Number is positive, same as above +// else mRanks2[--mOffset[Radix]] = mRanks[i]; // Number is negative, flip the sorting order + if(Radix<128) *mLink[Radix]++ = mRanks[i]; // Number is positive, same as above + else *(--mLink[Radix]) = mRanks[i]; // Number is negative, flip the sorting order + } + } + // Swap pointers for next pass. Valid indices - the most recent ones - are in mRanks after the swap. + udword* Tmp = mRanks; mRanks = mRanks2; mRanks2 = Tmp; + } + else + { + // The pass is useless, yet we still have to reverse the order of current list if all values are negative. + if(UniqueVal>=128) + { + if(INVALID_RANKS) + { + // ###Possible? + for(udword i=0;i=SqrLen) + { + fT = 1.0f; + Diff -= Dir; + } + else + { + fT /= SqrLen; + Diff -= fT*Dir; + } + } + + if(t) *t = fT; + + return Diff.SquareMagnitude(); +} diff --git a/contrib/Opcode/Ice/IceSegment.h b/contrib/Opcode/Ice/IceSegment.h new file mode 100644 index 0000000..72ddceb --- /dev/null +++ b/contrib/Opcode/Ice/IceSegment.h @@ -0,0 +1,55 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for segments. + * \file IceSegment.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICESEGMENT_H__ +#define __ICESEGMENT_H__ + + class ICEMATHS_API IceSegment + { + public: + //! Constructor + inline_ IceSegment() {} + //! Constructor + inline_ IceSegment(const IcePoint& p0, const IcePoint& p1) : mP0(p0), mP1(p1) {} + //! Copy constructor + inline_ IceSegment(const IceSegment& seg) : mP0(seg.mP0), mP1(seg.mP1) {} + //! Destructor + inline_ ~IceSegment() {} + + inline_ const IcePoint& GetOrigin() const { return mP0; } + inline_ IcePoint ComputeDirection() const { return mP1 - mP0; } + inline_ void ComputeDirection(IcePoint& dir) const { dir = mP1 - mP0; } + inline_ float ComputeLength() const { return mP1.Distance(mP0); } + inline_ float ComputeSquareLength() const { return mP1.SquareDistance(mP0); } + + inline_ void SetOriginDirection(const IcePoint& origin, const IcePoint& direction) + { + mP0 = mP1 = origin; + mP1 += direction; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Computes a IcePoint on the segment + * \param pt [out] IcePoint on segment + * \param t [in] IcePoint's parameter [t=0 => pt = mP0, t=1 => pt = mP1] + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void ComputePoint(IcePoint& pt, float t) const { pt = mP0 + t * (mP1 - mP0); } + + float SquareDistance(const IcePoint& IcePoint, float* t=null) const; + inline_ float Distance(const IcePoint& IcePoint, float* t=null) const { return sqrtf(SquareDistance(IcePoint, t)); } + + IcePoint mP0; //!< Start of segment + IcePoint mP1; //!< End of segment + }; + +#endif // __ICESEGMENT_H__ diff --git a/contrib/Opcode/Ice/IceTriangle.cpp b/contrib/Opcode/Ice/IceTriangle.cpp new file mode 100644 index 0000000..e55f73e --- /dev/null +++ b/contrib/Opcode/Ice/IceTriangle.cpp @@ -0,0 +1,286 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a handy triangle class. + * \file IceTriangle.cpp + * \author Pierre Terdiman + * \date January, 17, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace IceMaths; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a triangle class. + * + * \class Tri + * \author Pierre Terdiman + * \version 1.0 + * \date 08.15.98 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static sdword VPlaneSideEps(const IcePoint& v, const IcePlane& plane, float epsilon) +{ + // Compute distance from current vertex to the plane + float Dist = plane.Distance(v); + // Compute side: + // 1 = the vertex is on the positive side of the plane + // -1 = the vertex is on the negative side of the plane + // 0 = the vertex is on the plane (within epsilon) + return Dist > epsilon ? 1 : Dist < -epsilon ? -1 : 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Flips the winding order. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::Flip() +{ + IcePoint Tmp = mVerts[1]; + mVerts[1] = mVerts[2]; + mVerts[2] = Tmp; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle area. + * \return the area + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::Area() const +{ + const IcePoint& p0 = mVerts[0]; + const IcePoint& p1 = mVerts[1]; + const IcePoint& p2 = mVerts[2]; + return ((p0 - p1)^(p0 - p2)).Magnitude() * 0.5f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle perimeter. + * \return the perimeter + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::Perimeter() const +{ + const IcePoint& p0 = mVerts[0]; + const IcePoint& p1 = mVerts[1]; + const IcePoint& p2 = mVerts[2]; + return p0.Distance(p1) + + p0.Distance(p2) + + p1.Distance(p2); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle compacity. + * \return the compacity + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::Compacity() const +{ + float P = Perimeter(); + if(P==0.0f) return 0.0f; + return (4.0f*PI*Area()/(P*P)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle normal. + * \param normal [out] the computed normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::Normal(IcePoint& normal) const +{ + const IcePoint& p0 = mVerts[0]; + const IcePoint& p1 = mVerts[1]; + const IcePoint& p2 = mVerts[2]; + normal = ((p0 - p1)^(p0 - p2)).Normalize(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle denormalized normal. + * \param normal [out] the computed normal + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::DenormalizedNormal(IcePoint& normal) const +{ + const IcePoint& p0 = mVerts[0]; + const IcePoint& p1 = mVerts[1]; + const IcePoint& p2 = mVerts[2]; + normal = ((p0 - p1)^(p0 - p2)); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle center. + * \param center [out] the computed center + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::Center(IcePoint& center) const +{ + const IcePoint& p0 = mVerts[0]; + const IcePoint& p1 = mVerts[1]; + const IcePoint& p2 = mVerts[2]; + center = (p0 + p1 + p2)*INV3; +} + +PartVal Triangle::TestAgainstPlane(const IcePlane& plane, float epsilon) const +{ + bool Pos = false, Neg = false; + + // Loop through all vertices + for(udword i=0;i<3;i++) + { + // Compute side: + sdword Side = VPlaneSideEps(mVerts[i], plane, epsilon); + + if (Side < 0) Neg = true; + else if (Side > 0) Pos = true; + } + + if (!Pos && !Neg) return TRI_ON_PLANE; + else if (Pos && Neg) return TRI_INTERSECT; + else if (Pos && !Neg) return TRI_PLUS_SPACE; + else if (!Pos && Neg) return TRI_MINUS_SPACE; + + // What?! + return TRI_FORCEDWORD; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle moment. + * \param m [out] the moment + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* +void Triangle::ComputeMoment(Moment& m) +{ + // Compute the area of the triangle + m.mArea = Area(); + + // Compute the centroid + Center(m.mCentroid); + + // Second-order components. Handle zero-area faces. + IcePoint& p = mVerts[0]; + IcePoint& q = mVerts[1]; + IcePoint& r = mVerts[2]; + if(m.mArea==0.0f) + { + // This triangle has zero area. The second order components would be eliminated with the usual formula, so, for the + // sake of robustness we use an alternative form. These are the centroid and second-order components of the triangle's vertices. + m.mCovariance.m[0][0] = (p.x*p.x + q.x*q.x + r.x*r.x); + m.mCovariance.m[0][1] = (p.x*p.y + q.x*q.y + r.x*r.y); + m.mCovariance.m[0][2] = (p.x*p.z + q.x*q.z + r.x*r.z); + m.mCovariance.m[1][1] = (p.y*p.y + q.y*q.y + r.y*r.y); + m.mCovariance.m[1][2] = (p.y*p.z + q.y*q.z + r.y*r.z); + m.mCovariance.m[2][2] = (p.z*p.z + q.z*q.z + r.z*r.z); + m.mCovariance.m[2][1] = m.mCovariance.m[1][2]; + m.mCovariance.m[1][0] = m.mCovariance.m[0][1]; + m.mCovariance.m[2][0] = m.mCovariance.m[0][2]; + } + else + { + const float OneOverTwelve = 1.0f / 12.0f; + m.mCovariance.m[0][0] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.x + p.x*p.x + q.x*q.x + r.x*r.x) * OneOverTwelve; + m.mCovariance.m[0][1] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.y + p.x*p.y + q.x*q.y + r.x*r.y) * OneOverTwelve; + m.mCovariance.m[1][1] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.y + p.y*p.y + q.y*q.y + r.y*r.y) * OneOverTwelve; + m.mCovariance.m[0][2] = m.mArea * (9.0f * m.mCentroid.x*m.mCentroid.z + p.x*p.z + q.x*q.z + r.x*r.z) * OneOverTwelve; + m.mCovariance.m[1][2] = m.mArea * (9.0f * m.mCentroid.y*m.mCentroid.z + p.y*p.z + q.y*q.z + r.y*r.z) * OneOverTwelve; + m.mCovariance.m[2][2] = m.mArea * (9.0f * m.mCentroid.z*m.mCentroid.z + p.z*p.z + q.z*q.z + r.z*r.z) * OneOverTwelve; + m.mCovariance.m[2][1] = m.mCovariance.m[1][2]; + m.mCovariance.m[1][0] = m.mCovariance.m[0][1]; + m.mCovariance.m[2][0] = m.mCovariance.m[0][2]; + } +} +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle's smallest edge length. + * \return the smallest edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::MinEdgeLength() const +{ + float Min = MAX_FLOAT; + float Length01 = mVerts[0].Distance(mVerts[1]); + float Length02 = mVerts[0].Distance(mVerts[2]); + float Length12 = mVerts[1].Distance(mVerts[2]); + if(Length01 < Min) Min = Length01; + if(Length02 < Min) Min = Length02; + if(Length12 < Min) Min = Length12; + return Min; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the triangle's largest edge length. + * \return the largest edge length + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float Triangle::MaxEdgeLength() const +{ + float Max = MIN_FLOAT; + float Length01 = mVerts[0].Distance(mVerts[1]); + float Length02 = mVerts[0].Distance(mVerts[2]); + float Length12 = mVerts[1].Distance(mVerts[2]); + if(Length01 > Max) Max = Length01; + if(Length02 > Max) Max = Length02; + if(Length12 > Max) Max = Length12; + return Max; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a IcePoint on the triangle according to the stabbing information. + * \param u,v [in] IcePoint's barycentric coordinates + * \param pt [out] IcePoint on triangle + * \param nearvtx [out] index of nearest vertex + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Triangle::ComputePoint(float u, float v, IcePoint& pt, udword* nearvtx) const +{ + // Compute IcePoint coordinates + pt = (1.0f - u - v)*mVerts[0] + u*mVerts[1] + v*mVerts[2]; + + // Compute nearest vertex if needed + if(nearvtx) + { + // Compute distance vector + IcePoint d(mVerts[0].SquareDistance(pt), // Distance^2 from vertex 0 to IcePoint on the face + mVerts[1].SquareDistance(pt), // Distance^2 from vertex 1 to IcePoint on the face + mVerts[2].SquareDistance(pt)); // Distance^2 from vertex 2 to IcePoint on the face + + // Get smallest distance + *nearvtx = d.SmallestAxis(); + } +} + +void Triangle::Inflate(float fat_coeff, bool constant_border) +{ + // Compute triangle center + IcePoint TriangleCenter; + Center(TriangleCenter); + + // Don't normalize? + // Normalize => add a constant border, regardless of triangle size + // Don't => add more to big triangles + for(udword i=0;i<3;i++) + { + IcePoint v = mVerts[i] - TriangleCenter; + + if(constant_border) v.Normalize(); + + mVerts[i] += v * fat_coeff; + } +} diff --git a/contrib/Opcode/Ice/IceTriangle.h b/contrib/Opcode/Ice/IceTriangle.h new file mode 100644 index 0000000..e5c8426 --- /dev/null +++ b/contrib/Opcode/Ice/IceTriangle.h @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a handy triangle class. + * \file IceTriangle.h + * \author Pierre Terdiman + * \date January, 17, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICETRIANGLE_H__ +#define __ICETRIANGLE_H__ + + // Forward declarations + class Moment; + + // Partitioning values + enum PartVal + { + TRI_MINUS_SPACE = 0, //!< Triangle is in the negative space + TRI_PLUS_SPACE = 1, //!< Triangle is in the positive space + TRI_INTERSECT = 2, //!< Triangle intersects plane + TRI_ON_PLANE = 3, //!< Triangle and plane are coplanar + + TRI_FORCEDWORD = 0x7fffffff + }; + + // A triangle class. + class ICEMATHS_API Triangle + { + public: + //! Constructor + inline_ Triangle() {} + //! Constructor + inline_ Triangle(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) { mVerts[0]=p0; mVerts[1]=p1; mVerts[2]=p2; } + //! Copy constructor + inline_ Triangle(const Triangle& triangle) + { + mVerts[0] = triangle.mVerts[0]; + mVerts[1] = triangle.mVerts[1]; + mVerts[2] = triangle.mVerts[2]; + } + //! Destructor + inline_ ~Triangle() {} + //! Vertices + IcePoint mVerts[3]; + + // Methods + void Flip(); + float Area() const; + float Perimeter() const; + float Compacity() const; + void Normal(IcePoint& normal) const; + void DenormalizedNormal(IcePoint& normal) const; + void Center(IcePoint& center) const; + inline_ IcePlane PlaneEquation() const { return IcePlane(mVerts[0], mVerts[1], mVerts[2]); } + + PartVal TestAgainstPlane(const IcePlane& plane, float epsilon) const; +// float Distance(Point& cp, Point& cq, Tri& tri); + void ComputeMoment(Moment& m); + float MinEdgeLength() const; + float MaxEdgeLength() const; + void ComputePoint(float u, float v, IcePoint& pt, udword* nearvtx=null) const; + void Inflate(float fat_coeff, bool constant_border); + }; + +#endif // __ICETRIANGLE_H__ diff --git a/contrib/Opcode/Ice/IceTrilist.h b/contrib/Opcode/Ice/IceTrilist.h new file mode 100644 index 0000000..057f8df --- /dev/null +++ b/contrib/Opcode/Ice/IceTrilist.h @@ -0,0 +1,61 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a triangle container. + * \file IceTrilist.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICETRILIST_H__ +#define __ICETRILIST_H__ + + class ICEMATHS_API TriList : public Container + { + public: + // Constructor / Destructor + TriList() {} + ~TriList() {} + + inline_ udword GetNbTriangles() const { return GetNbEntries()/9; } + inline_ Triangle* GetTriangles() const { return (Triangle*)GetEntries(); } + + void AddTri(const Triangle& tri) + { + Add(tri.mVerts[0].x).Add(tri.mVerts[0].y).Add(tri.mVerts[0].z); + Add(tri.mVerts[1].x).Add(tri.mVerts[1].y).Add(tri.mVerts[1].z); + Add(tri.mVerts[2].x).Add(tri.mVerts[2].y).Add(tri.mVerts[2].z); + } + + void AddTri(const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) + { + Add(p0.x).Add(p0.y).Add(p0.z); + Add(p1.x).Add(p1.y).Add(p1.z); + Add(p2.x).Add(p2.y).Add(p2.z); + } + }; + + class ICEMATHS_API TriangleList : public Container + { + public: + // Constructor / Destructor + TriangleList() {} + ~TriangleList() {} + + inline_ udword GetNbTriangles() const { return GetNbEntries()/3; } + inline_ IndexedTriangle* GetTriangles() const { return (IndexedTriangle*)GetEntries();} + + void AddTriangle(const IndexedTriangle& tri) + { + Add(tri.mVRef[0]).Add(tri.mVRef[1]).Add(tri.mVRef[2]); + } + + void AddTriangle(udword vref0, udword vref1, udword vref2) + { + Add(vref0).Add(vref1).Add(vref2); + } + }; + +#endif //__ICETRILIST_H__ diff --git a/contrib/Opcode/Ice/IceTypes.h b/contrib/Opcode/Ice/IceTypes.h new file mode 100644 index 0000000..543be11 --- /dev/null +++ b/contrib/Opcode/Ice/IceTypes.h @@ -0,0 +1,157 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains custom types. + * \file IceTypes.h + * \author Pierre Terdiman + * \date April, 4, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __ICETYPES_H__ +#define __ICETYPES_H__ + + #define USE_HANDLE_MANAGER + + // Constants + #define PI 3.1415926535897932384626433832795028841971693993751f //!< PI + #define HALFPI 1.57079632679489661923f //!< 0.5 * PI + #define TWOPI 6.28318530717958647692f //!< 2.0 * PI + #define INVPI 0.31830988618379067154f //!< 1.0 / PI + + #define RADTODEG 57.2957795130823208768f //!< 180.0 / PI, convert radians to degrees + #define DEGTORAD 0.01745329251994329577f //!< PI / 180.0, convert degrees to radians + + #define EXP 2.71828182845904523536f //!< e + #define INVLOG2 3.32192809488736234787f //!< 1.0 / log10(2) + #define LN2 0.693147180559945f //!< ln(2) + #define INVLN2 1.44269504089f //!< 1.0f / ln(2) + + #define INV3 0.33333333333333333333f //!< 1/3 + #define INV6 0.16666666666666666666f //!< 1/6 + #define INV7 0.14285714285714285714f //!< 1/7 + #define INV9 0.11111111111111111111f //!< 1/9 + #define INV255 0.00392156862745098039f //!< 1/255 + + #define SQRT2 1.41421356237f //!< sqrt(2) + #define INVSQRT2 0.707106781188f //!< 1 / sqrt(2) + + #define SQRT3 1.73205080757f //!< sqrt(3) + #define INVSQRT3 0.577350269189f //!< 1 / sqrt(3) + + #define null 0 //!< our own NULL pointer + + // Custom types used in ICE + typedef signed char sbyte; //!< sizeof(sbyte) must be 1 + typedef unsigned char ubyte; //!< sizeof(ubyte) must be 1 + typedef signed short sword; //!< sizeof(sword) must be 2 + typedef unsigned short uword; //!< sizeof(uword) must be 2 + typedef signed int sdword; //!< sizeof(sdword) must be 4 + typedef unsigned int udword; //!< sizeof(udword) must be 4 + typedef signed __int64 sqword; //!< sizeof(sqword) must be 8 + typedef unsigned __int64 uqword; //!< sizeof(uqword) must be 8 + typedef float float32; //!< sizeof(float32) must be 4 + typedef double float64; //!< sizeof(float64) must be 4 + + ICE_COMPILE_TIME_ASSERT(sizeof(bool)==1); // ...otherwise things might fail with VC++ 4.2 ! + ICE_COMPILE_TIME_ASSERT(sizeof(ubyte)==1); + ICE_COMPILE_TIME_ASSERT(sizeof(sbyte)==1); + ICE_COMPILE_TIME_ASSERT(sizeof(sword)==2); + ICE_COMPILE_TIME_ASSERT(sizeof(uword)==2); + ICE_COMPILE_TIME_ASSERT(sizeof(udword)==4); + ICE_COMPILE_TIME_ASSERT(sizeof(sdword)==4); + ICE_COMPILE_TIME_ASSERT(sizeof(uqword)==8); + ICE_COMPILE_TIME_ASSERT(sizeof(sqword)==8); + + //! TO BE DOCUMENTED + #define DECLARE_ICE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name + + typedef udword DynID; //!< Dynamic identifier +#ifdef USE_HANDLE_MANAGER + typedef udword KID; //!< Kernel ID +// DECLARE_ICE_HANDLE(KID); +#else + typedef uword KID; //!< Kernel ID +#endif + typedef udword RTYPE; //!< Relationship-type (!) between owners and references + #define INVALID_ID 0xffffffff //!< Invalid dword ID (counterpart of null pointers) +#ifdef USE_HANDLE_MANAGER + #define INVALID_KID 0xffffffff //!< Invalid Kernel ID +#else + #define INVALID_KID 0xffff //!< Invalid Kernel ID +#endif + #define INVALID_NUMBER 0xDEADBEEF //!< Standard junk value + + // Define BOOL if needed + #ifndef BOOL + typedef int BOOL; //!< Another boolean type. + #endif + + //! Union of a float and a sdword + typedef union { + float f; //!< The float + sdword d; //!< The integer + }scell; + + //! Union of a float and a udword + typedef union { + float f; //!< The float + udword d; //!< The integer + }ucell; + + // Type ranges + #define MAX_SBYTE 0x7f //!< max possible sbyte value + #define MIN_SBYTE 0x80 //!< min possible sbyte value + #define MAX_UBYTE 0xff //!< max possible ubyte value + #define MIN_UBYTE 0x00 //!< min possible ubyte value + #define MAX_SWORD 0x7fff //!< max possible sword value + #define MIN_SWORD 0x8000 //!< min possible sword value + #define MAX_UWORD 0xffff //!< max possible uword value + #define MIN_UWORD 0x0000 //!< min possible uword value + #define MAX_SDWORD 0x7fffffff //!< max possible sdword value + #define MIN_SDWORD 0x80000000 //!< min possible sdword value + #define MAX_UDWORD 0xffffffff //!< max possible udword value + #define MIN_UDWORD 0x00000000 //!< min possible udword value + #define MAX_FLOAT FLT_MAX //!< max possible float value + #define MIN_FLOAT (-FLT_MAX) //!< min possible loat value + #define IEEE_1_0 0x3f800000 //!< integer representation of 1.0 + #define IEEE_255_0 0x437f0000 //!< integer representation of 255.0 + #define IEEE_MAX_FLOAT 0x7f7fffff //!< integer representation of MAX_FLOAT + #define IEEE_MIN_FLOAT 0xff7fffff //!< integer representation of MIN_FLOAT + #define IEEE_UNDERFLOW_LIMIT 0x1a000000 + + #define ONE_OVER_RAND_MAX (1.0f / float(RAND_MAX)) //!< Inverse of the max possible value returned by rand() + + typedef int (__stdcall* PROC)(); //!< A standard procedure call. + typedef bool (*ENUMERATION)(udword value, udword param, udword context); //!< ICE standard enumeration call + typedef void** VTABLE; //!< A V-Table. + + #undef MIN + #undef MAX + #define MIN(a, b) ((a) < (b) ? (a) : (b)) //!< Returns the min value between a and b + #define MAX(a, b) ((a) > (b) ? (a) : (b)) //!< Returns the max value between a and b + #define MAXMAX(a,b,c) ((a) > (b) ? MAX (a,c) : MAX (b,c)) //!< Returns the max value between a, b and c + + template inline_ const T& TMin (const T& a, const T& b) { return b < a ? b : a; } + template inline_ const T& TMax (const T& a, const T& b) { return a < b ? b : a; } + template inline_ void TSetMin (T& a, const T& b) { if(a>b) a = b; } + template inline_ void TSetMax (T& a, const T& b) { if(a> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa); + n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc); + n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0); + n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00); + n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000); + // Etc for larger intergers (64 bits in Java) + // NOTE: the >> operation must be unsigned! (>>> in java) + } + + //! Count the number of '1' bits in a 32 bit word (from Steve Baker's Cute Code Collection) + inline_ udword CountBits(udword n) + { + // This relies of the fact that the count of n bits can NOT overflow + // an n bit interger. EG: 1 bit count takes a 1 bit interger, 2 bit counts + // 2 bit interger, 3 bit count requires only a 2 bit interger. + // So we add all bit pairs, then each nible, then each byte etc... + n = (n & 0x55555555) + ((n & 0xaaaaaaaa) >> 1); + n = (n & 0x33333333) + ((n & 0xcccccccc) >> 2); + n = (n & 0x0f0f0f0f) + ((n & 0xf0f0f0f0) >> 4); + n = (n & 0x00ff00ff) + ((n & 0xff00ff00) >> 8); + n = (n & 0x0000ffff) + ((n & 0xffff0000) >> 16); + // Etc for larger intergers (64 bits in Java) + // NOTE: the >> operation must be unsigned! (>>> in java) + return n; + } + + //! Even faster? + inline_ udword CountBits2(udword bits) + { + bits = bits - ((bits >> 1) & 0x55555555); + bits = ((bits >> 2) & 0x33333333) + (bits & 0x33333333); + bits = ((bits >> 4) + bits) & 0x0F0F0F0F; + return (bits * 0x01010101) >> 24; + } + + //! Spread out bits. EG 00001111 -> 0101010101 + //! 00001010 -> 0100010000 + //! This is used to interleve to intergers to produce a `Morten Key' + //! used in Space Filling Curves (See DrDobbs Journal, July 1999) + //! Order is important. + inline_ void SpreadBits(udword& n) + { + n = ( n & 0x0000ffff) | (( n & 0xffff0000) << 16); + n = ( n & 0x000000ff) | (( n & 0x0000ff00) << 8); + n = ( n & 0x000f000f) | (( n & 0x00f000f0) << 4); + n = ( n & 0x03030303) | (( n & 0x0c0c0c0c) << 2); + n = ( n & 0x11111111) | (( n & 0x22222222) << 1); + } + + // Next Largest Power of 2 + // Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm + // that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with + // the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next + // largest power of 2. For a 32-bit value: + inline_ udword nlpo2(udword x) + { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return x+1; + } + + //! Test to see if a number is an exact power of two (from Steve Baker's Cute Code Collection) + inline_ bool IsPowerOfTwo(udword n) { return ((n&(n-1))==0); } + + //! Zero the least significant '1' bit in a word. (from Steve Baker's Cute Code Collection) + inline_ void ZeroLeastSetBit(udword& n) { n&=(n-1); } + + //! Set the least significant N bits in a word. (from Steve Baker's Cute Code Collection) + inline_ void SetLeastNBits(udword& x, udword n) { x|=~(~0<> 31; return (x^y)-y; } + + //!< Alternative min function + inline_ sdword min_(sdword a, sdword b) { sdword delta = b-a; return a + (delta&(delta>>31)); } + + // Determine if one of the bytes in a 4 byte word is zero + inline_ BOOL HasNullByte(udword x) { return ((x + 0xfefefeff) & (~x) & 0x80808080); } + + // To find the smallest 1 bit in a word EG: ~~~~~~10---0 => 0----010---0 + inline_ udword LowestOneBit(udword w) { return ((w) & (~(w)+1)); } +// inline_ udword LowestOneBit_(udword w) { return ((w) & (-(w))); } + + // Most Significant 1 Bit + // Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set) + // can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits. + // This process yields a bit vector with the same most significant 1 as x, but all 1's below it. + // Bitwise AND of the original value with the complement of the "folded" value shifted down by one + // yields the most significant bit. For a 32-bit value: + inline_ udword msb32(udword x) + { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + return (x & ~(x >> 1)); + } + + /* + "Just call it repeatedly with various input values and always with the same variable as "memory". + The sharpness determines the degree of filtering, where 0 completely filters out the input, and 1 + does no filtering at all. + + I seem to recall from college that this is called an IIR (Infinite Impulse Response) filter. As opposed + to the more typical FIR (Finite Impulse Response). + + Also, I'd say that you can make more intelligent and interesting filters than this, for example filters + that remove wrong responses from the mouse because it's being moved too fast. You'd want such a filter + to be applied before this one, of course." + + (JCAB on Flipcode) + */ + inline_ float FeedbackFilter(float val, float& memory, float sharpness) + { + ASSERT(sharpness>=0.0f && sharpness<=1.0f && "Invalid sharpness value in feedback filter"); + if(sharpness<0.0f) sharpness = 0.0f; + else if(sharpness>1.0f) sharpness = 1.0f; + return memory = val * sharpness + memory * (1.0f - sharpness); + } + + //! If you can guarantee that your input domain (i.e. value of x) is slightly + //! limited (abs(x) must be < ((1<<31u)-32767)), then you can use the + //! following code to clamp the resulting value into [-32768,+32767] range: + inline_ int ClampToInt16(int x) + { +// ASSERT(abs(x) < (int)((1<<31u)-32767)); + + int delta = 32767 - x; + x += (delta>>31) & delta; + delta = x + 32768; + x -= (delta>>31) & delta; + return x; + } + + // Generic functions + template inline_ void TSwap(Type& a, Type& b) { const Type c = a; a = b; b = c; } + template inline_ Type TClamp(const Type& x, const Type& lo, const Type& hi) { return ((xhi) ? hi : x); } + + template inline_ void TSort(Type& a, Type& b) + { + if(a>b) TSwap(a, b); + } + + template inline_ void TSort(Type& a, Type& b, Type& c) + { + if(a>b) TSwap(a, b); + if(b>c) TSwap(b, c); + if(a>b) TSwap(a, b); + if(b>c) TSwap(b, c); + } + + // Prevent nasty user-manipulations (strategy borrowed from Charles Bloom) +// #define PREVENT_COPY(curclass) void operator = (const curclass& object) { ASSERT(!"Bad use of operator ="); } + // ... actually this is better ! + #define PREVENT_COPY(cur_class) private: cur_class(const cur_class& object); cur_class& operator=(const cur_class& object); + + //! TO BE DOCUMENTED + #define OFFSET_OF(Class, Member) (size_t)&(((Class*)0)->Member) + //! TO BE DOCUMENTED + #define ICEARRAYSIZE(p) (sizeof(p)/sizeof(p[0])) + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Returns the alignment of the input address. + * \fn Alignment() + * \param address [in] address to check + * \return the best alignment (e.g. 1 for odd addresses, etc) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + FUNCTION ICECORE_API udword Alignment(udword address); + + #define IS_ALIGNED_2(x) ((x&1)==0) + #define IS_ALIGNED_4(x) ((x&3)==0) + #define IS_ALIGNED_8(x) ((x&7)==0) + + inline_ void _prefetch(void const* ptr) { (void)*(char const volatile *)ptr; } + + // Compute implicit coords from an index: + // The idea is to get back 2D coords from a 1D index. + // For example: + // + // 0 1 2 ... nbu-1 + // nbu nbu+1 i ... + // + // We have i, we're looking for the equivalent (u=2, v=1) location. + // i = u + v*nbu + // <=> i/nbu = u/nbu + v + // Since 0 <= u < nbu, u/nbu = 0 (integer) + // Hence: v = i/nbu + // Then we simply put it back in the original equation to compute u = i - v*nbu + inline_ void Compute2DCoords(udword& u, udword& v, udword i, udword nbu) + { + v = i / nbu; + u = i - (v * nbu); + } + + // In 3D: i = u + v*nbu + w*nbu*nbv + // <=> i/(nbu*nbv) = u/(nbu*nbv) + v/nbv + w + // u/(nbu*nbv) is null since u/nbu was null already. + // v/nbv is null as well for the same reason. + // Hence w = i/(nbu*nbv) + // Then we're left with a 2D problem: i' = i - w*nbu*nbv = u + v*nbu + inline_ void Compute3DCoords(udword& u, udword& v, udword& w, udword i, udword nbu, udword nbu_nbv) + { + w = i / (nbu_nbv); + Compute2DCoords(u, v, i - (w * nbu_nbv), nbu); + } + +#endif // __ICEUTILS_H__ diff --git a/contrib/Opcode/OPC_AABBCollider.cpp b/contrib/Opcode/OPC_AABBCollider.cpp new file mode 100644 index 0000000..a3cfa62 --- /dev/null +++ b/contrib/Opcode/OPC_AABBCollider.cpp @@ -0,0 +1,696 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an AABB collider. + * \file OPC_AABBCollider.cpp + * \author Pierre Terdiman + * \date January, 1st, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an AABB-vs-tree collider. + * + * \class AABBCollider + * \author Pierre Terdiman + * \version 1.3 + * \date January, 1st, 2002 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +#include "OPC_BoxBoxOverlap.h" +#include "OPC_TriBoxOverlap.h" + +#define SET_CONTACT(prim_index, flag) \ + /* Set contact status */ \ + mFlags |= flag; \ + mTouchedPrimitives->Add(prim_index); + +//! AABB-triangle test +#define AABB_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index);\ + mLeafVerts[0] = *VP.Vertex[0]; \ + mLeafVerts[1] = *VP.Vertex[1]; \ + mLeafVerts[2] = *VP.Vertex[2]; \ + /* Perform triangle-box overlap test */ \ + if(TriBoxOverlap()) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBCollider::AABBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBCollider::~AABBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a box cache + * \param box [in] collision AABB in world space + * \param model [in] Opcode model to collide with + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const Model& model) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, box)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - check temporal coherence + * + * \param cache [in/out] a box cache + * \param box [in] AABB in world space + * \return TRUE if we can return immediately + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL AABBCollider::InitQuery(AABBCache& cache, const CollisionAABB& box) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Keep track of the query box + mBox = box; + + // 3) Setup destination pointer + mTouchedPrimitives = &cache.TouchedPrimitives; + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the box (and set contact status if needed) + AABB_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // 5) Check temporal coherence : + if(TemporalCoherenceEnabled()) + { + // Here we use temporal coherence + // => check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the box (and set contact status if needed) + AABB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; + } + // else no face has been touched during previous query + // => we'll have to perform a normal query + } + else + { + // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious): + if(IsCacheValid(cache) && mBox.IsInside(cache.FatBox)) + { + // - if N is included in P, return previous list + // => we simply leave the list (mTouchedFaces) unchanged + + // Set contact status if needed + if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; + + // In any case we don't need to do a query + return TRUE; + } + else + { + // - else do the query using a fat N + + // Reset cache since we'll about to perform a real query + mTouchedPrimitives->Reset(); + + // Make a fat box so that coherence will work for subsequent frames + mBox.mExtents *= cache.FatCoeff; + + // Update cache with query data (signature for cached faces) + cache.FatBox = mBox; + } + } + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + // 5) Precompute min & max bounds if needed + mMin = box.mCenter - box.mExtents; + mMax = box.mCenter + box.mExtents; + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for vanilla AABB trees. + * \param cache [in/out] a box cache + * \param box [in] collision AABB in world space + * \param tree [in] AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree) +{ + // This is typically called for a scene tree, full of -AABBs-, not full of triangles. + // So we don't really have "primitives" to deal with. Hence it doesn't work with + // "FirstContact" + "TemporalCoherence". + ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); + + // Checkings + if(!tree) return false; + + // Init collision query + if(InitQuery(cache, box)) return true; + + // Perform collision query + _Collide(tree); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the AABB completely contains the box. In which case we can end the query sooner. + * \param bc [in] box center + * \param be [in] box extents + * \return true if the AABB contains the whole box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL AABBCollider::AABBContainsBox(const IcePoint& bc, const IcePoint& be) +{ + if(mMin.x > bc.x - be.x) return FALSE; + if(mMin.y > bc.y - be.y) return FALSE; + if(mMin.z > bc.z - be.z) return FALSE; + + if(mMax.x < bc.x + be.x) return FALSE; + if(mMax.y < bc.y + be.y) return FALSE; + if(mMax.z < bc.z + be.z) return FALSE; + + return TRUE; +} + +#define TEST_BOX_IN_AABB(center, extents) \ + if(AABBContainsBox(center, extents)) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBCollisionNode* node) +{ + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + AABB_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) +{ + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(Extents, Center)) return; + + TEST_BOX_IN_AABB(Center, Extents) + + if(node->IsLeaf()) + { + AABB_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(Extents, Center)) return; + + TEST_BOX_IN_AABB(Center, Extents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBNoLeafNode* node) +{ + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) +{ + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_AABB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(Extents, Center)) return; + + TEST_BOX_IN_AABB(Center, Extents) + + if(node->HasPosLeaf()) { AABB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { AABB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform AABB-AABB overlap test + if(!AABBAABBOverlap(Extents, Center)) return; + + TEST_BOX_IN_AABB(Center, Extents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for vanilla AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBCollider::_Collide(const AABBTreeNode* node) +{ + // Perform AABB-AABB overlap test + IcePoint Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!AABBAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf() || AABBContainsBox(Center, Extents)) + { + mFlags |= OPC_CONTACT; + mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _Collide(node->GetPos()); + _Collide(node->GetNeg()); + } +} + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridAABBCollider::HybridAABBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridAABBCollider::~HybridAABBCollider() +{ +} + +bool HybridAABBCollider::Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, box)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + for(udword i=0;imCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + while(Nb--) + { + const LeafTriangles& CurrentLeaf = LT[*Touched++]; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = *T++; + AABB_PRIM(TriangleIndex, OPC_CONTACT) + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = BaseIndex++; + AABB_PRIM(TriangleIndex, OPC_CONTACT) + } + } + } + } + + return true; +} diff --git a/contrib/Opcode/OPC_AABBCollider.h b/contrib/Opcode/OPC_AABBCollider.h new file mode 100644 index 0000000..c792b44 --- /dev/null +++ b/contrib/Opcode/OPC_AABBCollider.h @@ -0,0 +1,97 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an AABB collider. + * \file OPC_AABBCollider.h + * \author Pierre Terdiman + * \date January, 1st, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_AABBCOLLIDER_H__ +#define __OPC_AABBCOLLIDER_H__ + + struct OPCODE_API AABBCache : VolumeCache + { + AABBCache() : FatCoeff(1.1f) + { + FatBox.mCenter.Zero(); + FatBox.mExtents.Zero(); + } + + // Cached faces signature + CollisionAABB FatBox; //!< Box used when performing the query resulting in cached faces + // User settings + float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere + }; + + class OPCODE_API AABBCollider : public VolumeCollider + { + public: + // Constructor / Destructor + AABBCollider(); + virtual ~AABBCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a box cache + * \param box [in] collision AABB in world space + * \param model [in] Opcode model to collide with + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(AABBCache& cache, const CollisionAABB& box, const Model& model); + // + bool Collide(AABBCache& cache, const CollisionAABB& box, const AABBTree* tree); + protected: + CollisionAABB mBox; //!< Query box in (center, extents) form + IcePoint mMin; //!< Query box min IcePoint + IcePoint mMax; //!< Query box max IcePoint + // Leaf description + IcePoint mLeafVerts[3]; //!< Triangle vertices + // Internal methods + void _Collide(const AABBCollisionNode* node); + void _Collide(const AABBNoLeafNode* node); + void _Collide(const AABBQuantizedNode* node); + void _Collide(const AABBQuantizedNoLeafNode* node); + void _Collide(const AABBTreeNode* node); + void _CollideNoPrimitiveTest(const AABBCollisionNode* node); + void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); + // Overlap tests + inline_ BOOL AABBContainsBox(const IcePoint& bc, const IcePoint& be); + inline_ BOOL AABBAABBOverlap(const IcePoint& b, const IcePoint& Pb); + inline_ BOOL TriBoxOverlap(); + // Init methods + BOOL InitQuery(AABBCache& cache, const CollisionAABB& box); + }; + + class OPCODE_API HybridAABBCollider : public AABBCollider + { + public: + // Constructor / Destructor + HybridAABBCollider(); + virtual ~HybridAABBCollider(); + + bool Collide(AABBCache& cache, const CollisionAABB& box, const HybridModel& model); + protected: + Container mTouchedBoxes; + }; + +#endif // __OPC_AABBCOLLIDER_H__ diff --git a/contrib/Opcode/OPC_AABBTree.cpp b/contrib/Opcode/OPC_AABBTree.cpp new file mode 100644 index 0000000..bc1a4e0 --- /dev/null +++ b/contrib/Opcode/OPC_AABBTree.cpp @@ -0,0 +1,573 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a versatile AABB tree. + * \file OPC_AABBTree.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a generic AABB tree node. + * + * \class AABBTreeNode + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a generic AABB tree. + * This is a vanilla AABB tree, without any particular optimization. It contains anonymous references to + * user-provided primitives, which can theoretically be anything - triangles, boxes, etc. Each primitive + * is surrounded by an AABB, regardless of the primitive's nature. When the primitive is a triangle, the + * resulting tree can be converted into an optimized tree. If the primitive is a box, the resulting tree + * can be used for culling - VFC or occlusion -, assuming you cull on a mesh-by-mesh basis (modern way). + * + * \class AABBTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBTreeNode::AABBTreeNode() : + mPos (null), +#ifndef OPC_NO_NEG_VANILLA_TREE + mNeg (null), +#endif + mNbPrimitives (0), + mNodePrimitives (null) +{ +#ifdef OPC_USE_TREE_COHERENCE + mBitmask = 0; +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBTreeNode::~AABBTreeNode() +{ + // Opcode 1.3: + const AABBTreeNode* Pos = GetPos(); + const AABBTreeNode* Neg = GetNeg(); +#ifndef OPC_NO_NEG_VANILLA_TREE + if(!(mPos&1)) DELETESINGLE(Pos); + if(!(mNeg&1)) DELETESINGLE(Neg); +#else + if(!(mPos&1)) DELETEARRAY(Pos); +#endif + mNodePrimitives = null; // This was just a shortcut to the global list => no release + mNbPrimitives = 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Splits the node along a given axis. + * The list of indices is reorganized according to the split values. + * \param axis [in] splitting axis index + * \param builder [in] the tree builder + * \return the number of primitives assigned to the first child + * \warning this method reorganizes the internal list of primitives + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword AABBTreeNode::Split(udword axis, AABBTreeBuilder* builder) +{ + // Get node split value + float SplitValue = builder->GetSplittingValue(mNodePrimitives, mNbPrimitives, mBV, axis); + + udword NbPos = 0; + // Loop through all node-related primitives. Their indices range from mNodePrimitives[0] to mNodePrimitives[mNbPrimitives-1]. + // Those indices map the global list in the tree builder. + for(udword i=0;iGetSplittingValue(Index, axis); + + // Reorganize the list of indices in this order: positive - negative. + if(PrimitiveValue > SplitValue) + { + // Swap entries + udword Tmp = mNodePrimitives[i]; + mNodePrimitives[i] = mNodePrimitives[NbPos]; + mNodePrimitives[NbPos] = Tmp; + // Count primitives assigned to positive space + NbPos++; + } + } + return NbPos; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Subdivides the node. + * + * N + * / \ + * / \ + * N/2 N/2 + * / \ / \ + * N/4 N/4 N/4 N/4 + * (etc) + * + * A well-balanced tree should have a O(log n) depth. + * A degenerate tree would have a O(n) depth. + * Note a perfectly-balanced tree is not well-suited to collision detection anyway. + * + * \param builder [in] the tree builder + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeNode::Subdivide(AABBTreeBuilder* builder) +{ + // Checkings + if(!builder) return false; + + // Stop subdividing if we reach a leaf node. This is always performed here, + // else we could end in trouble if user overrides this. + if(mNbPrimitives==1) return true; + + // Let the user validate the subdivision + if(!builder->ValidateSubdivision(mNodePrimitives, mNbPrimitives, mBV)) return true; + + bool ValidSplit = true; // Optimism... + udword NbPos; + if(builder->mSettings.mRules & SPLIT_LARGEST_AXIS) + { + // Find the largest axis to split along + IcePoint Extents; mBV.GetExtents(Extents); // Box extents + udword Axis = Extents.LargestAxis(); // Index of largest axis + + // Split along the axis + NbPos = Split(Axis, builder); + + // Check split validity + if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false; + } + else if(builder->mSettings.mRules & SPLIT_SPLATTER_POINTS) + { + // Compute the means + IcePoint Means(0.0f, 0.0f, 0.0f); + for(udword i=0;iGetSplittingValue(Index, 0); + Means.y+=builder->GetSplittingValue(Index, 1); + Means.z+=builder->GetSplittingValue(Index, 2); + } + Means/=float(mNbPrimitives); + + // Compute variances + IcePoint Vars(0.0f, 0.0f, 0.0f); + for(udword i=0;iGetSplittingValue(Index, 0); + float Cy = builder->GetSplittingValue(Index, 1); + float Cz = builder->GetSplittingValue(Index, 2); + Vars.x += (Cx - Means.x)*(Cx - Means.x); + Vars.y += (Cy - Means.y)*(Cy - Means.y); + Vars.z += (Cz - Means.z)*(Cz - Means.z); + } + Vars/=float(mNbPrimitives-1); + + // Choose axis with greatest variance + udword Axis = Vars.LargestAxis(); + + // Split along the axis + NbPos = Split(Axis, builder); + + // Check split validity + if(!NbPos || NbPos==mNbPrimitives) ValidSplit = false; + } + else if(builder->mSettings.mRules & SPLIT_BALANCED) + { + // Test 3 axis, take the best + float Results[3]; + NbPos = Split(0, builder); Results[0] = float(NbPos)/float(mNbPrimitives); + NbPos = Split(1, builder); Results[1] = float(NbPos)/float(mNbPrimitives); + NbPos = Split(2, builder); Results[2] = float(NbPos)/float(mNbPrimitives); + Results[0]-=0.5f; Results[0]*=Results[0]; + Results[1]-=0.5f; Results[1]*=Results[1]; + Results[2]-=0.5f; Results[2]*=Results[2]; + udword Min=0; + if(Results[1]mSettings.mRules & SPLIT_BEST_AXIS) + { + // Test largest, then middle, then smallest axis... + + // Sort axis + IcePoint Extents; mBV.GetExtents(Extents); // Box extents + udword SortedAxis[] = { 0, 1, 2 }; + float* Keys = (float*)&Extents.x; + for(udword j=0;j<3;j++) + { + for(udword i=0;i<2;i++) + { + if(Keys[SortedAxis[i]]mSettings.mRules & SPLIT_FIFTY) + { + // Don't even bother splitting (mainly a performance test) + NbPos = mNbPrimitives>>1; + } + else return false; // Unknown splitting rules + + // Check the subdivision has been successful + if(!ValidSplit) + { + // Here, all boxes lie in the same sub-space. Two strategies: + // - if the tree *must* be complete, make an arbitrary 50-50 split + // - else stop subdividing +// if(builder->mSettings.mRules&SPLIT_COMPLETE) + if(builder->mSettings.mLimit==1) + { + builder->IncreaseNbInvalidSplits(); + NbPos = mNbPrimitives>>1; + } + else return true; + } + + // Now create children and assign their pointers. + if(builder->mNodeBase) + { + // We use a pre-allocated linear pool for complete trees [Opcode 1.3] + AABBTreeNode* Pool = (AABBTreeNode*)builder->mNodeBase; + udword Count = builder->GetCount() - 1; // Count begins to 1... + // Set last bit to tell it shouldn't be freed ### pretty ugly, find a better way. Maybe one bit in mNbPrimitives + ASSERT(!(udword(&Pool[Count+0])&1)); + ASSERT(!(udword(&Pool[Count+1])&1)); + mPos = udword(&Pool[Count+0])|1; +#ifndef OPC_NO_NEG_VANILLA_TREE + mNeg = udword(&Pool[Count+1])|1; +#endif + } + else + { + // Non-complete trees and/or Opcode 1.2 allocate nodes on-the-fly +#ifndef OPC_NO_NEG_VANILLA_TREE + mPos = (udword)new AABBTreeNode; CHECKALLOC(mPos); + mNeg = (udword)new AABBTreeNode; CHECKALLOC(mNeg); +#else + AABBTreeNode* PosNeg = new AABBTreeNode[2]; + CHECKALLOC(PosNeg); + mPos = (udword)PosNeg; +#endif + } + + // Update stats + builder->IncreaseCount(2); + + // Assign children + AABBTreeNode* Pos = (AABBTreeNode*)GetPos(); + AABBTreeNode* Neg = (AABBTreeNode*)GetNeg(); + Pos->mNodePrimitives = &mNodePrimitives[0]; + Pos->mNbPrimitives = NbPos; + Neg->mNodePrimitives = &mNodePrimitives[NbPos]; + Neg->mNbPrimitives = mNbPrimitives - NbPos; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive hierarchy building in a top-down fashion. + * \param builder [in] the tree builder + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeNode::_BuildHierarchy(AABBTreeBuilder* builder) +{ + // 1) Compute the global box for current node. The box is stored in mBV. + builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV); + + // 2) Subdivide current node + Subdivide(builder); + + // 3) Recurse + AABBTreeNode* Pos = (AABBTreeNode*)GetPos(); + AABBTreeNode* Neg = (AABBTreeNode*)GetNeg(); + if(Pos) Pos->_BuildHierarchy(builder); + if(Neg) Neg->_BuildHierarchy(builder); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the tree (top-down). + * \param builder [in] the tree builder + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeNode::_Refit(AABBTreeBuilder* builder) +{ + // 1) Recompute the new global box for current node + builder->ComputeGlobalBox(mNodePrimitives, mNbPrimitives, mBV); + + // 2) Recurse + AABBTreeNode* Pos = (AABBTreeNode*)GetPos(); + AABBTreeNode* Neg = (AABBTreeNode*)GetNeg(); + if(Pos) Pos->_Refit(builder); + if(Neg) Neg->_Refit(builder); +} + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBTree::AABBTree() : mIndices(null), mTotalNbNodes(0), mPool(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBTree::~AABBTree() +{ + Release(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Releases the tree. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTree::Release() +{ + DELETEARRAY(mPool); + DELETEARRAY(mIndices); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds a generic AABB tree from a tree builder. + * \param builder [in] the tree builder + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTree::Build(AABBTreeBuilder* builder) +{ + // Checkings + if(!builder || !builder->mNbPrimitives) return false; + + // Release previous tree + Release(); + + // Init stats + builder->SetCount(1); + builder->SetNbInvalidSplits(0); + + // Initialize indices. This list will be modified during build. + mIndices = new udword[builder->mNbPrimitives]; + CHECKALLOC(mIndices); + // Identity permutation + for(udword i=0;imNbPrimitives;i++) mIndices[i] = i; + + // Setup initial node. Here we have a complete permutation of the app's primitives. + mNodePrimitives = mIndices; + mNbPrimitives = builder->mNbPrimitives; + + // Use a linear array for complete trees (since we can predict the final number of nodes) [Opcode 1.3] +// if(builder->mRules&SPLIT_COMPLETE) + if(builder->mSettings.mLimit==1) + { + // Allocate a pool of nodes + mPool = new AABBTreeNode[builder->mNbPrimitives*2 - 1]; + + builder->mNodeBase = mPool; // ### ugly ! + } + + // Build the hierarchy + _BuildHierarchy(builder); + + // Get back total number of nodes + mTotalNbNodes = builder->GetCount(); + + // For complete trees, check the correct number of nodes has been created [Opcode 1.3] + if(mPool) ASSERT(mTotalNbNodes==builder->mNbPrimitives*2 - 1); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the depth of the tree. + * A well-balanced tree should have a log(n) depth. A degenerate tree O(n) depth. + * \return depth of the tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword AABBTree::ComputeDepth() const +{ + return Walk(null, null); // Use the walking code without callback +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Walks the tree, calling the user back for each node. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword AABBTree::Walk(WalkingCallback callback, void* user_data) const +{ + // Call it without callback to compute max depth + udword MaxDepth = 0; + udword CurrentDepth = 0; + + struct Local + { + static void _Walk(const AABBTreeNode* current_node, udword& max_depth, udword& current_depth, WalkingCallback callback, void* user_data) + { + // Checkings + if(!current_node) return; + // Entering a new node => increase depth + current_depth++; + // Keep track of max depth + if(current_depth>max_depth) max_depth = current_depth; + + // Callback + if(callback && !(callback)(current_node, current_depth, user_data)) return; + + // Recurse + if(current_node->GetPos()) { _Walk(current_node->GetPos(), max_depth, current_depth, callback, user_data); current_depth--; } + if(current_node->GetNeg()) { _Walk(current_node->GetNeg(), max_depth, current_depth, callback, user_data); current_depth--; } + } + }; + Local::_Walk(this, MaxDepth, CurrentDepth, callback, user_data); + return MaxDepth; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the tree in a top-down way. + * \param builder [in] the tree builder + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTree::Refit(AABBTreeBuilder* builder) +{ + if(!builder) return false; + _Refit(builder); + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the tree in a bottom-up way. + * \param builder [in] the tree builder + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTree::Refit2(AABBTreeBuilder* builder) +{ + // Checkings + if(!builder) return false; + + ASSERT(mPool); + + // Bottom-up update + IcePoint Min,Max; + IcePoint Min_,Max_; + udword Index = mTotalNbNodes; + while(Index--) + { + AABBTreeNode& Current = mPool[Index]; + + if(Current.IsLeaf()) + { + builder->ComputeGlobalBox(Current.GetPrimitives(), Current.GetNbPrimitives(), *(AABB*)Current.GetAABB()); + } + else + { + Current.GetPos()->GetAABB()->GetMin(Min); + Current.GetPos()->GetAABB()->GetMax(Max); + + Current.GetNeg()->GetAABB()->GetMin(Min_); + Current.GetNeg()->GetAABB()->GetMax(Max_); + + Min.Min(Min_); + Max.Max(Max_); + + ((AABB*)Current.GetAABB())->SetMinMax(Min, Max); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the number of bytes used by the tree. + * \return number of bytes used + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword AABBTree::GetUsedBytes() const +{ + udword TotalSize = mTotalNbNodes*GetNodeSize(); + if(mIndices) TotalSize+=mNbPrimitives*sizeof(udword); + return TotalSize; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the tree is a complete tree or not. + * A complete tree is made of 2*N-1 nodes, where N is the number of primitives in the tree. + * \return true for complete trees + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTree::IsComplete() const +{ + return (GetNbNodes()==GetNbPrimitives()*2-1); +} diff --git a/contrib/Opcode/OPC_AABBTree.h b/contrib/Opcode/OPC_AABBTree.h new file mode 100644 index 0000000..298f482 --- /dev/null +++ b/contrib/Opcode/OPC_AABBTree.h @@ -0,0 +1,137 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a versatile AABB tree. + * \file OPC_AABBTree.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_AABBTREE_H__ +#define __OPC_AABBTREE_H__ + +#ifdef OPC_NO_NEG_VANILLA_TREE + //! TO BE DOCUMENTED + #define IMPLEMENT_TREE(base_class, volume) \ + public: \ + /* Constructor / Destructor */ \ + base_class(); \ + ~base_class(); \ + /* Data access */ \ + inline_ const volume* Get##volume() const { return &mBV; } \ + /* Clear the last bit */ \ + inline_ const base_class* GetPos() const { return (const base_class*)(mPos&~1); } \ + inline_ const base_class* GetNeg() const { const base_class* P = GetPos(); return P ? P+1 : null;} \ + \ + /* We don't need to test both nodes since we can't have one without the other */ \ + inline_ bool IsLeaf() const { return !GetPos(); } \ + \ + /* Stats */ \ + inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ + protected: \ + /* Tree-independent data */ \ + /* Following data always belong to the BV-tree, regardless of what the tree actually contains.*/ \ + /* Whatever happens we need the two children and the enclosing volume.*/ \ + volume mBV; /* Global bounding-volume enclosing all the node-related primitives */ \ + udword mPos; /* "Positive" & "Negative" children */ +#else + //! TO BE DOCUMENTED + #define IMPLEMENT_TREE(base_class, volume) \ + public: \ + /* Constructor / Destructor */ \ + base_class(); \ + ~base_class(); \ + /* Data access */ \ + inline_ const volume* Get##volume() const { return &mBV; } \ + /* Clear the last bit */ \ + inline_ const base_class* GetPos() const { return (const base_class*)(mPos&~1); } \ + inline_ const base_class* GetNeg() const { return (const base_class*)(mNeg&~1); } \ + \ +/* inline_ bool IsLeaf() const { return (!GetPos() && !GetNeg()); } */ \ + /* We don't need to test both nodes since we can't have one without the other */ \ + inline_ bool IsLeaf() const { return !GetPos(); } \ + \ + /* Stats */ \ + inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ + protected: \ + /* Tree-independent data */ \ + /* Following data always belong to the BV-tree, regardless of what the tree actually contains.*/ \ + /* Whatever happens we need the two children and the enclosing volume.*/ \ + volume mBV; /* Global bounding-volume enclosing all the node-related primitives */ \ + udword mPos; /* "Positive" child */ \ + udword mNeg; /* "Negative" child */ +#endif + + typedef void (*CullingCallback) (udword nb_primitives, udword* node_primitives, BOOL need_clipping, void* user_data); + + class OPCODE_API AABBTreeNode + { + IMPLEMENT_TREE(AABBTreeNode, AABB) + public: + // Data access + inline_ const udword* GetPrimitives() const { return mNodePrimitives; } + inline_ udword GetNbPrimitives() const { return mNbPrimitives; } + + protected: + // Tree-dependent data + udword* mNodePrimitives; //!< Node-related primitives (shortcut to a position in mIndices below) + udword mNbPrimitives; //!< Number of primitives for this node + // Internal methods + udword Split(udword axis, AABBTreeBuilder* builder); + bool Subdivide(AABBTreeBuilder* builder); + void _BuildHierarchy(AABBTreeBuilder* builder); + void _Refit(AABBTreeBuilder* builder); + }; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * User-callback, called for each node by the walking code. + * \param current [in] current node + * \param depth [in] current node's depth + * \param user_data [in] user-defined data + * \return true to recurse through children, else false to bypass them + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef bool (*WalkingCallback) (const AABBTreeNode* current, udword depth, void* user_data); + + class OPCODE_API AABBTree : public AABBTreeNode + { + public: + // Constructor / Destructor + AABBTree(); + ~AABBTree(); + // Build + bool Build(AABBTreeBuilder* builder); + void Release(); + + // Data access + inline_ const udword* GetIndices() const { return mIndices; } //!< Catch the indices + inline_ udword GetNbNodes() const { return mTotalNbNodes; } //!< Catch the number of nodes + + // Infos + bool IsComplete() const; + // Stats + udword ComputeDepth() const; + udword GetUsedBytes() const; + udword Walk(WalkingCallback callback, void* user_data) const; + + bool Refit(AABBTreeBuilder* builder); + bool Refit2(AABBTreeBuilder* builder); + private: + udword* mIndices; //!< Indices in the app list. Indices are reorganized during build (permutation). + AABBTreeNode* mPool; //!< Linear pool of nodes for complete trees. Null otherwise. [Opcode 1.3] + // Stats + udword mTotalNbNodes; //!< Number of nodes in the tree. + }; + +#endif // __OPC_AABBTREE_H__ diff --git a/contrib/Opcode/OPC_BaseModel.cpp b/contrib/Opcode/OPC_BaseModel.cpp new file mode 100644 index 0000000..88b6a69 --- /dev/null +++ b/contrib/Opcode/OPC_BaseModel.cpp @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base model interface. + * \file OPC_BaseModel.cpp + * \author Pierre Terdiman + * \date May, 18, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * The base class for collision models. + * + * \class BaseModel + * \author Pierre Terdiman + * \version 1.3 + * \date May, 18, 2003 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +OPCODECREATE::OPCODECREATE() +{ + mIMesh = null; + mSettings.mRules = SPLIT_SPLATTER_POINTS | SPLIT_GEOM_CENTER; + mSettings.mLimit = 1; // Mandatory for complete trees + mNoLeaf = true; + mQuantized = true; +#ifdef __MESHMERIZER_H__ + mCollisionHull = false; +#endif // __MESHMERIZER_H__ + mKeepOriginal = false; + mCanRemap = false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BaseModel::BaseModel() : mIMesh(null), mModelCode(0), mSource(null), mTree(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BaseModel::~BaseModel() +{ + ReleaseBase(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Releases everything. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void BaseModel::ReleaseBase() +{ + DELETESINGLE(mSource); + DELETESINGLE(mTree); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Creates an optimized tree according to user-settings, and setups mModelCode. + * \param no_leaf [in] true for "no leaf" tree + * \param quantized [in] true for quantized tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool BaseModel::CreateTree(bool no_leaf, bool quantized) +{ + DELETESINGLE(mTree); + + // Setup model code + if(no_leaf) mModelCode |= OPC_NO_LEAF; + else mModelCode &= ~OPC_NO_LEAF; + + if(quantized) mModelCode |= OPC_QUANTIZED; + else mModelCode &= ~OPC_QUANTIZED; + + // Create the correct class + if(mModelCode & OPC_NO_LEAF) + { + if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedNoLeafTree; + else mTree = new AABBNoLeafTree; + } + else + { + if(mModelCode & OPC_QUANTIZED) mTree = new AABBQuantizedTree; + else mTree = new AABBCollisionTree; + } + CHECKALLOC(mTree); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the collision model. This can be used to handle dynamic meshes. Usage is: + * 1. modify your mesh vertices (keep the topology constant!) + * 2. refit the tree (call this method) + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool BaseModel::Refit() +{ + // Refit the optimized tree + return mTree->Refit(mIMesh); + +// Old code kept for reference : refit the source tree then rebuild ! +// if(!mSource) return false; +// // Ouch... +// mSource->Refit(&mTB); +// // Ouch... +// return mTree->Build(mSource); +} diff --git a/contrib/Opcode/OPC_BaseModel.h b/contrib/Opcode/OPC_BaseModel.h new file mode 100644 index 0000000..3c2e58c --- /dev/null +++ b/contrib/Opcode/OPC_BaseModel.h @@ -0,0 +1,175 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base model interface. + * \file OPC_BaseModel.h + * \author Pierre Terdiman + * \date May, 18, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_BASEMODEL_H__ +#define __OPC_BASEMODEL_H__ + + //! Model creation structure + struct OPCODE_API OPCODECREATE + { + //! Constructor + OPCODECREATE(); + + MeshInterface* mIMesh; //!< Mesh interface (access to triangles & vertices) (*) + BuildSettings mSettings; //!< Builder's settings + bool mNoLeaf; //!< true => discard leaf nodes (else use a normal tree) + bool mQuantized; //!< true => quantize the tree (else use a normal tree) +#ifdef __MESHMERIZER_H__ + bool mCollisionHull; //!< true => use convex hull + GJK +#endif // __MESHMERIZER_H__ + bool mKeepOriginal; //!< true => keep a copy of the original tree (debug purpose) + bool mCanRemap; //!< true => allows OPCODE to reorganize client arrays + + // (*) This pointer is saved internally and used by OPCODE until collision structures are released, + // so beware of the object's lifetime. + }; + + enum ModelFlag + { + OPC_QUANTIZED = (1<<0), //!< Compressed/uncompressed tree + OPC_NO_LEAF = (1<<1), //!< Leaf/NoLeaf tree + OPC_SINGLE_NODE = (1<<2) //!< Special case for 1-node models + }; + + class OPCODE_API BaseModel + { + public: + // Constructor/Destructor + BaseModel(); + virtual ~BaseModel(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds a collision model. + * \param create [in] model creation structure + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Build(const OPCODECREATE& create) = 0; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual udword GetUsedBytes() const = 0; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the collision model. This can be used to handle dynamic meshes. Usage is: + * 1. modify your mesh vertices (keep the topology constant!) + * 2. refit the tree (call this method) + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Refit(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the source tree. + * \return generic tree + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const AABBTree* GetSourceTree() const { return mSource; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the tree. + * \return the collision tree + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const AABBOptimizedTree* GetTree() const { return mTree; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the tree. + * \return the collision tree + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ AABBOptimizedTree* GetTree() { return mTree; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of nodes in the tree. + * Should be 2*N-1 for normal trees and N-1 for optimized ones. + * \return number of nodes + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbNodes() const { return mTree->GetNbNodes(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks whether the tree has leaf nodes or not. + * \return true if the tree has leaf nodes (normal tree), else false (optimized tree) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL HasLeafNodes() const { return !(mModelCode & OPC_NO_LEAF); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks whether the tree is quantized or not. + * \return true if the tree is quantized + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsQuantized() const { return mModelCode & OPC_QUANTIZED; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks whether the model has a single node or not. This special case must be handled separately. + * \return true if the model has only 1 node + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL HasSingleNode() const { return mModelCode & OPC_SINGLE_NODE; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the model's code. + * \return model's code + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetModelCode() const { return mModelCode; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the mesh interface. + * \return mesh interface + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const MeshInterface* GetMeshInterface() const { return mIMesh; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Sets the mesh interface. + * \param imesh [in] mesh interface + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetMeshInterface(const MeshInterface* imesh) { mIMesh = imesh; } + + protected: + const MeshInterface* mIMesh; //!< User-defined mesh interface + udword mModelCode; //!< Model code = combination of ModelFlag(s) + AABBTree* mSource; //!< Original source tree + AABBOptimizedTree* mTree; //!< Optimized tree owned by the model + // Internal methods + void ReleaseBase(); + bool CreateTree(bool no_leaf, bool quantized); + }; + +#endif //__OPC_BASEMODEL_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_BoxBoxOverlap.h b/contrib/Opcode/OPC_BoxBoxOverlap.h new file mode 100644 index 0000000..78a7675 --- /dev/null +++ b/contrib/Opcode/OPC_BoxBoxOverlap.h @@ -0,0 +1,122 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * OBB-OBB overlap test using the separating axis theorem. + * - original code by Gomez / Gamasutra (similar to Gottschalk's one in RAPID) + * - optimized for AABB trees by computing the rotation matrix once (SOLID-fashion) + * - the fabs matrix is precomputed as well and epsilon-tweaked (RAPID-style, we found this almost mandatory) + * - Class III axes can be disabled... (SOLID & Intel fashion) + * - ...or enabled to perform some profiling + * - CPU comparisons used when appropriate + * - lazy evaluation sometimes saves some work in case of early exits (unlike SOLID) + * + * \param ea [in] extents from box A + * \param ca [in] center from box A + * \param eb [in] extents from box B + * \param cb [in] center from box B + * \return true if boxes overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL AABBTreeCollider::BoxBoxOverlap(const IcePoint& ea, const IcePoint& ca, const IcePoint& eb, const IcePoint& cb) +{ + // Stats + mNbBVBVTests++; + + float t,t2; + + // Class I : A's basis vectors + float Tx = (mR1to0.m[0][0]*cb.x + mR1to0.m[1][0]*cb.y + mR1to0.m[2][0]*cb.z) + mT1to0.x - ca.x; + t = ea.x + eb.x*mAR.m[0][0] + eb.y*mAR.m[1][0] + eb.z*mAR.m[2][0]; + if(GREATER(Tx, t)) return FALSE; + + float Ty = (mR1to0.m[0][1]*cb.x + mR1to0.m[1][1]*cb.y + mR1to0.m[2][1]*cb.z) + mT1to0.y - ca.y; + t = ea.y + eb.x*mAR.m[0][1] + eb.y*mAR.m[1][1] + eb.z*mAR.m[2][1]; + if(GREATER(Ty, t)) return FALSE; + + float Tz = (mR1to0.m[0][2]*cb.x + mR1to0.m[1][2]*cb.y + mR1to0.m[2][2]*cb.z) + mT1to0.z - ca.z; + t = ea.z + eb.x*mAR.m[0][2] + eb.y*mAR.m[1][2] + eb.z*mAR.m[2][2]; + if(GREATER(Tz, t)) return FALSE; + + // Class II : B's basis vectors + t = Tx*mR1to0.m[0][0] + Ty*mR1to0.m[0][1] + Tz*mR1to0.m[0][2]; t2 = ea.x*mAR.m[0][0] + ea.y*mAR.m[0][1] + ea.z*mAR.m[0][2] + eb.x; + if(GREATER(t, t2)) return FALSE; + + t = Tx*mR1to0.m[1][0] + Ty*mR1to0.m[1][1] + Tz*mR1to0.m[1][2]; t2 = ea.x*mAR.m[1][0] + ea.y*mAR.m[1][1] + ea.z*mAR.m[1][2] + eb.y; + if(GREATER(t, t2)) return FALSE; + + t = Tx*mR1to0.m[2][0] + Ty*mR1to0.m[2][1] + Tz*mR1to0.m[2][2]; t2 = ea.x*mAR.m[2][0] + ea.y*mAR.m[2][1] + ea.z*mAR.m[2][2] + eb.z; + if(GREATER(t, t2)) return FALSE; + + // Class III : 9 cross products + // Cool trick: always perform the full test for first level, regardless of settings. + // That way pathological cases (such as the pencils scene) are quickly rejected anyway ! + if(mFullBoxBoxTest || mNbBVBVTests==1) + { + t = Tz*mR1to0.m[0][1] - Ty*mR1to0.m[0][2]; t2 = ea.y*mAR.m[0][2] + ea.z*mAR.m[0][1] + eb.y*mAR.m[2][0] + eb.z*mAR.m[1][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B0 + t = Tz*mR1to0.m[1][1] - Ty*mR1to0.m[1][2]; t2 = ea.y*mAR.m[1][2] + ea.z*mAR.m[1][1] + eb.x*mAR.m[2][0] + eb.z*mAR.m[0][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B1 + t = Tz*mR1to0.m[2][1] - Ty*mR1to0.m[2][2]; t2 = ea.y*mAR.m[2][2] + ea.z*mAR.m[2][1] + eb.x*mAR.m[1][0] + eb.y*mAR.m[0][0]; if(GREATER(t, t2)) return FALSE; // L = A0 x B2 + t = Tx*mR1to0.m[0][2] - Tz*mR1to0.m[0][0]; t2 = ea.x*mAR.m[0][2] + ea.z*mAR.m[0][0] + eb.y*mAR.m[2][1] + eb.z*mAR.m[1][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B0 + t = Tx*mR1to0.m[1][2] - Tz*mR1to0.m[1][0]; t2 = ea.x*mAR.m[1][2] + ea.z*mAR.m[1][0] + eb.x*mAR.m[2][1] + eb.z*mAR.m[0][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B1 + t = Tx*mR1to0.m[2][2] - Tz*mR1to0.m[2][0]; t2 = ea.x*mAR.m[2][2] + ea.z*mAR.m[2][0] + eb.x*mAR.m[1][1] + eb.y*mAR.m[0][1]; if(GREATER(t, t2)) return FALSE; // L = A1 x B2 + t = Ty*mR1to0.m[0][0] - Tx*mR1to0.m[0][1]; t2 = ea.x*mAR.m[0][1] + ea.y*mAR.m[0][0] + eb.y*mAR.m[2][2] + eb.z*mAR.m[1][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B0 + t = Ty*mR1to0.m[1][0] - Tx*mR1to0.m[1][1]; t2 = ea.x*mAR.m[1][1] + ea.y*mAR.m[1][0] + eb.x*mAR.m[2][2] + eb.z*mAR.m[0][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B1 + t = Ty*mR1to0.m[2][0] - Tx*mR1to0.m[2][1]; t2 = ea.x*mAR.m[2][1] + ea.y*mAR.m[2][0] + eb.x*mAR.m[1][2] + eb.y*mAR.m[0][2]; if(GREATER(t, t2)) return FALSE; // L = A2 x B2 + } + return TRUE; +} + +//! A dedicated version when one box is constant +inline_ BOOL OBBCollider::BoxBoxOverlap(const IcePoint& extents, const IcePoint& center) +{ + // Stats + mNbVolumeBVTests++; + + float t,t2; + + // Class I : A's basis vectors + float Tx = mTBoxToModel.x - center.x; t = extents.x + mBBx1; if(GREATER(Tx, t)) return FALSE; + float Ty = mTBoxToModel.y - center.y; t = extents.y + mBBy1; if(GREATER(Ty, t)) return FALSE; + float Tz = mTBoxToModel.z - center.z; t = extents.z + mBBz1; if(GREATER(Tz, t)) return FALSE; + + // Class II : B's basis vectors + t = Tx*mRBoxToModel.m[0][0] + Ty*mRBoxToModel.m[0][1] + Tz*mRBoxToModel.m[0][2]; + t2 = extents.x*mAR.m[0][0] + extents.y*mAR.m[0][1] + extents.z*mAR.m[0][2] + mBoxExtents.x; + if(GREATER(t, t2)) return FALSE; + + t = Tx*mRBoxToModel.m[1][0] + Ty*mRBoxToModel.m[1][1] + Tz*mRBoxToModel.m[1][2]; + t2 = extents.x*mAR.m[1][0] + extents.y*mAR.m[1][1] + extents.z*mAR.m[1][2] + mBoxExtents.y; + if(GREATER(t, t2)) return FALSE; + + t = Tx*mRBoxToModel.m[2][0] + Ty*mRBoxToModel.m[2][1] + Tz*mRBoxToModel.m[2][2]; + t2 = extents.x*mAR.m[2][0] + extents.y*mAR.m[2][1] + extents.z*mAR.m[2][2] + mBoxExtents.z; + if(GREATER(t, t2)) return FALSE; + + // Class III : 9 cross products + // Cool trick: always perform the full test for first level, regardless of settings. + // That way pathological cases (such as the pencils scene) are quickly rejected anyway ! + if(mFullBoxBoxTest || mNbVolumeBVTests==1) + { + t = Tz*mRBoxToModel.m[0][1] - Ty*mRBoxToModel.m[0][2]; t2 = extents.y*mAR.m[0][2] + extents.z*mAR.m[0][1] + mBB_1; if(GREATER(t, t2)) return FALSE; // L = A0 x B0 + t = Tz*mRBoxToModel.m[1][1] - Ty*mRBoxToModel.m[1][2]; t2 = extents.y*mAR.m[1][2] + extents.z*mAR.m[1][1] + mBB_2; if(GREATER(t, t2)) return FALSE; // L = A0 x B1 + t = Tz*mRBoxToModel.m[2][1] - Ty*mRBoxToModel.m[2][2]; t2 = extents.y*mAR.m[2][2] + extents.z*mAR.m[2][1] + mBB_3; if(GREATER(t, t2)) return FALSE; // L = A0 x B2 + t = Tx*mRBoxToModel.m[0][2] - Tz*mRBoxToModel.m[0][0]; t2 = extents.x*mAR.m[0][2] + extents.z*mAR.m[0][0] + mBB_4; if(GREATER(t, t2)) return FALSE; // L = A1 x B0 + t = Tx*mRBoxToModel.m[1][2] - Tz*mRBoxToModel.m[1][0]; t2 = extents.x*mAR.m[1][2] + extents.z*mAR.m[1][0] + mBB_5; if(GREATER(t, t2)) return FALSE; // L = A1 x B1 + t = Tx*mRBoxToModel.m[2][2] - Tz*mRBoxToModel.m[2][0]; t2 = extents.x*mAR.m[2][2] + extents.z*mAR.m[2][0] + mBB_6; if(GREATER(t, t2)) return FALSE; // L = A1 x B2 + t = Ty*mRBoxToModel.m[0][0] - Tx*mRBoxToModel.m[0][1]; t2 = extents.x*mAR.m[0][1] + extents.y*mAR.m[0][0] + mBB_7; if(GREATER(t, t2)) return FALSE; // L = A2 x B0 + t = Ty*mRBoxToModel.m[1][0] - Tx*mRBoxToModel.m[1][1]; t2 = extents.x*mAR.m[1][1] + extents.y*mAR.m[1][0] + mBB_8; if(GREATER(t, t2)) return FALSE; // L = A2 x B1 + t = Ty*mRBoxToModel.m[2][0] - Tx*mRBoxToModel.m[2][1]; t2 = extents.x*mAR.m[2][1] + extents.y*mAR.m[2][0] + mBB_9; if(GREATER(t, t2)) return FALSE; // L = A2 x B2 + } + return TRUE; +} + +//! A special version for 2 axis-aligned boxes +inline_ BOOL AABBCollider::AABBAABBOverlap(const IcePoint& extents, const IcePoint& center) +{ + // Stats + mNbVolumeBVTests++; + + float tx = mBox.mCenter.x - center.x; float ex = extents.x + mBox.mExtents.x; if(GREATER(tx, ex)) return FALSE; + float ty = mBox.mCenter.y - center.y; float ey = extents.y + mBox.mExtents.y; if(GREATER(ty, ey)) return FALSE; + float tz = mBox.mCenter.z - center.z; float ez = extents.z + mBox.mExtents.z; if(GREATER(tz, ez)) return FALSE; + + return TRUE; +} diff --git a/contrib/Opcode/OPC_BoxPruning.cpp b/contrib/Opcode/OPC_BoxPruning.cpp new file mode 100644 index 0000000..3735a39 --- /dev/null +++ b/contrib/Opcode/OPC_BoxPruning.cpp @@ -0,0 +1,367 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for box pruning. + * \file IceBoxPruning.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + You could use a complex sweep-and-prune as implemented in I-Collide. + You could use a complex hashing scheme as implemented in V-Clip or recently in ODE it seems. + You could use a "Recursive Dimensional Clustering" algorithm as implemented in GPG2. + + Or you could use this. + Faster ? I don't know. Probably not. It would be a shame. But who knows ? + Easier ? Definitely. Enjoy the sheer simplicity. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +*/ + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + + inline_ void FindRunningIndex(udword& index, float* array, udword* sorted, int last, float max) + { + int First=index; + while(First<=last) + { + index = (First+last)>>1; + + if(max>array[sorted[index]]) First = index+1; + else last = index-1; + } + } +// ### could be log(n) ! +// and maybe use cmp integers + +// InsertionSort has better coherence, RadixSort is better for one-shot queries. +#define PRUNING_SORTER RadixSort +//#define PRUNING_SORTER InsertionSort + +// Static for coherence +static PRUNING_SORTER* gCompletePruningSorter = null; +static PRUNING_SORTER* gBipartitePruningSorter0 = null; +static PRUNING_SORTER* gBipartitePruningSorter1 = null; +inline_ PRUNING_SORTER* GetCompletePruningSorter() +{ + if(!gCompletePruningSorter) gCompletePruningSorter = new PRUNING_SORTER; + return gCompletePruningSorter; +} +inline_ PRUNING_SORTER* GetBipartitePruningSorter0() +{ + if(!gBipartitePruningSorter0) gBipartitePruningSorter0 = new PRUNING_SORTER; + return gBipartitePruningSorter0; +} +inline_ PRUNING_SORTER* GetBipartitePruningSorter1() +{ + if(!gBipartitePruningSorter1) gBipartitePruningSorter1 = new PRUNING_SORTER; + return gBipartitePruningSorter1; +} +void ReleasePruningSorters() +{ + DELETESINGLE(gBipartitePruningSorter1); + DELETESINGLE(gBipartitePruningSorter0); + DELETESINGLE(gCompletePruningSorter); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set. + * \param nb0 [in] number of boxes in the first set + * \param array0 [in] array of boxes for the first set + * \param nb1 [in] number of boxes in the second set + * \param array1 [in] array of boxes for the second set + * \param pairs [out] array of overlapping pairs + * \param axes [in] projection order (0,2,1 is often best) + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Opcode::BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes) +{ + // Checkings + if(!nb0 || !array0 || !nb1 || !array1) return false; + + // Catch axes + udword Axis0 = axes.mAxis0; + udword Axis1 = axes.mAxis1; + udword Axis2 = axes.mAxis2; + + // Allocate some temporary data + float* MinPosList0 = new float[nb0]; + float* MinPosList1 = new float[nb1]; + + // 1) Build main lists using the primary axis + for(udword i=0;iGetMin(Axis0); + for(udword i=0;iGetMin(Axis0); + + // 2) Sort the lists + PRUNING_SORTER* RS0 = GetBipartitePruningSorter0(); + PRUNING_SORTER* RS1 = GetBipartitePruningSorter1(); + const udword* Sorted0 = RS0->Sort(MinPosList0, nb0).GetRanks(); + const udword* Sorted1 = RS1->Sort(MinPosList1, nb1).GetRanks(); + + // 3) Prune the lists + udword Index0, Index1; + + const udword* const LastSorted0 = &Sorted0[nb0]; + const udword* const LastSorted1 = &Sorted1[nb1]; + const udword* RunningAddress0 = Sorted0; + const udword* RunningAddress1 = Sorted1; + + while(RunningAddress1GetMax(Axis0)) + { + if(array0[Index0]->Intersect(*array1[Index1], Axis1)) + { + if(array0[Index0]->Intersect(*array1[Index1], Axis2)) + { + pairs.AddPair(Index0, Index1); + } + } + } + } + + //// + + while(RunningAddress0GetMax(Axis0)) + { + if(array0[Index1]->Intersect(*array1[Index0], Axis1)) + { + if(array0[Index1]->Intersect(*array1[Index0], Axis2)) + { + pairs.AddPair(Index1, Index0); + } + } + + } + } + + DELETEARRAY(MinPosList1); + DELETEARRAY(MinPosList0); + + return true; +} + +#define ORIGINAL_VERSION +//#define JOAKIM + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set. + * \param nb [in] number of boxes + * \param array [in] array of boxes + * \param pairs [out] array of overlapping pairs + * \param axes [in] projection order (0,2,1 is often best) + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Opcode::CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes) +{ + // Checkings + if(!nb || !array) return false; + + // Catch axes + udword Axis0 = axes.mAxis0; + udword Axis1 = axes.mAxis1; + udword Axis2 = axes.mAxis2; + +#ifdef ORIGINAL_VERSION + // Allocate some temporary data +// float* PosList = new float[nb]; + float* PosList = new float[nb+1]; + + // 1) Build main list using the primary axis + for(udword i=0;iGetMin(Axis0); +PosList[nb++] = MAX_FLOAT; + + // 2) Sort the list + PRUNING_SORTER* RS = GetCompletePruningSorter(); + const udword* Sorted = RS->Sort(PosList, nb).GetRanks(); + + // 3) Prune the list + const udword* const LastSorted = &Sorted[nb]; + const udword* RunningAddress = Sorted; + udword Index0, Index1; + while(RunningAddressGetMax(Axis0)) + while(PosList[Index1 = *RunningAddress2++]<=array[Index0]->GetMax(Axis0)) + { +// if(Index0!=Index1) +// { + if(array[Index0]->Intersect(*array[Index1], Axis1)) + { + if(array[Index0]->Intersect(*array[Index1], Axis2)) + { + pairs.AddPair(Index0, Index1); + } + } +// } + } + } + } + + DELETEARRAY(PosList); +#endif + +#ifdef JOAKIM + // Allocate some temporary data +// float* PosList = new float[nb]; + float* MinList = new float[nb+1]; + + // 1) Build main list using the primary axis + for(udword i=0;iGetMin(Axis0); + MinList[nb] = MAX_FLOAT; + + // 2) Sort the list + PRUNING_SORTER* RS = GetCompletePruningSorter(); + udword* Sorted = RS->Sort(MinList, nb+1).GetRanks(); + + // 3) Prune the list +// const udword* const LastSorted = &Sorted[nb]; +// const udword* const LastSorted = &Sorted[nb-1]; + const udword* RunningAddress = Sorted; + udword Index0, Index1; + +// while(RunningAddressGetMax(Axis0)) + +// float CurrentMin = array[Index0]->GetMin(Axis0); + float CurrentMax = array[Index0]->GetMax(Axis0); + + while(MinList[Index1 = *RunningAddress2] <= CurrentMax) +// while(PosList[Index1 = *RunningAddress] <= CurrentMax) + { +// if(Index0!=Index1) +// { + if(array[Index0]->Intersect(*array[Index1], Axis1)) + { + if(array[Index0]->Intersect(*array[Index1], Axis2)) + { + pairs.AddPair(Index0, Index1); + } + } +// } + + RunningAddress2++; +// RunningAddress++; + } + } + } + + DELETEARRAY(MinList); +#endif + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Brute-force versions are kept: +// - to check the optimized versions return the correct list of intersections +// - to check the speed of the optimized code against the brute-force one +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Brute-force bipartite box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to a different set. + * \param nb0 [in] number of boxes in the first set + * \param array0 [in] array of boxes for the first set + * \param nb1 [in] number of boxes in the second set + * \param array1 [in] array of boxes for the second set + * \param pairs [out] array of overlapping pairs + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Opcode::BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs) +{ + // Checkings + if(!nb0 || !array0 || !nb1 || !array1) return false; + + // Brute-force nb0*nb1 overlap tests + for(udword i=0;iIntersect(*array1[j])) pairs.AddPair(i, j); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Complete box pruning. Returns a list of overlapping pairs of boxes, each box of the pair belongs to the same set. + * \param nb [in] number of boxes + * \param array [in] array of boxes + * \param pairs [out] array of overlapping pairs + * \return true if success. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Opcode::BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs) +{ + // Checkings + if(!nb || !array) return false; + + // Brute-force n(n-1)/2 overlap tests + for(udword i=0;iIntersect(*array[j])) pairs.AddPair(i, j); + } + } + return true; +} diff --git a/contrib/Opcode/OPC_BoxPruning.h b/contrib/Opcode/OPC_BoxPruning.h new file mode 100644 index 0000000..b431946 --- /dev/null +++ b/contrib/Opcode/OPC_BoxPruning.h @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for box pruning. + * \file IceBoxPruning.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_BOXPRUNING_H__ +#define __OPC_BOXPRUNING_H__ + + // Optimized versions + FUNCTION OPCODE_API bool CompleteBoxPruning(udword nb, const AABB** array, Pairs& pairs, const Axes& axes); + FUNCTION OPCODE_API bool BipartiteBoxPruning(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs, const Axes& axes); + + // Brute-force versions + FUNCTION OPCODE_API bool BruteForceCompleteBoxTest(udword nb, const AABB** array, Pairs& pairs); + FUNCTION OPCODE_API bool BruteForceBipartiteBoxTest(udword nb0, const AABB** array0, udword nb1, const AABB** array1, Pairs& pairs); + +#endif //__OPC_BOXPRUNING_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_Collider.cpp b/contrib/Opcode/OPC_Collider.cpp new file mode 100644 index 0000000..c352618 --- /dev/null +++ b/contrib/Opcode/OPC_Collider.cpp @@ -0,0 +1,54 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base collider class. + * \file OPC_Collider.cpp + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains the abstract class for colliders. + * + * \class Collider + * \author Pierre Terdiman + * \version 1.3 + * \date June, 2, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Collider::Collider() : + mFlags (0), + mCurrentModel (null), + mIMesh (null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Collider::~Collider() +{ +} diff --git a/contrib/Opcode/OPC_Collider.h b/contrib/Opcode/OPC_Collider.h new file mode 100644 index 0000000..d718e02 --- /dev/null +++ b/contrib/Opcode/OPC_Collider.h @@ -0,0 +1,176 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base collider class. + * \file OPC_Collider.h + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_COLLIDER_H__ +#define __OPC_COLLIDER_H__ + + enum CollisionFlag + { + OPC_FIRST_CONTACT = (1<<0), //!< Report all contacts (false) or only first one (true) + OPC_TEMPORAL_COHERENCE = (1<<1), //!< Use temporal coherence or not + OPC_CONTACT = (1<<2), //!< Final contact status after a collision query + OPC_TEMPORAL_HIT = (1<<3), //!< There has been an early exit due to temporal coherence + OPC_NO_PRIMITIVE_TESTS = (1<<4), //!< Keep or discard primitive-bv tests in leaf nodes (volume-mesh queries) + + OPC_CONTACT_FOUND = OPC_FIRST_CONTACT | OPC_CONTACT, + OPC_TEMPORAL_CONTACT = OPC_TEMPORAL_HIT | OPC_CONTACT, + + OPC_FORCE_DWORD = 0x7fffffff + }; + + class OPCODE_API Collider + { + public: + // Constructor / Destructor + Collider(); + virtual ~Collider(); + + // Collision report + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the last collision status after a collision query. + * \return true if a collision occured + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL GetContactStatus() const { return mFlags & OPC_CONTACT; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the "first contact" mode. + * \return true if "first contact" mode is on + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL FirstContactEnabled() const { return mFlags & OPC_FIRST_CONTACT; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the temporal coherence mode. + * \return true if temporal coherence is on + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL TemporalCoherenceEnabled() const { return mFlags & OPC_TEMPORAL_COHERENCE; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks a first contact has already been found. + * \return true if a first contact has been found and we can stop a query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL ContactFound() const { return (mFlags&OPC_CONTACT_FOUND)==OPC_CONTACT_FOUND; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks there's been an early exit due to temporal coherence; + * \return true if a temporal hit has occured + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL TemporalHit() const { return mFlags & OPC_TEMPORAL_HIT; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks primitive tests are enabled; + * \return true if primitive tests must be skipped + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL SkipPrimitiveTests() const { return mFlags & OPC_NO_PRIMITIVE_TESTS; } + + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Reports all contacts (false) or first contact only (true) + * \param flag [in] true for first contact, false for all contacts + * \see SetTemporalCoherence(bool flag) + * \see ValidateSettings() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetFirstContact(bool flag) + { + if(flag) mFlags |= OPC_FIRST_CONTACT; + else mFlags &= ~OPC_FIRST_CONTACT; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Enable/disable temporal coherence. + * \param flag [in] true to enable temporal coherence, false to discard it + * \see SetFirstContact(bool flag) + * \see ValidateSettings() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetTemporalCoherence(bool flag) + { + if(flag) mFlags |= OPC_TEMPORAL_COHERENCE; + else mFlags &= ~OPC_TEMPORAL_COHERENCE; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Enable/disable primitive tests. + * \param flag [in] true to enable primitive tests, false to discard them + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetPrimitiveTests(bool flag) + { + if(!flag) mFlags |= OPC_NO_PRIMITIVE_TESTS; + else mFlags &= ~OPC_NO_PRIMITIVE_TESTS; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual const char* ValidateSettings() = 0; + + protected: + udword mFlags; //!< Bit flags + const BaseModel* mCurrentModel; //!< Current model for collision query (owner of touched faces) + // User mesh interface + const MeshInterface* mIMesh; //!< User-defined mesh interface + + // Internal methods + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups current collision model + * \param model [in] current collision model + * \return TRUE if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL Setup(const BaseModel* model) + { + // Keep track of current model + mCurrentModel = model; + if(!mCurrentModel) return FALSE; + + mIMesh = model->GetMeshInterface(); + return mIMesh!=null; + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Initializes a query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual inline_ void InitQuery() { mFlags &= ~OPC_TEMPORAL_CONTACT; } + }; + +#endif // __OPC_COLLIDER_H__ diff --git a/contrib/Opcode/OPC_Common.cpp b/contrib/Opcode/OPC_Common.cpp new file mode 100644 index 0000000..6bd9722 --- /dev/null +++ b/contrib/Opcode/OPC_Common.cpp @@ -0,0 +1,48 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains common classes & defs used in OPCODE. + * \file OPC_Common.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * An AABB dedicated to collision detection. + * We don't use the generic AABB class included in ICE, since it can be a Min/Max or a Center/Extents one (depends + * on compilation flags). Since the Center/Extents model is more efficient in collision detection, it was worth + * using an extra special class. + * + * \class CollisionAABB + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A quantized AABB. + * Center/Extent model, using 16-bits integers. + * + * \class QuantizedAABB + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; diff --git a/contrib/Opcode/OPC_Common.h b/contrib/Opcode/OPC_Common.h new file mode 100644 index 0000000..84ccf8d --- /dev/null +++ b/contrib/Opcode/OPC_Common.h @@ -0,0 +1,101 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains common classes & defs used in OPCODE. + * \file OPC_Common.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_COMMON_H__ +#define __OPC_COMMON_H__ + +// [GOTTFRIED]: Just a small change for readability. +#ifdef OPC_CPU_COMPARE + #define GREATER(x, y) AIR(x) > IR(y) +#else + #define GREATER(x, y) fabsf(x) > (y) +#endif + + class OPCODE_API CollisionAABB + { + public: + //! Constructor + inline_ CollisionAABB() {} + //! Constructor + inline_ CollisionAABB(const AABB& b) { b.GetCenter(mCenter); b.GetExtents(mExtents); } + //! Destructor + inline_ ~CollisionAABB() {} + + //! Get min IcePoint of the box + inline_ void GetMin(IcePoint& min) const { min = mCenter - mExtents; } + //! Get max IcePoint of the box + inline_ void GetMax(IcePoint& max) const { max = mCenter + mExtents; } + + //! Get component of the box's min IcePoint along a given axis + inline_ float GetMin(udword axis) const { return mCenter[axis] - mExtents[axis]; } + //! Get component of the box's max IcePoint along a given axis + inline_ float GetMax(udword axis) const { return mCenter[axis] + mExtents[axis]; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Setups an AABB from min & max vectors. + * \param min [in] the min IcePoint + * \param max [in] the max IcePoint + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetMinMax(const IcePoint& min, const IcePoint& max) { mCenter = (max + min)*0.5f; mExtents = (max - min)*0.5f; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks a box is inside another box. + * \param box [in] the other box + * \return true if current box is inside input box + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ BOOL IsInside(const CollisionAABB& box) const + { + if(box.GetMin(0)>GetMin(0)) return FALSE; + if(box.GetMin(1)>GetMin(1)) return FALSE; + if(box.GetMin(2)>GetMin(2)) return FALSE; + if(box.GetMax(0)IsValid()) return false; + + // Look for degenerate faces. + udword NbDegenerate = create.mIMesh->CheckTopology(); + if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate); + // We continue nonetheless.... + + Release(); // Make sure previous tree has been discarded + + // 1-1) Setup mesh interface automatically + SetMeshInterface(create.mIMesh); + + bool Status = false; + AABBTree* LeafTree = null; + Internal Data; + + // 2) Build a generic AABB Tree. + mSource = new AABBTree; + CHECKALLOC(mSource); + + // 2-1) Setup a builder. Our primitives here are triangles from input mesh, + // so we use an AABBTreeOfTrianglesBuilder..... + { + AABBTreeOfTrianglesBuilder TB; + TB.mIMesh = create.mIMesh; + TB.mNbPrimitives = create.mIMesh->GetNbTriangles(); + TB.mSettings = create.mSettings; + TB.mSettings.mLimit = 16; // ### Hardcoded, but maybe we could let the user choose 8 / 16 / 32 ... + if(!mSource->Build(&TB)) goto FreeAndExit; + } + + // 2-2) Here's the trick : create *another* AABB tree using the leaves of the first one (which are boxes, this time) + struct Local + { + // A callback to count leaf nodes + static bool CountLeaves(const AABBTreeNode* current, udword depth, void* user_data) + { + if(current->IsLeaf()) + { + Internal* Data = (Internal*)user_data; + Data->mNbLeaves++; + } + return true; + } + + // A callback to setup leaf nodes in our internal structures + static bool SetupLeafData(const AABBTreeNode* current, udword depth, void* user_data) + { + if(current->IsLeaf()) + { + Internal* Data = (Internal*)user_data; + + // Get current leaf's box + Data->mLeaves[Data->mNbLeaves] = *current->GetAABB(); + + // Setup leaf data + udword Index = (udword(current->GetPrimitives()) - udword(Data->mBase))/sizeof(udword); + Data->mTriangles[Data->mNbLeaves].SetData(current->GetNbPrimitives(), Index); + + Data->mNbLeaves++; + } + return true; + } + }; + + // Walk the tree & count number of leaves + Data.mNbLeaves = 0; + mSource->Walk(Local::CountLeaves, &Data); + mNbLeaves = Data.mNbLeaves; // Keep track of it + + // Special case for 1-leaf meshes + if(mNbLeaves==1) + { + mModelCode |= OPC_SINGLE_NODE; + Status = true; + goto FreeAndExit; + } + + // Allocate our structures + Data.mLeaves = new AABB[Data.mNbLeaves]; CHECKALLOC(Data.mLeaves); + mTriangles = new LeafTriangles[Data.mNbLeaves]; CHECKALLOC(mTriangles); + + // Walk the tree again & setup leaf data + Data.mTriangles = mTriangles; + Data.mBase = mSource->GetIndices(); + Data.mNbLeaves = 0; // Reset for incoming walk + mSource->Walk(Local::SetupLeafData, &Data); + + // Handle source indices + { + bool MustKeepIndices = true; + if(create.mCanRemap) + { + // We try to get rid of source indices (saving more ram!) by reorganizing triangle arrays... + // Remap can fail when we use callbacks => keep track of indices in that case (it still + // works, only using more memory) + if(create.mIMesh->RemapClient(mSource->GetNbPrimitives(), mSource->GetIndices())) + { + MustKeepIndices = false; + } + } + + if(MustKeepIndices) + { + // Keep track of source indices (from vanilla tree) + mNbPrimitives = mSource->GetNbPrimitives(); + mIndices = new udword[mNbPrimitives]; + CopyMemory(mIndices, mSource->GetIndices(), mNbPrimitives*sizeof(udword)); + } + } + + // Now, create our optimized tree using previous leaf nodes + LeafTree = new AABBTree; + CHECKALLOC(LeafTree); + { + AABBTreeOfAABBsBuilder TB; // Now using boxes ! + TB.mSettings = create.mSettings; + TB.mSettings.mLimit = 1; // We now want a complete tree so that we can "optimize" it + TB.mNbPrimitives = Data.mNbLeaves; + TB.mAABBArray = Data.mLeaves; + if(!LeafTree->Build(&TB)) goto FreeAndExit; + } + + // 3) Create an optimized tree according to user-settings + if(!CreateTree(create.mNoLeaf, create.mQuantized)) goto FreeAndExit; + + // 3-2) Create optimized tree + if(!mTree->Build(LeafTree)) goto FreeAndExit; + + // Finally ok... + Status = true; + +FreeAndExit: // Allow me this one... + DELETESINGLE(LeafTree); + + // 3-3) Delete generic tree if needed + if(!create.mKeepOriginal) DELETESINGLE(mSource); + + return Status; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword HybridModel::GetUsedBytes() const +{ + udword UsedBytes = 0; + if(mTree) UsedBytes += mTree->GetUsedBytes(); + if(mIndices) UsedBytes += mNbPrimitives * sizeof(udword); // mIndices + if(mTriangles) UsedBytes += mNbLeaves * sizeof(LeafTriangles); // mTriangles + return UsedBytes; +} + +inline_ void ComputeMinMax(IcePoint& min, IcePoint& max, const VertexPointers& vp) +{ + // Compute triangle's AABB = a leaf box +#ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much + min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); + max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); + + min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); + max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); + + min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); + max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); +#else + min = *vp.Vertex[0]; + max = *vp.Vertex[0]; + min.Min(*vp.Vertex[1]); + max.Max(*vp.Vertex[1]); + min.Min(*vp.Vertex[2]); + max.Max(*vp.Vertex[2]); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the collision model. This can be used to handle dynamic meshes. Usage is: + * 1. modify your mesh vertices (keep the topology constant!) + * 2. refit the tree (call this method) + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool HybridModel::Refit() +{ + if(!mIMesh) return false; + if(!mTree) return false; + + if(IsQuantized()) return false; + if(HasLeafNodes()) return false; + + const LeafTriangles* LT = GetLeafTriangles(); + const udword* Indices = GetIndices(); + + // Bottom-up update + VertexPointers VP; + IcePoint Min,Max; + IcePoint Min_,Max_; + udword Index = mTree->GetNbNodes(); + AABBNoLeafNode* Nodes = (AABBNoLeafNode*)((AABBNoLeafTree*)mTree)->GetNodes(); + while(Index--) + { + AABBNoLeafNode& Current = Nodes[Index]; + + if(Current.HasPosLeaf()) + { + const LeafTriangles& CurrentLeaf = LT[Current.GetPosPrimitive()]; + + Min.SetPlusInfinity(); + Max.SetMinusInfinity(); + + IcePoint TmpMin, TmpMax; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + mIMesh->GetTriangle(VP, *T++); + ComputeMinMax(TmpMin, TmpMax, VP); + Min.Min(TmpMin); + Max.Max(TmpMax); + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + mIMesh->GetTriangle(VP, BaseIndex++); + ComputeMinMax(TmpMin, TmpMax, VP); + Min.Min(TmpMin); + Max.Max(TmpMax); + } + } + } + else + { + const CollisionAABB& CurrentBox = Current.GetPos()->mAABB; + CurrentBox.GetMin(Min); + CurrentBox.GetMax(Max); + } + + if(Current.HasNegLeaf()) + { + const LeafTriangles& CurrentLeaf = LT[Current.GetNegPrimitive()]; + + Min_.SetPlusInfinity(); + Max_.SetMinusInfinity(); + + IcePoint TmpMin, TmpMax; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + mIMesh->GetTriangle(VP, *T++); + ComputeMinMax(TmpMin, TmpMax, VP); + Min_.Min(TmpMin); + Max_.Max(TmpMax); + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + mIMesh->GetTriangle(VP, BaseIndex++); + ComputeMinMax(TmpMin, TmpMax, VP); + Min_.Min(TmpMin); + Max_.Max(TmpMax); + } + } + } + else + { + const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB; + CurrentBox.GetMin(Min_); + CurrentBox.GetMax(Max_); + } +#ifdef OPC_USE_FCOMI + Min.x = FCMin2(Min.x, Min_.x); + Max.x = FCMax2(Max.x, Max_.x); + Min.y = FCMin2(Min.y, Min_.y); + Max.y = FCMax2(Max.y, Max_.y); + Min.z = FCMin2(Min.z, Min_.z); + Max.z = FCMax2(Max.z, Max_.z); +#else + Min.Min(Min_); + Max.Max(Max_); +#endif + Current.mAABB.SetMinMax(Min, Max); + } + return true; +} diff --git a/contrib/Opcode/OPC_HybridModel.h b/contrib/Opcode/OPC_HybridModel.h new file mode 100644 index 0000000..c7eb59d --- /dev/null +++ b/contrib/Opcode/OPC_HybridModel.h @@ -0,0 +1,106 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for hybrid models. + * \file OPC_HybridModel.h + * \author Pierre Terdiman + * \date May, 18, 2003 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_HYBRIDMODEL_H__ +#define __OPC_HYBRIDMODEL_H__ + + //! Leaf descriptor + struct LeafTriangles + { + udword Data; //!< Packed data + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets number of triangles in the leaf. + * \return number of triangles N, with 0 < N <= 16 + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbTriangles() const { return (Data & 15)+1; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets triangle index for this leaf. Indexed model's array of indices retrieved with HybridModel::GetIndices() + * \return triangle index + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetTriangleIndex() const { return Data>>4; } + inline_ void SetData(udword nb, udword index) { ASSERT(nb>0 && nb<=16); nb--; Data = (index<<4)|(nb&15); } + }; + + class OPCODE_API HybridModel : public BaseModel + { + public: + // Constructor/Destructor + HybridModel(); + virtual ~HybridModel(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds a collision model. + * \param create [in] model creation structure + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) bool Build(const OPCODECREATE& create); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) udword GetUsedBytes() const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the collision model. This can be used to handle dynamic meshes. Usage is: + * 1. modify your mesh vertices (keep the topology constant!) + * 2. refit the tree (call this method) + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) bool Refit(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets array of triangles. + * \return array of triangles + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const LeafTriangles* GetLeafTriangles() const { return mTriangles; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets array of indices. + * \return array of indices + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const udword* GetIndices() const { return mIndices; } + + private: + udword mNbLeaves; //!< Number of leaf nodes in the model + LeafTriangles* mTriangles; //!< Array of mNbLeaves leaf descriptors + udword mNbPrimitives; //!< Number of primitives in the model + udword* mIndices; //!< Array of primitive indices + + // Internal methods + void Release(); + }; + +#endif // __OPC_HYBRIDMODEL_H__ diff --git a/contrib/Opcode/OPC_IceHook.h b/contrib/Opcode/OPC_IceHook.h new file mode 100644 index 0000000..d33120b --- /dev/null +++ b/contrib/Opcode/OPC_IceHook.h @@ -0,0 +1,70 @@ + +// Should be included by Opcode.h if needed + + #define ICE_DONT_CHECK_COMPILER_OPTIONS + + // From Windows... + typedef int BOOL; + #ifndef FALSE + #define FALSE 0 + #endif + + #ifndef TRUE + #define TRUE 1 + #endif + + #include + #include + #include + #include + #include + #include + + #ifndef ASSERT + #define ASSERT(exp) {} + #endif + #define ICE_COMPILE_TIME_ASSERT(exp) extern char ICE_Dummy[ (exp) ? 1 : -1 ] + + #define Log {} + #define SetIceError false + #define EC_OUTOFMEMORY "Out of memory" + + #include "Ice/IcePreprocessor.h" + + #undef ICECORE_API + #define ICECORE_API OPCODE_API + + #include "Ice/IceTypes.h" + #include "Ice/IceFPU.h" + #include "Ice/IceMemoryMacros.h" + + namespace IceCore + { + #include "Ice/IceUtils.h" + #include "Ice/IceContainer.h" + #include "Ice/IcePairs.h" + #include "Ice/IceRevisitedRadix.h" + #include "Ice/IceRandom.h" + } + using namespace IceCore; + + #define ICEMATHS_API OPCODE_API + namespace IceMaths + { + #include "Ice/IceAxes.h" + #include "Ice/IcePoint.h" + #include "Ice/IceHPoint.h" + #include "Ice/IceMatrix3x3.h" + #include "Ice/IceMatrix4x4.h" + #include "Ice/IcePlane.h" + #include "Ice/IceRay.h" + #include "Ice/IceIndexedTriangle.h" + #include "Ice/IceTriangle.h" + #include "Ice/IceTrilist.h" + #include "Ice/IceAABB.h" + #include "Ice/IceOBB.h" + #include "Ice/IceBoundingSphere.h" + #include "Ice/IceSegment.h" + #include "Ice/IceLSS.h" + } + using namespace IceMaths; diff --git a/contrib/Opcode/OPC_LSSAABBOverlap.h b/contrib/Opcode/OPC_LSSAABBOverlap.h new file mode 100644 index 0000000..5afb190 --- /dev/null +++ b/contrib/Opcode/OPC_LSSAABBOverlap.h @@ -0,0 +1,523 @@ + +// Following code from Magic-Software (http://www.magic-software.com/) +// A bit modified for Opcode + +inline_ float OPC_PointAABBSqrDist(const IcePoint& Point, const IcePoint& center, const IcePoint& extents) +{ + // Compute coordinates of IcePoint in box coordinate system + IcePoint Closest = Point - center; + + float SqrDistance = 0.0f; + + if(Closest.x < -extents.x) + { + float Delta = Closest.x + extents.x; + SqrDistance += Delta*Delta; + } + else if(Closest.x > extents.x) + { + float Delta = Closest.x - extents.x; + SqrDistance += Delta*Delta; + } + + if(Closest.y < -extents.y) + { + float Delta = Closest.y + extents.y; + SqrDistance += Delta*Delta; + } + else if(Closest.y > extents.y) + { + float Delta = Closest.y - extents.y; + SqrDistance += Delta*Delta; + } + + if(Closest.z < -extents.z) + { + float Delta = Closest.z + extents.z; + SqrDistance += Delta*Delta; + } + else if(Closest.z > extents.z) + { + float Delta = Closest.z - extents.z; + SqrDistance += Delta*Delta; + } + return SqrDistance; +} + +static void Face(int i0, int i1, int i2, IcePoint& rkPnt, const IcePoint& rkDir, const IcePoint& extents, const IcePoint& rkPmE, float* pfLParam, float& rfSqrDistance) +{ + IcePoint kPpE; + float fLSqr, fInv, fTmp, fParam, fT, fDelta; + + kPpE[i1] = rkPnt[i1] + extents[i1]; + kPpE[i2] = rkPnt[i2] + extents[i2]; + if(rkDir[i0]*kPpE[i1] >= rkDir[i1]*rkPmE[i0]) + { + if(rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0]) + { + // v[i1] >= -e[i1], v[i2] >= -e[i2] (distance = 0) + if(pfLParam) + { + rkPnt[i0] = extents[i0]; + fInv = 1.0f/rkDir[i0]; + rkPnt[i1] -= rkDir[i1]*rkPmE[i0]*fInv; + rkPnt[i2] -= rkDir[i2]*rkPmE[i0]*fInv; + *pfLParam = -rkPmE[i0]*fInv; + } + } + else + { + // v[i1] >= -e[i1], v[i2] < -e[i2] + fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i2]*rkDir[i2]; + fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]); + if(fTmp <= 2.0f*fLSqr*extents[i1]) + { + fT = fTmp/fLSqr; + fLSqr += rkDir[i1]*rkDir[i1]; + fTmp = kPpE[i1] - fT; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = fT - extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + else + { + fLSqr += rkDir[i1]*rkDir[i1]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + } + } + else + { + if ( rkDir[i0]*kPpE[i2] >= rkDir[i2]*rkPmE[i0] ) + { + // v[i1] < -e[i1], v[i2] >= -e[i2] + fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]; + fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]); + if(fTmp <= 2.0f*fLSqr*extents[i2]) + { + fT = fTmp/fLSqr; + fLSqr += rkDir[i2]*rkDir[i2]; + fTmp = kPpE[i2] - fT; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = fT - extents[i2]; + } + } + else + { + fLSqr += rkDir[i2]*rkDir[i2]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = extents[i2]; + } + } + } + else + { + // v[i1] < -e[i1], v[i2] < -e[i2] + fLSqr = rkDir[i0]*rkDir[i0]+rkDir[i2]*rkDir[i2]; + fTmp = fLSqr*kPpE[i1] - rkDir[i1]*(rkDir[i0]*rkPmE[i0] + rkDir[i2]*kPpE[i2]); + if(fTmp >= 0.0f) + { + // v[i1]-edge is closest + if ( fTmp <= 2.0f*fLSqr*extents[i1] ) + { + fT = fTmp/fLSqr; + fLSqr += rkDir[i1]*rkDir[i1]; + fTmp = kPpE[i1] - fT; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*fTmp + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + fTmp*fTmp + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = fT - extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + else + { + fLSqr += rkDir[i1]*rkDir[i1]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*rkPmE[i1] + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + rkPmE[i1]*rkPmE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + return; + } + + fLSqr = rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]; + fTmp = fLSqr*kPpE[i2] - rkDir[i2]*(rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1]); + if(fTmp >= 0.0f) + { + // v[i2]-edge is closest + if(fTmp <= 2.0f*fLSqr*extents[i2]) + { + fT = fTmp/fLSqr; + fLSqr += rkDir[i2]*rkDir[i2]; + fTmp = kPpE[i2] - fT; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*fTmp; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + fTmp*fTmp + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = fT - extents[i2]; + } + } + else + { + fLSqr += rkDir[i2]*rkDir[i2]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*rkPmE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + rkPmE[i2]*rkPmE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = extents[i2]; + } + } + return; + } + + // (v[i1],v[i2])-corner is closest + fLSqr += rkDir[i2]*rkDir[i2]; + fDelta = rkDir[i0]*rkPmE[i0] + rkDir[i1]*kPpE[i1] + rkDir[i2]*kPpE[i2]; + fParam = -fDelta/fLSqr; + rfSqrDistance += rkPmE[i0]*rkPmE[i0] + kPpE[i1]*kPpE[i1] + kPpE[i2]*kPpE[i2] + fDelta*fParam; + + if(pfLParam) + { + *pfLParam = fParam; + rkPnt[i0] = extents[i0]; + rkPnt[i1] = -extents[i1]; + rkPnt[i2] = -extents[i2]; + } + } + } +} + +static void CaseNoZeros(IcePoint& rkPnt, const IcePoint& rkDir, const IcePoint& extents, float* pfLParam, float& rfSqrDistance) +{ + IcePoint kPmE(rkPnt.x - extents.x, rkPnt.y - extents.y, rkPnt.z - extents.z); + + float fProdDxPy, fProdDyPx, fProdDzPx, fProdDxPz, fProdDzPy, fProdDyPz; + + fProdDxPy = rkDir.x*kPmE.y; + fProdDyPx = rkDir.y*kPmE.x; + if(fProdDyPx >= fProdDxPy) + { + fProdDzPx = rkDir.z*kPmE.x; + fProdDxPz = rkDir.x*kPmE.z; + if(fProdDzPx >= fProdDxPz) + { + // line intersects x = e0 + Face(0, 1, 2, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); + } + else + { + // line intersects z = e2 + Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); + } + } + else + { + fProdDzPy = rkDir.z*kPmE.y; + fProdDyPz = rkDir.y*kPmE.z; + if(fProdDzPy >= fProdDyPz) + { + // line intersects y = e1 + Face(1, 2, 0, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); + } + else + { + // line intersects z = e2 + Face(2, 0, 1, rkPnt, rkDir, extents, kPmE, pfLParam, rfSqrDistance); + } + } +} + +static void Case0(int i0, int i1, int i2, IcePoint& rkPnt, const IcePoint& rkDir, const IcePoint& extents, float* pfLParam, float& rfSqrDistance) +{ + float fPmE0 = rkPnt[i0] - extents[i0]; + float fPmE1 = rkPnt[i1] - extents[i1]; + float fProd0 = rkDir[i1]*fPmE0; + float fProd1 = rkDir[i0]*fPmE1; + float fDelta, fInvLSqr, fInv; + + if(fProd0 >= fProd1) + { + // line intersects P[i0] = e[i0] + rkPnt[i0] = extents[i0]; + + float fPpE1 = rkPnt[i1] + extents[i1]; + fDelta = fProd0 - rkDir[i0]*fPpE1; + if(fDelta >= 0.0f) + { + fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]); + rfSqrDistance += fDelta*fDelta*fInvLSqr; + if(pfLParam) + { + rkPnt[i1] = -extents[i1]; + *pfLParam = -(rkDir[i0]*fPmE0+rkDir[i1]*fPpE1)*fInvLSqr; + } + } + else + { + if(pfLParam) + { + fInv = 1.0f/rkDir[i0]; + rkPnt[i1] -= fProd0*fInv; + *pfLParam = -fPmE0*fInv; + } + } + } + else + { + // line intersects P[i1] = e[i1] + rkPnt[i1] = extents[i1]; + + float fPpE0 = rkPnt[i0] + extents[i0]; + fDelta = fProd1 - rkDir[i1]*fPpE0; + if(fDelta >= 0.0f) + { + fInvLSqr = 1.0f/(rkDir[i0]*rkDir[i0] + rkDir[i1]*rkDir[i1]); + rfSqrDistance += fDelta*fDelta*fInvLSqr; + if(pfLParam) + { + rkPnt[i0] = -extents[i0]; + *pfLParam = -(rkDir[i0]*fPpE0+rkDir[i1]*fPmE1)*fInvLSqr; + } + } + else + { + if(pfLParam) + { + fInv = 1.0f/rkDir[i1]; + rkPnt[i0] -= fProd1*fInv; + *pfLParam = -fPmE1*fInv; + } + } + } + + if(rkPnt[i2] < -extents[i2]) + { + fDelta = rkPnt[i2] + extents[i2]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i2] = -extents[i2]; + } + else if ( rkPnt[i2] > extents[i2] ) + { + fDelta = rkPnt[i2] - extents[i2]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i2] = extents[i2]; + } +} + +static void Case00(int i0, int i1, int i2, IcePoint& rkPnt, const IcePoint& rkDir, const IcePoint& extents, float* pfLParam, float& rfSqrDistance) +{ + float fDelta; + + if(pfLParam) + *pfLParam = (extents[i0] - rkPnt[i0])/rkDir[i0]; + + rkPnt[i0] = extents[i0]; + + if(rkPnt[i1] < -extents[i1]) + { + fDelta = rkPnt[i1] + extents[i1]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i1] = -extents[i1]; + } + else if(rkPnt[i1] > extents[i1]) + { + fDelta = rkPnt[i1] - extents[i1]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i1] = extents[i1]; + } + + if(rkPnt[i2] < -extents[i2]) + { + fDelta = rkPnt[i2] + extents[i2]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i1] = -extents[i2]; + } + else if(rkPnt[i2] > extents[i2]) + { + fDelta = rkPnt[i2] - extents[i2]; + rfSqrDistance += fDelta*fDelta; + rkPnt[i2] = extents[i2]; + } +} + +static void Case000(IcePoint& rkPnt, const IcePoint& extents, float& rfSqrDistance) +{ + float fDelta; + + if(rkPnt.x < -extents.x) + { + fDelta = rkPnt.x + extents.x; + rfSqrDistance += fDelta*fDelta; + rkPnt.x = -extents.x; + } + else if(rkPnt.x > extents.x) + { + fDelta = rkPnt.x - extents.x; + rfSqrDistance += fDelta*fDelta; + rkPnt.x = extents.x; + } + + if(rkPnt.y < -extents.y) + { + fDelta = rkPnt.y + extents.y; + rfSqrDistance += fDelta*fDelta; + rkPnt.y = -extents.y; + } + else if(rkPnt.y > extents.y) + { + fDelta = rkPnt.y - extents.y; + rfSqrDistance += fDelta*fDelta; + rkPnt.y = extents.y; + } + + if(rkPnt.z < -extents.z) + { + fDelta = rkPnt.z + extents.z; + rfSqrDistance += fDelta*fDelta; + rkPnt.z = -extents.z; + } + else if(rkPnt.z > extents.z) + { + fDelta = rkPnt.z - extents.z; + rfSqrDistance += fDelta*fDelta; + rkPnt.z = extents.z; + } +} + +static float SqrDistance(const Ray& rkLine, const IcePoint& center, const IcePoint& extents, float* pfLParam) +{ + // compute coordinates of line in box coordinate system + IcePoint kDiff = rkLine.mOrig - center; + IcePoint kPnt = kDiff; + IcePoint kDir = rkLine.mDir; + + // Apply reflections so that direction vector has nonnegative components. + bool bReflect[3]; + for(int i=0;i<3;i++) + { + if(kDir[i]<0.0f) + { + kPnt[i] = -kPnt[i]; + kDir[i] = -kDir[i]; + bReflect[i] = true; + } + else + { + bReflect[i] = false; + } + } + + float fSqrDistance = 0.0f; + + if(kDir.x>0.0f) + { + if(kDir.y>0.0f) + { + if(kDir.z>0.0f) CaseNoZeros(kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,+,+) + else Case0(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,+,0) + } + else + { + if(kDir.z>0.0f) Case0(0, 2, 1, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,0,+) + else Case00(0, 1, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (+,0,0) + } + } + else + { + if(kDir.y>0.0f) + { + if(kDir.z>0.0f) Case0(1, 2, 0, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,+,+) + else Case00(1, 0, 2, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,+,0) + } + else + { + if(kDir.z>0.0f) Case00(2, 0, 1, kPnt, kDir, extents, pfLParam, fSqrDistance); // (0,0,+) + else + { + Case000(kPnt, extents, fSqrDistance); // (0,0,0) + if(pfLParam) *pfLParam = 0.0f; + } + } + } + return fSqrDistance; +} + +inline_ float OPC_SegmentOBBSqrDist(const IceSegment& segment, const IcePoint& c0, const IcePoint& e0) +{ + float fLP; + float fSqrDistance = SqrDistance(Ray(segment.GetOrigin(), segment.ComputeDirection()), c0, e0, &fLP); + if(fLP>=0.0f) + { + if(fLP<=1.0f) return fSqrDistance; + else return OPC_PointAABBSqrDist(segment.mP1, c0, e0); + } + else return OPC_PointAABBSqrDist(segment.mP0, c0, e0); +} + +inline_ BOOL LSSCollider::LSSAABBOverlap(const IcePoint& center, const IcePoint& extents) +{ + // Stats + mNbVolumeBVTests++; + + float s2 = OPC_SegmentOBBSqrDist(mSeg, center, extents); + if(s2Add(prim_index); + +//! LSS-triangle overlap test +#define LSS_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ + \ + /* Perform LSS-tri overlap test */ \ + if(LSSTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +LSSCollider::LSSCollider() +{ +// mCenter.Zero(); +// mRadius2 = 0.0f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +LSSCollider::~LSSCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] an lss cache + * \param lss [in] collision lss in local space + * \param model [in] Opcode model to collide with + * \param worldl [in] lss world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl, const Matrix4x4* worldm) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, lss, worldl, worldm)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - setup matrices + * - check temporal coherence + * + * \param cache [in/out] an lss cache + * \param lss [in] lss in local space + * \param worldl [in] lss world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL LSSCollider::InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl, const Matrix4x4* worldm) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Compute LSS in model space: + // - Precompute R^2 + mRadius2 = lss.mRadius * lss.mRadius; + // - Compute segment + mSeg.mP0 = lss.mP0; + mSeg.mP1 = lss.mP1; + // -> to world space + if(worldl) + { + mSeg.mP0 *= *worldl; + mSeg.mP1 *= *worldl; + } + // -> to model space + if(worldm) + { + // Invert model matrix + Matrix4x4 InvWorldM; + InvertPRMatrix(InvWorldM, *worldm); + + mSeg.mP0 *= InvWorldM; + mSeg.mP1 *= InvWorldM; + } + + // 3) Setup destination pointer + mTouchedPrimitives = &cache.TouchedPrimitives; + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the LSS (and set contact status if needed) + LSS_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // 5) Check temporal coherence : + if(TemporalCoherenceEnabled()) + { + // Here we use temporal coherence + // => check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the LSS (and set contact status if needed) + LSS_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; + } + // else no face has been touched during previous query + // => we'll have to perform a normal query + } + else + { + // We're interested in all contacts =>test the new real LSS N(ew) against the previous fat LSS P(revious): + + // ### rewrite this + + LSS Test(mSeg, lss.mRadius); // in model space + LSS Previous(cache.Previous, sqrtf(cache.Previous.mRadius)); + +// if(cache.Previous.Contains(Test)) + if(IsCacheValid(cache) && Previous.Contains(Test)) + { + // - if N is included in P, return previous list + // => we simply leave the list (mTouchedFaces) unchanged + + // Set contact status if needed + if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; + + // In any case we don't need to do a query + return TRUE; + } + else + { + // - else do the query using a fat N + + // Reset cache since we'll about to perform a real query + mTouchedPrimitives->Reset(); + + // Make a fat sphere so that coherence will work for subsequent frames + mRadius2 *= cache.FatCoeff; +// mRadius2 = (lss.mRadius * cache.FatCoeff)*(lss.mRadius * cache.FatCoeff); + + + // Update cache with query data (signature for cached faces) + cache.Previous.mP0 = mSeg.mP0; + cache.Previous.mP1 = mSeg.mP1; + cache.Previous.mRadius = mRadius2; + } + } + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for vanilla AABB trees. + * \param cache [in/out] an lss cache + * \param lss [in] collision lss in world space + * \param tree [in] AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool LSSCollider::Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree) +{ + // This is typically called for a scene tree, full of -AABBs-, not full of triangles. + // So we don't really have "primitives" to deal with. Hence it doesn't work with + // "FirstContact" + "TemporalCoherence". + ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); + + // Checkings + if(!tree) return false; + + // Init collision query + if(InitQuery(cache, lss)) return true; + + // Perform collision query + _Collide(tree); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the LSS completely contains the box. In which case we can end the query sooner. + * \param bc [in] box center + * \param be [in] box extents + * \return true if the LSS contains the whole box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL LSSCollider::LSSContainsBox(const IcePoint& bc, const IcePoint& be) +{ + // Not implemented + return FALSE; +} + +#define TEST_BOX_IN_LSS(center, extents) \ + if(LSSContainsBox(center, extents)) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBCollisionNode* node) +{ + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + LSS_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) +{ + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_LSS(Center, Extents) + + if(node->IsLeaf()) + { + LSS_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_LSS(Center, Extents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBNoLeafNode* node) +{ + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) +{ + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_LSS(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_LSS(Center, Extents) + + if(node->HasPosLeaf()) { LSS_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { LSS_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform LSS-AABB overlap test + if(!LSSAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_LSS(Center, Extents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for vanilla AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void LSSCollider::_Collide(const AABBTreeNode* node) +{ + // Perform LSS-AABB overlap test + IcePoint Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!LSSAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf() || LSSContainsBox(Center, Extents)) + { + mFlags |= OPC_CONTACT; + mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _Collide(node->GetPos()); + _Collide(node->GetNeg()); + } +} + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridLSSCollider::HybridLSSCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridLSSCollider::~HybridLSSCollider() +{ +} + +bool HybridLSSCollider::Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl, const Matrix4x4* worldm) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, lss, worldl, worldm)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + for(udword i=0;imCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + while(Nb--) + { + const LeafTriangles& CurrentLeaf = LT[*Touched++]; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = *T++; + LSS_PRIM(TriangleIndex, OPC_CONTACT) + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = BaseIndex++; + LSS_PRIM(TriangleIndex, OPC_CONTACT) + } + } + } + } + + return true; +} diff --git a/contrib/Opcode/OPC_LSSCollider.h b/contrib/Opcode/OPC_LSSCollider.h new file mode 100644 index 0000000..426564c --- /dev/null +++ b/contrib/Opcode/OPC_LSSCollider.h @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an LSS collider. + * \file OPC_LSSCollider.h + * \author Pierre Terdiman + * \date December, 28, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_LSSCOLLIDER_H__ +#define __OPC_LSSCOLLIDER_H__ + + struct OPCODE_API LSSCache : VolumeCache + { + LSSCache() + { + Previous.mP0 = IcePoint(0.0f, 0.0f, 0.0f); + Previous.mP1 = IcePoint(0.0f, 0.0f, 0.0f); + Previous.mRadius = 0.0f; + FatCoeff = 1.1f; + } + + // Cached faces signature + LSS Previous; //!< LSS used when performing the query resulting in cached faces + // User settings + float FatCoeff; //!< mRadius2 multiplier used to create a fat LSS + }; + + class OPCODE_API LSSCollider : public VolumeCollider + { + public: + // Constructor / Destructor + LSSCollider(); + virtual ~LSSCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] an lss cache + * \param lss [in] collision lss in local space + * \param model [in] Opcode model to collide with + * \param worldl [in] lss world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(LSSCache& cache, const LSS& lss, const Model& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); + // + bool Collide(LSSCache& cache, const LSS& lss, const AABBTree* tree); + protected: + // LSS in model space + IceSegment mSeg; //!< IceSegment + float mRadius2; //!< LSS radius squared + // Internal methods + void _Collide(const AABBCollisionNode* node); + void _Collide(const AABBNoLeafNode* node); + void _Collide(const AABBQuantizedNode* node); + void _Collide(const AABBQuantizedNoLeafNode* node); + void _Collide(const AABBTreeNode* node); + void _CollideNoPrimitiveTest(const AABBCollisionNode* node); + void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); + // Overlap tests + inline_ BOOL LSSContainsBox(const IcePoint& bc, const IcePoint& be); + inline_ BOOL LSSAABBOverlap(const IcePoint& center, const IcePoint& extents); + inline_ BOOL LSSTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2); + // Init methods + BOOL InitQuery(LSSCache& cache, const LSS& lss, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); + }; + + class OPCODE_API HybridLSSCollider : public LSSCollider + { + public: + // Constructor / Destructor + HybridLSSCollider(); + virtual ~HybridLSSCollider(); + + bool Collide(LSSCache& cache, const LSS& lss, const HybridModel& model, const Matrix4x4* worldl=null, const Matrix4x4* worldm=null); + protected: + Container mTouchedBoxes; + }; + +#endif // __OPC_LSSCOLLIDER_H__ diff --git a/contrib/Opcode/OPC_LSSTriOverlap.h b/contrib/Opcode/OPC_LSSTriOverlap.h new file mode 100644 index 0000000..9957534 --- /dev/null +++ b/contrib/Opcode/OPC_LSSTriOverlap.h @@ -0,0 +1,679 @@ +// Following code from Magic-Software (http://www.magic-software.com/) +// A bit modified for Opcode + +static const float gs_fTolerance = 1e-05f; + +static float OPC_PointTriangleSqrDist(const IcePoint& Point, const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) +{ + // Hook + IcePoint TriEdge0 = p1 - p0; + IcePoint TriEdge1 = p2 - p0; + + IcePoint kDiff = p0 - Point; + float fA00 = TriEdge0.SquareMagnitude(); + float fA01 = TriEdge0 | TriEdge1; + float fA11 = TriEdge1.SquareMagnitude(); + float fB0 = kDiff | TriEdge0; + float fB1 = kDiff | TriEdge1; + float fC = kDiff.SquareMagnitude(); + float fDet = fabsf(fA00*fA11 - fA01*fA01); + float fS = fA01*fB1-fA11*fB0; + float fT = fA01*fB0-fA00*fB1; + float fSqrDist; + + if(fS + fT <= fDet) + { + if(fS < 0.0f) + { + if(fT < 0.0f) // region 4 + { + if(fB0 < 0.0f) + { + if(-fB0 >= fA00) fSqrDist = fA00+2.0f*fB0+fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + if(fB1 >= 0.0f) fSqrDist = fC; + else if(-fB1 >= fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + else // region 3 + { + if(fB1 >= 0.0f) fSqrDist = fC; + else if(-fB1 >= fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + else if(fT < 0.0f) // region 5 + { + if(fB0 >= 0.0f) fSqrDist = fC; + else if(-fB0 >= fA00) fSqrDist = fA00+2.0f*fB0+fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + else // region 0 + { + // minimum at interior IcePoint + if(fDet==0.0f) + { + fSqrDist = MAX_FLOAT; + } + else + { + float fInvDet = 1.0f/fDet; + fS *= fInvDet; + fT *= fInvDet; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + } + } + else + { + float fTmp0, fTmp1, fNumer, fDenom; + + if(fS < 0.0f) // region 2 + { + fTmp0 = fA01 + fB0; + fTmp1 = fA11 + fB1; + if(fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { + fSqrDist = fA00+2.0f*fB0+fC; + } + else + { + fS = fNumer/fDenom; + fT = 1.0f - fS; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + } + else + { + if(fTmp1 <= 0.0f) fSqrDist = fA11+2.0f*fB1+fC; + else if(fB1 >= 0.0f) fSqrDist = fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + else if(fT < 0.0f) // region 6 + { + fTmp0 = fA01 + fB1; + fTmp1 = fA00 + fB0; + if(fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { + fSqrDist = fA11+2.0f*fB1+fC; + } + else + { + fT = fNumer/fDenom; + fS = 1.0f - fT; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + } + else + { + if(fTmp1 <= 0.0f) fSqrDist = fA00+2.0f*fB0+fC; + else if(fB0 >= 0.0f) fSqrDist = fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + } + else // region 1 + { + fNumer = fA11 + fB1 - fA01 - fB0; + if(fNumer <= 0.0f) + { + fSqrDist = fA11+2.0f*fB1+fC; + } + else + { + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { + fSqrDist = fA00+2.0f*fB0+fC; + } + else + { + fS = fNumer/fDenom; + fT = 1.0f - fS; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + } + } + } + return fabsf(fSqrDist); +} + +static float OPC_SegmentSegmentSqrDist(const IceSegment& rkSeg0, const IceSegment& rkSeg1) +{ + // Hook + IcePoint rkSeg0Direction = rkSeg0.ComputeDirection(); + IcePoint rkSeg1Direction = rkSeg1.ComputeDirection(); + + IcePoint kDiff = rkSeg0.mP0 - rkSeg1.mP0; + float fA00 = rkSeg0Direction.SquareMagnitude(); + float fA01 = -rkSeg0Direction.Dot(rkSeg1Direction); + float fA11 = rkSeg1Direction.SquareMagnitude(); + float fB0 = kDiff.Dot(rkSeg0Direction); + float fC = kDiff.SquareMagnitude(); + float fDet = fabsf(fA00*fA11-fA01*fA01); + + float fB1, fS, fT, fSqrDist, fTmp; + + if(fDet>=gs_fTolerance) + { + // line segments are not parallel + fB1 = -kDiff.Dot(rkSeg1Direction); + fS = fA01*fB1-fA11*fB0; + fT = fA01*fB0-fA00*fB1; + + if(fS >= 0.0f) + { + if(fS <= fDet) + { + if(fT >= 0.0f) + { + if(fT <= fDet) // region 0 (interior) + { + // minimum at two interior points of 3D lines + float fInvDet = 1.0f/fDet; + fS *= fInvDet; + fT *= fInvDet; + fSqrDist = fS*(fA00*fS+fA01*fT+2.0f*fB0) + fT*(fA01*fS+fA11*fT+2.0f*fB1)+fC; + } + else // region 3 (side) + { + fTmp = fA01+fB0; + if(fTmp>=0.0f) fSqrDist = fA11+2.0f*fB1+fC; + else if(-fTmp>=fA00) fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp); + else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; + } + } + else // region 7 (side) + { + if(fB0>=0.0f) fSqrDist = fC; + else if(-fB0>=fA00) fSqrDist = fA00+2.0f*fB0+fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + } + else + { + if ( fT >= 0.0 ) + { + if ( fT <= fDet ) // region 1 (side) + { + fTmp = fA01+fB1; + if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; + else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); + else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; + } + else // region 2 (corner) + { + fTmp = fA01+fB0; + if ( -fTmp <= fA00 ) + { + if(fTmp>=0.0f) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; + } + else + { + fTmp = fA01+fB1; + if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; + else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); + else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; + } + } + } + else // region 8 (corner) + { + if ( -fB0 < fA00 ) + { + if(fB0>=0.0f) fSqrDist = fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + fTmp = fA01+fB1; + if(fTmp>=0.0f) fSqrDist = fA00+2.0f*fB0+fC; + else if(-fTmp>=fA11) fSqrDist = fA00+fA11+fC+2.0f*(fB0+fTmp); + else fSqrDist = fTmp*(-fTmp/fA11)+fA00+2.0f*fB0+fC; + } + } + } + } + else + { + if ( fT >= 0.0f ) + { + if ( fT <= fDet ) // region 5 (side) + { + if(fB1>=0.0f) fSqrDist = fC; + else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + else // region 4 (corner) + { + fTmp = fA01+fB0; + if ( fTmp < 0.0f ) + { + if(-fTmp>=fA00) fSqrDist = fA00+fA11+fC+2.0f*(fB1+fTmp); + else fSqrDist = fTmp*(-fTmp/fA00)+fA11+2.0f*fB1+fC; + } + else + { + if(fB1>=0.0f) fSqrDist = fC; + else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + } + else // region 6 (corner) + { + if ( fB0 < 0.0f ) + { + if(-fB0>=fA00) fSqrDist = fA00+2.0f*fB0+fC; + else fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + if(fB1>=0.0f) fSqrDist = fC; + else if(-fB1>=fA11) fSqrDist = fA11+2.0f*fB1+fC; + else fSqrDist = fB1*(-fB1/fA11)+fC; + } + } + } + } + else + { + // line segments are parallel + if ( fA01 > 0.0f ) + { + // direction vectors form an obtuse angle + if ( fB0 >= 0.0f ) + { + fSqrDist = fC; + } + else if ( -fB0 <= fA00 ) + { + fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + fB1 = -kDiff.Dot(rkSeg1Direction); + fTmp = fA00+fB0; + if ( -fTmp >= fA01 ) + { + fSqrDist = fA00+fA11+fC+2.0f*(fA01+fB0+fB1); + } + else + { + fT = -fTmp/fA01; + fSqrDist = fA00+2.0f*fB0+fC+fT*(fA11*fT+2.0f*(fA01+fB1)); + } + } + } + else + { + // direction vectors form an acute angle + if ( -fB0 >= fA00 ) + { + fSqrDist = fA00+2.0f*fB0+fC; + } + else if ( fB0 <= 0.0f ) + { + fSqrDist = fB0*(-fB0/fA00)+fC; + } + else + { + fB1 = -kDiff.Dot(rkSeg1Direction); + if ( fB0 >= -fA01 ) + { + fSqrDist = fA11+2.0f*fB1+fC; + } + else + { + fT = -fB0/fA01; + fSqrDist = fC+fT*(2.0f*fB1+fA11*fT); + } + } + } + } + return fabsf(fSqrDist); +} + +inline_ float OPC_SegmentRaySqrDist(const IceSegment& rkSeg0, const Ray& rkSeg1) +{ + return OPC_SegmentSegmentSqrDist(rkSeg0, IceSegment(rkSeg1.mOrig, rkSeg1.mOrig + rkSeg1.mDir)); +} + +static float OPC_SegmentTriangleSqrDist(const IceSegment& segment, const IcePoint& p0, const IcePoint& p1, const IcePoint& p2) +{ + // Hook + const IcePoint TriEdge0 = p1 - p0; + const IcePoint TriEdge1 = p2 - p0; + + const IcePoint& rkSegOrigin = segment.GetOrigin(); + IcePoint rkSegDirection = segment.ComputeDirection(); + + IcePoint kDiff = p0 - rkSegOrigin; + float fA00 = rkSegDirection.SquareMagnitude(); + float fA01 = -rkSegDirection.Dot(TriEdge0); + float fA02 = -rkSegDirection.Dot(TriEdge1); + float fA11 = TriEdge0.SquareMagnitude(); + float fA12 = TriEdge0.Dot(TriEdge1); + float fA22 = TriEdge1.Dot(TriEdge1); + float fB0 = -kDiff.Dot(rkSegDirection); + float fB1 = kDiff.Dot(TriEdge0); + float fB2 = kDiff.Dot(TriEdge1); + float fCof00 = fA11*fA22-fA12*fA12; + float fCof01 = fA02*fA12-fA01*fA22; + float fCof02 = fA01*fA12-fA02*fA11; + float fDet = fA00*fCof00+fA01*fCof01+fA02*fCof02; + + Ray kTriSeg; + IcePoint kPt; + float fSqrDist, fSqrDist0; + + if(fabsf(fDet)>=gs_fTolerance) + { + float fCof11 = fA00*fA22-fA02*fA02; + float fCof12 = fA02*fA01-fA00*fA12; + float fCof22 = fA00*fA11-fA01*fA01; + float fInvDet = 1.0f/fDet; + float fRhs0 = -fB0*fInvDet; + float fRhs1 = -fB1*fInvDet; + float fRhs2 = -fB2*fInvDet; + + float fR = fCof00*fRhs0+fCof01*fRhs1+fCof02*fRhs2; + float fS = fCof01*fRhs0+fCof11*fRhs1+fCof12*fRhs2; + float fT = fCof02*fRhs0+fCof12*fRhs1+fCof22*fRhs2; + + if ( fR < 0.0f ) + { + if ( fS+fT <= 1.0f ) + { + if ( fS < 0.0f ) + { + if ( fT < 0.0f ) // region 4m + { + // min on face s=0 or t=0 or r=0 + kTriSeg.mOrig = p0; + kTriSeg.mDir = TriEdge1; + fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg); + kTriSeg.mOrig = p0; + kTriSeg.mDir = TriEdge0; + fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg); + if(fSqrDist0 1 + { + if ( fS+fT <= 1.0f ) + { + if ( fS < 0.0f ) + { + if ( fT < 0.0f ) // region 4p + { + // min on face s=0 or t=0 or r=1 + kTriSeg.mOrig = p0; + kTriSeg.mDir = TriEdge1; + fSqrDist = OPC_SegmentRaySqrDist(segment, kTriSeg); + kTriSeg.mOrig = p0; + kTriSeg.mDir = TriEdge0; + fSqrDist0 = OPC_SegmentRaySqrDist(segment, kTriSeg); + if(fSqrDist0GetTriangle(triangle_index); + * // Setup pointers to vertices for the collision system + * triangle.Vertex[0] = MyMesh->GetVertex(Tri->mVRef[0]); + * triangle.Vertex[1] = MyMesh->GetVertex(Tri->mVRef[1]); + * triangle.Vertex[2] = MyMesh->GetVertex(Tri->mVRef[2]); + * } + * + * // Setup callbacks + * MeshInterface0->SetCallback(ColCallback, udword(Mesh0)); + * MeshInterface1->SetCallback(ColCallback, udword(Mesh1)); + * \endcode + * + * Of course, you should make this callback as fast as possible. And you're also not supposed + * to modify the geometry *after* the collision trees have been built. The alternative was to + * store the geometry & topology in the collision system as well (as in RAPID) but we have found + * this approach to waste a lot of ram in many cases. + * + * + * POINTERS: + * + * If you're internally using the following canonical structures: + * - a vertex made of three 32-bits floating IcePoint values + * - a triangle made of three 32-bits integer vertex references + * ...then you may want to use pointers instead of callbacks. This is the same, except OPCODE will directly + * use provided pointers to access the topology and geometry, without using a callback. It might be faster, + * but probably not as safe. Pointers have been introduced in OPCODE 1.2. + * + * Ex: + * + * \code + * // Setup pointers + * MeshInterface0->SetPointers(Mesh0->GetFaces(), Mesh0->GetVerts()); + * MeshInterface1->SetPointers(Mesh1->GetFaces(), Mesh1->GetVerts()); + * \endcode + * + * + * STRIDES: + * + * If your vertices are D3D-like entities interleaving a position, a normal and/or texture coordinates + * (i.e. if your vertices are FVFs), you might want to use a vertex stride to skip extra data OPCODE + * doesn't need. Using a stride shouldn't be notably slower than not using it, but it might increase + * cache misses. Please also note that you *shouldn't* read from AGP or video-memory buffers ! + * + * + * In any case, compilation flags are here to select callbacks/pointers/strides at compile time, so + * choose what's best for your application. All of this has been wrapped into this MeshInterface. + * + * \class MeshInterface + * \author Pierre Terdiman + * \version 1.3 + * \date November, 27, 2002 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +MeshInterface::MeshInterface() : +#ifdef OPC_USE_CALLBACKS + mUserData (null), + mObjCallback (null), +#else + mTris (null), + mVerts (null), + #ifdef OPC_USE_STRIDE + mTriStride (sizeof(IndexedTriangle)), + mVertexStride (sizeof(IcePoint)), + #endif +#endif + mNbTris (0), + mNbVerts (0) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +MeshInterface::~MeshInterface() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the mesh interface is valid, i.e. things have been setup correctly. + * \return true if valid + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool MeshInterface::IsValid() const +{ + if(!mNbTris || !mNbVerts) return false; +#ifdef OPC_USE_CALLBACKS + if(!mObjCallback) return false; +#else + if(!mTris || !mVerts) return false; +#endif + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the mesh itself is valid. + * Currently we only look for degenerate faces. + * \return number of degenerate faces + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword MeshInterface::CheckTopology() const +{ + // Check topology. If the model contains degenerate faces, collision report can be wrong in some cases. + // e.g. it happens with the standard MAX teapot. So clean your meshes first... If you don't have a mesh cleaner + // you can try this: www.codercorner.com/Consolidation.zip + + udword NbDegenerate = 0; + + VertexPointers VP; + + // Using callbacks, we don't have access to vertex indices. Nevertheless we still can check for + // redundant vertex pointers, which cover all possibilities (callbacks/pointers/strides). + for(udword i=0;i= 0.0f; + } + }; + +#ifdef OPC_USE_CALLBACKS + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * User-callback, called by OPCODE to request vertices from the app. + * \param triangle_index [in] face index for which the system is requesting the vertices + * \param triangle [out] triangle's vertices (must be provided by the user) + * \param user_data [in] user-defined data from SetCallback() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef void (*RequestCallback) (udword triangle_index, VertexPointers& triangle, void* user_data); +#endif + + class OPCODE_API MeshInterface + { + public: + // Constructor / Destructor + MeshInterface(); + ~MeshInterface(); + // Common settings + inline_ udword GetNbTriangles() const { return mNbTris; } + inline_ udword GetNbVertices() const { return mNbVerts; } + inline_ void SetNbTriangles(udword nb) { mNbTris = nb; } + inline_ void SetNbVertices(udword nb) { mNbVerts = nb; } + +#ifdef OPC_USE_CALLBACKS + // Callback settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Callback control: setups object callback. Must provide triangle-vertices for a given triangle index. + * \param callback [in] user-defined callback + * \param user_data [in] user-defined data + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetCallback(RequestCallback callback, void* user_data); + inline_ void* GetUserData() const { return mUserData; } + inline_ RequestCallback GetCallback() const { return mObjCallback; } +#else + // Pointers settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Pointers control: setups object pointers. Must provide access to faces and vertices for a given object. + * \param tris [in] pointer to triangles + * \param verts [in] pointer to vertices + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetPointers(const IndexedTriangle* tris, const IcePoint* verts); + inline_ const IndexedTriangle* GetTris() const { return mTris; } + inline_ const IcePoint* GetVerts() const { return mVerts; } + + #ifdef OPC_USE_STRIDE + // Strides settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Strides control + * \param tri_stride [in] size of a triangle in bytes. The first sizeof(IndexedTriangle) bytes are used to get vertex indices. + * \param vertex_stride [in] size of a vertex in bytes. The first sizeof(IcePoint) bytes are used to get vertex position. + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool SetStrides(udword tri_stride=sizeof(IndexedTriangle), udword vertex_stride=sizeof(IcePoint)); + inline_ udword GetTriStride() const { return mTriStride; } + inline_ udword GetVertexStride() const { return mVertexStride; } + #endif +#endif + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Fetches a triangle given a triangle index. + * \param vp [out] required triangle's vertex pointers + * \param index [in] triangle index + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void GetTriangle(VertexPointers& vp, udword index) const + { +#ifdef OPC_USE_CALLBACKS + (mObjCallback)(index, vp, mUserData); +#else + #ifdef OPC_USE_STRIDE + const IndexedTriangle* T = (const IndexedTriangle*)(((ubyte*)mTris) + index * mTriStride); + vp.Vertex[0] = (const IcePoint*)(((ubyte*)mVerts) + T->mVRef[0] * mVertexStride); + vp.Vertex[1] = (const IcePoint*)(((ubyte*)mVerts) + T->mVRef[1] * mVertexStride); + vp.Vertex[2] = (const IcePoint*)(((ubyte*)mVerts) + T->mVRef[2] * mVertexStride); + #else + const IndexedTriangle* T = &mTris[index]; + vp.Vertex[0] = &mVerts[T->mVRef[0]]; + vp.Vertex[1] = &mVerts[T->mVRef[1]]; + vp.Vertex[2] = &mVerts[T->mVRef[2]]; + #endif +#endif + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Remaps client's mesh according to a permutation. + * \param nb_indices [in] number of indices in the permutation (will be checked against number of triangles) + * \param permutation [in] list of triangle indices + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool RemapClient(udword nb_indices, const udword* permutation) const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the mesh interface is valid, i.e. things have been setup correctly. + * \return true if valid + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool IsValid() const; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Checks the mesh itself is valid. + * Currently we only look for degenerate faces. + * \return number of degenerate faces + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + udword CheckTopology() const; + private: + + udword mNbTris; //!< Number of triangles in the input model + udword mNbVerts; //!< Number of vertices in the input model +#ifdef OPC_USE_CALLBACKS + // User callback + void* mUserData; //!< User-defined data sent to callback + RequestCallback mObjCallback; //!< Object callback +#else + // User pointers + const IndexedTriangle* mTris; //!< Array of indexed triangles + const IcePoint* mVerts; //!< Array of vertices + #ifdef OPC_USE_STRIDE + udword mTriStride; //!< Possible triangle stride in bytes [Opcode 1.3] + udword mVertexStride; //!< Possible vertex stride in bytes [Opcode 1.3] + #endif +#endif + }; + +#endif //__OPC_MESHINTERFACE_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_Model.cpp b/contrib/Opcode/OPC_Model.cpp new file mode 100644 index 0000000..a9e660c --- /dev/null +++ b/contrib/Opcode/OPC_Model.cpp @@ -0,0 +1,222 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for OPCODE models. + * \file OPC_Model.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * The main collision wrapper, for all trees. Supported trees are: + * - Normal trees (2*N-1 nodes, full size) + * - No-leaf trees (N-1 nodes, full size) + * - Quantized trees (2*N-1 nodes, half size) + * - Quantized no-leaf trees (N-1 nodes, half size) + * + * Usage: + * + * 1) Create a static mesh interface using callbacks or pointers. (see OPC_MeshInterface.cpp). + * Keep it around in your app, since a pointer to this interface is saved internally and + * used until you release the collision structures. + * + * 2) Build a Model using a creation structure: + * + * \code + * Model Sample; + * + * OPCODECREATE OPCC; + * OPCC.IMesh = ...; + * OPCC.Rules = ...; + * OPCC.NoLeaf = ...; + * OPCC.Quantized = ...; + * OPCC.KeepOriginal = ...; + * bool Status = Sample.Build(OPCC); + * \endcode + * + * 3) Create a tree collider and set it up: + * + * \code + * AABBTreeCollider TC; + * TC.SetFirstContact(...); + * TC.SetFullBoxBoxTest(...); + * TC.SetFullPrimBoxTest(...); + * TC.SetTemporalCoherence(...); + * \endcode + * + * 4) Perform a collision query + * + * \code + * // Setup cache + * static BVTCache ColCache; + * ColCache.Model0 = &Model0; + * ColCache.Model1 = &Model1; + * + * // Collision query + * bool IsOk = TC.Collide(ColCache, World0, World1); + * + * // Get collision status => if true, objects overlap + * BOOL Status = TC.GetContactStatus(); + * + * // Number of colliding pairs and list of pairs + * udword NbPairs = TC.GetNbPairs(); + * const Pair* p = TC.GetPairs() + * \endcode + * + * 5) Stats + * + * \code + * Model0.GetUsedBytes() = number of bytes used for this collision tree + * TC.GetNbBVBVTests() = number of BV-BV overlap tests performed during last query + * TC.GetNbPrimPrimTests() = number of Triangle-Triangle overlap tests performed during last query + * TC.GetNbBVPrimTests() = number of Triangle-BV overlap tests performed during last query + * \endcode + * + * \class Model + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Model::Model() +{ +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + mHull = null; +#endif // __MESHMERIZER_H__ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +Model::~Model() +{ + Release(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Releases the model. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Model::Release() +{ + ReleaseBase(); +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + DELETESINGLE(mHull); +#endif // __MESHMERIZER_H__ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds a collision model. + * \param create [in] model creation structure + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool Model::Build(const OPCODECREATE& create) +{ + // 1) Checkings + if(!create.mIMesh || !create.mIMesh->IsValid()) return false; + + // For this model, we only support complete trees + if (create.mSettings.mLimit != 1) return SetIceError; // ("OPCODE WARNING: supports complete trees only! Use mLimit = 1.\n", null); + + // Look for degenerate faces. + udword NbDegenerate = create.mIMesh->CheckTopology(); + if(NbDegenerate) Log("OPCODE WARNING: found %d degenerate faces in model! Collision might report wrong results!\n", NbDegenerate); + // We continue nonetheless.... + + Release(); // Make sure previous tree has been discarded [Opcode 1.3, thanks Adam] + + // 1-1) Setup mesh interface automatically [Opcode 1.3] + SetMeshInterface(create.mIMesh); + + // Special case for 1-triangle meshes [Opcode 1.3] + udword NbTris = create.mIMesh->GetNbTriangles(); + if(NbTris==1) + { + // We don't need to actually create a tree here, since we'll only have a single triangle to deal with anyway. + // It's a waste to use a "model" for this but at least it will work. + mModelCode |= OPC_SINGLE_NODE; + return true; + } + + // 2) Build a generic AABB Tree. + mSource = new AABBTree; + CHECKALLOC(mSource); + + // 2-1) Setup a builder. Our primitives here are triangles from input mesh, + // so we use an AABBTreeOfTrianglesBuilder..... + { + AABBTreeOfTrianglesBuilder TB; + TB.mIMesh = create.mIMesh; + TB.mSettings = create.mSettings; + TB.mNbPrimitives = NbTris; + if(!mSource->Build(&TB)) return false; + } + + // 3) Create an optimized tree according to user-settings + if(!CreateTree(create.mNoLeaf, create.mQuantized)) return false; + + // 3-2) Create optimized tree + if(!mTree->Build(mSource)) return false; + + // 3-3) Delete generic tree if needed + if(!create.mKeepOriginal) DELETESINGLE(mSource); + +#ifdef __MESHMERIZER_H__ + // 4) Convex hull + if(create.mCollisionHull) + { + // Create hull + mHull = new CollisionHull; + CHECKALLOC(mHull); + + CONVEXHULLCREATE CHC; + // ### doesn't work with strides + CHC.NbVerts = create.mIMesh->GetNbVertices(); + CHC.Vertices = create.mIMesh->GetVerts(); + CHC.UnifyNormals = true; + CHC.ReduceVertices = true; + CHC.WordFaces = false; + mHull->Compute(CHC); + } +#endif // __MESHMERIZER_H__ + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +udword Model::GetUsedBytes() const +{ + if(!mTree) return 0; + return mTree->GetUsedBytes(); +} diff --git a/contrib/Opcode/OPC_Model.h b/contrib/Opcode/OPC_Model.h new file mode 100644 index 0000000..1b39e60 --- /dev/null +++ b/contrib/Opcode/OPC_Model.h @@ -0,0 +1,65 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for OPCODE models. + * \file OPC_Model.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_MODEL_H__ +#define __OPC_MODEL_H__ + + class OPCODE_API Model : public BaseModel + { + public: + // Constructor/Destructor + Model(); + virtual ~Model(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds a collision model. + * \param create [in] model creation structure + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) bool Build(const OPCODECREATE& create); + +#ifdef __MESHMERIZER_H__ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the collision hull. + * \return the collision hull if it exists + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const CollisionHull* GetHull() const { return mHull; } +#endif // __MESHMERIZER_H__ + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of bytes used by the tree. + * \return amount of bytes used + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(BaseModel) udword GetUsedBytes() const; + + private: +#ifdef __MESHMERIZER_H__ + CollisionHull* mHull; //!< Possible convex hull +#endif // __MESHMERIZER_H__ + // Internal methods + void Release(); + }; + +#endif //__OPC_MODEL_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_OBBCollider.cpp b/contrib/Opcode/OPC_OBBCollider.cpp new file mode 100644 index 0000000..8761fce --- /dev/null +++ b/contrib/Opcode/OPC_OBBCollider.cpp @@ -0,0 +1,767 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an OBB collider. + * \file OPC_OBBCollider.cpp + * \author Pierre Terdiman + * \date January, 1st, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an OBB-vs-tree collider. + * + * \class OBBCollider + * \author Pierre Terdiman + * \version 1.3 + * \date January, 1st, 2002 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +#include "OPC_BoxBoxOverlap.h" +#include "OPC_TriBoxOverlap.h" + +#define SET_CONTACT(prim_index, flag) \ + /* Set contact status */ \ + mFlags |= flag; \ + mTouchedPrimitives->Add(prim_index); + +//! OBB-triangle test +#define OBB_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ + /* Transform them in a common space */ \ + TransformPoint(mLeafVerts[0], *VP.Vertex[0], mRModelToBox, mTModelToBox); \ + TransformPoint(mLeafVerts[1], *VP.Vertex[1], mRModelToBox, mTModelToBox); \ + TransformPoint(mLeafVerts[2], *VP.Vertex[2], mRModelToBox, mTModelToBox); \ + /* Perform triangle-box overlap test */ \ + if(TriBoxOverlap()) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +OBBCollider::OBBCollider() : mFullBoxBoxTest(true) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +OBBCollider::~OBBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Validates current settings. You should call this method after all the settings and callbacks have been defined. + * \return null if everything is ok, else a string describing the problem + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const char* OBBCollider::ValidateSettings() +{ + if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; + + return VolumeCollider::ValidateSettings(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a box cache + * \param box [in] collision OBB in local space + * \param model [in] Opcode model to collide with + * \param worldb [in] OBB's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool OBBCollider::Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb, const Matrix4x4* worldm) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, box, worldb, worldm)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - setup matrices + * - check temporal coherence + * + * \param cache [in/out] a box cache + * \param box [in] obb in local space + * \param worldb [in] obb's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL OBBCollider::InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb, const Matrix4x4* worldm) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Compute obb in world space + mBoxExtents = box.mExtents; + + Matrix4x4 WorldB; + + if(worldb) + { + WorldB = Matrix4x4( box.mRot * Matrix3x3(*worldb) ); + WorldB.SetTrans(box.mCenter * *worldb); + } + else + { + WorldB = box.mRot; + WorldB.SetTrans(box.mCenter); + } + + // Setup matrices + Matrix4x4 InvWorldB; + InvertPRMatrix(InvWorldB, WorldB); + + if(worldm) + { + Matrix4x4 InvWorldM; + InvertPRMatrix(InvWorldM, *worldm); + + Matrix4x4 WorldBtoM = WorldB * InvWorldM; + Matrix4x4 WorldMtoB = *worldm * InvWorldB; + + mRModelToBox = WorldMtoB; WorldMtoB.GetTrans(mTModelToBox); + mRBoxToModel = WorldBtoM; WorldBtoM.GetTrans(mTBoxToModel); + } + else + { + mRModelToBox = InvWorldB; InvWorldB.GetTrans(mTModelToBox); + mRBoxToModel = WorldB; WorldB.GetTrans(mTBoxToModel); + } + + // 3) Setup destination pointer + mTouchedPrimitives = &cache.TouchedPrimitives; + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the box (and set contact status if needed) + OBB_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // 5) Check temporal coherence: + if(TemporalCoherenceEnabled()) + { + // Here we use temporal coherence + // => check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the box (and set contact status if needed) + OBB_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; + } + // else no face has been touched during previous query + // => we'll have to perform a normal query + } + else + { + // ### rewrite this + OBB TestBox(mTBoxToModel, mBoxExtents, mRBoxToModel); + + // We're interested in all contacts =>test the new real box N(ew) against the previous fat box P(revious): + if(IsCacheValid(cache) && TestBox.IsInside(cache.FatBox)) + { + // - if N is included in P, return previous list + // => we simply leave the list (mTouchedFaces) unchanged + + // Set contact status if needed + if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; + + // In any case we don't need to do a query + return TRUE; + } + else + { + // - else do the query using a fat N + + // Reset cache since we'll about to perform a real query + mTouchedPrimitives->Reset(); + + // Make a fat box so that coherence will work for subsequent frames + TestBox.mExtents *= cache.FatCoeff; + mBoxExtents *= cache.FatCoeff; + + // Update cache with query data (signature for cached faces) + cache.FatBox = TestBox; + } + } + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + // Now we can precompute box-box data + + // Precompute absolute box-to-model rotation matrix + for(udword i=0;i<3;i++) + { + for(udword j=0;j<3;j++) + { + // Epsilon value prevents floating-IcePoint inaccuracies (strategy borrowed from RAPID) + mAR.m[i][j] = 1e-6f + fabsf(mRBoxToModel.m[i][j]); + } + } + + // Precompute bounds for box-in-box test + mB0 = mBoxExtents - mTModelToBox; + mB1 = - mBoxExtents - mTModelToBox; + + // Precompute box-box data - Courtesy of Erwin de Vries + mBBx1 = mBoxExtents.x*mAR.m[0][0] + mBoxExtents.y*mAR.m[1][0] + mBoxExtents.z*mAR.m[2][0]; + mBBy1 = mBoxExtents.x*mAR.m[0][1] + mBoxExtents.y*mAR.m[1][1] + mBoxExtents.z*mAR.m[2][1]; + mBBz1 = mBoxExtents.x*mAR.m[0][2] + mBoxExtents.y*mAR.m[1][2] + mBoxExtents.z*mAR.m[2][2]; + + mBB_1 = mBoxExtents.y*mAR.m[2][0] + mBoxExtents.z*mAR.m[1][0]; + mBB_2 = mBoxExtents.x*mAR.m[2][0] + mBoxExtents.z*mAR.m[0][0]; + mBB_3 = mBoxExtents.x*mAR.m[1][0] + mBoxExtents.y*mAR.m[0][0]; + mBB_4 = mBoxExtents.y*mAR.m[2][1] + mBoxExtents.z*mAR.m[1][1]; + mBB_5 = mBoxExtents.x*mAR.m[2][1] + mBoxExtents.z*mAR.m[0][1]; + mBB_6 = mBoxExtents.x*mAR.m[1][1] + mBoxExtents.y*mAR.m[0][1]; + mBB_7 = mBoxExtents.y*mAR.m[2][2] + mBoxExtents.z*mAR.m[1][2]; + mBB_8 = mBoxExtents.x*mAR.m[2][2] + mBoxExtents.z*mAR.m[0][2]; + mBB_9 = mBoxExtents.x*mAR.m[1][2] + mBoxExtents.y*mAR.m[0][2]; + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the OBB completely contains the box. In which case we can end the query sooner. + * \param bc [in] box center + * \param be [in] box extents + * \return true if the OBB contains the whole box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL OBBCollider::OBBContainsBox(const IcePoint& bc, const IcePoint& be) +{ + // I assume if all 8 box vertices are inside the OBB, so does the whole box. + // Sounds ok but maybe there's a better way? +/* +#define TEST_PT(a,b,c) \ + p.x=a; p.y=b; p.z=c; p+=bc; \ + f = p.x * mRModelToBox.m[0][0] + p.y * mRModelToBox.m[1][0] + p.z * mRModelToBox.m[2][0]; if(f>mB0.x || fmB0.y || fmB0.z || f NCx-NEx) return FALSE; + + float NCy = bc.x * mRModelToBox.m[0][1] + bc.y * mRModelToBox.m[1][1] + bc.z * mRModelToBox.m[2][1]; + float NEy = fabsf(mRModelToBox.m[0][1] * be.x) + fabsf(mRModelToBox.m[1][1] * be.y) + fabsf(mRModelToBox.m[2][1] * be.z); + + if(mB0.y < NCy+NEy) return FALSE; + if(mB1.y > NCy-NEy) return FALSE; + + float NCz = bc.x * mRModelToBox.m[0][2] + bc.y * mRModelToBox.m[1][2] + bc.z * mRModelToBox.m[2][2]; + float NEz = fabsf(mRModelToBox.m[0][2] * be.x) + fabsf(mRModelToBox.m[1][2] * be.y) + fabsf(mRModelToBox.m[2][2] * be.z); + + if(mB0.z < NCz+NEz) return FALSE; + if(mB1.z > NCz-NEz) return FALSE; + + return TRUE; +} + +#define TEST_BOX_IN_OBB(center, extents) \ + if(OBBContainsBox(center, extents)) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_Collide(const AABBCollisionNode* node) +{ + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + OBB_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) +{ + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_Collide(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(Extents, Center)) return; + + TEST_BOX_IN_OBB(Center, Extents) + + if(node->IsLeaf()) + { + OBB_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(Extents, Center)) return; + + TEST_BOX_IN_OBB(Center, Extents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_Collide(const AABBNoLeafNode* node) +{ + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) +{ + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(node->mAABB.mExtents, node->mAABB.mCenter)) return; + + TEST_BOX_IN_OBB(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_Collide(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(Extents, Center)) return; + + TEST_BOX_IN_OBB(Center, Extents) + + if(node->HasPosLeaf()) { OBB_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { OBB_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void OBBCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform OBB-AABB overlap test + if(!BoxBoxOverlap(Extents, Center)) return; + + TEST_BOX_IN_OBB(Center, Extents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridOBBCollider::HybridOBBCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridOBBCollider::~HybridOBBCollider() +{ +} + +bool HybridOBBCollider::Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb, const Matrix4x4* worldm) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, box, worldb, worldm)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + for(udword i=0;imCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + while(Nb--) + { + const LeafTriangles& CurrentLeaf = LT[*Touched++]; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = *T++; + OBB_PRIM(TriangleIndex, OPC_CONTACT) + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = BaseIndex++; + OBB_PRIM(TriangleIndex, OPC_CONTACT) + } + } + } + } + + return true; +} diff --git a/contrib/Opcode/OPC_OBBCollider.h b/contrib/Opcode/OPC_OBBCollider.h new file mode 100644 index 0000000..9753384 --- /dev/null +++ b/contrib/Opcode/OPC_OBBCollider.h @@ -0,0 +1,142 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for an OBB collider. + * \file OPC_OBBCollider.h + * \author Pierre Terdiman + * \date January, 1st, 2002 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_OBBCOLLIDER_H__ +#define __OPC_OBBCOLLIDER_H__ + + struct OPCODE_API OBBCache : VolumeCache + { + OBBCache() : FatCoeff(1.1f) + { + FatBox.mCenter.Zero(); + FatBox.mExtents.Zero(); + FatBox.mRot.Identity(); + } + + // Cached faces signature + OBB FatBox; //!< Box used when performing the query resulting in cached faces + // User settings + float FatCoeff; //!< extents multiplier used to create a fat box + }; + + class OPCODE_API OBBCollider : public VolumeCollider + { + public: + // Constructor / Destructor + OBBCollider(); + virtual ~OBBCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a box cache + * \param box [in] collision OBB in local space + * \param model [in] Opcode model to collide with + * \param worldb [in] OBB's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(OBBCache& cache, const OBB& box, const Model& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); + + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: select between full box-box tests or "SAT-lite" tests (where Class III axes are discarded) + * \param flag [in] true for full tests, false for coarse tests + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; } + + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) const char* ValidateSettings(); + + protected: + // Precomputed data + Matrix3x3 mAR; //!< Absolute rotation matrix + Matrix3x3 mRModelToBox; //!< Rotation from model space to obb space + Matrix3x3 mRBoxToModel; //!< Rotation from obb space to model space + IcePoint mTModelToBox; //!< Translation from model space to obb space + IcePoint mTBoxToModel; //!< Translation from obb space to model space + + IcePoint mBoxExtents; + IcePoint mB0; //!< - mTModelToBox + mBoxExtents + IcePoint mB1; //!< - mTModelToBox - mBoxExtents + + float mBBx1; + float mBBy1; + float mBBz1; + + float mBB_1; + float mBB_2; + float mBB_3; + float mBB_4; + float mBB_5; + float mBB_6; + float mBB_7; + float mBB_8; + float mBB_9; + + // Leaf description + IcePoint mLeafVerts[3]; //!< Triangle vertices + // Settings + bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false) + // Internal methods + void _Collide(const AABBCollisionNode* node); + void _Collide(const AABBNoLeafNode* node); + void _Collide(const AABBQuantizedNode* node); + void _Collide(const AABBQuantizedNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBCollisionNode* node); + void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); + // Overlap tests + inline_ BOOL OBBContainsBox(const IcePoint& bc, const IcePoint& be); + inline_ BOOL BoxBoxOverlap(const IcePoint& extents, const IcePoint& center); + inline_ BOOL TriBoxOverlap(); + // Init methods + BOOL InitQuery(OBBCache& cache, const OBB& box, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); + }; + + class OPCODE_API HybridOBBCollider : public OBBCollider + { + public: + // Constructor / Destructor + HybridOBBCollider(); + virtual ~HybridOBBCollider(); + + bool Collide(OBBCache& cache, const OBB& box, const HybridModel& model, const Matrix4x4* worldb=null, const Matrix4x4* worldm=null); + protected: + Container mTouchedBoxes; + }; + +#endif // __OPC_OBBCOLLIDER_H__ diff --git a/contrib/Opcode/OPC_OptimizedTree.cpp b/contrib/Opcode/OPC_OptimizedTree.cpp new file mode 100644 index 0000000..a84ac5a --- /dev/null +++ b/contrib/Opcode/OPC_OptimizedTree.cpp @@ -0,0 +1,782 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for optimized trees. Implements 4 trees: + * - normal + * - no leaf + * - quantized + * - no leaf / quantized + * + * \file OPC_OptimizedTree.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A standard AABB tree. + * + * \class AABBCollisionTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A no-leaf AABB tree. + * + * \class AABBNoLeafTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A quantized AABB tree. + * + * \class AABBQuantizedTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A quantized no-leaf AABB tree. + * + * \class AABBQuantizedNoLeafTree + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +//! Compilation flag: +//! - true to fix quantized boxes (i.e. make sure they enclose the original ones) +//! - false to see the effects of quantization errors (faster, but wrong results in some cases) +static bool gFixQuantized = true; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds an implicit tree from a standard one. An implicit tree is a complete tree (2*N-1 nodes) whose negative + * box pointers and primitive pointers have been made implicit, hence packing 3 pointers in one. + * + * Layout for implicit trees: + * Node: + * - box + * - data (32-bits value) + * + * if data's LSB = 1 => remaining bits are a primitive pointer + * else remaining bits are a P-node pointer, and N = P + 1 + * + * \relates AABBCollisionNode + * \fn _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) + * \param linear [in] base address of destination nodes + * \param box_id [in] index of destination node + * \param current_id [in] current running index + * \param current_node [in] current node from input tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static void _BuildCollisionTree(AABBCollisionNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) +{ + // Current node from input tree is "current_node". Must be flattened into "linear[boxid]". + + // Store the AABB + current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter); + current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents); + // Store remaining info + if(current_node->IsLeaf()) + { + // The input tree must be complete => i.e. one primitive/leaf + ASSERT(current_node->GetNbPrimitives()==1); + // Get the primitive index from the input tree + udword PrimitiveIndex = current_node->GetPrimitives()[0]; + // Setup box data as the primitive index, marked as leaf + linear[box_id].mData = (PrimitiveIndex<<1)|1; + } + else + { + // To make the negative one implicit, we must store P and N in successive order + udword PosID = current_id++; // Get a new id for positive child + udword NegID = current_id++; // Get a new id for negative child + // Setup box data as the forthcoming new P pointer + linear[box_id].mData = (udword)&linear[PosID]; + // Make sure it's not marked as leaf + ASSERT(!(linear[box_id].mData&1)); + // Recurse with new IDs + _BuildCollisionTree(linear, PosID, current_id, current_node->GetPos()); + _BuildCollisionTree(linear, NegID, current_id, current_node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds a "no-leaf" tree from a standard one. This is a tree whose leaf nodes have been removed. + * + * Layout for no-leaf trees: + * + * Node: + * - box + * - P pointer => a node (LSB=0) or a primitive (LSB=1) + * - N pointer => a node (LSB=0) or a primitive (LSB=1) + * + * \relates AABBNoLeafNode + * \fn _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) + * \param linear [in] base address of destination nodes + * \param box_id [in] index of destination node + * \param current_id [in] current running index + * \param current_node [in] current node from input tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static void _BuildNoLeafTree(AABBNoLeafNode* linear, const udword box_id, udword& current_id, const AABBTreeNode* current_node) +{ + const AABBTreeNode* P = current_node->GetPos(); + const AABBTreeNode* N = current_node->GetNeg(); + // Leaf nodes here?! + ASSERT(P); + ASSERT(N); + // Internal node => keep the box + current_node->GetAABB()->GetCenter(linear[box_id].mAABB.mCenter); + current_node->GetAABB()->GetExtents(linear[box_id].mAABB.mExtents); + + if(P->IsLeaf()) + { + // The input tree must be complete => i.e. one primitive/leaf + ASSERT(P->GetNbPrimitives()==1); + // Get the primitive index from the input tree + udword PrimitiveIndex = P->GetPrimitives()[0]; + // Setup prev box data as the primitive index, marked as leaf + linear[box_id].mPosData = (PrimitiveIndex<<1)|1; + } + else + { + // Get a new id for positive child + udword PosID = current_id++; + // Setup box data + linear[box_id].mPosData = (udword)&linear[PosID]; + // Make sure it's not marked as leaf + ASSERT(!(linear[box_id].mPosData&1)); + // Recurse + _BuildNoLeafTree(linear, PosID, current_id, P); + } + + if(N->IsLeaf()) + { + // The input tree must be complete => i.e. one primitive/leaf + ASSERT(N->GetNbPrimitives()==1); + // Get the primitive index from the input tree + udword PrimitiveIndex = N->GetPrimitives()[0]; + // Setup prev box data as the primitive index, marked as leaf + linear[box_id].mNegData = (PrimitiveIndex<<1)|1; + } + else + { + // Get a new id for negative child + udword NegID = current_id++; + // Setup box data + linear[box_id].mNegData = (udword)&linear[NegID]; + // Make sure it's not marked as leaf + ASSERT(!(linear[box_id].mNegData&1)); + // Recurse + _BuildNoLeafTree(linear, NegID, current_id, N); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBCollisionTree::AABBCollisionTree() : mNodes(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBCollisionTree::~AABBCollisionTree() +{ + DELETEARRAY(mNodes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollisionTree::Build(AABBTree* tree) +{ + // Checkings + if(!tree) return false; + // Check the input tree is complete + udword NbTriangles = tree->GetNbPrimitives(); + udword NbNodes = tree->GetNbNodes(); + if(NbNodes!=NbTriangles*2-1) return false; + + // Get nodes + if(mNbNodes!=NbNodes) // Same number of nodes => keep moving + { + mNbNodes = NbNodes; + DELETEARRAY(mNodes); + mNodes = new AABBCollisionNode[mNbNodes]; + CHECKALLOC(mNodes); + } + + // Build the tree + udword CurID = 1; + _BuildCollisionTree(mNodes, 0, CurID, tree); + ASSERT(CurID==mNbNodes); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the collision tree after vertices have been modified. + * \param mesh_interface [in] mesh interface for current model + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollisionTree::Refit(const MeshInterface* mesh_interface) +{ + ASSERT(!"Not implemented since AABBCollisionTrees have twice as more nodes to refit as AABBNoLeafTrees!"); + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Walks the tree and call the user back for each node. + * \param callback [in] walking callback + * \param user_data [in] callback's user data + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBCollisionTree::Walk(GenericWalkingCallback callback, void* user_data) const +{ + if(!callback) return false; + + struct Local + { + static void _Walk(const AABBCollisionNode* current_node, GenericWalkingCallback callback, void* user_data) + { + if(!current_node || !(callback)(current_node, user_data)) return; + + if(!current_node->IsLeaf()) + { + _Walk(current_node->GetPos(), callback, user_data); + _Walk(current_node->GetNeg(), callback, user_data); + } + } + }; + Local::_Walk(mNodes, callback, user_data); + return true; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBNoLeafTree::AABBNoLeafTree() : mNodes(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBNoLeafTree::~AABBNoLeafTree() +{ + DELETEARRAY(mNodes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBNoLeafTree::Build(AABBTree* tree) +{ + // Checkings + if(!tree) return false; + // Check the input tree is complete + udword NbTriangles = tree->GetNbPrimitives(); + udword NbNodes = tree->GetNbNodes(); + if(NbNodes!=NbTriangles*2-1) return false; + + // Get nodes + if(mNbNodes!=NbTriangles-1) // Same number of nodes => keep moving + { + mNbNodes = NbTriangles-1; + DELETEARRAY(mNodes); + mNodes = new AABBNoLeafNode[mNbNodes]; + CHECKALLOC(mNodes); + } + + // Build the tree + udword CurID = 1; + _BuildNoLeafTree(mNodes, 0, CurID, tree); + ASSERT(CurID==mNbNodes); + + return true; +} + +inline_ void ComputeMinMax(IcePoint& min, IcePoint& max, const VertexPointers& vp) +{ + // Compute triangle's AABB = a leaf box +#ifdef OPC_USE_FCOMI // a 15% speedup on my machine, not much + min.x = FCMin3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); + max.x = FCMax3(vp.Vertex[0]->x, vp.Vertex[1]->x, vp.Vertex[2]->x); + + min.y = FCMin3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); + max.y = FCMax3(vp.Vertex[0]->y, vp.Vertex[1]->y, vp.Vertex[2]->y); + + min.z = FCMin3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); + max.z = FCMax3(vp.Vertex[0]->z, vp.Vertex[1]->z, vp.Vertex[2]->z); +#else + min = *vp.Vertex[0]; + max = *vp.Vertex[0]; + min.Min(*vp.Vertex[1]); + max.Max(*vp.Vertex[1]); + min.Min(*vp.Vertex[2]); + max.Max(*vp.Vertex[2]); +#endif +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Refits the collision tree after vertices have been modified. + * \param mesh_interface [in] mesh interface for current model + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBNoLeafTree::Refit(const MeshInterface* mesh_interface) +{ + // Checkings + if(!mesh_interface) return false; + + // Bottom-up update + VertexPointers VP; + IcePoint Min,Max; + IcePoint Min_,Max_; + udword Index = mNbNodes; + while(Index--) + { + AABBNoLeafNode& Current = mNodes[Index]; + + if(Current.HasPosLeaf()) + { + mesh_interface->GetTriangle(VP, Current.GetPosPrimitive()); + ComputeMinMax(Min, Max, VP); + } + else + { + const CollisionAABB& CurrentBox = Current.GetPos()->mAABB; + CurrentBox.GetMin(Min); + CurrentBox.GetMax(Max); + } + + if(Current.HasNegLeaf()) + { + mesh_interface->GetTriangle(VP, Current.GetNegPrimitive()); + ComputeMinMax(Min_, Max_, VP); + } + else + { + const CollisionAABB& CurrentBox = Current.GetNeg()->mAABB; + CurrentBox.GetMin(Min_); + CurrentBox.GetMax(Max_); + } +#ifdef OPC_USE_FCOMI + Min.x = FCMin2(Min.x, Min_.x); + Max.x = FCMax2(Max.x, Max_.x); + Min.y = FCMin2(Min.y, Min_.y); + Max.y = FCMax2(Max.y, Max_.y); + Min.z = FCMin2(Min.z, Min_.z); + Max.z = FCMax2(Max.z, Max_.z); +#else + Min.Min(Min_); + Max.Max(Max_); +#endif + Current.mAABB.SetMinMax(Min, Max); + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Walks the tree and call the user back for each node. + * \param callback [in] walking callback + * \param user_data [in] callback's user data + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBNoLeafTree::Walk(GenericWalkingCallback callback, void* user_data) const +{ + if(!callback) return false; + + struct Local + { + static void _Walk(const AABBNoLeafNode* current_node, GenericWalkingCallback callback, void* user_data) + { + if(!current_node || !(callback)(current_node, user_data)) return; + + if(!current_node->HasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data); + if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data); + } + }; + Local::_Walk(mNodes, callback, user_data); + return true; +} + +// Quantization notes: +// - We could use the highest bits of mData to store some more quantized bits. Dequantization code +// would be slightly more complex, but number of overlap tests would be reduced (and anyhow those +// bits are currently wasted). Of course it's not possible if we move to 16 bits mData. +// - Something like "16 bits floats" could be tested, to bypass the int-to-float conversion. +// - A dedicated BV-BV test could be used, dequantizing while testing for overlap. (i.e. it's some +// lazy-dequantization which may save some work in case of early exits). At the very least some +// muls could be saved by precomputing several more matrices. But maybe not worth the pain. +// - Do we need to dequantize anyway? Not doing the extents-related muls only implies the box has +// been scaled, for example. +// - The deeper we move into the hierarchy, the smaller the extents should be. May not need a fixed +// number of quantization bits. Even better, could probably be best delta-encoded. + + +// Find max values. Some people asked why I wasn't simply using the first node. Well, I can't. +// I'm not looking for (min, max) values like in a standard AABB, I'm looking for the extremal +// centers/extents in order to quantize them. The first node would only give a single center and +// a single extents. While extents would be the biggest, the center wouldn't. +#define FIND_MAX_VALUES \ + /* Get max values */ \ + IcePoint CMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \ + IcePoint EMax(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT); \ + for(udword i=0;iCMax.x) CMax.x = fabsf(Nodes[i].mAABB.mCenter.x); \ + if(fabsf(Nodes[i].mAABB.mCenter.y)>CMax.y) CMax.y = fabsf(Nodes[i].mAABB.mCenter.y); \ + if(fabsf(Nodes[i].mAABB.mCenter.z)>CMax.z) CMax.z = fabsf(Nodes[i].mAABB.mCenter.z); \ + if(fabsf(Nodes[i].mAABB.mExtents.x)>EMax.x) EMax.x = fabsf(Nodes[i].mAABB.mExtents.x); \ + if(fabsf(Nodes[i].mAABB.mExtents.y)>EMax.y) EMax.y = fabsf(Nodes[i].mAABB.mExtents.y); \ + if(fabsf(Nodes[i].mAABB.mExtents.z)>EMax.z) EMax.z = fabsf(Nodes[i].mAABB.mExtents.z); \ + } + +#define INIT_QUANTIZATION \ + udword nbc=15; /* Keep one bit for sign */ \ + udword nbe=15; /* Keep one bit for fix */ \ + if(!gFixQuantized) nbe++; \ + \ + /* Compute quantization coeffs */ \ + IcePoint CQuantCoeff, EQuantCoeff; \ + CQuantCoeff.x = CMax.x!=0.0f ? float((1<Min[j]) mNodes[i].mAABB.mExtents[j]++; \ + else FixMe=false; \ + /* Prevent wrapping */ \ + if(!mNodes[i].mAABB.mExtents[j]) \ + { \ + mNodes[i].mAABB.mExtents[j]=0xffff; \ + FixMe=false; \ + } \ + }while(FixMe); \ + } \ + } + +#define REMAP_DATA(member) \ + /* Fix data */ \ + Data = Nodes[i].member; \ + if(!(Data&1)) \ + { \ + /* Compute box number */ \ + udword Nb = (Data - udword(Nodes))/Nodes[i].GetNodeSize(); \ + Data = udword(&mNodes[Nb]); \ + } \ + /* ...remapped */ \ + mNodes[i].member = Data; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBQuantizedTree::AABBQuantizedTree() : mNodes(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBQuantizedTree::~AABBQuantizedTree() +{ + DELETEARRAY(mNodes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBQuantizedTree::Build(AABBTree* tree) +{ + // Checkings + if(!tree) return false; + // Check the input tree is complete + udword NbTriangles = tree->GetNbPrimitives(); + udword NbNodes = tree->GetNbNodes(); + if(NbNodes!=NbTriangles*2-1) return false; + + // Get nodes + mNbNodes = NbNodes; + DELETEARRAY(mNodes); + AABBCollisionNode* Nodes = new AABBCollisionNode[mNbNodes]; + CHECKALLOC(Nodes); + + // Build the tree + udword CurID = 1; + _BuildCollisionTree(Nodes, 0, CurID, tree); + + // Quantize + { + mNodes = new AABBQuantizedNode[mNbNodes]; + CHECKALLOC(mNodes); + + // Get max values + FIND_MAX_VALUES + + // Quantization + INIT_QUANTIZATION + + // Quantize + udword Data; + for(udword i=0;iIsLeaf()) + { + _Walk(current_node->GetPos(), callback, user_data); + _Walk(current_node->GetNeg(), callback, user_data); + } + } + }; + Local::_Walk(mNodes, callback, user_data); + return true; +} + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBQuantizedNoLeafTree::AABBQuantizedNoLeafTree() : mNodes(null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +AABBQuantizedNoLeafTree::~AABBQuantizedNoLeafTree() +{ + DELETEARRAY(mNodes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBQuantizedNoLeafTree::Build(AABBTree* tree) +{ + // Checkings + if(!tree) return false; + // Check the input tree is complete + udword NbTriangles = tree->GetNbPrimitives(); + udword NbNodes = tree->GetNbNodes(); + if(NbNodes!=NbTriangles*2-1) return false; + + // Get nodes + mNbNodes = NbTriangles-1; + DELETEARRAY(mNodes); + AABBNoLeafNode* Nodes = new AABBNoLeafNode[mNbNodes]; + CHECKALLOC(Nodes); + + // Build the tree + udword CurID = 1; + _BuildNoLeafTree(Nodes, 0, CurID, tree); + ASSERT(CurID==mNbNodes); + + // Quantize + { + mNodes = new AABBQuantizedNoLeafNode[mNbNodes]; + CHECKALLOC(mNodes); + + // Get max values + FIND_MAX_VALUES + + // Quantization + INIT_QUANTIZATION + + // Quantize + udword Data; + for(udword i=0;iHasPosLeaf()) _Walk(current_node->GetPos(), callback, user_data); + if(!current_node->HasNegLeaf()) _Walk(current_node->GetNeg(), callback, user_data); + } + }; + Local::_Walk(mNodes, callback, user_data); + return true; +} diff --git a/contrib/Opcode/OPC_OptimizedTree.h b/contrib/Opcode/OPC_OptimizedTree.h new file mode 100644 index 0000000..c36e21e --- /dev/null +++ b/contrib/Opcode/OPC_OptimizedTree.h @@ -0,0 +1,206 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for optimized trees. + * \file OPC_OptimizedTree.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_OPTIMIZEDTREE_H__ +#define __OPC_OPTIMIZEDTREE_H__ + + //! Common interface for a node of an implicit tree + #define IMPLEMENT_IMPLICIT_NODE(base_class, volume) \ + public: \ + /* Constructor / Destructor */ \ + inline_ base_class() : mData(0) {} \ + inline_ ~base_class() {} \ + /* Leaf test */ \ + inline_ BOOL IsLeaf() const { return mData&1; } \ + /* Data access */ \ + inline_ const base_class* GetPos() const { return (base_class*)mData; } \ + inline_ const base_class* GetNeg() const { return ((base_class*)mData)+1; } \ + inline_ udword GetPrimitive() const { return (mData>>1); } \ + /* Stats */ \ + inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ + \ + volume mAABB; \ + udword mData; + + //! Common interface for a node of a no-leaf tree + #define IMPLEMENT_NOLEAF_NODE(base_class, volume) \ + public: \ + /* Constructor / Destructor */ \ + inline_ base_class() : mPosData(0), mNegData(0) {} \ + inline_ ~base_class() {} \ + /* Leaf tests */ \ + inline_ BOOL HasPosLeaf() const { return mPosData&1; } \ + inline_ BOOL HasNegLeaf() const { return mNegData&1; } \ + /* Data access */ \ + inline_ const base_class* GetPos() const { return (base_class*)mPosData; } \ + inline_ const base_class* GetNeg() const { return (base_class*)mNegData; } \ + inline_ udword GetPosPrimitive() const { return (mPosData>>1); } \ + inline_ udword GetNegPrimitive() const { return (mNegData>>1); } \ + /* Stats */ \ + inline_ udword GetNodeSize() const { return SIZEOFOBJECT; } \ + \ + volume mAABB; \ + udword mPosData; \ + udword mNegData; + + class OPCODE_API AABBCollisionNode + { + IMPLEMENT_IMPLICIT_NODE(AABBCollisionNode, CollisionAABB) + + inline_ float GetVolume() const { return mAABB.mExtents.x * mAABB.mExtents.y * mAABB.mExtents.z; } + inline_ float GetSize() const { return mAABB.mExtents.SquareMagnitude(); } + inline_ udword GetRadius() const + { + udword* Bits = (udword*)&mAABB.mExtents.x; + udword Max = Bits[0]; + if(Bits[1]>Max) Max = Bits[1]; + if(Bits[2]>Max) Max = Bits[2]; + return Max; + } + + // NB: using the square-magnitude or the true volume of the box, seems to yield better results + // (assuming UNC-like informed traversal methods). I borrowed this idea from PQP. The usual "size" + // otherwise, is the largest box extent. In SOLID that extent is computed on-the-fly each time it's + // needed (the best approach IMHO). In RAPID the rotation matrix is permuted so that Extent[0] is + // always the greatest, which saves looking for it at runtime. On the other hand, it yields matrices + // whose determinant is not 1, i.e. you can't encode them anymore as unit quaternions. Not a very + // good strategy. + }; + + class OPCODE_API AABBQuantizedNode + { + IMPLEMENT_IMPLICIT_NODE(AABBQuantizedNode, QuantizedAABB) + + inline_ uword GetSize() const + { + const uword* Bits = mAABB.mExtents; + uword Max = Bits[0]; + if(Bits[1]>Max) Max = Bits[1]; + if(Bits[2]>Max) Max = Bits[2]; + return Max; + } + // NB: for quantized nodes I don't feel like computing a square-magnitude with integers all + // over the place.......! + }; + + class OPCODE_API AABBNoLeafNode + { + IMPLEMENT_NOLEAF_NODE(AABBNoLeafNode, CollisionAABB) + }; + + class OPCODE_API AABBQuantizedNoLeafNode + { + IMPLEMENT_NOLEAF_NODE(AABBQuantizedNoLeafNode, QuantizedAABB) + }; + + //! Common interface for a collision tree + #define IMPLEMENT_COLLISION_TREE(base_class, node) \ + public: \ + /* Constructor / Destructor */ \ + base_class(); \ + virtual ~base_class(); \ + /* Builds from a standard tree */ \ + override(AABBOptimizedTree) bool Build(AABBTree* tree); \ + /* Refits the tree */ \ + override(AABBOptimizedTree) bool Refit(const MeshInterface* mesh_interface); \ + /* Walks the tree */ \ + override(AABBOptimizedTree) bool Walk(GenericWalkingCallback callback, void* user_data) const; \ + /* Data access */ \ + inline_ const node* GetNodes() const { return mNodes; } \ + /* Stats */ \ + override(AABBOptimizedTree) udword GetUsedBytes() const { return mNbNodes*sizeof(node); } \ + private: \ + node* mNodes; + + typedef bool (*GenericWalkingCallback) (const void* current, void* user_data); + + class OPCODE_API AABBOptimizedTree + { + public: + // Constructor / Destructor + AABBOptimizedTree() : + mNbNodes (0) + {} + virtual ~AABBOptimizedTree() {} + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Builds the collision tree from a generic AABB tree. + * \param tree [in] generic AABB tree + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Build(AABBTree* tree) = 0; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Refits the collision tree after vertices have been modified. + * \param mesh_interface [in] mesh interface for current model + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Refit(const MeshInterface* mesh_interface) = 0; + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Walks the tree and call the user back for each node. + * \param callback [in] walking callback + * \param user_data [in] callback's user data + * \return true if success + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + virtual bool Walk(GenericWalkingCallback callback, void* user_data) const = 0; + + // Data access + virtual udword GetUsedBytes() const = 0; + inline_ udword GetNbNodes() const { return mNbNodes; } + + protected: + udword mNbNodes; + }; + + class OPCODE_API AABBCollisionTree : public AABBOptimizedTree + { + IMPLEMENT_COLLISION_TREE(AABBCollisionTree, AABBCollisionNode) + }; + + class OPCODE_API AABBNoLeafTree : public AABBOptimizedTree + { + IMPLEMENT_COLLISION_TREE(AABBNoLeafTree, AABBNoLeafNode) + }; + + class OPCODE_API AABBQuantizedTree : public AABBOptimizedTree + { + IMPLEMENT_COLLISION_TREE(AABBQuantizedTree, AABBQuantizedNode) + + public: + IcePoint mCenterCoeff; + IcePoint mExtentsCoeff; + }; + + class OPCODE_API AABBQuantizedNoLeafTree : public AABBOptimizedTree + { + IMPLEMENT_COLLISION_TREE(AABBQuantizedNoLeafTree, AABBQuantizedNoLeafNode) + + public: + IcePoint mCenterCoeff; + IcePoint mExtentsCoeff; + }; + +#endif // __OPC_OPTIMIZEDTREE_H__ diff --git a/contrib/Opcode/OPC_Picking.cpp b/contrib/Opcode/OPC_Picking.cpp new file mode 100644 index 0000000..5a48403 --- /dev/null +++ b/contrib/Opcode/OPC_Picking.cpp @@ -0,0 +1,182 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code to perform "picking". + * \file OPC_Picking.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +#ifdef OPC_RAYHIT_CALLBACK + +/* + Possible RayCollider usages: + - boolean query (shadow feeler) + - closest hit + - all hits + - number of intersection (boolean) + +*/ + +bool Opcode::SetupAllHits(RayCollider& collider, CollisionFaces& contacts) +{ + struct Local + { + static void AllContacts(const CollisionFace& hit, void* user_data) + { + CollisionFaces* CF = (CollisionFaces*)user_data; + CF->AddFace(hit); + } + }; + + collider.SetFirstContact(false); + collider.SetHitCallback(Local::AllContacts); + collider.SetUserData(&contacts); + return true; +} + +bool Opcode::SetupClosestHit(RayCollider& collider, CollisionFace& closest_contact) +{ + struct Local + { + static void ClosestContact(const CollisionFace& hit, void* user_data) + { + CollisionFace* CF = (CollisionFace*)user_data; + if(hit.mDistancemDistance) *CF = hit; + } + }; + + collider.SetFirstContact(false); + collider.SetHitCallback(Local::ClosestContact); + collider.SetUserData(&closest_contact); + closest_contact.mDistance = MAX_FLOAT; + return true; +} + +bool Opcode::SetupShadowFeeler(RayCollider& collider) +{ + collider.SetFirstContact(true); + collider.SetHitCallback(null); + return true; +} + +bool Opcode::SetupInOutTest(RayCollider& collider) +{ + collider.SetFirstContact(false); + collider.SetHitCallback(null); + // Results with collider.GetNbIntersections() + return true; +} + +bool Opcode::Picking( +CollisionFace& picked_face, +const Ray& world_ray, const Model& model, const Matrix4x4* world, +float min_dist, float max_dist, const IcePoint& view_point, CullModeCallback callback, void* user_data) +{ + struct Local + { + struct CullData + { + CollisionFace* Closest; + float MinLimit; + CullModeCallback Callback; + void* UserData; + IcePoint ViewPoint; + const MeshInterface* IMesh; + }; + + // Called for each stabbed face + static void RenderCullingCallback(const CollisionFace& hit, void* user_data) + { + CullData* Data = (CullData*)user_data; + + // Discard face if we already have a closer hit + if(hit.mDistance>=Data->Closest->mDistance) return; + + // Discard face if hit IcePoint is smaller than min limit. This mainly happens when the face is in front + // of the near clip plane (or straddles it). If we keep the face nonetheless, the user can select an + // object that he may not even be able to see, which is very annoying. + if(hit.mDistance<=Data->MinLimit) return; + + // This is the index of currently stabbed triangle. + udword StabbedFaceIndex = hit.mFaceID; + + // We may keep it or not, depending on backface culling + bool KeepIt = true; + + // Catch *render* cull mode for this face + CullMode CM = (Data->Callback)(StabbedFaceIndex, Data->UserData); + + if(CM!=CULLMODE_NONE) // Don't even compute culling for double-sided triangles + { + // Compute backface culling for current face + + VertexPointers VP; + Data->IMesh->GetTriangle(VP, StabbedFaceIndex); + if(VP.BackfaceCulling(Data->ViewPoint)) + { + if(CM==CULLMODE_CW) KeepIt = false; + } + else + { + if(CM==CULLMODE_CCW) KeepIt = false; + } + } + + if(KeepIt) *Data->Closest = hit; + } + }; + + RayCollider RC; + RC.SetMaxDist(max_dist); + RC.SetTemporalCoherence(false); + RC.SetCulling(false); // We need all faces since some of them can be double-sided + RC.SetFirstContact(false); + RC.SetHitCallback(Local::RenderCullingCallback); + + picked_face.mFaceID = INVALID_ID; + picked_face.mDistance = MAX_FLOAT; + picked_face.mU = 0.0f; + picked_face.mV = 0.0f; + + Local::CullData Data; + Data.Closest = &picked_face; + Data.MinLimit = min_dist; + Data.Callback = callback; + Data.UserData = user_data; + Data.ViewPoint = view_point; + Data.IMesh = model.GetMeshInterface(); + + if(world) + { + // Get matrices + Matrix4x4 InvWorld; + InvertPRMatrix(InvWorld, *world); + + // Compute camera position in mesh space + Data.ViewPoint *= InvWorld; + } + + RC.SetUserData(&Data); + if(RC.Collide(world_ray, model, world)) + { + return picked_face.mFaceID!=INVALID_ID; + } + return false; +} + +#endif diff --git a/contrib/Opcode/OPC_Picking.h b/contrib/Opcode/OPC_Picking.h new file mode 100644 index 0000000..cae5402 --- /dev/null +++ b/contrib/Opcode/OPC_Picking.h @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code to perform "picking". + * \file OPC_Picking.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_PICKING_H__ +#define __OPC_PICKING_H__ + +#ifdef OPC_RAYHIT_CALLBACK + + enum CullMode + { + CULLMODE_NONE = 0, + CULLMODE_CW = 1, + CULLMODE_CCW = 2 + }; + + typedef CullMode (*CullModeCallback)(udword triangle_index, void* user_data); + + OPCODE_API bool SetupAllHits (RayCollider& collider, CollisionFaces& contacts); + OPCODE_API bool SetupClosestHit (RayCollider& collider, CollisionFace& closest_contact); + OPCODE_API bool SetupShadowFeeler (RayCollider& collider); + OPCODE_API bool SetupInOutTest (RayCollider& collider); + + OPCODE_API bool Picking( + CollisionFace& picked_face, + const Ray& world_ray, const Model& model, const Matrix4x4* world, + float min_dist, float max_dist, const IcePoint& view_point, CullModeCallback callback, void* user_data); +#endif + +#endif //__OPC_PICKING_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_PlanesAABBOverlap.h b/contrib/Opcode/OPC_PlanesAABBOverlap.h new file mode 100644 index 0000000..2bc70d7 --- /dev/null +++ b/contrib/Opcode/OPC_PlanesAABBOverlap.h @@ -0,0 +1,50 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Planes-AABB overlap test. + * - original code by Ville Miettinen, from Umbra/dPVS (released on the GD-Algorithms mailing list) + * - almost used "as-is", I even left the comments (hence the frustum-related notes) + * + * \param center [in] box center + * \param extents [in] box extents + * \param out_clip_mask [out] bitmask for active planes + * \param in_clip_mask [in] bitmask for active planes + * \return TRUE if boxes overlap planes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL PlanesCollider::PlanesAABBOverlap(const IcePoint& center, const IcePoint& extents, udword& out_clip_mask, udword in_clip_mask) +{ + // Stats + mNbVolumeBVTests++; + + const IcePlane* p = mPlanes; + + // Evaluate through all active frustum planes. We determine the relation + // between the AABB and a plane by using the concept of "near" and "far" + // vertices originally described by Zhang (and later by Möller). Our + // variant here uses 3 fabs ops, 6 muls, 7 adds and two floating IcePoint + // comparisons per plane. The routine early-exits if the AABB is found + // to be outside any of the planes. The loop also constructs a new output + // clip mask. Most FPUs have a native single-cycle fabsf() operation. + + udword Mask = 1; // current mask index (1,2,4,8,..) + udword TmpOutClipMask = 0; // initialize output clip mask into empty. + + while(Mask<=in_clip_mask) // keep looping while we have active planes left... + { + if(in_clip_mask & Mask) // if clip plane is active, process it.. + { + float NP = extents.x*fabsf(p->n.x) + extents.y*fabsf(p->n.y) + extents.z*fabsf(p->n.z); // ### fabsf could be precomputed + float MP = center.x*p->n.x + center.y*p->n.y + center.z*p->n.z + p->d; + + if(NP < MP) // near vertex behind the clip plane... + return FALSE; // .. so there is no intersection.. + if((-NP) < MP) // near and far vertices on different sides of plane.. + TmpOutClipMask |= Mask; // .. so update the clip mask... + } + Mask+=Mask; // mk = (1<Add(prim_index); + +//! Planes-triangle test +#define PLANES_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + mIMesh->GetTriangle(mVP, prim_index); \ + /* Perform triangle-box overlap test */ \ + if(PlanesTriOverlap(clip_mask)) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +PlanesCollider::PlanesCollider() : + mPlanes (null), + mNbPlanes (0) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +PlanesCollider::~PlanesCollider() +{ + DELETEARRAY(mPlanes); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Validates current settings. You should call this method after all the settings and callbacks have been defined. + * \return null if everything is ok, else a string describing the problem + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const char* PlanesCollider::ValidateSettings() +{ + if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; + + return VolumeCollider::ValidateSettings(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a planes cache + * \param planes [in] list of planes in world space + * \param nb_planes [in] number of planes + * \param model [in] Opcode model to collide with + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool PlanesCollider::Collide(PlanesCache& cache, const IcePlane* planes, udword nb_planes, const Model& model, const Matrix4x4* worldm) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, planes, nb_planes, worldm)) return true; + + udword PlaneMask = (1<mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + else _Collide(Tree->GetNodes(), PlaneMask); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + else _Collide(Tree->GetNodes(), PlaneMask); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + else _Collide(Tree->GetNodes(), PlaneMask); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + else _Collide(Tree->GetNodes(), PlaneMask); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - compute planes in model space + * - check temporal coherence + * + * \param cache [in/out] a planes cache + * \param planes [in] list of planes + * \param nb_planes [in] number of planes + * \param worldm [in] model's world matrix, or null + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL PlanesCollider::InitQuery(PlanesCache& cache, const IcePlane* planes, udword nb_planes, const Matrix4x4* worldm) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Compute planes in model space + if(nb_planes>mNbPlanes) + { + DELETEARRAY(mPlanes); + mPlanes = new IcePlane[nb_planes]; + } + mNbPlanes = nb_planes; + + if(worldm) + { + Matrix4x4 InvWorldM; + InvertPRMatrix(InvWorldM, *worldm); + +// for(udword i=0;iHasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the planes (and set contact status if needed) + udword clip_mask = (1< check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the planes (and set contact status if needed) + udword clip_mask = (1< we'll have to perform a normal query + } + else mTouchedPrimitives->Reset(); + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + return FALSE; +} + +#define TEST_CLIP_MASK \ + /* If the box is completely included, so are its children. We don't need to do extra tests, we */ \ + /* can immediately output a list of visible children. Those ones won't need to be clipped. */ \ + if(!OutClipMask) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_Collide(const AABBCollisionNode* node, udword clip_mask) +{ + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->IsLeaf()) + { + PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + _Collide(node->GetNeg(), OutClipMask); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node, udword clip_mask) +{ + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_Collide(const AABBQuantizedNode* node, udword clip_mask) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->IsLeaf()) + { + PLANES_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + _Collide(node->GetNeg(), OutClipMask); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node, udword clip_mask) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_Collide(const AABBNoLeafNode* node, udword clip_mask) +{ + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg(), OutClipMask); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node, udword clip_mask) +{ + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_Collide(const AABBQuantizedNoLeafNode* node, udword clip_mask) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->HasPosLeaf()) { PLANES_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { PLANES_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg(), OutClipMask); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void PlanesCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node, udword clip_mask) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Test the box against the planes. If the box is completely culled, so are its children, hence we exit. + udword OutClipMask; + if(!PlanesAABBOverlap(Center, Extents, OutClipMask, clip_mask)) return; + + TEST_CLIP_MASK + + // Else the box straddles one or several planes, so we need to recurse down the tree. + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos(), OutClipMask); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg(), OutClipMask); +} + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridPlanesCollider::HybridPlanesCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridPlanesCollider::~HybridPlanesCollider() +{ +} + +bool HybridPlanesCollider::Collide(PlanesCache& cache, const IcePlane* planes, udword nb_planes, const HybridModel& model, const Matrix4x4* worldm) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, planes, nb_planes, worldm)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + udword clip_mask = (1<mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes(), PlaneMask); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + udword clip_mask = (1<Distance(*mVP.Vertex[0]); + float d1 = p->Distance(*mVP.Vertex[1]); + float d2 = p->Distance(*mVP.Vertex[2]); + if(d0>0.0f && d1>0.0f && d2>0.0f) return FALSE; +// if(!(IR(d0)&SIGN_BITMASK) && !(IR(d1)&SIGN_BITMASK) && !(IR(d2)&SIGN_BITMASK)) return FALSE; + } + Mask+=Mask; + p++; + } +/* + for(udword i=0;i<6;i++) + { + float d0 = p[i].Distance(mLeafVerts[0]); + float d1 = p[i].Distance(mLeafVerts[1]); + float d2 = p[i].Distance(mLeafVerts[2]); + if(d0>0.0f && d1>0.0f && d2>0.0f) return false; + } +*/ + return TRUE; +} diff --git a/contrib/Opcode/OPC_RayAABBOverlap.h b/contrib/Opcode/OPC_RayAABBOverlap.h new file mode 100644 index 0000000..cd2bdfb --- /dev/null +++ b/contrib/Opcode/OPC_RayAABBOverlap.h @@ -0,0 +1,63 @@ +// Opcode 1.1: ray-AABB overlap tests based on Woo's code +// Opcode 1.2: ray-AABB overlap tests based on the separating axis theorem +// +// The IcePoint of intersection is not computed anymore. The distance to impact is not needed anymore +// since we now have two different queries for segments or rays. + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a segment-AABB overlap test using the separating axis theorem. IceSegment is cached within the class. + * \param center [in] AABB center + * \param extents [in] AABB extents + * \return true on overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL RayCollider::SegmentAABBOverlap(const IcePoint& center, const IcePoint& extents) +{ + // Stats + mNbRayBVTests++; + + float Dx = mData2.x - center.x; if(fabsf(Dx) > extents.x + mFDir.x) return FALSE; + float Dy = mData2.y - center.y; if(fabsf(Dy) > extents.y + mFDir.y) return FALSE; + float Dz = mData2.z - center.z; if(fabsf(Dz) > extents.z + mFDir.z) return FALSE; + + float f; + f = mData.y * Dz - mData.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE; + f = mData.z * Dx - mData.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE; + f = mData.x * Dy - mData.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE; + + return TRUE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a ray-AABB overlap test using the separating axis theorem. Ray is cached within the class. + * \param center [in] AABB center + * \param extents [in] AABB extents + * \return true on overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL RayCollider::RayAABBOverlap(const IcePoint& center, const IcePoint& extents) +{ + // Stats + mNbRayBVTests++; + +// float Dx = mOrigin.x - center.x; if(fabsf(Dx) > extents.x && Dx*mDir.x>=0.0f) return FALSE; +// float Dy = mOrigin.y - center.y; if(fabsf(Dy) > extents.y && Dy*mDir.y>=0.0f) return FALSE; +// float Dz = mOrigin.z - center.z; if(fabsf(Dz) > extents.z && Dz*mDir.z>=0.0f) return FALSE; + + float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && Dx*mDir.x>=0.0f) return FALSE; + float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && Dy*mDir.y>=0.0f) return FALSE; + float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && Dz*mDir.z>=0.0f) return FALSE; + +// float Dx = mOrigin.x - center.x; if(GREATER(Dx, extents.x) && ((SIR(Dx)-1)^SIR(mDir.x))>=0.0f) return FALSE; +// float Dy = mOrigin.y - center.y; if(GREATER(Dy, extents.y) && ((SIR(Dy)-1)^SIR(mDir.y))>=0.0f) return FALSE; +// float Dz = mOrigin.z - center.z; if(GREATER(Dz, extents.z) && ((SIR(Dz)-1)^SIR(mDir.z))>=0.0f) return FALSE; + + float f; + f = mDir.y * Dz - mDir.z * Dy; if(fabsf(f) > extents.y*mFDir.z + extents.z*mFDir.y) return FALSE; + f = mDir.z * Dx - mDir.x * Dz; if(fabsf(f) > extents.x*mFDir.z + extents.z*mFDir.x) return FALSE; + f = mDir.x * Dy - mDir.y * Dx; if(fabsf(f) > extents.x*mFDir.y + extents.y*mFDir.x) return FALSE; + + return TRUE; +} diff --git a/contrib/Opcode/OPC_RayCollider.cpp b/contrib/Opcode/OPC_RayCollider.cpp new file mode 100644 index 0000000..d1c90a5 --- /dev/null +++ b/contrib/Opcode/OPC_RayCollider.cpp @@ -0,0 +1,762 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a ray collider. + * \file OPC_RayCollider.cpp + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a ray-vs-tree collider. + * This class performs a stabbing query on an AABB tree, i.e. does a ray-mesh collision. + * + * HIGHER DISTANCE BOUND: + * + * If P0 and P1 are two 3D points, let's define: + * - d = distance between P0 and P1 + * - Origin = P0 + * - Direction = (P1 - P0) / d = normalized direction vector + * - A parameter t such as a IcePoint P on the line (P0,P1) is P = Origin + t * Direction + * - t = 0 --> P = P0 + * - t = d --> P = P1 + * + * Then we can define a general "ray" as: + * + * struct Ray + * { + * IcePoint Origin; + * IcePoint Direction; + * }; + * + * But it actually maps three different things: + * - a segment, when 0 <= t <= d + * - a half-line, when 0 <= t < +infinity, or -infinity < t <= d + * - a line, when -infinity < t < +infinity + * + * In Opcode, we support segment queries, which yield half-line queries by setting d = +infinity. + * We don't support line-queries. If you need them, shift the origin along the ray by an appropriate margin. + * + * In short, the lower bound is always 0, and you can setup the higher bound "d" with RayCollider::SetMaxDist(). + * + * Query |segment |half-line |line + * --------|-------------------|---------------|---------------- + * Usages |-shadow feelers |-raytracing |- + * |-sweep tests |-in/out tests | + * + * FIRST CONTACT: + * + * - You can setup "first contact" mode or "all contacts" mode with RayCollider::SetFirstContact(). + * - In "first contact" mode we return as soon as the ray hits one face. If can be useful e.g. for shadow feelers, where + * you want to know whether the path to the light is free or not (a boolean answer is enough). + * - In "all contacts" mode we return all faces hit by the ray. + * + * TEMPORAL COHERENCE: + * + * - You can enable or disable temporal coherence with RayCollider::SetTemporalCoherence(). + * - It currently only works in "first contact" mode. + * - If temporal coherence is enabled, the previously hit triangle is cached during the first query. Then, next queries + * start by colliding the ray against the cached triangle. If they still collide, we return immediately. + * + * CLOSEST HIT: + * + * - You can enable or disable "closest hit" with RayCollider::SetClosestHit(). + * - It currently only works in "all contacts" mode. + * - If closest hit is enabled, faces are sorted by distance on-the-fly and the closest one only is reported. + * + * BACKFACE CULLING: + * + * - You can enable or disable backface culling with RayCollider::SetCulling(). + * - If culling is enabled, ray will not hit back faces (only front faces). + * + * + * + * \class RayCollider + * \author Pierre Terdiman + * \version 1.3 + * \date June, 2, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * This class describes a face hit by a ray or segment. + * This is a particular class dedicated to stabbing queries. + * + * \class CollisionFace + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * This class is a dedicated collection of CollisionFace. + * + * \class CollisionFaces + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +#include "OPC_RayAABBOverlap.h" +#include "OPC_RayTriOverlap.h" + +#define SET_CONTACT(prim_index, flag) \ + mNbIntersections++; \ + /* Set contact status */ \ + mFlags |= flag; \ + /* In any case the contact has been found and recorded in mStabbedFace */ \ + mStabbedFace.mFaceID = prim_index; + +#ifdef OPC_RAYHIT_CALLBACK + + #define HANDLE_CONTACT(prim_index, flag) \ + SET_CONTACT(prim_index, flag) \ + \ + if(mHitCallback) (mHitCallback)(mStabbedFace, mUserData); + + #define UPDATE_CACHE \ + if(cache && GetContactStatus()) \ + { \ + *cache = mStabbedFace.mFaceID; \ + } +#else + + #define HANDLE_CONTACT(prim_index, flag) \ + SET_CONTACT(prim_index, flag) \ + \ + /* Now we can also record it in mStabbedFaces if available */ \ + if(mStabbedFaces) \ + { \ + /* If we want all faces or if that's the first one we hit */ \ + if(!mClosestHit || !mStabbedFaces->GetNbFaces()) \ + { \ + mStabbedFaces->AddFace(mStabbedFace); \ + } \ + else \ + { \ + /* We only keep closest hit */ \ + CollisionFace* Current = const_cast(mStabbedFaces->GetFaces()); \ + if(Current && mStabbedFace.mDistancemDistance) \ + { \ + *Current = mStabbedFace; \ + } \ + } \ + } + + #define UPDATE_CACHE \ + if(cache && GetContactStatus() && mStabbedFaces) \ + { \ + const CollisionFace* Current = mStabbedFaces->GetFaces(); \ + if(Current) *cache = Current->mFaceID; \ + else *cache = INVALID_ID; \ + } +#endif + +#define SEGMENT_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ + \ + /* Perform ray-tri overlap test and return */ \ + if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ + { \ + /* Intersection IcePoint is valid if dist < segment's length */ \ + /* We know dist>0 so we can use integers */ \ + if(IR(mStabbedFace.mDistance)GetTriangle(VP, prim_index); \ + \ + /* Perform ray-tri overlap test and return */ \ + if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ + { \ + HANDLE_CONTACT(prim_index, flag) \ + } + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RayCollider::RayCollider() : + mNbRayBVTests (0), + mNbRayPrimTests (0), + mNbIntersections (0), + mCulling (true), +#ifdef OPC_RAYHIT_CALLBACK + mHitCallback (null), + mUserData (0), +#else + mClosestHit (false), + mStabbedFaces (null), +#endif + mMaxDist (MAX_FLOAT) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +RayCollider::~RayCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Validates current settings. You should call this method after all the settings and callbacks have been defined. + * \return null if everything is ok, else a string describing the problem + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +const char* RayCollider::ValidateSettings() +{ + if(mMaxDist<0.0f) return "Higher distance bound must be positive!"; + if(TemporalCoherenceEnabled() && !FirstContactEnabled()) return "Temporal coherence only works with ""First contact"" mode!"; +#ifndef OPC_RAYHIT_CALLBACK + if(mClosestHit && FirstContactEnabled()) return "Closest hit doesn't work with ""First contact"" mode!"; + if(TemporalCoherenceEnabled() && mClosestHit) return "Temporal coherence can't guarantee to report closest hit!"; +#endif + if(SkipPrimitiveTests()) return "SkipPrimitiveTests not possible for RayCollider ! (not implemented)"; + return null; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic stabbing query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - in the user-provided destination array + * + * \param world_ray [in] stabbing ray in world space + * \param model [in] Opcode model to collide with + * \param world [in] model's world matrix, or null + * \param cache [in] a possibly cached face index, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool RayCollider::Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world, udword* cache) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(world_ray, world, cache)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); + else _RayStab(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); + else _RayStab(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); + else _RayStab(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(Tree->GetNodes()); + else _RayStab(Tree->GetNodes()); + } + } + + // Update cache if needed + UPDATE_CACHE + return true; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a stabbing query : + * - reset stats & contact status + * - compute ray in local space + * - check temporal coherence + * + * \param world_ray [in] stabbing ray in world space + * \param world [in] object's world matrix, or null + * \param face_id [in] index of previously stabbed triangle + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrix must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL RayCollider::InitQuery(const Ray& world_ray, const Matrix4x4* world, udword* face_id) +{ + // Reset stats & contact status + Collider::InitQuery(); + mNbRayBVTests = 0; + mNbRayPrimTests = 0; + mNbIntersections = 0; +#ifndef OPC_RAYHIT_CALLBACK + if(mStabbedFaces) mStabbedFaces->Reset(); +#endif + + // Compute ray in local space + // The (Origin/Dir) form is needed for the ray-triangle test anyway (even for segment tests) + if(world) + { + Matrix3x3 InvWorld = *world; + mDir = InvWorld * world_ray.mDir; + + Matrix4x4 World; + InvertPRMatrix(World, *world); + mOrigin = world_ray.mOrig * World; + } + else + { + mDir = world_ray.mDir; + mOrigin = world_ray.mOrig; + } + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + if(!SkipPrimitiveTests()) + { + // Perform overlap test between the unique triangle and the ray (and set contact status if needed) + SEGMENT_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // Check temporal coherence : + + // Test previously colliding primitives first + if(TemporalCoherenceEnabled() && FirstContactEnabled() && face_id && *face_id!=INVALID_ID) + { +#ifdef OLD_CODE +#ifndef OPC_RAYHIT_CALLBACK + if(!mClosestHit) +#endif + { + // Request vertices from the app + VertexPointers VP; + mIMesh->GetTriangle(VP, *face_id); + // Perform ray-cached tri overlap test + if(RayTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) + { + // Intersection IcePoint is valid if: + // - distance is positive (else it can just be a face behind the orig IcePoint) + // - distance is smaller than a given max distance (useful for shadow feelers) +// if(mStabbedFace.mDistance>0.0f && mStabbedFace.mDistanceAddFace(mStabbedFace); +#endif + return TRUE; + } + } + } +#else + // New code + // We handle both IceSegment/ray queries with the same segment code, and a possible infinite limit + SEGMENT_PRIM(*face_id, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; +#endif + } + + // Precompute data (moved after temporal coherence since only needed for ray-AABB) + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) + { + // For IceSegment-AABB overlap + mData = 0.5f * mDir * mMaxDist; + mData2 = mOrigin + mData; + + // Precompute mFDir; + mFDir.x = fabsf(mData.x); + mFDir.y = fabsf(mData.y); + mFDir.z = fabsf(mData.z); + } + else + { + // For Ray-AABB overlap +// udword x = SIR(mDir.x)-1; +// udword y = SIR(mDir.y)-1; +// udword z = SIR(mDir.z)-1; +// mData.x = FR(x); +// mData.y = FR(y); +// mData.z = FR(z); + + // Precompute mFDir; + mFDir.x = fabsf(mDir.x); + mFDir.y = fabsf(mDir.y); + mFDir.z = fabsf(mDir.z); + } + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Stabbing query for vanilla AABB trees. + * \param world_ray [in] stabbing ray in world space + * \param tree [in] AABB tree + * \param box_indices [out] indices of stabbed boxes + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool RayCollider::Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices) +{ + // ### bad design here + + // This is typically called for a scene tree, full of -AABBs-, not full of triangles. + // So we don't really have "primitives" to deal with. Hence it doesn't work with + // "FirstContact" + "TemporalCoherence". + ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); + + // Checkings + if(!tree) return false; + + // Init collision query + // Basically this is only called to initialize precomputed data + if(InitQuery(world_ray)) return true; + + // Perform stabbing query + if(IR(mMaxDist)!=IEEE_MAX_FLOAT) _SegmentStab(tree, box_indices); + else _RayStab(tree, box_indices); + + return true; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBCollisionNode* node) +{ + // Perform IceSegment-AABB overlap test + if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + if(node->IsLeaf()) + { + SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _SegmentStab(node->GetPos()); + + if(ContactFound()) return; + + _SegmentStab(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform IceSegment-AABB overlap test + if(!SegmentAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf()) + { + SEGMENT_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _SegmentStab(node->GetPos()); + + if(ContactFound()) return; + + _SegmentStab(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBNoLeafNode* node) +{ + // Perform IceSegment-AABB overlap test + if(!SegmentAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + if(node->HasPosLeaf()) + { + SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT) + } + else _SegmentStab(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) + { + SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT) + } + else _SegmentStab(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform IceSegment-AABB overlap test + if(!SegmentAABBOverlap(Center, Extents)) return; + + if(node->HasPosLeaf()) + { + SEGMENT_PRIM(node->GetPosPrimitive(), OPC_CONTACT) + } + else _SegmentStab(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) + { + SEGMENT_PRIM(node->GetNegPrimitive(), OPC_CONTACT) + } + else _SegmentStab(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for vanilla AABB trees. + * \param node [in] current collision node + * \param box_indices [out] indices of stabbed boxes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_SegmentStab(const AABBTreeNode* node, Container& box_indices) +{ + // Test the box against the segment + IcePoint Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!SegmentAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf()) + { + box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _SegmentStab(node->GetPos(), box_indices); + _SegmentStab(node->GetNeg(), box_indices); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBCollisionNode* node) +{ + // Perform Ray-AABB overlap test + if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + if(node->IsLeaf()) + { + RAY_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _RayStab(node->GetPos()); + + if(ContactFound()) return; + + _RayStab(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Ray-AABB overlap test + if(!RayAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf()) + { + RAY_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _RayStab(node->GetPos()); + + if(ContactFound()) return; + + _RayStab(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBNoLeafNode* node) +{ + // Perform Ray-AABB overlap test + if(!RayAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + if(node->HasPosLeaf()) + { + RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT) + } + else _RayStab(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) + { + RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT) + } + else _RayStab(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Ray-AABB overlap test + if(!RayAABBOverlap(Center, Extents)) return; + + if(node->HasPosLeaf()) + { + RAY_PRIM(node->GetPosPrimitive(), OPC_CONTACT) + } + else _RayStab(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) + { + RAY_PRIM(node->GetNegPrimitive(), OPC_CONTACT) + } + else _RayStab(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive stabbing query for vanilla AABB trees. + * \param node [in] current collision node + * \param box_indices [out] indices of stabbed boxes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void RayCollider::_RayStab(const AABBTreeNode* node, Container& box_indices) +{ + // Test the box against the ray + IcePoint Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!RayAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf()) + { + mFlags |= OPC_CONTACT; + box_indices.Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _RayStab(node->GetPos(), box_indices); + _RayStab(node->GetNeg(), box_indices); + } +} diff --git a/contrib/Opcode/OPC_RayCollider.h b/contrib/Opcode/OPC_RayCollider.h new file mode 100644 index 0000000..393bc5f --- /dev/null +++ b/contrib/Opcode/OPC_RayCollider.h @@ -0,0 +1,225 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a ray collider. + * \file OPC_RayCollider.h + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_RAYCOLLIDER_H__ +#define __OPC_RAYCOLLIDER_H__ + + class OPCODE_API CollisionFace + { + public: + //! Constructor + inline_ CollisionFace() {} + //! Destructor + inline_ ~CollisionFace() {} + + udword mFaceID; //!< Index of touched face + float mDistance; //!< Distance from collider to hitpoint + float mU, mV; //!< Impact barycentric coordinates + }; + + class OPCODE_API CollisionFaces : private Container + { + public: + //! Constructor + CollisionFaces() {} + //! Destructor + ~CollisionFaces() {} + + inline_ udword GetNbFaces() const { return GetNbEntries()>>2; } + inline_ const CollisionFace* GetFaces() const { return (const CollisionFace*)GetEntries(); } + + inline_ void Reset() { Container::Reset(); } + + inline_ void AddFace(const CollisionFace& face) { Add(face.mFaceID).Add(face.mDistance).Add(face.mU).Add(face.mV); } + }; + +#ifdef OPC_RAYHIT_CALLBACK + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * User-callback, called by OPCODE to record a hit. + * \param hit [in] current hit + * \param user_data [in] user-defined data from SetCallback() + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef void (*HitCallback) (const CollisionFace& hit, void* user_data); +#endif + + class OPCODE_API RayCollider : public Collider + { + public: + // Constructor / Destructor + RayCollider(); + virtual ~RayCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic stabbing query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - in the user-provided destination array + * + * \param world_ray [in] stabbing ray in world space + * \param model [in] Opcode model to collide with + * \param world [in] model's world matrix, or null + * \param cache [in] a possibly cached face index, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world=null, udword* cache=null); + // + bool Collide(const Ray& world_ray, const AABBTree* tree, Container& box_indices); + // Settings + +#ifndef OPC_RAYHIT_CALLBACK + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: enable or disable "closest hit" mode. + * \param flag [in] true to report closest hit only + * \see SetCulling(bool flag) + * \see SetMaxDist(float max_dist) + * \see SetDestination(StabbedFaces* sf) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetClosestHit(bool flag) { mClosestHit = flag; } +#endif + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: enable or disable backface culling. + * \param flag [in] true to enable backface culling + * \see SetClosestHit(bool flag) + * \see SetMaxDist(float max_dist) + * \see SetDestination(StabbedFaces* sf) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetCulling(bool flag) { mCulling = flag; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: sets the higher distance bound. + * \param max_dist [in] higher distance bound. Default = maximal value, for ray queries (else segment) + * \see SetClosestHit(bool flag) + * \see SetCulling(bool flag) + * \see SetDestination(StabbedFaces* sf) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetMaxDist(float max_dist=MAX_FLOAT) { mMaxDist = max_dist; } + +#ifdef OPC_RAYHIT_CALLBACK + inline_ void SetHitCallback(HitCallback cb) { mHitCallback = cb; } + inline_ void SetUserData(void* user_data) { mUserData = user_data; } +#else + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: sets the destination array for stabbed faces. + * \param cf [in] destination array, filled during queries + * \see SetClosestHit(bool flag) + * \see SetCulling(bool flag) + * \see SetMaxDist(float max_dist) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetDestination(CollisionFaces* cf) { mStabbedFaces = cf; } +#endif + // Stats + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Ray-BV overlap tests after a collision query. + * \see GetNbRayPrimTests() + * \see GetNbIntersections() + * \return the number of Ray-BV tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbRayBVTests() const { return mNbRayBVTests; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Ray-Triangle overlap tests after a collision query. + * \see GetNbRayBVTests() + * \see GetNbIntersections() + * \return the number of Ray-Triangle tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbRayPrimTests() const { return mNbRayPrimTests; } + + // In-out test + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of intersection found after a collision query. Can be used for in/out tests. + * \see GetNbRayBVTests() + * \see GetNbRayPrimTests() + * \return the number of valid intersections during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbIntersections() const { return mNbIntersections; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) const char* ValidateSettings(); + + protected: + // Ray in local space + IcePoint mOrigin; //!< Ray origin + IcePoint mDir; //!< Ray direction (normalized) + IcePoint mFDir; //!< fabsf(mDir) + IcePoint mData, mData2; + // Stabbed faces + CollisionFace mStabbedFace; //!< Current stabbed face +#ifdef OPC_RAYHIT_CALLBACK + HitCallback mHitCallback; //!< Callback used to record a hit + void* mUserData; //!< User-defined data +#else + CollisionFaces* mStabbedFaces; //!< List of stabbed faces +#endif + // Stats + udword mNbRayBVTests; //!< Number of Ray-BV tests + udword mNbRayPrimTests; //!< Number of Ray-Primitive tests + // In-out test + udword mNbIntersections; //!< Number of valid intersections + // Dequantization coeffs + IcePoint mCenterCoeff; + IcePoint mExtentsCoeff; + // Settings + float mMaxDist; //!< Valid segment on the ray +#ifndef OPC_RAYHIT_CALLBACK + bool mClosestHit; //!< Report closest hit only +#endif + bool mCulling; //!< Stab culled faces or not + // Internal methods + void _SegmentStab(const AABBCollisionNode* node); + void _SegmentStab(const AABBNoLeafNode* node); + void _SegmentStab(const AABBQuantizedNode* node); + void _SegmentStab(const AABBQuantizedNoLeafNode* node); + void _SegmentStab(const AABBTreeNode* node, Container& box_indices); + void _RayStab(const AABBCollisionNode* node); + void _RayStab(const AABBNoLeafNode* node); + void _RayStab(const AABBQuantizedNode* node); + void _RayStab(const AABBQuantizedNoLeafNode* node); + void _RayStab(const AABBTreeNode* node, Container& box_indices); + // Overlap tests + inline_ BOOL RayAABBOverlap(const IcePoint& center, const IcePoint& extents); + inline_ BOOL SegmentAABBOverlap(const IcePoint& center, const IcePoint& extents); + inline_ BOOL RayTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2); + // Init methods + BOOL InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null); + }; + +#endif // __OPC_RAYCOLLIDER_H__ diff --git a/contrib/Opcode/OPC_RayTriOverlap.h b/contrib/Opcode/OPC_RayTriOverlap.h new file mode 100644 index 0000000..405c7e1 --- /dev/null +++ b/contrib/Opcode/OPC_RayTriOverlap.h @@ -0,0 +1,89 @@ +#define LOCAL_EPSILON 0.000001f + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes a ray-triangle intersection test. + * Original code from Tomas Möller's "Fast Minimum Storage Ray-Triangle Intersection". + * It's been optimized a bit with integer code, and modified to return a non-intersection if distance from + * ray origin to triangle is negative. + * + * \param vert0 [in] triangle vertex + * \param vert1 [in] triangle vertex + * \param vert2 [in] triangle vertex + * \return true on overlap. mStabbedFace is filled with relevant info. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL RayCollider::RayTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2) +{ + // Stats + mNbRayPrimTests++; + + // Find vectors for two edges sharing vert0 + IcePoint edge1 = vert1 - vert0; + IcePoint edge2 = vert2 - vert0; + + // Begin calculating determinant - also used to calculate U parameter + IcePoint pvec = mDir^edge2; + + // If determinant is near zero, ray lies in plane of triangle + float det = edge1|pvec; + + if(mCulling) + { + if(det 0. So we can use integer cmp. + + // Calculate distance from vert0 to ray origin + IcePoint tvec = mOrigin - vert0; + + // Calculate U parameter and test bounds + mStabbedFace.mU = tvec|pvec; +// if(IR(u)&0x80000000 || u>det) return FALSE; + if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IR(det)) return FALSE; + + // Prepare to test V parameter + IcePoint qvec = tvec^edge1; + + // Calculate V parameter and test bounds + mStabbedFace.mV = mDir|qvec; + if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>det) return FALSE; + + // Calculate t, scale parameters, ray intersects triangle + mStabbedFace.mDistance = edge2|qvec; + // Det > 0 so we can early exit here + // Intersection IcePoint is valid if distance is positive (else it can just be a face behind the orig IcePoint) + if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE; + // Else go on + float OneOverDet = 1.0f / det; + mStabbedFace.mDistance *= OneOverDet; + mStabbedFace.mU *= OneOverDet; + mStabbedFace.mV *= OneOverDet; + } + else + { + // the non-culling branch + if(det>-LOCAL_EPSILON && det1.0f) return FALSE; + if(IS_NEGATIVE_FLOAT(mStabbedFace.mU) || IR(mStabbedFace.mU)>IEEE_1_0) return FALSE; + + // prepare to test V parameter + IcePoint qvec = tvec^edge1; + + // Calculate V parameter and test bounds + mStabbedFace.mV = (mDir|qvec) * OneOverDet; + if(IS_NEGATIVE_FLOAT(mStabbedFace.mV) || mStabbedFace.mU+mStabbedFace.mV>1.0f) return FALSE; + + // Calculate t, ray intersects triangle + mStabbedFace.mDistance = (edge2|qvec) * OneOverDet; + // Intersection IcePoint is valid if distance is positive (else it can just be a face behind the orig IcePoint) + if(IS_NEGATIVE_FLOAT(mStabbedFace.mDistance)) return FALSE; + } + return TRUE; +} diff --git a/contrib/Opcode/OPC_Settings.h b/contrib/Opcode/OPC_Settings.h new file mode 100644 index 0000000..88d2ccd --- /dev/null +++ b/contrib/Opcode/OPC_Settings.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains compilation flags. + * \file OPC_Settings.h + * \author Pierre Terdiman + * \date May, 12, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_SETTINGS_H__ +#define __OPC_SETTINGS_H__ + + //! Use CPU comparisons (comment that line to use standard FPU compares) + #define OPC_CPU_COMPARE + + //! Use FCOMI / FCMOV on Pentium-Pro based processors (comment that line to use plain C++) + #define OPC_USE_FCOMI + + //! Use epsilon value in tri-tri overlap test + #define OPC_TRITRI_EPSILON_TEST + + //! Use tree-coherence or not [not implemented yet] +// #define OPC_USE_TREE_COHERENCE + + //! Use callbacks or direct pointers. Using callbacks might be a bit slower (but probably not much) +// #define OPC_USE_CALLBACKS + + //! Support triangle and vertex strides or not. Using strides might be a bit slower (but probably not much) +// #define OPC_USE_STRIDE + + //! Discard negative pointer in vanilla trees + #define OPC_NO_NEG_VANILLA_TREE + + //! Use a callback in the ray collider + #define OPC_RAYHIT_CALLBACK + + // NB: no compilation flag to enable/disable stats since they're actually needed in the box/box overlap test + +#endif //__OPC_SETTINGS_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_SphereAABBOverlap.h b/contrib/Opcode/OPC_SphereAABBOverlap.h new file mode 100644 index 0000000..b7b4376 --- /dev/null +++ b/contrib/Opcode/OPC_SphereAABBOverlap.h @@ -0,0 +1,128 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Sphere-AABB overlap test, based on Jim Arvo's code. + * \param center [in] box center + * \param extents [in] box extents + * \return TRUE on overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL SphereCollider::SphereAABBOverlap(const IcePoint& center, const IcePoint& extents) +{ + // Stats + mNbVolumeBVTests++; + + float d = 0.0f; + + //find the square of the distance + //from the sphere to the box +#ifdef OLDIES + for(udword i=0;i<3;i++) + { + float tmp = mCenter[i] - center[i]; + float s = tmp + extents[i]; + + if(s<0.0f) d += s*s; + else + { + s = tmp - extents[i]; + if(s>0.0f) d += s*s; + } + } +#endif + +//#ifdef NEW_TEST + +// float tmp = mCenter.x - center.x; +// float s = tmp + extents.x; + + float tmp,s; + + tmp = mCenter.x - center.x; + s = tmp + extents.x; + + if(s<0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + else + { + s = tmp - extents.x; + if(s>0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + } + + tmp = mCenter.y - center.y; + s = tmp + extents.y; + + if(s<0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + else + { + s = tmp - extents.y; + if(s>0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + } + + tmp = mCenter.z - center.z; + s = tmp + extents.z; + + if(s<0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + else + { + s = tmp - extents.z; + if(s>0.0f) + { + d += s*s; + if(d>mRadius2) return FALSE; + } + } +//#endif + +#ifdef OLDIES +// IcePoint Min = center - extents; +// IcePoint Max = center + extents; + + float d = 0.0f; + + //find the square of the distance + //from the sphere to the box + for(udword i=0;i<3;i++) + { +float Min = center[i] - extents[i]; + +// if(mCenter[i]Max[i]) + if(mCenter[i]>Max) + { + float s = mCenter[i] - Max; + d += s*s; + } + } + } +#endif + return d <= mRadius2; +} diff --git a/contrib/Opcode/OPC_SphereCollider.cpp b/contrib/Opcode/OPC_SphereCollider.cpp new file mode 100644 index 0000000..32af6e6 --- /dev/null +++ b/contrib/Opcode/OPC_SphereCollider.cpp @@ -0,0 +1,726 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a sphere collider. + * \file OPC_SphereCollider.cpp + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains a sphere-vs-tree collider. + * This class performs a collision test between a sphere and an AABB tree. You can use this to do a standard player vs world collision, + * in a Nettle/Telemachos way. It doesn't suffer from all reported bugs in those two classic codes - the "new" one by Paul Nettle is a + * debuggued version I think. Collision response can be driven by reported collision data - it works extremely well for me. In sake of + * efficiency, all meshes (that is, all AABB trees) should of course also be kept in an extra hierarchical structure (octree, whatever). + * + * \class SphereCollider + * \author Pierre Terdiman + * \version 1.3 + * \date June, 2, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +#include "OPC_SphereAABBOverlap.h" +#include "OPC_SphereTriOverlap.h" + +#define SET_CONTACT(prim_index, flag) \ + /* Set contact status */ \ + mFlags |= flag; \ + mTouchedPrimitives->Add(prim_index); + +//! Sphere-triangle overlap test +#define SPHERE_PRIM(prim_index, flag) \ + /* Request vertices from the app */ \ + VertexPointers VP; mIMesh->GetTriangle(VP, prim_index); \ + \ + /* Perform sphere-tri overlap test */ \ + if(SphereTriOverlap(*VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) \ + { \ + SET_CONTACT(prim_index, flag) \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SphereCollider::SphereCollider() +{ + mCenter.Zero(); + mRadius2 = 0.0f; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SphereCollider::~SphereCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a sphere cache + * \param sphere [in] collision sphere in local space + * \param model [in] Opcode model to collide with + * \param worlds [in] sphere's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds, const Matrix4x4* worldm) +{ + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, sphere, worlds, worldm)) return true; + + if(!model.HasLeafNodes()) + { + if(model.IsQuantized()) + { + const AABBQuantizedNoLeafTree* Tree = (const AABBQuantizedNoLeafTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query + if(SkipPrimitiveTests()) _CollideNoPrimitiveTest(Tree->GetNodes()); + else _Collide(Tree->GetNodes()); + } + } + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - setup matrices + * - check temporal coherence + * + * \param cache [in/out] a sphere cache + * \param sphere [in] sphere in local space + * \param worlds [in] sphere's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return TRUE if we can return immediately + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL SphereCollider::InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds, const Matrix4x4* worldm) +{ + // 1) Call the base method + VolumeCollider::InitQuery(); + + // 2) Compute sphere in model space: + // - Precompute R^2 + mRadius2 = sphere.mRadius * sphere.mRadius; + // - Compute center position + mCenter = sphere.mCenter; + // -> to world space + if(worlds) mCenter *= *worlds; + // -> to model space + if(worldm) + { + // Invert model matrix + Matrix4x4 InvWorldM; + InvertPRMatrix(InvWorldM, *worldm); + + mCenter *= InvWorldM; + } + + // 3) Setup destination pointer + mTouchedPrimitives = &cache.TouchedPrimitives; + + // 4) Special case: 1-triangle meshes [Opcode 1.3] + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + if(!SkipPrimitiveTests()) + { + // We simply perform the BV-Prim overlap test each time. We assume single triangle has index 0. + mTouchedPrimitives->Reset(); + + // Perform overlap test between the unique triangle and the sphere (and set contact status if needed) + SPHERE_PRIM(udword(0), OPC_CONTACT) + + // Return immediately regardless of status + return TRUE; + } + } + + // 5) Check temporal coherence : + if(TemporalCoherenceEnabled()) + { + // Here we use temporal coherence + // => check results from previous frame before performing the collision query + if(FirstContactEnabled()) + { + // We're only interested in the first contact found => test the unique previously touched face + if(mTouchedPrimitives->GetNbEntries()) + { + // Get index of previously touched face = the first entry in the array + udword PreviouslyTouchedFace = mTouchedPrimitives->GetEntry(0); + + // Then reset the array: + // - if the overlap test below is successful, the index we'll get added back anyway + // - if it isn't, then the array should be reset anyway for the normal query + mTouchedPrimitives->Reset(); + + // Perform overlap test between the cached triangle and the sphere (and set contact status if needed) + SPHERE_PRIM(PreviouslyTouchedFace, OPC_TEMPORAL_CONTACT) + + // Return immediately if possible + if(GetContactStatus()) return TRUE; + } + // else no face has been touched during previous query + // => we'll have to perform a normal query + } + else + { + // We're interested in all contacts =>test the new real sphere N(ew) against the previous fat sphere P(revious): + float r = sqrtf(cache.FatRadius2) - sphere.mRadius; + if(IsCacheValid(cache) && cache.Center.SquareDistance(mCenter) < r*r) + { + // - if N is included in P, return previous list + // => we simply leave the list (mTouchedFaces) unchanged + + // Set contact status if needed + if(mTouchedPrimitives->GetNbEntries()) mFlags |= OPC_TEMPORAL_CONTACT; + + // In any case we don't need to do a query + return TRUE; + } + else + { + // - else do the query using a fat N + + // Reset cache since we'll about to perform a real query + mTouchedPrimitives->Reset(); + + // Make a fat sphere so that coherence will work for subsequent frames + mRadius2 *= cache.FatCoeff; +// mRadius2 = (sphere.mRadius * cache.FatCoeff)*(sphere.mRadius * cache.FatCoeff); + + // Update cache with query data (signature for cached faces) + cache.Center = mCenter; + cache.FatRadius2 = mRadius2; + } + } + } + else + { + // Here we don't use temporal coherence => do a normal query + mTouchedPrimitives->Reset(); + } + + return FALSE; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for vanilla AABB trees. + * \param cache [in/out] a sphere cache + * \param sphere [in] collision sphere in world space + * \param tree [in] AABB tree + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool SphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree) +{ + // This is typically called for a scene tree, full of -AABBs-, not full of triangles. + // So we don't really have "primitives" to deal with. Hence it doesn't work with + // "FirstContact" + "TemporalCoherence". + ASSERT( !(FirstContactEnabled() && TemporalCoherenceEnabled()) ); + + // Checkings + if(!tree) return false; + + // Init collision query + if(InitQuery(cache, sphere)) return true; + + // Perform collision query + _Collide(tree); + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Checks the sphere completely contains the box. In which case we can end the query sooner. + * \param bc [in] box center + * \param be [in] box extents + * \return true if the sphere contains the whole box + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL SphereCollider::SphereContainsBox(const IcePoint& bc, const IcePoint& be) +{ + // I assume if all 8 box vertices are inside the sphere, so does the whole box. + // Sounds ok but maybe there's a better way? + IcePoint p; + p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z+be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x+be.x; p.y=bc.y+be.y; p.z=bc.z-be.z; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x+be.x; p.y=bc.y-be.y; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + p.x=bc.x-be.x; if(mCenter.SquareDistance(p)>=mRadius2) return FALSE; + + return TRUE; +} + +#define TEST_BOX_IN_SPHERE(center, extents) \ + if(SphereContainsBox(center, extents)) \ + { \ + /* Set contact status */ \ + mFlags |= OPC_CONTACT; \ + _Dump(node); \ + return; \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBCollisionNode* node) +{ + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_CollideNoPrimitiveTest(const AABBCollisionNode* node) +{ + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_SPHERE(Center, Extents) + + if(node->IsLeaf()) + { + SPHERE_PRIM(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _Collide(node->GetPos()); + + if(ContactFound()) return; + + _Collide(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_SPHERE(Center, Extents) + + if(node->IsLeaf()) + { + SET_CONTACT(node->GetPrimitive(), OPC_CONTACT) + } + else + { + _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + _CollideNoPrimitiveTest(node->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBNoLeafNode* node) +{ + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_CollideNoPrimitiveTest(const AABBNoLeafNode* node) +{ + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(node->mAABB.mCenter, node->mAABB.mExtents)) return; + + TEST_BOX_IN_SPHERE(node->mAABB.mCenter, node->mAABB.mExtents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_SPHERE(Center, Extents) + + if(node->HasPosLeaf()) { SPHERE_PRIM(node->GetPosPrimitive(), OPC_CONTACT) } + else _Collide(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SPHERE_PRIM(node->GetNegPrimitive(), OPC_CONTACT) } + else _Collide(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees, without primitive tests. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node) +{ + // Dequantize box + const QuantizedAABB& Box = node->mAABB; + const IcePoint Center(float(Box.mCenter[0]) * mCenterCoeff.x, float(Box.mCenter[1]) * mCenterCoeff.y, float(Box.mCenter[2]) * mCenterCoeff.z); + const IcePoint Extents(float(Box.mExtents[0]) * mExtentsCoeff.x, float(Box.mExtents[1]) * mExtentsCoeff.y, float(Box.mExtents[2]) * mExtentsCoeff.z); + + // Perform Sphere-AABB overlap test + if(!SphereAABBOverlap(Center, Extents)) return; + + TEST_BOX_IN_SPHERE(Center, Extents) + + if(node->HasPosLeaf()) { SET_CONTACT(node->GetPosPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetPos()); + + if(ContactFound()) return; + + if(node->HasNegLeaf()) { SET_CONTACT(node->GetNegPrimitive(), OPC_CONTACT) } + else _CollideNoPrimitiveTest(node->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for vanilla AABB trees. + * \param node [in] current collision node + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void SphereCollider::_Collide(const AABBTreeNode* node) +{ + // Perform Sphere-AABB overlap test + IcePoint Center, Extents; + node->GetAABB()->GetCenter(Center); + node->GetAABB()->GetExtents(Extents); + if(!SphereAABBOverlap(Center, Extents)) return; + + if(node->IsLeaf() || SphereContainsBox(Center, Extents)) + { + mFlags |= OPC_CONTACT; + mTouchedPrimitives->Add(node->GetPrimitives(), node->GetNbPrimitives()); + } + else + { + _Collide(node->GetPos()); + _Collide(node->GetNeg()); + } +} + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridSphereCollider::HybridSphereCollider() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +HybridSphereCollider::~HybridSphereCollider() +{ +} + +bool HybridSphereCollider::Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds, const Matrix4x4* worldm) +{ + // We don't want primitive tests here! + mFlags |= OPC_NO_PRIMITIVE_TESTS; + + // Checkings + if(!Setup(&model)) return false; + + // Init collision query + if(InitQuery(cache, sphere, worlds, worldm)) return true; + + // Special case for 1-leaf trees + if(mCurrentModel && mCurrentModel->HasSingleNode()) + { + // Here we're supposed to perform a normal query, except our tree has a single node, i.e. just a few triangles + udword Nb = mIMesh->GetNbTriangles(); + + // Loop through all triangles + for(udword i=0;imCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBNoLeafTree* Tree = (const AABBNoLeafTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + else + { + if(model.IsQuantized()) + { + const AABBQuantizedTree* Tree = (const AABBQuantizedTree*)model.GetTree(); + + // Setup dequantization coeffs + mCenterCoeff = Tree->mCenterCoeff; + mExtentsCoeff = Tree->mExtentsCoeff; + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + else + { + const AABBCollisionTree* Tree = (const AABBCollisionTree*)model.GetTree(); + + // Perform collision query - we don't want primitive tests here! + _CollideNoPrimitiveTest(Tree->GetNodes()); + } + } + + // We only have a list of boxes so far + if(GetContactStatus()) + { + // Reset contact status, since it currently only reflects collisions with leaf boxes + Collider::InitQuery(); + + // Change dest container so that we can use built-in overlap tests and get collided primitives + cache.TouchedPrimitives.Reset(); + mTouchedPrimitives = &cache.TouchedPrimitives; + + // Read touched leaf boxes + udword Nb = mTouchedBoxes.GetNbEntries(); + const udword* Touched = mTouchedBoxes.GetEntries(); + + const LeafTriangles* LT = model.GetLeafTriangles(); + const udword* Indices = model.GetIndices(); + + // Loop through touched leaves + while(Nb--) + { + const LeafTriangles& CurrentLeaf = LT[*Touched++]; + + // Each leaf box has a set of triangles + udword NbTris = CurrentLeaf.GetNbTriangles(); + if(Indices) + { + const udword* T = &Indices[CurrentLeaf.GetTriangleIndex()]; + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = *T++; + SPHERE_PRIM(TriangleIndex, OPC_CONTACT) + } + } + else + { + udword BaseIndex = CurrentLeaf.GetTriangleIndex(); + + // Loop through triangles and test each of them + while(NbTris--) + { + udword TriangleIndex = BaseIndex++; + SPHERE_PRIM(TriangleIndex, OPC_CONTACT) + } + } + } + } + + return true; +} diff --git a/contrib/Opcode/OPC_SphereCollider.h b/contrib/Opcode/OPC_SphereCollider.h new file mode 100644 index 0000000..095824a --- /dev/null +++ b/contrib/Opcode/OPC_SphereCollider.h @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a sphere collider. + * \file OPC_SphereCollider.h + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_SPHERECOLLIDER_H__ +#define __OPC_SPHERECOLLIDER_H__ + + struct OPCODE_API SphereCache : VolumeCache + { + SphereCache() : Center(0.0f,0.0f,0.0f), FatRadius2(0.0f), FatCoeff(1.1f) {} + ~SphereCache() {} + + // Cached faces signature + IcePoint Center; //!< Sphere used when performing the query resulting in cached faces + float FatRadius2; //!< Sphere used when performing the query resulting in cached faces + // User settings + float FatCoeff; //!< mRadius2 multiplier used to create a fat sphere + }; + + class OPCODE_API SphereCollider : public VolumeCollider + { + public: + // Constructor / Destructor + SphereCollider(); + virtual ~SphereCollider(); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results: + * - with GetContactStatus() + * - with GetNbTouchedPrimitives() + * - with GetTouchedPrimitives() + * + * \param cache [in/out] a sphere cache + * \param sphere [in] collision sphere in local space + * \param model [in] Opcode model to collide with + * \param worlds [in] sphere's world matrix, or null + * \param worldm [in] model's world matrix, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(SphereCache& cache, const Sphere& sphere, const Model& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); + + // + bool Collide(SphereCache& cache, const Sphere& sphere, const AABBTree* tree); + protected: + // Sphere in model space + IcePoint mCenter; //!< Sphere center + float mRadius2; //!< Sphere radius squared + // Internal methods + void _Collide(const AABBCollisionNode* node); + void _Collide(const AABBNoLeafNode* node); + void _Collide(const AABBQuantizedNode* node); + void _Collide(const AABBQuantizedNoLeafNode* node); + void _Collide(const AABBTreeNode* node); + void _CollideNoPrimitiveTest(const AABBCollisionNode* node); + void _CollideNoPrimitiveTest(const AABBNoLeafNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNode* node); + void _CollideNoPrimitiveTest(const AABBQuantizedNoLeafNode* node); + // Overlap tests + inline_ BOOL SphereContainsBox(const IcePoint& bc, const IcePoint& be); + inline_ BOOL SphereAABBOverlap(const IcePoint& center, const IcePoint& extents); + BOOL SphereTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2); + // Init methods + BOOL InitQuery(SphereCache& cache, const Sphere& sphere, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); + }; + + class OPCODE_API HybridSphereCollider : public SphereCollider + { + public: + // Constructor / Destructor + HybridSphereCollider(); + virtual ~HybridSphereCollider(); + + bool Collide(SphereCache& cache, const Sphere& sphere, const HybridModel& model, const Matrix4x4* worlds=null, const Matrix4x4* worldm=null); + protected: + Container mTouchedBoxes; + }; + +#endif // __OPC_SPHERECOLLIDER_H__ diff --git a/contrib/Opcode/OPC_SphereTriOverlap.h b/contrib/Opcode/OPC_SphereTriOverlap.h new file mode 100644 index 0000000..012d9ea --- /dev/null +++ b/contrib/Opcode/OPC_SphereTriOverlap.h @@ -0,0 +1,187 @@ + +// This is collision detection. If you do another distance test for collision *response*, +// if might be useful to simply *skip* the test below completely, and report a collision. +// - if sphere-triangle overlap, result is ok +// - if they don't, we'll discard them during collision response with a similar test anyway +// Overall this approach should run faster. + +// Original code by David Eberly in Magic. +BOOL SphereCollider::SphereTriOverlap(const IcePoint& vert0, const IcePoint& vert1, const IcePoint& vert2) +{ + // Stats + mNbVolumePrimTests++; + + // Early exit if one of the vertices is inside the sphere + IcePoint kDiff = vert2 - mCenter; + float fC = kDiff.SquareMagnitude(); + if(fC <= mRadius2) return TRUE; + + kDiff = vert1 - mCenter; + fC = kDiff.SquareMagnitude(); + if(fC <= mRadius2) return TRUE; + + kDiff = vert0 - mCenter; + fC = kDiff.SquareMagnitude(); + if(fC <= mRadius2) return TRUE; + + // Else do the full distance test + IcePoint TriEdge0 = vert1 - vert0; + IcePoint TriEdge1 = vert2 - vert0; + +//IcePoint kDiff = vert0 - mCenter; + float fA00 = TriEdge0.SquareMagnitude(); + float fA01 = TriEdge0 | TriEdge1; + float fA11 = TriEdge1.SquareMagnitude(); + float fB0 = kDiff | TriEdge0; + float fB1 = kDiff | TriEdge1; +//float fC = kDiff.SquareMagnitude(); + float fDet = fabsf(fA00*fA11 - fA01*fA01); + float u = fA01*fB1-fA11*fB0; + float v = fA01*fB0-fA00*fB1; + float SqrDist; + + if(u + v <= fDet) + { + if(u < 0.0f) + { + if(v < 0.0f) // region 4 + { + if(fB0 < 0.0f) + { +// v = 0.0f; + if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } + else { u = -fB0/fA00; SqrDist = fB0*u+fC; } + } + else + { +// u = 0.0f; + if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; } + else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } + else { v = -fB1/fA11; SqrDist = fB1*v+fC; } + } + } + else // region 3 + { +// u = 0.0f; + if(fB1>=0.0f) { /*v = 0.0f;*/ SqrDist = fC; } + else if(-fB1>=fA11) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } + else { v = -fB1/fA11; SqrDist = fB1*v+fC; } + } + } + else if(v < 0.0f) // region 5 + { +// v = 0.0f; + if(fB0>=0.0f) { /*u = 0.0f;*/ SqrDist = fC; } + else if(-fB0>=fA00) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } + else { u = -fB0/fA00; SqrDist = fB0*u+fC; } + } + else // region 0 + { + // minimum at interior IcePoint + if(fDet==0.0f) + { +// u = 0.0f; +// v = 0.0f; + SqrDist = MAX_FLOAT; + } + else + { + float fInvDet = 1.0f/fDet; + u *= fInvDet; + v *= fInvDet; + SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; + } + } + } + else + { + float fTmp0, fTmp1, fNumer, fDenom; + + if(u < 0.0f) // region 2 + { + fTmp0 = fA01 + fB0; + fTmp1 = fA11 + fB1; + if(fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { +// u = 1.0f; +// v = 0.0f; + SqrDist = fA00+2.0f*fB0+fC; + } + else + { + u = fNumer/fDenom; + v = 1.0f - u; + SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; + } + } + else + { +// u = 0.0f; + if(fTmp1 <= 0.0f) { /*v = 1.0f;*/ SqrDist = fA11+2.0f*fB1+fC; } + else if(fB1 >= 0.0f) { /*v = 0.0f;*/ SqrDist = fC; } + else { v = -fB1/fA11; SqrDist = fB1*v+fC; } + } + } + else if(v < 0.0f) // region 6 + { + fTmp0 = fA01 + fB1; + fTmp1 = fA00 + fB0; + if(fTmp1 > fTmp0) + { + fNumer = fTmp1 - fTmp0; + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { +// v = 1.0f; +// u = 0.0f; + SqrDist = fA11+2.0f*fB1+fC; + } + else + { + v = fNumer/fDenom; + u = 1.0f - v; + SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; + } + } + else + { +// v = 0.0f; + if(fTmp1 <= 0.0f) { /*u = 1.0f;*/ SqrDist = fA00+2.0f*fB0+fC; } + else if(fB0 >= 0.0f) { /*u = 0.0f;*/ SqrDist = fC; } + else { u = -fB0/fA00; SqrDist = fB0*u+fC; } + } + } + else // region 1 + { + fNumer = fA11 + fB1 - fA01 - fB0; + if(fNumer <= 0.0f) + { +// u = 0.0f; +// v = 1.0f; + SqrDist = fA11+2.0f*fB1+fC; + } + else + { + fDenom = fA00-2.0f*fA01+fA11; + if(fNumer >= fDenom) + { +// u = 1.0f; +// v = 0.0f; + SqrDist = fA00+2.0f*fB0+fC; + } + else + { + u = fNumer/fDenom; + v = 1.0f - u; + SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; + } + } + } + } + + return fabsf(SqrDist) < mRadius2; +} diff --git a/contrib/Opcode/OPC_SweepAndPrune.cpp b/contrib/Opcode/OPC_SweepAndPrune.cpp new file mode 100644 index 0000000..e56e7ab --- /dev/null +++ b/contrib/Opcode/OPC_SweepAndPrune.cpp @@ -0,0 +1,664 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide) + * \file OPC_SweepAndPrune.cpp + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +inline_ void Sort(udword& id0, udword& id1) +{ + if(id0>id1) Swap(id0, id1); +} + + class Opcode::SAP_Element + { + public: + inline_ SAP_Element() {} + inline_ SAP_Element(udword id, SAP_Element* next) : mID(id), mNext(next) {} + inline_ ~SAP_Element() {} + + udword mID; + SAP_Element* mNext; + }; + + class Opcode::SAP_Box + { + public: + SAP_EndPoint* Min[3]; + SAP_EndPoint* Max[3]; + }; + + class Opcode::SAP_EndPoint + { + public: + float Value; // Min or Max value + SAP_EndPoint* Previous; // Previous EndPoint whose Value is smaller than ours (or null) + SAP_EndPoint* Next; // Next EndPoint whose Value is greater than ours (or null) + udword Data; // Parent box ID *2 | MinMax flag + + inline_ void SetData(udword box_id, BOOL is_max) { Data = (box_id<<1)|is_max; } + inline_ BOOL IsMax() const { return Data & 1; } + inline_ udword GetBoxID() const { return Data>>1; } + + inline_ void InsertAfter(SAP_EndPoint* element) + { + if(this!=element && this!=element->Next) + { + // Remove + if(Previous) Previous->Next = Next; + if(Next) Next->Previous = Previous; + + // Insert + Next = element->Next; + if(Next) Next->Previous = this; + + element->Next = this; + Previous = element; + } + } + + inline_ void InsertBefore(SAP_EndPoint* element) + { + if(this!=element && this!=element->Previous) + { + // Remove + if(Previous) Previous->Next = Next; + if(Next) Next->Previous = Previous; + + // Insert + Previous = element->Previous; + element->Previous = this; + + Next = element; + if(Previous) Previous->Next = this; + } + } + }; + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SAP_PairData::SAP_PairData() : + mNbElements (0), + mNbUsedElements (0), + mElementPool (null), + mFirstFree (null), + mNbObjects (0), + mArray (null) +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SAP_PairData::~SAP_PairData() +{ + Release(); +} + +void SAP_PairData::Release() +{ + mNbElements = 0; + mNbUsedElements = 0; + mNbObjects = 0; + DELETEARRAY(mElementPool); + DELETEARRAY(mArray); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes. + * \param nb_objects [in] + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool SAP_PairData::Init(udword nb_objects) +{ + // Make sure everything has been released + Release(); + if(!nb_objects) return false; + + mArray = new SAP_Element*[nb_objects]; + CHECKALLOC(mArray); + ZeroMemory(mArray, nb_objects*sizeof(SAP_Element*)); + mNbObjects = nb_objects; + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Remaps a pointer when pool gets resized. + * \param element [in/out] remapped element + * \param delta [in] offset in bytes + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ void Remap(SAP_Element*& element, udword delta) +{ + if(element) element = (SAP_Element*)(udword(element) + delta); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Gets a free element in the pool. + * \param id [in] element id + * \param next [in] next element + * \param remap [out] possible remapping offset + * \return the new element + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SAP_Element* SAP_PairData::GetFreeElem(udword id, SAP_Element* next, udword* remap) +{ + if(remap) *remap = 0; + + SAP_Element* FreeElem; + if(mFirstFree) + { + // Recycle + FreeElem = mFirstFree; + mFirstFree = mFirstFree->mNext; // First free = next free (or null) + } + else + { + if(mNbUsedElements==mNbElements) + { + // Resize + mNbElements = mNbElements ? (mNbElements<<1) : 2; + + SAP_Element* NewElems = new SAP_Element[mNbElements]; + + if(mNbUsedElements) CopyMemory(NewElems, mElementPool, mNbUsedElements*sizeof(SAP_Element)); + + // Remap everything + { + udword Delta = udword(NewElems) - udword(mElementPool); + + for(udword i=0;imID = id; + FreeElem->mNext = next; + + return FreeElem; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Frees an element of the pool. + * \param elem [in] element to free/recycle + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ void SAP_PairData::FreeElem(SAP_Element* elem) +{ + elem->mNext = mFirstFree; // Next free + mFirstFree = elem; +} + +// Add a pair to the set. +void SAP_PairData::AddPair(udword id1, udword id2) +{ + // Order the ids + Sort(id1, id2); + + ASSERT(id1=mNbObjects) return; + + // Select the right list from "mArray". + SAP_Element* Current = mArray[id1]; + + if(!Current) + { + // Empty slot => create new element + mArray[id1] = GetFreeElem(id2, null); + } + else if(Current->mID>id2) + { + // The list is not empty but all elements are greater than id2 => insert id2 in the front. + mArray[id1] = GetFreeElem(id2, mArray[id1]); + } + else + { + // Else find the correct location in the sorted list (ascending order) and insert id2 there. + while(Current->mNext) + { + if(Current->mNext->mID > id2) break; + + Current = Current->mNext; + } + + if(Current->mID==id2) return; // The pair already exists + +// Current->mNext = GetFreeElem(id2, Current->mNext); + udword Delta; + SAP_Element* E = GetFreeElem(id2, Current->mNext, &Delta); + if(Delta) Remap(Current, Delta); + Current->mNext = E; + } +} + +// Delete a pair from the set. +void SAP_PairData::RemovePair(udword id1, udword id2) +{ + // Order the ids. + Sort(id1, id2); + + // Exit if the pair doesn't exist in the set + if(id1>=mNbObjects) return; + + // Otherwise, select the correct list. + SAP_Element* Current = mArray[id1]; + + // If this list is empty, the pair doesn't exist. + if(!Current) return; + + // Otherwise, if id2 is the first element, delete it. + if(Current->mID==id2) + { + mArray[id1] = Current->mNext; + FreeElem(Current); + } + else + { + // If id2 is not the first element, start traversing the sorted list. + while(Current->mNext) + { + // If we have moved too far away without hitting id2, then the pair doesn't exist + if(Current->mNext->mID > id2) return; + + // Otherwise, delete id2. + if(Current->mNext->mID == id2) + { + SAP_Element* Temp = Current->mNext; + Current->mNext = Temp->mNext; + FreeElem(Temp); + return; + } + Current = Current->mNext; + } + } +} + +void SAP_PairData::DumpPairs(Pairs& pairs) const +{ + // ### Ugly and slow + for(udword i=0;imIDmID); + Current = Current->mNext; + } + } +} + +void SAP_PairData::DumpPairs(PairCallback callback, void* user_data) const +{ + if(!callback) return; + + // ### Ugly and slow + for(udword i=0;imIDmID, user_data)) return; + Current = Current->mNext; + } + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Constructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SweepAndPrune::SweepAndPrune() +{ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Destructor. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +SweepAndPrune::~SweepAndPrune() +{ +} + +void SweepAndPrune::GetPairs(Pairs& pairs) const +{ + mPairs.DumpPairs(pairs); +} + +void SweepAndPrune::GetPairs(PairCallback callback, void* user_data) const +{ + mPairs.DumpPairs(callback, user_data); +} + +bool SweepAndPrune::Init(udword nb_objects, const AABB** boxes) +{ + // 1) Create sorted lists + mNbObjects = nb_objects; + + mBoxes = new SAP_Box[nb_objects]; +// for(udword i=0;iGetMin(Axis); + Data[i*2+1] = boxes[i]->GetMax(Axis); + } + RadixSort RS; + const udword* Sorted = RS.Sort(Data, nb_objects*2).GetRanks(); + + SAP_EndPoint* PreviousEndPoint = null; + + for(udword i=0;i>1; + + ASSERT(BoxIndexValue = SortedCoord; +// CurrentEndPoint->IsMax = SortedIndex&1; // ### could be implicit ? +// CurrentEndPoint->ID = BoxIndex; // ### could be implicit ? + CurrentEndPoint->SetData(BoxIndex, SortedIndex&1); // ### could be implicit ? + CurrentEndPoint->Previous = PreviousEndPoint; + CurrentEndPoint->Next = null; + if(PreviousEndPoint) PreviousEndPoint->Next = CurrentEndPoint; + + if(CurrentEndPoint->IsMax()) mBoxes[BoxIndex].Max[Axis] = CurrentEndPoint; + else mBoxes[BoxIndex].Min[Axis] = CurrentEndPoint; + + PreviousEndPoint = CurrentEndPoint; + } + } + + DELETEARRAY(Data); + + CheckListsIntegrity(); + + // 2) Quickly find starting pairs + + mPairs.Init(nb_objects); + + { + Pairs P; + CompleteBoxPruning(nb_objects, boxes, P, Axes(AXES_XZY)); + for(udword i=0;iid0; + udword id1 = PP->id1; + + if(id0!=id1 && boxes[id0]->Intersect(*boxes[id1])) + { + mPairs.AddPair(id0, id1); + } + else ASSERT(0); + } + } + + return true; +} + +bool SweepAndPrune::CheckListsIntegrity() +{ + for(udword Axis=0;Axis<3;Axis++) + { + // Find list head + SAP_EndPoint* Current = mList[Axis]; + while(Current->Previous) Current = Current->Previous; + + udword Nb = 0; + + SAP_EndPoint* Previous = null; + while(Current) + { + Nb++; + + if(Previous) + { + ASSERT(Previous->Value <= Current->Value); + if(Previous->Value > Current->Value) return false; + } + + ASSERT(Current->Previous==Previous); + if(Current->Previous!=Previous) return false; + + Previous = Current; + Current = Current->Next; + } + + ASSERT(Nb==mNbObjects*2); + } + return true; +} + +inline_ BOOL Intersect(const AABB& a, const SAP_Box& b) +{ + if(b.Max[0]->Value < a.GetMin(0) || a.GetMax(0) < b.Min[0]->Value + || b.Max[1]->Value < a.GetMin(1) || a.GetMax(1) < b.Min[1]->Value + || b.Max[2]->Value < a.GetMin(2) || a.GetMax(2) < b.Min[2]->Value) return FALSE; + + return TRUE; +} + + + +bool SweepAndPrune::UpdateObject(udword i, const AABB& box) +{ + for(udword Axis=0;Axis<3;Axis++) + { +// udword Base = (udword)&mList[Axis][0]; + + // Update min + { + SAP_EndPoint* const CurrentMin = mBoxes[i].Min[Axis]; + ASSERT(!CurrentMin->IsMax()); + + const float Limit = box.GetMin(Axis); + if(Limit == CurrentMin->Value) + { + } + else if(Limit < CurrentMin->Value) + { + CurrentMin->Value = Limit; + + // Min is moving left: + SAP_EndPoint* NewPos = CurrentMin; + ASSERT(NewPos); + + SAP_EndPoint* tmp; + while((tmp = NewPos->Previous) && tmp->Value > Limit) + { + NewPos = tmp; + + if(NewPos->IsMax()) + { + // Our min passed a max => start overlap + //udword SortedIndex = (udword(CurrentMin) - Base)/sizeof(NS_EndPoint); + const udword id0 = CurrentMin->GetBoxID(); + const udword id1 = NewPos->GetBoxID(); + + if(id0!=id1 && Intersect(box, mBoxes[id1])) mPairs.AddPair(id0, id1); + } + } + + CurrentMin->InsertBefore(NewPos); + } + else// if(Limit > CurrentMin->Value) + { + CurrentMin->Value = Limit; + + // Min is moving right: + SAP_EndPoint* NewPos = CurrentMin; + ASSERT(NewPos); + + SAP_EndPoint* tmp; + while((tmp = NewPos->Next) && tmp->Value < Limit) + { + NewPos = tmp; + + if(NewPos->IsMax()) + { + // Our min passed a max => stop overlap + const udword id0 = CurrentMin->GetBoxID(); + const udword id1 = NewPos->GetBoxID(); + + if(id0!=id1) mPairs.RemovePair(id0, id1); + } + } + + CurrentMin->InsertAfter(NewPos); + } + } + + // Update max + { + SAP_EndPoint* const CurrentMax = mBoxes[i].Max[Axis]; + ASSERT(CurrentMax->IsMax()); + + const float Limit = box.GetMax(Axis); + if(Limit == CurrentMax->Value) + { + } + else if(Limit > CurrentMax->Value) + { + CurrentMax->Value = Limit; + + // Max is moving right: + SAP_EndPoint* NewPos = CurrentMax; + ASSERT(NewPos); + + SAP_EndPoint* tmp; + while((tmp = NewPos->Next) && tmp->Value < Limit) + { + NewPos = tmp; + + if(!NewPos->IsMax()) + { + // Our max passed a min => start overlap + const udword id0 = CurrentMax->GetBoxID(); + const udword id1 = NewPos->GetBoxID(); + + if(id0!=id1 && Intersect(box, mBoxes[id1])) mPairs.AddPair(id0, id1); + } + } + + CurrentMax->InsertAfter(NewPos); + } + else// if(Limit < CurrentMax->Value) + { + CurrentMax->Value = Limit; + + // Max is moving left: + SAP_EndPoint* NewPos = CurrentMax; + ASSERT(NewPos); + + SAP_EndPoint* tmp; + while((tmp = NewPos->Previous) && tmp->Value > Limit) + { + NewPos = tmp; + + if(!NewPos->IsMax()) + { + // Our max passed a min => stop overlap + const udword id0 = CurrentMax->GetBoxID(); + const udword id1 = NewPos->GetBoxID(); + + if(id0!=id1) mPairs.RemovePair(id0, id1); + } + } + + CurrentMax->InsertBefore(NewPos); + } + } + } + + return true; +} diff --git a/contrib/Opcode/OPC_SweepAndPrune.h b/contrib/Opcode/OPC_SweepAndPrune.h new file mode 100644 index 0000000..cbb87ac --- /dev/null +++ b/contrib/Opcode/OPC_SweepAndPrune.h @@ -0,0 +1,86 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains an implementation of the sweep-and-prune algorithm (moved from Z-Collide) + * \file OPC_SweepAndPrune.h + * \author Pierre Terdiman + * \date January, 29, 2000 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_SWEEPANDPRUNE_H__ +#define __OPC_SWEEPANDPRUNE_H__ + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * User-callback, called by OPCODE for each colliding pairs. + * \param id0 [in] id of colliding object + * \param id1 [in] id of colliding object + * \param user_data [in] user-defined data + * \return TRUE to continue enumeration + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + typedef BOOL (*PairCallback) (udword id0, udword id1, void* user_data); + + class SAP_Element; + class SAP_EndPoint; + class SAP_Box; + + class OPCODE_API SAP_PairData + { + public: + SAP_PairData(); + ~SAP_PairData(); + + bool Init(udword nb_objects); + + void AddPair(udword id1, udword id2); + void RemovePair(udword id1, udword id2); + + void DumpPairs(Pairs& pairs) const; + void DumpPairs(PairCallback callback, void* user_data) const; + private: + udword mNbElements; //!< Total number of elements in the pool + udword mNbUsedElements; //!< Number of used elements + SAP_Element* mElementPool; //!< Array of mNbElements elements + SAP_Element* mFirstFree; //!< First free element in the pool + + udword mNbObjects; //!< Max number of objects we can handle + SAP_Element** mArray; //!< Pointers to pool + // Internal methods + SAP_Element* GetFreeElem(udword id, SAP_Element* next, udword* remap=null); + inline_ void FreeElem(SAP_Element* elem); + void Release(); + }; + + class OPCODE_API SweepAndPrune + { + public: + SweepAndPrune(); + ~SweepAndPrune(); + + bool Init(udword nb_objects, const AABB** boxes); + bool UpdateObject(udword i, const AABB& box); + + void GetPairs(Pairs& pairs) const; + void GetPairs(PairCallback callback, void* user_data) const; + private: + SAP_PairData mPairs; + + udword mNbObjects; + SAP_Box* mBoxes; + SAP_EndPoint* mList[3]; + // Internal methods + bool CheckListsIntegrity(); + }; + +#endif //__OPC_SWEEPANDPRUNE_H__ \ No newline at end of file diff --git a/contrib/Opcode/OPC_TreeBuilders.cpp b/contrib/Opcode/OPC_TreeBuilders.cpp new file mode 100644 index 0000000..89dd93b --- /dev/null +++ b/contrib/Opcode/OPC_TreeBuilders.cpp @@ -0,0 +1,255 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for tree builders. + * \file OPC_TreeBuilders.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A builder for AABB-trees of vertices. + * + * \class AABBTreeOfVerticesBuilder + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A builder for AABB-trees of AABBs. + * + * \class AABBTreeOfAABBsBuilder + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * A builder for AABB-trees of triangles. + * + * \class AABBTreeOfTrianglesBuilder + * \author Pierre Terdiman + * \version 1.3 + * \date March, 20, 2001 +*/ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +using namespace Opcode; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the AABB of a set of primitives. + * \param primitives [in] list of indices of primitives + * \param nb_prims [in] number of indices + * \param global_box [out] global AABB enclosing the set of input primitives + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeOfAABBsBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const +{ + // Checkings + if(!primitives || !nb_prims) return false; + + // Initialize global box + global_box = mAABBArray[primitives[0]]; + + // Loop through boxes + for(udword i=1;iGetTriangle(VP, *primitives++); + // Update global box + Min.Min(*VP.Vertex[0]).Min(*VP.Vertex[1]).Min(*VP.Vertex[2]); + Max.Max(*VP.Vertex[0]).Max(*VP.Vertex[1]).Max(*VP.Vertex[2]); + } + global_box.SetMinMax(Min, Max); + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the splitting value along a given axis for a given primitive. + * \param index [in] index of the primitive to split + * \param axis [in] axis index (0,1,2) + * \return splitting value + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float AABBTreeOfTrianglesBuilder::GetSplittingValue(udword index, udword axis) const +{ +/* // Compute center of triangle + IcePoint Center; + mTriList[index].Center(mVerts, Center); + // Return value + return Center[axis];*/ + + // Compute correct component from center of triangle +// return (mVerts[mTriList[index].mVRef[0]][axis] +// +mVerts[mTriList[index].mVRef[1]][axis] +// +mVerts[mTriList[index].mVRef[2]][axis])*INV3; + + VertexPointers VP; + mIMesh->GetTriangle(VP, index); + + // Compute correct component from center of triangle + return ((*VP.Vertex[0])[axis] + +(*VP.Vertex[1])[axis] + +(*VP.Vertex[2])[axis])*INV3; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the splitting value along a given axis for a given node. + * \param primitives [in] list of indices of primitives + * \param nb_prims [in] number of indices + * \param global_box [in] global AABB enclosing the set of input primitives + * \param axis [in] axis index (0,1,2) + * \return splitting value + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +float AABBTreeOfTrianglesBuilder::GetSplittingValue(const udword* primitives, udword nb_prims, const AABB& global_box, udword axis) const +{ + if(mSettings.mRules&SPLIT_GEOM_CENTER) + { + // Loop through triangles + float SplitValue = 0.0f; + VertexPointers VP; + for(udword i=0;iGetTriangle(VP, primitives[i]); + // Update split value + SplitValue += (*VP.Vertex[0])[axis]; + SplitValue += (*VP.Vertex[1])[axis]; + SplitValue += (*VP.Vertex[2])[axis]; + } + return SplitValue / float(nb_prims*3); + } + else return AABBTreeBuilder::GetSplittingValue(primitives, nb_prims, global_box, axis); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Computes the AABB of a set of primitives. + * \param primitives [in] list of indices of primitives + * \param nb_prims [in] number of indices + * \param global_box [out] global AABB enclosing the set of input primitives + * \return true if success + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeOfVerticesBuilder::ComputeGlobalBox(const udword* primitives, udword nb_prims, AABB& global_box) const +{ + // Checkings + if(!primitives || !nb_prims) return false; + + // Initialize global box + global_box.SetEmpty(); + + // Loop through vertices + for(udword i=0;iHasLeafNodes()!=cache.Model1->HasLeafNodes()) return false; + if(cache.Model0->IsQuantized()!=cache.Model1->IsQuantized()) return false; + + /* + + Rules: + - perform hull test + - when hulls collide, disable hull test + - if meshes overlap, reset countdown + - if countdown reaches 0, enable hull test + + */ + +#ifdef __MESHMERIZER_H__ + // Handle hulls + if(cache.HullTest) + { + if(cache.Model0->GetHull() && cache.Model1->GetHull()) + { + struct Local + { + static IcePoint* SVCallback(const IcePoint& sv, udword& previndex, udword user_data) + { + CollisionHull* Hull = (CollisionHull*)user_data; + previndex = Hull->ComputeSupportingVertex(sv, previndex); + return (IcePoint*)&Hull->GetVerts()[previndex]; + } + }; + + bool Collide; + + if(0) + { + static GJKEngine GJK; + static bool GJKInitDone=false; + if(!GJKInitDone) + { + GJK.Enable(GJK_BACKUP_PROCEDURE); + GJK.Enable(GJK_DEGENERATE); + GJK.Enable(GJK_HILLCLIMBING); + GJKInitDone = true; + } + GJK.SetCallbackObj0(Local::SVCallback); + GJK.SetCallbackObj1(Local::SVCallback); + GJK.SetUserData0(udword(cache.Model0->GetHull())); + GJK.SetUserData1(udword(cache.Model1->GetHull())); + Collide = GJK.Collide(*world0, *world1, &cache.SepVector); + } + else + { + static SVEngine SVE; + SVE.SetCallbackObj0(Local::SVCallback); + SVE.SetCallbackObj1(Local::SVCallback); + SVE.SetUserData0(udword(cache.Model0->GetHull())); + SVE.SetUserData1(udword(cache.Model1->GetHull())); + Collide = SVE.Collide(*world0, *world1, &cache.SepVector); + } + + if(!Collide) + { + // Reset stats & contact status + mFlags &= ~OPC_CONTACT; + mNbBVBVTests = 0; + mNbPrimPrimTests = 0; + mNbBVPrimTests = 0; + mPairs.Reset(); + return true; + } + } + } + + // Here, hulls collide + cache.HullTest = false; +#endif // __MESHMERIZER_H__ + + // Checkings + if(!Setup(cache.Model0->GetMeshInterface(), cache.Model1->GetMeshInterface())) return false; + + // Simple double-dispatch + bool Status; + if(!cache.Model0->HasLeafNodes()) + { + if(cache.Model0->IsQuantized()) + { + const AABBQuantizedNoLeafTree* T0 = (const AABBQuantizedNoLeafTree*)cache.Model0->GetTree(); + const AABBQuantizedNoLeafTree* T1 = (const AABBQuantizedNoLeafTree*)cache.Model1->GetTree(); + Status = Collide(T0, T1, world0, world1, &cache); + } + else + { + const AABBNoLeafTree* T0 = (const AABBNoLeafTree*)cache.Model0->GetTree(); + const AABBNoLeafTree* T1 = (const AABBNoLeafTree*)cache.Model1->GetTree(); + Status = Collide(T0, T1, world0, world1, &cache); + } + } + else + { + if(cache.Model0->IsQuantized()) + { + const AABBQuantizedTree* T0 = (const AABBQuantizedTree*)cache.Model0->GetTree(); + const AABBQuantizedTree* T1 = (const AABBQuantizedTree*)cache.Model1->GetTree(); + Status = Collide(T0, T1, world0, world1, &cache); + } + else + { + const AABBCollisionTree* T0 = (const AABBCollisionTree*)cache.Model0->GetTree(); + const AABBCollisionTree* T1 = (const AABBCollisionTree*)cache.Model1->GetTree(); + Status = Collide(T0, T1, world0, world1, &cache); + } + } + +#ifdef __MESHMERIZER_H__ + if(Status) + { + // Reset counter as long as overlap occurs + if(GetContactStatus()) cache.ResetCountDown(); + + // Enable hull test again when counter reaches zero + cache.CountDown--; + if(!cache.CountDown) + { + cache.ResetCountDown(); + cache.HullTest = true; + } + } +#endif + return Status; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Initializes a collision query : + * - reset stats & contact status + * - setup matrices + * + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::InitQuery(const Matrix4x4* world0, const Matrix4x4* world1) +{ + // Reset stats & contact status + Collider::InitQuery(); + mNbBVBVTests = 0; + mNbPrimPrimTests = 0; + mNbBVPrimTests = 0; + mPairs.Reset(); + + // Setup matrices + Matrix4x4 InvWorld0, InvWorld1; + if(world0) InvertPRMatrix(InvWorld0, *world0); + else InvWorld0.Identity(); + + if(world1) InvertPRMatrix(InvWorld1, *world1); + else InvWorld1.Identity(); + + Matrix4x4 World0to1 = world0 ? (*world0 * InvWorld1) : InvWorld1; + Matrix4x4 World1to0 = world1 ? (*world1 * InvWorld0) : InvWorld0; + + mR0to1 = World0to1; World0to1.GetTrans(mT0to1); + mR1to0 = World1to0; World1to0.GetTrans(mT1to0); + + // Precompute absolute 1-to-0 rotation matrix + for(udword i=0;i<3;i++) + { + for(udword j=0;j<3;j++) + { + // Epsilon value prevents floating-IcePoint inaccuracies (strategy borrowed from RAPID) + mAR.m[i][j] = 1e-6f + fabsf(mR1to0.m[i][j]); + } + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Takes advantage of temporal coherence. + * \param cache [in] cache for a pair of previously colliding primitives + * \return true if we can return immediately + * \warning only works for "First Contact" mode + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::CheckTemporalCoherence(Pair* cache) +{ + // Checkings + if(!cache) return false; + + // Test previously colliding primitives first + if(TemporalCoherenceEnabled() && FirstContactEnabled()) + { + PrimTest(cache->id0, cache->id1); + if(GetContactStatus()) return true; + } + return false; +} + +#define UPDATE_CACHE \ + if(cache && GetContactStatus()) \ + { \ + cache->id0 = mPairs.GetEntry(0); \ + cache->id1 = mPairs.GetEntry(1); \ + } + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for normal AABB trees. + * \param tree0 [in] AABB tree from first object + * \param tree1 [in] AABB tree from second object + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \param cache [in/out] cache for a pair of previously colliding primitives + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) +{ + // Init collision query + InitQuery(world0, world1); + + // Check previous state + if(CheckTemporalCoherence(cache)) return true; + + // Perform collision query + _Collide(tree0->GetNodes(), tree1->GetNodes()); + + UPDATE_CACHE + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for no-leaf AABB trees. + * \param tree0 [in] AABB tree from first object + * \param tree1 [in] AABB tree from second object + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \param cache [in/out] cache for a pair of previously colliding primitives + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) +{ + // Init collision query + InitQuery(world0, world1); + + // Check previous state + if(CheckTemporalCoherence(cache)) return true; + + // Perform collision query + _Collide(tree0->GetNodes(), tree1->GetNodes()); + + UPDATE_CACHE + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for quantized AABB trees. + * \param tree0 [in] AABB tree from first object + * \param tree1 [in] AABB tree from second object + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \param cache [in/out] cache for a pair of previously colliding primitives + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) +{ + // Init collision query + InitQuery(world0, world1); + + // Check previous state + if(CheckTemporalCoherence(cache)) return true; + + // Setup dequantization coeffs + mCenterCoeff0 = tree0->mCenterCoeff; + mExtentsCoeff0 = tree0->mExtentsCoeff; + mCenterCoeff1 = tree1->mCenterCoeff; + mExtentsCoeff1 = tree1->mExtentsCoeff; + + // Dequantize box A + const AABBQuantizedNode* N0 = tree0->GetNodes(); + const IcePoint a(float(N0->mAABB.mExtents[0]) * mExtentsCoeff0.x, float(N0->mAABB.mExtents[1]) * mExtentsCoeff0.y, float(N0->mAABB.mExtents[2]) * mExtentsCoeff0.z); + const IcePoint Pa(float(N0->mAABB.mCenter[0]) * mCenterCoeff0.x, float(N0->mAABB.mCenter[1]) * mCenterCoeff0.y, float(N0->mAABB.mCenter[2]) * mCenterCoeff0.z); + // Dequantize box B + const AABBQuantizedNode* N1 = tree1->GetNodes(); + const IcePoint b(float(N1->mAABB.mExtents[0]) * mExtentsCoeff1.x, float(N1->mAABB.mExtents[1]) * mExtentsCoeff1.y, float(N1->mAABB.mExtents[2]) * mExtentsCoeff1.z); + const IcePoint Pb(float(N1->mAABB.mCenter[0]) * mCenterCoeff1.x, float(N1->mAABB.mCenter[1]) * mCenterCoeff1.y, float(N1->mAABB.mCenter[2]) * mCenterCoeff1.z); + + // Perform collision query + _Collide(N0, N1, a, Pa, b, Pb); + + UPDATE_CACHE + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Collision query for quantized no-leaf AABB trees. + * \param tree0 [in] AABB tree from first object + * \param tree1 [in] AABB tree from second object + * \param world0 [in] world matrix for first object + * \param world1 [in] world matrix for second object + * \param cache [in/out] cache for a pair of previously colliding primitives + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool AABBTreeCollider::Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0, const Matrix4x4* world1, Pair* cache) +{ + // Init collision query + InitQuery(world0, world1); + + // Check previous state + if(CheckTemporalCoherence(cache)) return true; + + // Setup dequantization coeffs + mCenterCoeff0 = tree0->mCenterCoeff; + mExtentsCoeff0 = tree0->mExtentsCoeff; + mCenterCoeff1 = tree1->mCenterCoeff; + mExtentsCoeff1 = tree1->mExtentsCoeff; + + // Perform collision query + _Collide(tree0->GetNodes(), tree1->GetNodes()); + + UPDATE_CACHE + + return true; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Standard trees +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// The normal AABB tree can use 2 different descent rules (with different performances) +//#define ORIGINAL_CODE //!< UNC-like descent rules +#define ALTERNATIVE_CODE //!< Alternative descent rules + +#ifdef ORIGINAL_CODE +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param b0 [in] collision node from first tree + * \param b1 [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1) +{ + // Perform BV-BV overlap test + if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter)) return; + + if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; } + + if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize()))) + { + _Collide(b0->GetNeg(), b1); + if(ContactFound()) return; + _Collide(b0->GetPos(), b1); + } + else + { + _Collide(b0, b1->GetNeg()); + if(ContactFound()) return; + _Collide(b0, b1->GetPos()); + } +} +#endif + +#ifdef ALTERNATIVE_CODE +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for normal AABB trees. + * \param b0 [in] collision node from first tree + * \param b1 [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1) +{ + // Perform BV-BV overlap test + if(!BoxBoxOverlap(b0->mAABB.mExtents, b0->mAABB.mCenter, b1->mAABB.mExtents, b1->mAABB.mCenter)) + { + return; + } + + if(b0->IsLeaf()) + { + if(b1->IsLeaf()) + { + PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); + } + else + { + _Collide(b0, b1->GetNeg()); + if(ContactFound()) return; + _Collide(b0, b1->GetPos()); + } + } + else if(b1->IsLeaf()) + { + _Collide(b0->GetNeg(), b1); + if(ContactFound()) return; + _Collide(b0->GetPos(), b1); + } + else + { + _Collide(b0->GetNeg(), b1->GetNeg()); + if(ContactFound()) return; + _Collide(b0->GetNeg(), b1->GetPos()); + if(ContactFound()) return; + _Collide(b0->GetPos(), b1->GetNeg()); + if(ContactFound()) return; + _Collide(b0->GetPos(), b1->GetPos()); + } +} +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// No-leaf trees +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Leaf-leaf test for two primitive indices. + * \param id0 [in] index from first leaf-triangle + * \param id1 [in] index from second leaf-triangle + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::PrimTest(udword id0, udword id1) +{ + // Request vertices from the app + VertexPointers VP0; + VertexPointers VP1; + mIMesh0->GetTriangle(VP0, id0); + mIMesh1->GetTriangle(VP1, id1); + + // Transform from space 1 to space 0 + IcePoint u0,u1,u2; + TransformPoint(u0, *VP1.Vertex[0], mR1to0, mT1to0); + TransformPoint(u1, *VP1.Vertex[1], mR1to0, mT1to0); + TransformPoint(u2, *VP1.Vertex[2], mR1to0, mT1to0); + + // Perform triangle-triangle overlap test + if(TriTriOverlap(*VP0.Vertex[0], *VP0.Vertex[1], *VP0.Vertex[2], u0, u1, u2)) + { + // Keep track of colliding pairs + mPairs.Add(id0).Add(id1); + // Set contact status + mFlags |= OPC_CONTACT; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Leaf-leaf test for a previously fetched triangle from tree A (in B's space) and a new leaf from B. + * \param id1 [in] leaf-triangle index from tree B + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ void AABBTreeCollider::PrimTestTriIndex(udword id1) +{ + // Request vertices from the app + VertexPointers VP; + mIMesh1->GetTriangle(VP, id1); + + // Perform triangle-triangle overlap test + if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) + { + // Keep track of colliding pairs + mPairs.Add(mLeafIndex).Add(id1); + // Set contact status + mFlags |= OPC_CONTACT; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Leaf-leaf test for a previously fetched triangle from tree B (in A's space) and a new leaf from A. + * \param id0 [in] leaf-triangle index from tree A + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ void AABBTreeCollider::PrimTestIndexTri(udword id0) +{ + // Request vertices from the app + VertexPointers VP; + mIMesh0->GetTriangle(VP, id0); + + // Perform triangle-triangle overlap test + if(TriTriOverlap(mLeafVerts[0], mLeafVerts[1], mLeafVerts[2], *VP.Vertex[0], *VP.Vertex[1], *VP.Vertex[2])) + { + // Keep track of colliding pairs + mPairs.Add(id0).Add(mLeafIndex); + // Set contact status + mFlags |= OPC_CONTACT; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision of a leaf node from A and a branch from B. + * \param b [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_CollideTriBox(const AABBNoLeafNode* b) +{ + // Perform triangle-box overlap test + if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents)) return; + + // Keep same triangle, deal with first child + if(b->HasPosLeaf()) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + // Keep same triangle, deal with second child + if(b->HasNegLeaf()) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision of a leaf node from B and a branch from A. + * \param b [in] collision node from first tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_CollideBoxTri(const AABBNoLeafNode* b) +{ + // Perform triangle-box overlap test + if(!TriBoxOverlap(b->mAABB.mCenter, b->mAABB.mExtents)) return; + + // Keep same triangle, deal with first child + if(b->HasPosLeaf()) PrimTestIndexTri(b->GetPosPrimitive()); + else _CollideBoxTri(b->GetPos()); + + if(ContactFound()) return; + + // Keep same triangle, deal with second child + if(b->HasNegLeaf()) PrimTestIndexTri(b->GetNegPrimitive()); + else _CollideBoxTri(b->GetNeg()); +} + +//! Request triangle vertices from the app and transform them +#define FETCH_LEAF(prim_index, imesh, rot, trans) \ + mLeafIndex = prim_index; \ + /* Request vertices from the app */ \ + VertexPointers VP; imesh->GetTriangle(VP, prim_index); \ + /* Transform them in a common space */ \ + TransformPoint(mLeafVerts[0], *VP.Vertex[0], rot, trans); \ + TransformPoint(mLeafVerts[1], *VP.Vertex[1], rot, trans); \ + TransformPoint(mLeafVerts[2], *VP.Vertex[2], rot, trans); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for no-leaf AABB trees. + * \param a [in] collision node from first tree + * \param b [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b) +{ + // Perform BV-BV overlap test + if(!BoxBoxOverlap(a->mAABB.mExtents, a->mAABB.mCenter, b->mAABB.mExtents, b->mAABB.mCenter)) return; + + // Catch leaf status + BOOL BHasPosLeaf = b->HasPosLeaf(); + BOOL BHasNegLeaf = b->HasNegLeaf(); + + if(a->HasPosLeaf()) + { + FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1) + + if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); + } + else + { + if(BHasPosLeaf) + { + FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetPos()); + } + else _Collide(a->GetPos(), b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) + { + FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetPos()); + } + else _Collide(a->GetPos(), b->GetNeg()); + } + + if(ContactFound()) return; + + if(a->HasNegLeaf()) + { + FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1) + + if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); + } + else + { + if(BHasPosLeaf) + { + // ### That leaf has possibly already been fetched + FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetNeg()); + } + else _Collide(a->GetNeg(), b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) + { + // ### That leaf has possibly already been fetched + FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetNeg()); + } + else _Collide(a->GetNeg(), b->GetNeg()); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Quantized trees +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized AABB trees. + * \param b0 [in] collision node from first tree + * \param b1 [in] collision node from second tree + * \param a [in] extent from box A + * \param Pa [in] center from box A + * \param b [in] extent from box B + * \param Pb [in] center from box B + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const IcePoint& a, const IcePoint& Pa, const IcePoint& b, const IcePoint& Pb) +{ + // Perform BV-BV overlap test + if(!BoxBoxOverlap(a, Pa, b, Pb)) return; + + if(b0->IsLeaf() && b1->IsLeaf()) { PrimTest(b0->GetPrimitive(), b1->GetPrimitive()); return; } + + if(b1->IsLeaf() || (!b0->IsLeaf() && (b0->GetSize() > b1->GetSize()))) + { + // Dequantize box + const QuantizedAABB* Box = &b0->GetNeg()->mAABB; + const IcePoint negPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z); + const IcePoint nega(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z); + _Collide(b0->GetNeg(), b1, nega, negPa, b, Pb); + + if(ContactFound()) return; + + // Dequantize box + Box = &b0->GetPos()->mAABB; + const IcePoint posPa(float(Box->mCenter[0]) * mCenterCoeff0.x, float(Box->mCenter[1]) * mCenterCoeff0.y, float(Box->mCenter[2]) * mCenterCoeff0.z); + const IcePoint posa(float(Box->mExtents[0]) * mExtentsCoeff0.x, float(Box->mExtents[1]) * mExtentsCoeff0.y, float(Box->mExtents[2]) * mExtentsCoeff0.z); + _Collide(b0->GetPos(), b1, posa, posPa, b, Pb); + } + else + { + // Dequantize box + const QuantizedAABB* Box = &b1->GetNeg()->mAABB; + const IcePoint negPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z); + const IcePoint negb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z); + _Collide(b0, b1->GetNeg(), a, Pa, negb, negPb); + + if(ContactFound()) return; + + // Dequantize box + Box = &b1->GetPos()->mAABB; + const IcePoint posPb(float(Box->mCenter[0]) * mCenterCoeff1.x, float(Box->mCenter[1]) * mCenterCoeff1.y, float(Box->mCenter[2]) * mCenterCoeff1.z); + const IcePoint posb(float(Box->mExtents[0]) * mExtentsCoeff1.x, float(Box->mExtents[1]) * mExtentsCoeff1.y, float(Box->mExtents[2]) * mExtentsCoeff1.z); + _Collide(b0, b1->GetPos(), a, Pa, posb, posPb); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Quantized no-leaf trees +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision of a leaf node from A and a quantized branch from B. + * \param leaf [in] leaf triangle from first tree + * \param b [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_CollideTriBox(const AABBQuantizedNoLeafNode* b) +{ + // Dequantize box + const QuantizedAABB* bb = &b->mAABB; + const IcePoint Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z); + const IcePoint eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z); + + // Perform triangle-box overlap test + if(!TriBoxOverlap(Pb, eb)) return; + + if(b->HasPosLeaf()) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(b->HasNegLeaf()) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision of a leaf node from B and a quantized branch from A. + * \param b [in] collision node from first tree + * \param leaf [in] leaf triangle from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_CollideBoxTri(const AABBQuantizedNoLeafNode* b) +{ + // Dequantize box + const QuantizedAABB* bb = &b->mAABB; + const IcePoint Pa(float(bb->mCenter[0]) * mCenterCoeff0.x, float(bb->mCenter[1]) * mCenterCoeff0.y, float(bb->mCenter[2]) * mCenterCoeff0.z); + const IcePoint ea(float(bb->mExtents[0]) * mExtentsCoeff0.x, float(bb->mExtents[1]) * mExtentsCoeff0.y, float(bb->mExtents[2]) * mExtentsCoeff0.z); + + // Perform triangle-box overlap test + if(!TriBoxOverlap(Pa, ea)) return; + + if(b->HasPosLeaf()) PrimTestIndexTri(b->GetPosPrimitive()); + else _CollideBoxTri(b->GetPos()); + + if(ContactFound()) return; + + if(b->HasNegLeaf()) PrimTestIndexTri(b->GetNegPrimitive()); + else _CollideBoxTri(b->GetNeg()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Recursive collision query for quantized no-leaf AABB trees. + * \param a [in] collision node from first tree + * \param b [in] collision node from second tree + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void AABBTreeCollider::_Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b) +{ + // Dequantize box A + const QuantizedAABB* ab = &a->mAABB; + const IcePoint Pa(float(ab->mCenter[0]) * mCenterCoeff0.x, float(ab->mCenter[1]) * mCenterCoeff0.y, float(ab->mCenter[2]) * mCenterCoeff0.z); + const IcePoint ea(float(ab->mExtents[0]) * mExtentsCoeff0.x, float(ab->mExtents[1]) * mExtentsCoeff0.y, float(ab->mExtents[2]) * mExtentsCoeff0.z); + // Dequantize box B + const QuantizedAABB* bb = &b->mAABB; + const IcePoint Pb(float(bb->mCenter[0]) * mCenterCoeff1.x, float(bb->mCenter[1]) * mCenterCoeff1.y, float(bb->mCenter[2]) * mCenterCoeff1.z); + const IcePoint eb(float(bb->mExtents[0]) * mExtentsCoeff1.x, float(bb->mExtents[1]) * mExtentsCoeff1.y, float(bb->mExtents[2]) * mExtentsCoeff1.z); + + // Perform BV-BV overlap test + if(!BoxBoxOverlap(ea, Pa, eb, Pb)) return; + + // Catch leaf status + BOOL BHasPosLeaf = b->HasPosLeaf(); + BOOL BHasNegLeaf = b->HasNegLeaf(); + + if(a->HasPosLeaf()) + { + FETCH_LEAF(a->GetPosPrimitive(), mIMesh0, mR0to1, mT0to1) + + if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); + } + else + { + if(BHasPosLeaf) + { + FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetPos()); + } + else _Collide(a->GetPos(), b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) + { + FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetPos()); + } + else _Collide(a->GetPos(), b->GetNeg()); + } + + if(ContactFound()) return; + + if(a->HasNegLeaf()) + { + FETCH_LEAF(a->GetNegPrimitive(), mIMesh0, mR0to1, mT0to1) + + if(BHasPosLeaf) PrimTestTriIndex(b->GetPosPrimitive()); + else _CollideTriBox(b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) PrimTestTriIndex(b->GetNegPrimitive()); + else _CollideTriBox(b->GetNeg()); + } + else + { + if(BHasPosLeaf) + { + // ### That leaf has possibly already been fetched + FETCH_LEAF(b->GetPosPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetNeg()); + } + else _Collide(a->GetNeg(), b->GetPos()); + + if(ContactFound()) return; + + if(BHasNegLeaf) + { + // ### That leaf has possibly already been fetched + FETCH_LEAF(b->GetNegPrimitive(), mIMesh1, mR1to0, mT1to0) + + _CollideBoxTri(a->GetNeg()); + } + else _Collide(a->GetNeg(), b->GetNeg()); + } +} diff --git a/contrib/Opcode/OPC_TreeCollider.h b/contrib/Opcode/OPC_TreeCollider.h new file mode 100644 index 0000000..ec0e517 --- /dev/null +++ b/contrib/Opcode/OPC_TreeCollider.h @@ -0,0 +1,244 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains code for a tree collider. + * \file OPC_TreeCollider.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_TREECOLLIDER_H__ +#define __OPC_TREECOLLIDER_H__ + + //! This structure holds cached information used by the algorithm. + //! Two model pointers and two colliding primitives are cached. Model pointers are assigned + //! to their respective meshes, and the pair of colliding primitives is used for temporal + //! coherence. That is, in case temporal coherence is enabled, those two primitives are + //! tested for overlap before everything else. If they still collide, we're done before + //! even entering the recursive collision code. + struct OPCODE_API BVTCache : Pair + { + //! Constructor + inline_ BVTCache() + { + ResetCache(); + ResetCountDown(); + } + + void ResetCache() + { + Model0 = null; + Model1 = null; + id0 = 0; + id1 = 1; +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + HullTest = true; + SepVector.pid = 0; + SepVector.qid = 0; + SepVector.SV = IcePoint(1.0f, 0.0f, 0.0f); +#endif // __MESHMERIZER_H__ + } + + inline_ void ResetCountDown() + { +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + CountDown = 50; +#endif // __MESHMERIZER_H__ + } + + const Model* Model0; //!< Model for first object + const Model* Model1; //!< Model for second object + +#ifdef __MESHMERIZER_H__ // Collision hulls only supported within ICE ! + SVCache SepVector; + udword CountDown; + bool HullTest; +#endif // __MESHMERIZER_H__ + }; + + class OPCODE_API AABBTreeCollider : public Collider + { + public: + // Constructor / Destructor + AABBTreeCollider(); + virtual ~AABBTreeCollider(); + // Generic collision query + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Generic collision query for generic OPCODE models. After the call, access the results with: + * - GetContactStatus() + * - GetNbPairs() + * - GetPairs() + * + * \param cache [in] collision cache for model pointers and a colliding pair of primitives + * \param world0 [in] world matrix for first object, or null + * \param world1 [in] world matrix for second object, or null + * \return true if success + * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + bool Collide(BVTCache& cache, const Matrix4x4* world0=null, const Matrix4x4* world1=null); + + // Collision queries + bool Collide(const AABBCollisionTree* tree0, const AABBCollisionTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); + bool Collide(const AABBNoLeafTree* tree0, const AABBNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); + bool Collide(const AABBQuantizedTree* tree0, const AABBQuantizedTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); + bool Collide(const AABBQuantizedNoLeafTree* tree0, const AABBQuantizedNoLeafTree* tree1, const Matrix4x4* world0=null, const Matrix4x4* world1=null, Pair* cache=null); + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: selects between full box-box tests or "SAT-lite" tests (where Class III axes are discarded) + * \param flag [in] true for full tests, false for coarse tests + * \see SetFullPrimBoxTest(bool flag) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetFullBoxBoxTest(bool flag) { mFullBoxBoxTest = flag; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Settings: selects between full triangle-box tests or "SAT-lite" tests (where Class III axes are discarded) + * \param flag [in] true for full tests, false for coarse tests + * \see SetFullBoxBoxTest(bool flag) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ void SetFullPrimBoxTest(bool flag) { mFullPrimBoxTest = flag; } + + // Stats + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of BV-BV overlap tests after a collision query. + * \see GetNbPrimPrimTests() + * \see GetNbBVPrimTests() + * \return the number of BV-BV tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbBVBVTests() const { return mNbBVBVTests; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Triangle-Triangle overlap tests after a collision query. + * \see GetNbBVBVTests() + * \see GetNbBVPrimTests() + * \return the number of Triangle-Triangle tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbPrimPrimTests() const { return mNbPrimPrimTests; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of BV-Triangle overlap tests after a collision query. + * \see GetNbBVBVTests() + * \see GetNbPrimPrimTests() + * \return the number of BV-Triangle tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbBVPrimTests() const { return mNbBVPrimTests; } + + // Data access + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of contacts after a collision query. + * \see GetContactStatus() + * \see GetPairs() + * \return the number of contacts / colliding pairs. + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbPairs() const { return mPairs.GetNbEntries()>>1; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the pairs of colliding triangles after a collision query. + * \see GetContactStatus() + * \see GetNbPairs() + * \return the list of colliding pairs (triangle indices) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const Pair* GetPairs() const { return (const Pair*)mPairs.GetEntries(); } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) const char* ValidateSettings(); + + protected: + // Colliding pairs + Container mPairs; //!< Pairs of colliding primitives + // User mesh interfaces + const MeshInterface* mIMesh0; //!< User-defined mesh interface for object0 + const MeshInterface* mIMesh1; //!< User-defined mesh interface for object1 + // Stats + udword mNbBVBVTests; //!< Number of BV-BV tests + udword mNbPrimPrimTests; //!< Number of Primitive-Primitive tests + udword mNbBVPrimTests; //!< Number of BV-Primitive tests + // Precomputed data + Matrix3x3 mAR; //!< Absolute rotation matrix + Matrix3x3 mR0to1; //!< Rotation from object0 to object1 + Matrix3x3 mR1to0; //!< Rotation from object1 to object0 + IcePoint mT0to1; //!< Translation from object0 to object1 + IcePoint mT1to0; //!< Translation from object1 to object0 + // Dequantization coeffs + IcePoint mCenterCoeff0; + IcePoint mExtentsCoeff0; + IcePoint mCenterCoeff1; + IcePoint mExtentsCoeff1; + // Leaf description + IcePoint mLeafVerts[3]; //!< Triangle vertices + udword mLeafIndex; //!< Triangle index + // Settings + bool mFullBoxBoxTest; //!< Perform full BV-BV tests (true) or SAT-lite tests (false) + bool mFullPrimBoxTest; //!< Perform full Primitive-BV tests (true) or SAT-lite tests (false) + // Internal methods + + // Standard AABB trees + void _Collide(const AABBCollisionNode* b0, const AABBCollisionNode* b1); + // Quantized AABB trees + void _Collide(const AABBQuantizedNode* b0, const AABBQuantizedNode* b1, const IcePoint& a, const IcePoint& Pa, const IcePoint& b, const IcePoint& Pb); + // No-leaf AABB trees + void _CollideTriBox(const AABBNoLeafNode* b); + void _CollideBoxTri(const AABBNoLeafNode* b); + void _Collide(const AABBNoLeafNode* a, const AABBNoLeafNode* b); + // Quantized no-leaf AABB trees + void _CollideTriBox(const AABBQuantizedNoLeafNode* b); + void _CollideBoxTri(const AABBQuantizedNoLeafNode* b); + void _Collide(const AABBQuantizedNoLeafNode* a, const AABBQuantizedNoLeafNode* b); + // Overlap tests + void PrimTest(udword id0, udword id1); + inline_ void PrimTestTriIndex(udword id1); + inline_ void PrimTestIndexTri(udword id0); + + inline_ BOOL BoxBoxOverlap(const IcePoint& ea, const IcePoint& ca, const IcePoint& eb, const IcePoint& cb); + inline_ BOOL TriBoxOverlap(const IcePoint& center, const IcePoint& extents); + inline_ BOOL TriTriOverlap(const IcePoint& V0, const IcePoint& V1, const IcePoint& V2, const IcePoint& U0, const IcePoint& U1, const IcePoint& U2); + // Init methods + void InitQuery(const Matrix4x4* world0=null, const Matrix4x4* world1=null); + bool CheckTemporalCoherence(Pair* cache); + + inline_ BOOL Setup(const MeshInterface* mi0, const MeshInterface* mi1) + { + mIMesh0 = mi0; + mIMesh1 = mi1; + + if(!mIMesh0 || !mIMesh1) return FALSE; + + return TRUE; + } + }; + +#endif // __OPC_TREECOLLIDER_H__ diff --git a/contrib/Opcode/OPC_TriBoxOverlap.h b/contrib/Opcode/OPC_TriBoxOverlap.h new file mode 100644 index 0000000..e32673b --- /dev/null +++ b/contrib/Opcode/OPC_TriBoxOverlap.h @@ -0,0 +1,339 @@ + +//! This macro quickly finds the min & max values among 3 variables +#define FINDMINMAX(x0, x1, x2, min, max) \ + min = max = x0; \ + if(x1max) max=x1; \ + if(x2max) max=x2; + +//! TO BE DOCUMENTED +inline_ BOOL planeBoxOverlap(const IcePoint& normal, const float d, const IcePoint& maxbox) +{ + IcePoint vmin, vmax; + for(udword q=0;q<=2;q++) + { + if(normal[q]>0.0f) { vmin[q]=-maxbox[q]; vmax[q]=maxbox[q]; } + else { vmin[q]=maxbox[q]; vmax[q]=-maxbox[q]; } + } + if((normal|vmin)+d>0.0f) return FALSE; + if((normal|vmax)+d>=0.0f) return TRUE; + + return FALSE; +} + +//! TO BE DOCUMENTED +#define AXISTEST_X01(a, b, fa, fb) \ + min = a*v0.y - b*v0.z; \ + max = a*v2.y - b*v2.z; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.y + fb * extents.z; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_X2(a, b, fa, fb) \ + min = a*v0.y - b*v0.z; \ + max = a*v1.y - b*v1.z; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.y + fb * extents.z; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_Y02(a, b, fa, fb) \ + min = b*v0.z - a*v0.x; \ + max = b*v2.z - a*v2.x; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.x + fb * extents.z; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_Y1(a, b, fa, fb) \ + min = b*v0.z - a*v0.x; \ + max = b*v1.z - a*v1.x; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.x + fb * extents.z; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_Z12(a, b, fa, fb) \ + min = a*v1.x - b*v1.y; \ + max = a*v2.x - b*v2.y; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.x + fb * extents.y; \ + if(min>rad || max<-rad) return FALSE; + +//! TO BE DOCUMENTED +#define AXISTEST_Z0(a, b, fa, fb) \ + min = a*v0.x - b*v0.y; \ + max = a*v1.x - b*v1.y; \ + if(min>max) {const float tmp=max; max=min; min=tmp; } \ + rad = fa * extents.x + fb * extents.y; \ + if(min>rad || max<-rad) return FALSE; + +// compute triangle edges +// - edges lazy evaluated to take advantage of early exits +// - fabs precomputed (half less work, possible since extents are always >0) +// - customized macros to take advantage of the null component +// - axis vector discarded, possibly saves useless movs +#define IMPLEMENT_CLASS3_TESTS \ + float rad; \ + float min, max; \ + \ + const float fey0 = fabsf(e0.y); \ + const float fez0 = fabsf(e0.z); \ + AXISTEST_X01(e0.z, e0.y, fez0, fey0); \ + const float fex0 = fabsf(e0.x); \ + AXISTEST_Y02(e0.z, e0.x, fez0, fex0); \ + AXISTEST_Z12(e0.y, e0.x, fey0, fex0); \ + \ + const float fey1 = fabsf(e1.y); \ + const float fez1 = fabsf(e1.z); \ + AXISTEST_X01(e1.z, e1.y, fez1, fey1); \ + const float fex1 = fabsf(e1.x); \ + AXISTEST_Y02(e1.z, e1.x, fez1, fex1); \ + AXISTEST_Z0(e1.y, e1.x, fey1, fex1); \ + \ + const IcePoint e2 = mLeafVerts[0] - mLeafVerts[2]; \ + const float fey2 = fabsf(e2.y); \ + const float fez2 = fabsf(e2.z); \ + AXISTEST_X2(e2.z, e2.y, fez2, fey2); \ + const float fex2 = fabsf(e2.x); \ + AXISTEST_Y1(e2.z, e2.x, fez2, fex2); \ + AXISTEST_Z12(e2.y, e2.x, fey2, fex2); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Triangle-Box overlap test using the separating axis theorem. + * This is the code from Tomas Möller, a bit optimized: + * - with some more lazy evaluation (faster path on PC) + * - with a tiny bit of assembly + * - with "SAT-lite" applied if needed + * - and perhaps with some more minor modifs... + * + * \param center [in] box center + * \param extents [in] box extents + * \return true if triangle & box overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL AABBTreeCollider::TriBoxOverlap(const IcePoint& center, const IcePoint& extents) +{ + // Stats + mNbBVPrimTests++; + + // use separating axis theorem to test overlap between triangle and box + // need to test for overlap in these directions: + // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle + // we do not even need to test these) + // 2) normal of the triangle + // 3) crossproduct(edge from tri, {x,y,z}-directin) + // this gives 3x3=9 more tests + + // move everything so that the boxcenter is in (0,0,0) + IcePoint v0, v1, v2; + v0.x = mLeafVerts[0].x - center.x; + v1.x = mLeafVerts[1].x - center.x; + v2.x = mLeafVerts[2].x - center.x; + + // First, test overlap in the {x,y,z}-directions +#ifdef OPC_USE_FCOMI + // find min, max of the triangle in x-direction, and test for overlap in X + if(FCMin3(v0.x, v1.x, v2.x)>extents.x) return FALSE; + if(FCMax3(v0.x, v1.x, v2.x)<-extents.x) return FALSE; + + // same for Y + v0.y = mLeafVerts[0].y - center.y; + v1.y = mLeafVerts[1].y - center.y; + v2.y = mLeafVerts[2].y - center.y; + + if(FCMin3(v0.y, v1.y, v2.y)>extents.y) return FALSE; + if(FCMax3(v0.y, v1.y, v2.y)<-extents.y) return FALSE; + + // same for Z + v0.z = mLeafVerts[0].z - center.z; + v1.z = mLeafVerts[1].z - center.z; + v2.z = mLeafVerts[2].z - center.z; + + if(FCMin3(v0.z, v1.z, v2.z)>extents.z) return FALSE; + if(FCMax3(v0.z, v1.z, v2.z)<-extents.z) return FALSE; +#else + float min,max; + // Find min, max of the triangle in x-direction, and test for overlap in X + FINDMINMAX(v0.x, v1.x, v2.x, min, max); + if(min>extents.x || max<-extents.x) return FALSE; + + // Same for Y + v0.y = mLeafVerts[0].y - center.y; + v1.y = mLeafVerts[1].y - center.y; + v2.y = mLeafVerts[2].y - center.y; + + FINDMINMAX(v0.y, v1.y, v2.y, min, max); + if(min>extents.y || max<-extents.y) return FALSE; + + // Same for Z + v0.z = mLeafVerts[0].z - center.z; + v1.z = mLeafVerts[1].z - center.z; + v2.z = mLeafVerts[2].z - center.z; + + FINDMINMAX(v0.z, v1.z, v2.z, min, max); + if(min>extents.z || max<-extents.z) return FALSE; +#endif + // 2) Test if the box intersects the plane of the triangle + // compute plane equation of triangle: normal*x+d=0 + // ### could be precomputed since we use the same leaf triangle several times + const IcePoint e0 = v1 - v0; + const IcePoint e1 = v2 - v1; + const IcePoint normal = e0 ^ e1; + const float d = -normal|v0; + if(!planeBoxOverlap(normal, d, extents)) return FALSE; + + // 3) "Class III" tests + if(mFullPrimBoxTest) + { + IMPLEMENT_CLASS3_TESTS + } + return TRUE; +} + +//! A dedicated version where the box is constant +inline_ BOOL OBBCollider::TriBoxOverlap() +{ + // Stats + mNbVolumePrimTests++; + + // Hook + const IcePoint& extents = mBoxExtents; + const IcePoint& v0 = mLeafVerts[0]; + const IcePoint& v1 = mLeafVerts[1]; + const IcePoint& v2 = mLeafVerts[2]; + + // use separating axis theorem to test overlap between triangle and box + // need to test for overlap in these directions: + // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle + // we do not even need to test these) + // 2) normal of the triangle + // 3) crossproduct(edge from tri, {x,y,z}-directin) + // this gives 3x3=9 more tests + + // Box center is already in (0,0,0) + + // First, test overlap in the {x,y,z}-directions +#ifdef OPC_USE_FCOMI + // find min, max of the triangle in x-direction, and test for overlap in X + if(FCMin3(v0.x, v1.x, v2.x)>mBoxExtents.x) return FALSE; + if(FCMax3(v0.x, v1.x, v2.x)<-mBoxExtents.x) return FALSE; + + if(FCMin3(v0.y, v1.y, v2.y)>mBoxExtents.y) return FALSE; + if(FCMax3(v0.y, v1.y, v2.y)<-mBoxExtents.y) return FALSE; + + if(FCMin3(v0.z, v1.z, v2.z)>mBoxExtents.z) return FALSE; + if(FCMax3(v0.z, v1.z, v2.z)<-mBoxExtents.z) return FALSE; +#else + float min,max; + // Find min, max of the triangle in x-direction, and test for overlap in X + FINDMINMAX(v0.x, v1.x, v2.x, min, max); + if(min>mBoxExtents.x || max<-mBoxExtents.x) return FALSE; + + FINDMINMAX(v0.y, v1.y, v2.y, min, max); + if(min>mBoxExtents.y || max<-mBoxExtents.y) return FALSE; + + FINDMINMAX(v0.z, v1.z, v2.z, min, max); + if(min>mBoxExtents.z || max<-mBoxExtents.z) return FALSE; +#endif + // 2) Test if the box intersects the plane of the triangle + // compute plane equation of triangle: normal*x+d=0 + // ### could be precomputed since we use the same leaf triangle several times + const IcePoint e0 = v1 - v0; + const IcePoint e1 = v2 - v1; + const IcePoint normal = e0 ^ e1; + const float d = -normal|v0; + if(!planeBoxOverlap(normal, d, mBoxExtents)) return FALSE; + + // 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV) + { + IMPLEMENT_CLASS3_TESTS + } + return TRUE; +} + +//! ...and another one, jeez +inline_ BOOL AABBCollider::TriBoxOverlap() +{ + // Stats + mNbVolumePrimTests++; + + // Hook + const IcePoint& center = mBox.mCenter; + const IcePoint& extents = mBox.mExtents; + + // use separating axis theorem to test overlap between triangle and box + // need to test for overlap in these directions: + // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle + // we do not even need to test these) + // 2) normal of the triangle + // 3) crossproduct(edge from tri, {x,y,z}-directin) + // this gives 3x3=9 more tests + + // move everything so that the boxcenter is in (0,0,0) + IcePoint v0, v1, v2; + v0.x = mLeafVerts[0].x - center.x; + v1.x = mLeafVerts[1].x - center.x; + v2.x = mLeafVerts[2].x - center.x; + + // First, test overlap in the {x,y,z}-directions +#ifdef OPC_USE_FCOMI + // find min, max of the triangle in x-direction, and test for overlap in X + if(FCMin3(v0.x, v1.x, v2.x)>extents.x) return FALSE; + if(FCMax3(v0.x, v1.x, v2.x)<-extents.x) return FALSE; + + // same for Y + v0.y = mLeafVerts[0].y - center.y; + v1.y = mLeafVerts[1].y - center.y; + v2.y = mLeafVerts[2].y - center.y; + + if(FCMin3(v0.y, v1.y, v2.y)>extents.y) return FALSE; + if(FCMax3(v0.y, v1.y, v2.y)<-extents.y) return FALSE; + + // same for Z + v0.z = mLeafVerts[0].z - center.z; + v1.z = mLeafVerts[1].z - center.z; + v2.z = mLeafVerts[2].z - center.z; + + if(FCMin3(v0.z, v1.z, v2.z)>extents.z) return FALSE; + if(FCMax3(v0.z, v1.z, v2.z)<-extents.z) return FALSE; +#else + float min,max; + // Find min, max of the triangle in x-direction, and test for overlap in X + FINDMINMAX(v0.x, v1.x, v2.x, min, max); + if(min>extents.x || max<-extents.x) return FALSE; + + // Same for Y + v0.y = mLeafVerts[0].y - center.y; + v1.y = mLeafVerts[1].y - center.y; + v2.y = mLeafVerts[2].y - center.y; + + FINDMINMAX(v0.y, v1.y, v2.y, min, max); + if(min>extents.y || max<-extents.y) return FALSE; + + // Same for Z + v0.z = mLeafVerts[0].z - center.z; + v1.z = mLeafVerts[1].z - center.z; + v2.z = mLeafVerts[2].z - center.z; + + FINDMINMAX(v0.z, v1.z, v2.z, min, max); + if(min>extents.z || max<-extents.z) return FALSE; +#endif + // 2) Test if the box intersects the plane of the triangle + // compute plane equation of triangle: normal*x+d=0 + // ### could be precomputed since we use the same leaf triangle several times + const IcePoint e0 = v1 - v0; + const IcePoint e1 = v2 - v1; + const IcePoint normal = e0 ^ e1; + const float d = -normal|v0; + if(!planeBoxOverlap(normal, d, extents)) return FALSE; + + // 3) "Class III" tests - here we always do full tests since the box is a primitive (not a BV) + { + IMPLEMENT_CLASS3_TESTS + } + return TRUE; +} diff --git a/contrib/Opcode/OPC_TriTriOverlap.h b/contrib/Opcode/OPC_TriTriOverlap.h new file mode 100644 index 0000000..a9ee9c5 --- /dev/null +++ b/contrib/Opcode/OPC_TriTriOverlap.h @@ -0,0 +1,279 @@ + +//! if OPC_TRITRI_EPSILON_TEST is true then we do a check (if |dv|b) \ + { \ + const float c=a; \ + a=b; \ + b=c; \ + } + +//! Edge to edge test based on Franlin Antonio's gem: "Faster Line IceSegment Intersection", in Graphics Gems III, pp. 199-202 +#define EDGE_EDGE_TEST(V0, U0, U1) \ + Bx = U0[i0] - U1[i0]; \ + By = U0[i1] - U1[i1]; \ + Cx = V0[i0] - U0[i0]; \ + Cy = V0[i1] - U0[i1]; \ + f = Ay*Bx - Ax*By; \ + d = By*Cx - Bx*Cy; \ + if((f>0.0f && d>=0.0f && d<=f) || (f<0.0f && d<=0.0f && d>=f)) \ + { \ + const float e=Ax*Cy - Ay*Cx; \ + if(f>0.0f) \ + { \ + if(e>=0.0f && e<=f) return TRUE; \ + } \ + else \ + { \ + if(e<=0.0f && e>=f) return TRUE; \ + } \ + } + +//! TO BE DOCUMENTED +#define EDGE_AGAINST_TRI_EDGES(V0, V1, U0, U1, U2) \ +{ \ + float Bx,By,Cx,Cy,d,f; \ + const float Ax = V1[i0] - V0[i0]; \ + const float Ay = V1[i1] - V0[i1]; \ + /* test edge U0,U1 against V0,V1 */ \ + EDGE_EDGE_TEST(V0, U0, U1); \ + /* test edge U1,U2 against V0,V1 */ \ + EDGE_EDGE_TEST(V0, U1, U2); \ + /* test edge U2,U1 against V0,V1 */ \ + EDGE_EDGE_TEST(V0, U2, U0); \ +} + +//! TO BE DOCUMENTED +#define POINT_IN_TRI(V0, U0, U1, U2) \ +{ \ + /* is T1 completly inside T2? */ \ + /* check if V0 is inside tri(U0,U1,U2) */ \ + float a = U1[i1] - U0[i1]; \ + float b = -(U1[i0] - U0[i0]); \ + float c = -a*U0[i0] - b*U0[i1]; \ + float d0 = a*V0[i0] + b*V0[i1] + c; \ + \ + a = U2[i1] - U1[i1]; \ + b = -(U2[i0] - U1[i0]); \ + c = -a*U1[i0] - b*U1[i1]; \ + const float d1 = a*V0[i0] + b*V0[i1] + c; \ + \ + a = U0[i1] - U2[i1]; \ + b = -(U0[i0] - U2[i0]); \ + c = -a*U2[i0] - b*U2[i1]; \ + const float d2 = a*V0[i0] + b*V0[i1] + c; \ + if(d0*d1>0.0f) \ + { \ + if(d0*d2>0.0f) return TRUE; \ + } \ +} + +//! TO BE DOCUMENTED +BOOL CoplanarTriTri(const IcePoint& n, const IcePoint& v0, const IcePoint& v1, const IcePoint& v2, const IcePoint& u0, const IcePoint& u1, const IcePoint& u2) +{ + float A[3]; + short i0,i1; + /* first project onto an axis-aligned plane, that maximizes the area */ + /* of the triangles, compute indices: i0,i1. */ + A[0] = fabsf(n[0]); + A[1] = fabsf(n[1]); + A[2] = fabsf(n[2]); + if(A[0]>A[1]) + { + if(A[0]>A[2]) + { + i0=1; /* A[0] is greatest */ + i1=2; + } + else + { + i0=0; /* A[2] is greatest */ + i1=1; + } + } + else /* A[0]<=A[1] */ + { + if(A[2]>A[1]) + { + i0=0; /* A[2] is greatest */ + i1=1; + } + else + { + i0=0; /* A[1] is greatest */ + i1=2; + } + } + + /* test all edges of triangle 1 against the edges of triangle 2 */ + EDGE_AGAINST_TRI_EDGES(v0, v1, u0, u1, u2); + EDGE_AGAINST_TRI_EDGES(v1, v2, u0, u1, u2); + EDGE_AGAINST_TRI_EDGES(v2, v0, u0, u1, u2); + + /* finally, test if tri1 is totally contained in tri2 or vice versa */ + POINT_IN_TRI(v0, u0, u1, u2); + POINT_IN_TRI(u0, v0, v1, v2); + + return FALSE; +} + +//! TO BE DOCUMENTED +#define NEWCOMPUTE_INTERVALS(VV0, VV1, VV2, D0, D1, D2, D0D1, D0D2, A, B, C, X0, X1) \ +{ \ + if(D0D1>0.0f) \ + { \ + /* here we know that D0D2<=0.0 */ \ + /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \ + A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1; \ + } \ + else if(D0D2>0.0f) \ + { \ + /* here we know that d0d1<=0.0 */ \ + A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2; \ + } \ + else if(D1*D2>0.0f || D0!=0.0f) \ + { \ + /* here we know that d0d1<=0.0 or that D0!=0.0 */ \ + A=VV0; B=(VV1 - VV0)*D0; C=(VV2 - VV0)*D0; X0=D0 - D1; X1=D0 - D2; \ + } \ + else if(D1!=0.0f) \ + { \ + A=VV1; B=(VV0 - VV1)*D1; C=(VV2 - VV1)*D1; X0=D1 - D0; X1=D1 - D2; \ + } \ + else if(D2!=0.0f) \ + { \ + A=VV2; B=(VV0 - VV2)*D2; C=(VV1 - VV2)*D2; X0=D2 - D0; X1=D2 - D1; \ + } \ + else \ + { \ + /* triangles are coplanar */ \ + return CoplanarTriTri(N1, V0, V1, V2, U0, U1, U2); \ + } \ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Triangle/triangle intersection test routine, + * by Tomas Moller, 1997. + * See article "A Fast Triangle-Triangle Intersection Test", + * Journal of Graphics Tools, 2(2), 1997 + * + * Updated June 1999: removed the divisions -- a little faster now! + * Updated October 1999: added {} to CROSS and SUB macros + * + * int NoDivTriTriIsect(float V0[3],float V1[3],float V2[3], + * float U0[3],float U1[3],float U2[3]) + * + * \param V0 [in] triangle 0, vertex 0 + * \param V1 [in] triangle 0, vertex 1 + * \param V2 [in] triangle 0, vertex 2 + * \param U0 [in] triangle 1, vertex 0 + * \param U1 [in] triangle 1, vertex 1 + * \param U2 [in] triangle 1, vertex 2 + * \return true if triangles overlap + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +inline_ BOOL AABBTreeCollider::TriTriOverlap(const IcePoint& V0, const IcePoint& V1, const IcePoint& V2, const IcePoint& U0, const IcePoint& U1, const IcePoint& U2) +{ + // Stats + mNbPrimPrimTests++; + + // Compute plane equation of triangle(V0,V1,V2) + IcePoint E1 = V1 - V0; + IcePoint E2 = V2 - V0; + const IcePoint N1 = E1 ^ E2; + const float d1 =-N1 | V0; + // IcePlane equation 1: N1.X+d1=0 + + // Put U0,U1,U2 into plane equation 1 to compute signed distances to the plane + float du0 = (N1|U0) + d1; + float du1 = (N1|U1) + d1; + float du2 = (N1|U2) + d1; + + // Coplanarity robustness check +#ifdef OPC_TRITRI_EPSILON_TEST + if(fabsf(du0)0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ? + return FALSE; // no intersection occurs + + // Compute plane of triangle (U0,U1,U2) + E1 = U1 - U0; + E2 = U2 - U0; + const IcePoint N2 = E1 ^ E2; + const float d2=-N2 | U0; + // plane equation 2: N2.X+d2=0 + + // put V0,V1,V2 into plane equation 2 + float dv0 = (N2|V0) + d2; + float dv1 = (N2|V1) + d2; + float dv2 = (N2|V2) + d2; + +#ifdef OPC_TRITRI_EPSILON_TEST + if(fabsf(dv0)0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ? + return FALSE; // no intersection occurs + + // Compute direction of intersection line + const IcePoint D = N1^N2; + + // Compute and index to the largest component of D + float max=fabsf(D[0]); + short index=0; + float bb=fabsf(D[1]); + float cc=fabsf(D[2]); + if(bb>max) max=bb,index=1; + if(cc>max) max=cc,index=2; + + // This is the simplified projection onto L + const float vp0 = V0[index]; + const float vp1 = V1[index]; + const float vp2 = V2[index]; + + const float up0 = U0[index]; + const float up1 = U1[index]; + const float up2 = U2[index]; + + // Compute interval for triangle 1 + float a,b,c,x0,x1; + NEWCOMPUTE_INTERVALS(vp0,vp1,vp2,dv0,dv1,dv2,dv0dv1,dv0dv2,a,b,c,x0,x1); + + // Compute interval for triangle 2 + float d,e,f,y0,y1; + NEWCOMPUTE_INTERVALS(up0,up1,up2,du0,du1,du2,du0du1,du0du2,d,e,f,y0,y1); + + const float xx=x0*x1; + const float yy=y0*y1; + const float xxyy=xx*yy; + + float isect1[2], isect2[2]; + + float tmp=a*xxyy; + isect1[0]=tmp+b*x1*yy; + isect1[1]=tmp+c*x0*yy; + + tmp=d*xxyy; + isect2[0]=tmp+e*xx*y1; + isect2[1]=tmp+f*xx*y0; + + SORT(isect1[0],isect1[1]); + SORT(isect2[0],isect2[1]); + + if(isect1[1]HasPosLeaf()) mTouchedPrimitives->Add(node->GetPosPrimitive()); \ + else _Dump(node->GetPos()); \ + \ + if(ContactFound()) return; \ + \ + if(node->HasNegLeaf()) mTouchedPrimitives->Add(node->GetNegPrimitive()); \ + else _Dump(node->GetNeg()); \ +} + +#define IMPLEMENT_LEAFDUMP(type) \ +void VolumeCollider::_Dump(const type* node) \ +{ \ + if(node->IsLeaf()) \ + { \ + mTouchedPrimitives->Add(node->GetPrimitive()); \ + } \ + else \ + { \ + _Dump(node->GetPos()); \ + \ + if(ContactFound()) return; \ + \ + _Dump(node->GetNeg()); \ + } \ +} + +IMPLEMENT_NOLEAFDUMP(AABBNoLeafNode) +IMPLEMENT_NOLEAFDUMP(AABBQuantizedNoLeafNode) + +IMPLEMENT_LEAFDUMP(AABBCollisionNode) +IMPLEMENT_LEAFDUMP(AABBQuantizedNode) diff --git a/contrib/Opcode/OPC_VolumeCollider.h b/contrib/Opcode/OPC_VolumeCollider.h new file mode 100644 index 0000000..330f6a6 --- /dev/null +++ b/contrib/Opcode/OPC_VolumeCollider.h @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Contains base volume collider class. + * \file OPC_VolumeCollider.h + * \author Pierre Terdiman + * \date June, 2, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPC_VOLUMECOLLIDER_H__ +#define __OPC_VOLUMECOLLIDER_H__ + + struct OPCODE_API VolumeCache + { + VolumeCache() : Model(null) {} + ~VolumeCache() {} + + Container TouchedPrimitives; //!< Indices of touched primitives + const BaseModel* Model; //!< Owner + }; + + class OPCODE_API VolumeCollider : public Collider + { + public: + // Constructor / Destructor + VolumeCollider(); + virtual ~VolumeCollider() = 0; + + // Collision report + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the number of touched primitives after a collision query. + * \see GetContactStatus() + * \see GetTouchedPrimitives() + * \return the number of touched primitives + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetNbEntries() : 0; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Gets the list of touched primitives after a collision query. + * \see GetContactStatus() + * \see GetNbTouchedPrimitives() + * \return the list of touched primitives (primitive indices) + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ const udword* GetTouchedPrimitives() const { return mTouchedPrimitives ? mTouchedPrimitives->GetEntries() : null; } + + // Stats + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Volume-BV overlap tests after a collision query. + * \see GetNbVolumePrimTests() + * \return the number of Volume-BV tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbVolumeBVTests() const { return mNbVolumeBVTests; } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Stats: gets the number of Volume-Triangle overlap tests after a collision query. + * \see GetNbVolumeBVTests() + * \return the number of Volume-Triangle tests performed during last query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + inline_ udword GetNbVolumePrimTests() const { return mNbVolumePrimTests; } + + // Settings + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Validates current settings. You should call this method after all the settings / callbacks have been defined for a collider. + * \return null if everything is ok, else a string describing the problem + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) const char* ValidateSettings(); + + protected: + // Touched primitives + Container* mTouchedPrimitives; //!< List of touched primitives + + // Dequantization coeffs + IcePoint mCenterCoeff; + IcePoint mExtentsCoeff; + // Stats + udword mNbVolumeBVTests; //!< Number of Volume-BV tests + udword mNbVolumePrimTests; //!< Number of Volume-Primitive tests + // Internal methods + void _Dump(const AABBCollisionNode* node); + void _Dump(const AABBNoLeafNode* node); + void _Dump(const AABBQuantizedNode* node); + void _Dump(const AABBQuantizedNoLeafNode* node); + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * Initializes a query + */ + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + override(Collider) inline_ void InitQuery() + { + // Reset stats & contact status + mNbVolumeBVTests = 0; + mNbVolumePrimTests = 0; + Collider::InitQuery(); + } + + inline_ BOOL IsCacheValid(VolumeCache& cache) + { + // We're going to do a volume-vs-model query. + if(cache.Model!=mCurrentModel) + { + // Cached list was for another model so we can't keep it + // Keep track of new owner and reset cache + cache.Model = mCurrentModel; + return FALSE; + } + else + { + // Same models, no problem + return TRUE; + } + } + }; + +#endif // __OPC_VOLUMECOLLIDER_H__ diff --git a/contrib/Opcode/Opcode.cpp b/contrib/Opcode/Opcode.cpp new file mode 100644 index 0000000..7a90153 --- /dev/null +++ b/contrib/Opcode/Opcode.cpp @@ -0,0 +1,65 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Main file for Opcode.dll. + * \file Opcode.cpp + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/* + Finding a good name is difficult! + Here's the draft for this lib.... Spooky, uh? + + VOID? Very Optimized Interference Detection + ZOID? Zappy's Optimized Interference Detection + CID? Custom/Clever Interference Detection + AID / ACID! Accurate Interference Detection + QUID? Quick Interference Detection + RIDE? Realtime Interference DEtection + WIDE? Wicked Interference DEtection (....) + GUID! + KID ! k-dop interference detection :) + OPCODE! OPtimized COllision DEtection +*/ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Precompiled Header +#include "StdAfx.h" + +bool Opcode::InitOpcode() +{ + Log("// Initializing OPCODE\n\n"); +// LogAPIInfo(); + return true; +} + +void ReleasePruningSorters(); +bool Opcode::CloseOpcode() +{ + Log("// Closing OPCODE\n\n"); + + ReleasePruningSorters(); + + return true; +} + +#ifdef ICE_MAIN + +void ModuleAttach(HINSTANCE hinstance) +{ +} + +void ModuleDetach() +{ +} + +#endif \ No newline at end of file diff --git a/contrib/Opcode/Opcode.h b/contrib/Opcode/Opcode.h new file mode 100644 index 0000000..5dc8c91 --- /dev/null +++ b/contrib/Opcode/Opcode.h @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * Main file for Opcode.dll. + * \file Opcode.h + * \author Pierre Terdiman + * \date March, 20, 2001 + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Guard +#ifndef __OPCODE_H__ +#define __OPCODE_H__ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Preprocessor +#ifdef OPCODE_EXPORTS + #define OPCODE_API __declspec(dllexport) +#else + #define OPCODE_API __declspec(dllimport) +#endif + + #include "OPC_IceHook.h" + + namespace Opcode + { + // Bulk-of-the-work + #include "OPC_Settings.h" + #include "OPC_Common.h" + #include "OPC_MeshInterface.h" + // Builders + #include "OPC_TreeBuilders.h" + // Trees + #include "OPC_AABBTree.h" + #include "OPC_OptimizedTree.h" + // Models + #include "OPC_BaseModel.h" + #include "OPC_Model.h" + #include "OPC_HybridModel.h" + // Colliders + #include "OPC_Collider.h" + #include "OPC_VolumeCollider.h" + #include "OPC_TreeCollider.h" + #include "OPC_RayCollider.h" + #include "OPC_SphereCollider.h" + #include "OPC_OBBCollider.h" + #include "OPC_AABBCollider.h" + #include "OPC_LSSCollider.h" + #include "OPC_PlanesCollider.h" + // Usages + #include "OPC_Picking.h" + // Sweep-and-prune + #include "OPC_BoxPruning.h" + #include "OPC_SweepAndPrune.h" + + FUNCTION OPCODE_API bool InitOpcode(); + FUNCTION OPCODE_API bool CloseOpcode(); + } + +#endif // __OPCODE_H__ diff --git a/contrib/Opcode/ReadMe.txt b/contrib/Opcode/ReadMe.txt new file mode 100644 index 0000000..ee16382 --- /dev/null +++ b/contrib/Opcode/ReadMe.txt @@ -0,0 +1,171 @@ + + OPCODE distribution 1.3 (june 2003) + ----------------------- + + New in Opcode 1.3: + - fixed the divide by 0 bug that was happening when all centers where located on a coordinate axis (thanks to Jorrit T) + - linearized "complete" vanilla AABB trees + - ANSI-compliant "for" loops (for the ones porting it to Linux...) + - callbacks & pointers moved to mesh interface + - support for triangle & vertex strides + - optimized the sphere-triangle overlap code a bit + - dynamic trees (refit) + - more builders + - ValidateSubdivision in builders + - LSS collider + - primitive-bv tests can now be skipped in most volume queries + - temporal coherence now also works for airborne objects + - temporal coherence completed for boxes / all contacts, LSS, etc + - ray-collider now uses a callback + - some common "usages" have been introduced (only picking for now) + - SPLIT_COMPLETE removed (now implicitely using mLimit = 1) + - hybrid collision models + - sweep-and-prune code added, moved from my old Z-Collide lib + - it now works with meshes made of only 1 triangle (except in mesh-mesh case!) + + Disclaimer: + + - I forced myself to actually *do* the release today no matter what. Else it would never have been done. That's + why the code may not be very polished. I also removed a *lot* of things (more usages, distance queries, etc...) + that weren't ready for prime-time (or that were linked to too many of my supporting libs) + + - Some comments may also be obsolete here and there. The old User Manual for Opcode 1.2 may not fit version 1.3 + either, since there's a new "mesh interface" to support strides, etc. + + - Everything in the "Ice" directory has been hacked out of my engine and edited until everything compiled. Don't + expect anything out there to be cute or something. In particular, some CPP files are not even included when not + needed, so you can expect some linker errors if you try messing around with them... + + Otherwise, it should be just like previous version, only better. In particular, hybrid models can be very + memory-friendly (sometimes using like 10 times less ram than the best trees from version 1.2). The possible + speed hit is often invisible (if it even exists), especially using temporal coherence in "all contacts" mode. + (Admittedly, this depends on your particular usage pattern / what you do on collided triangles). + + The sweep-and-prune code is similar to the "vanilla" version found in V-Collide (but that one's better IMHO...) + The simple "radix" version is often just as good, see for yourself. + + OPCODE distribution 1.2 (august 2002) + ----------------------- + + New in Opcode 1.2: + - new VolumeCollider base class + - simplified callback setup + - you can now use callbacks or pointers (setup at compile time) + - destination array not needed anymore in the RayCollider (faster in-out tests) + - renamed classes: AABBRayCollider => RayCollider, AABBSphereCollider => SphereCollider + - the sphere query now only returns a list of faces (extra info discarded). On the other hand it's a lot faster. + - OBB, AABB and planes queries. Original OBB and AABB queries contributed by Erwin de Vries. + - cosmetic changes in OPC_BoxBoxOverlap.h contributed by Gottfried Chen + - some inlining problems fixed + - faster ray-mesh tests using the separating axis theorem + - new split value in AABB tree construction (contributed by Igor Kravtchenko). Provides faster queries most of the time. + - improved temporal coherence for sphere & AABB queries (works in "All contacts" mode) + + Notes: + + - Everything in the "Ice code" directory (in VC++) is basically copy-pasted from my engine, with a lot + of code removed until there was no link error anymore. Don't expect those files to be cute or anything, + they've never been meant to be released and they're often updated/modified/messy. + - Some experimental features have been removed as well. Else I would never have released the 1.2... + - Not as polished/optimal as I would like it to be, but that's life. I promised myself to release it + before october 2002 (one YEAR later ?!).... That's the only reason why it's there. + - Some people reported ColDet was faster. Uh, come on. They were using Opcode in + "All contacts" mode whereas ColDet was doing "first contact"... + + OPCODE distribution 1.1 (october 2001) + ----------------------- + + New in Opcode 1.1: + - stabbing queries + - sphere queries + - abtract base class for colliders + - settings validation methods + - compilation flags now grouped in OPC_Settings.h + - smaller files, new VC++ virtual dirs (cleaner) + + Notes: + + - "override(baseclass)" is a personal cosmetic thing. It's the same as "virtual", but provides more info. + - I code in 1600*1200, so some lines may look a bit long.. + - This version is not as polished as the previous one due to lack of time. The stabbing & sphere queries + can still be optimized: for example by trying other atomic overlap tests. I'm using my first ray-AABB + code, but the newer one seems better. Tim Schröder's one is good as well. See: www.codercorner.com/RayAABB.cpp + - The trees can easily be compressed even more, I save this for later (lack of time, lack of time!) + - I removed various tests before releasing this one: + - a separation line, a.k.a. "front" in QuickCD, because gains were unclear + - distance queries in a PQP style, because it was way too slow + - support for deformable models, too slow as well + - You can easily use Opcode to do your player-vs-world collision detection, in a Nettle/Telemachos way. + If someone out there wants to donate some art / level for the cause, I'd be glad to release a demo. (current + demo uses copyrighted art I'm not allowed to spread) + - Sorry for the lack of real docs and/or solid examples. I just don't have enough time. + + OPCODE distribution 1.0 (march 2001) + ----------------------- + + - First release + + =============================================================================== + + WHAT ? + + OPCODE means OPtimized COllision DEtection. + So this is a collision detection package similar to RAPID. Here's a + quick list of features: + + - C++ interface, developed for Windows systems using VC++ 6.0 + - Works on arbitrary meshes (convex or non-convex), even polygon soups + - Current implementation uses AABB-trees + - Introduces Primitive-BV overlap tests during recursive collision queries (whereas + standard libraries only rely on Primitive-Primitive and BV-BV tests) + - Introduces no-leaf trees, i.e. collision trees whose leaf nodes have been removed + - Supports collision queries on quantized trees (decompressed on-the-fly) + - Supports "first contact" or "all contacts" modes (à la RAPID) + - Uses temporal coherence for "first contact" mode (~10 to 20 times faster, useful + in rigid body simulation during bisection) + - Memory footprint is 7.2 times smaller than RAPID's one, which is ideal for console + games with limited ram (actually, if you use the unmodified RAPID code using double + precision, it's more like 13 times smaller...) + - And yet it often runs faster than RAPID (according to RDTSC, sometimes more than 5 + times faster when objects are deeply overlapping) + - Performance is usually close to RAPID's one in close-proximity situations + - Stabbing, planes & volume queries (sphere, AABB, OBB, LSS) + - Sweep-and-prune + - Now works with deformable meshes + - Hybrid trees + + + What it can be used for: + - standard mesh-mesh collision detection (similar to RAPID, SOLID, QuickCD, PQP, ColDet...) + - N-body collisions (similar to V-Collide) + - camera-vs-world collisions (similar to Telemachos/Paul Nettle/Stan Melax articles) + - shadow feelers to speed up lightmap computations + - in-out tests to speed up voxelization processes + - picking + - rigid body simulation + - view frustum culling + - etc + + WHY ? + + - Because RAPID uses too many bytes. + - Because the idea was nice... + + WHEN ? + + It's been coded in march 2001 following a thread on the GD-Algorithms list. + + GDAlgorithms-list mailing list + GDAlgorithms-list@lists.sourceforge.net + http://lists.sourceforge.net/lists/listinfo/gdalgorithms-list + + WHO ? + + Pierre Terdiman + June, 1, 2003 + + p.terdiman@wanadoo.fr + p.terdiman@codercorner.com + + http://www.codercorner.com + http://www.codercorner.com/Opcode.htm diff --git a/contrib/Opcode/StdAfx.cpp b/contrib/Opcode/StdAfx.cpp new file mode 100644 index 0000000..2350f92 --- /dev/null +++ b/contrib/Opcode/StdAfx.cpp @@ -0,0 +1,10 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +//#define ICE_MAIN +#include "StdAfx.h" diff --git a/contrib/Opcode/StdAfx.h b/contrib/Opcode/StdAfx.h new file mode 100644 index 0000000..0223a6c --- /dev/null +++ b/contrib/Opcode/StdAfx.h @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * OPCODE - Optimized Collision Detection + * Copyright (C) 2001 Pierre Terdiman + * Homepage: http://www.codercorner.com/Opcode.htm + */ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_) +#define AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// Insert your headers here +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include "Opcode.h" + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__EFB95044_1D31_11D5_8B0F_0050BAC83302__INCLUDED_) diff --git a/contrib/Opcode/TemporalCoherence.txt b/contrib/Opcode/TemporalCoherence.txt new file mode 100644 index 0000000..8fde158 --- /dev/null +++ b/contrib/Opcode/TemporalCoherence.txt @@ -0,0 +1,32 @@ + +> Hi John, +> +> I know I'll forget to tell you this if I don't write it right now.... +> +> >(2) How is the receiving geometry for the shadow decided? +> +> I wrote about an LSS-test but actually performing a new VFC test (from the +> light's view) is the same. In both cases, here's a trick to take advantage +> of temporal coherence : test the world against a slightly larger than +> necessary LSS or frustum. Keep the list of touched surfaces. Then next +> frame, if the new volume is still contained within the previous one used +for +> the query, you can reuse the same list immediately. Actually it's a bit +> similar to what you did in your sphere-tree, I think. Anyway, now the +O(log +> N) VFC is O(1) for some frames. It's not worth it for the "real" VFC, but +> when you have N virtual frustum to test to drop N shadows, that's another +> story. +> +> Two downsides: +> - You need more ram to keep track of one list of meshes / shadow, but +> usually it's not a lot. +> - By using a larger volume for the query you possibly touch more +> faces/surfaces, which will be rendered in the shadow pass. Usually it's +not +> a problem either since rendering is simply faster than geometric queries +> those days. But of course, "your mileage may vary". +> +> Happy new year ! +> +> Pierre diff --git a/contrib/libpng/ANNOUNCE b/contrib/libpng/ANNOUNCE new file mode 100644 index 0000000..4a3b018 --- /dev/null +++ b/contrib/libpng/ANNOUNCE @@ -0,0 +1,96 @@ + +Libpng 1.5.1 - February 3, 2011 + +This is a public release of libpng, intended for use in production codes. + +Files available for download: + +Source files with LF line endings (for Unix/Linux) and with a +"configure" script + + libpng-1.5.1.tar.xz (LZMA-compressed, recommended) + libpng-1.5.1.tar.gz + libpng-1.5.1.tar.bz2 + +Source files with CRLF line endings (for Windows), without the +"configure" script + + lpng151.7z (LZMA-compressed, recommended) + lpng151.zip + +Other information: + + libpng-1.5.1-README.txt + libpng-1.5.1-LICENSE.txt + +Changes since the last public release (1.5.0): + + Added description of png_set_crc_action() to the manual. + Added a note in the manual that the type of the iCCP profile was changed + from png_charpp to png_bytepp in png_get_iCCP(). Similarly, + it was changed from png_charpp to png_const_bytepp in png_set_iCCP(). + Ensure that png_rgb_to_gray ignores palette mapped images, if libpng + internally happens to call it with one. + Fixed the failure to handle palette mapped images correctly. + Fixed a bug in handling of interlaced images (bero at arklinux.org). + Updated CMakeLists.txt (Clifford Yapp) + Fixed typecasting of some png_debug() statements (Cosmin) + Updated documentation of png_set|get_tRNS() (Thomas Klausner). + Mentioned in the documentation that applications must #include "zlib.h" + if they need access to anything in zlib.h, and that a number of + macros such as png_memset() are no longer accessible by applications. + Corrected pngvalid gamma test "sample" function to access all of the color + samples of each pixel, instead of sampling the red channel three times. + Changed variable names index, div, exp, and gamma to char_index, divisor, + exp_b10, and gamma_val, respectively, to avoid "shadow" warnings. + Prevent png_push_crc_skip() from hanging while reading an unknown chunk + or an over-large compressed zTXt chunk with the progressive reader. + Eliminated more GCC "shadow" warnings. + Revised png_fixed() in png.c to avoid compiler warning about reaching the + end without returning anything. + In the manual, describe the png_get_IHDR() arguments in the correct order. + Added const_png_structp and const_png_infop types, and used them in + prototypes for most png_get_*() functions. + Added png_get_io_chunk_type() and deprecated png_get_io_chunk_name() + Added synopses for the IO_STATE functions and other missing synopses + to the manual. Removed the synopses from libpngpf.3 because they + were out of date and no longer useful. Better information can be + obtained by reading the prototypes and comments in pngpriv.h + Attempted to fix cpp on Solaris with S. Studio 12 cc, fix build + Added a make macro DFNCPP that is a CPP that will accept the tokens in + a .dfn file and adds configure stuff to test for such a CPP. ./configure + should fail if one is not available. + Corrected const_png_ in png.h to png_const_ to avoid polluting the namespace. + Added png_get_current_row_number and png_get_current_pass_number for the + benefit of the user transform callback. + Added png_process_data_pause and png_process_data_skip for the benefit of + progressive readers that need to stop data processing or want to optimize + skipping of unread data (e.g. if the reader marks a chunk to be skipped.) + Enhanced pngvalid, corrected an error in gray_to_rgb, corrected doc error. + pngvalid contains tests of transforms, which tests are currently disabled + because they are incompletely tested. gray_to_rgb was failing to expand + the bit depth for smaller bit depth images; this seems to be a long + standing error and resulted, apparently, in invalid output. The + documentation did not accurately describe what libpng really does when + converting RGB to gray. + Fixed incorrect examples of callback prototypes in the manual, that were + introduced in libpng-1.0.0. + In addition the order of the png_get_uint macros with respect to the + relevant function definitions has been reversed. This helps the + preprocessing of the symbol files be more robust. Furthermore, the + symbol file preprocessing now uses -DPNG_NO_USE_READ_MACROS even when + the library may actually be built with PNG_USE_READ_MACROS; this stops + the read macros interfering with the symbol file format. + Made the manual, synopses, and function prototypes use the function + argument names file_gamma, int_file_gamma, and srgb_intent consistently. + Changed PNG_UNUSED from "param=param;" to "(void)param;". + Added transform tests to pngvalid and simplified the arguments. + Added a request in the manual that applications do not use "png_" or + "PNG_" to begin any of their own symbols. + +Send comments/corrections/commendations to png-mng-implement at lists.sf.net +(subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe) or to glennrp at users.sourceforge.net + +Glenn R-P diff --git a/contrib/libpng/CHANGES b/contrib/libpng/CHANGES new file mode 100644 index 0000000..fa5f2aa --- /dev/null +++ b/contrib/libpng/CHANGES @@ -0,0 +1,3253 @@ +#if 0 +libpng_changes(){ /* +CHANGES - changes for libpng + +Version 0.2 + added reader into png.h + fixed small problems in stub file + +Version 0.3 + added pull reader + split up pngwrite.c to several files + added pnglib.txt + added example.c + cleaned up writer, adding a few new transformations + fixed some bugs in writer + interfaced with zlib 0.5 + added K&R support + added check for 64 KB blocks for 16 bit machines + +Version 0.4 + cleaned up code and commented code + simplified time handling into png_time + created png_color_16 and png_color_8 to handle color needs + cleaned up color type defines + fixed various bugs + made various names more consistent + interfaced with zlib 0.71 + cleaned up zTXt reader and writer (using zlib's Reset functions) + split transformations into pngrtran.c and pngwtran.c + +Version 0.5 + interfaced with zlib 0.8 + fixed many reading and writing bugs + saved using 3 spaces instead of tabs + +Version 0.6 + added png_large_malloc() and png_large_free() + added png_size_t + cleaned up some compiler warnings + added png_start_read_image() + +Version 0.7 + cleaned up lots of bugs + finished dithering and other stuff + added test program + changed name from pnglib to libpng + +Version 0.71 [June, 1995] + changed pngtest.png for zlib 0.93 + fixed error in libpng.txt and example.c + +Version 0.8 + cleaned up some bugs + added png_set_filler() + split up pngstub.c into pngmem.c, pngio.c, and pngerror.c + added #define's to remove unwanted code + moved png_info_init() to png.c + added old_size into png_realloc() + added functions to manually set filtering and compression info + changed compression parameters based on image type + optimized filter selection code + added version info + changed external functions passing floats to doubles (k&r problems?) + put all the configurable stuff in pngconf.h + enabled png_set_shift to work with paletted images on read + added png_read_update_info() - updates info structure with transformations + +Version 0.81 [August, 1995] + incorporated Tim Wegner's medium model code (thanks, Tim) + +Version 0.82 [September, 1995] + [unspecified changes] + +Version 0.85 [December, 1995] + added more medium model code (almost everything's a far) + added i/o, error, and memory callback functions + fixed some bugs (16 bit, 4 bit interlaced, etc.) + added first run progressive reader (barely tested) + +Version 0.86 [January, 1996] + fixed bugs + improved documentation + +Version 0.87 [January, 1996] + fixed medium model bugs + fixed other bugs introduced in 0.85 and 0.86 + added some minor documentation + +Version 0.88 [January, 1996] + fixed progressive bugs + replaced tabs with spaces + cleaned up documentation + added callbacks for read/write and warning/error functions + +Version 0.89 [July, 1996] + Added new initialization API to make libpng work better with shared libs + we now have png_create_read_struct(), png_create_write_struct(), + png_create_info_struct(), png_destroy_read_struct(), and + png_destroy_write_struct() instead of the separate calls to + malloc and png_read_init(), png_info_init(), and png_write_init() + Changed warning/error callback functions to fix bug - this means you + should use the new initialization API if you were using the old + png_set_message_fn() calls, and that the old API no longer exists + so that people are aware that they need to change their code + Changed filter selection API to allow selection of multiple filters + since it didn't work in previous versions of libpng anyways + Optimized filter selection code + Fixed png_set_background() to allow using an arbitrary RGB color for + paletted images + Fixed gamma and background correction for paletted images, so + png_correct_palette is not needed unless you are correcting an + external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED + in pngconf.h) - if nobody uses this, it may disappear in the future. + Fixed bug with Borland 64K memory allocation (Alexander Lehmann) + Fixed bug in interlace handling (Smarasderagd, I think) + Added more error checking for writing and image to reduce invalid files + Separated read and write functions so that they won't both be linked + into a binary when only reading or writing functionality is used + New pngtest image also has interlacing and zTXt + Updated documentation to reflect new API + +Version 0.90 [January, 1997] + Made CRC errors/warnings on critical and ancillary chunks configurable + libpng will use the zlib CRC routines by (compile-time) default + Changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner) + Added external C++ wrapper statements to png.h (Gilles Dauphin) + Allow PNG file to be read when some or all of file signature has already + been read from the beginning of the stream. ****This affects the size + of info_struct and invalidates all programs that use a shared libpng**** + Fixed png_filler() declarations + Fixed? background color conversions + Fixed order of error function pointers to match documentation + Current chunk name is now available in png_struct to reduce the number + of nearly identical error messages (will simplify multi-lingual + support when available) + Try to get ready for unknown-chunk callback functions: + - previously read critical chunks are flagged, so the chunk handling + routines can determine if the chunk is in the right place + - all chunk handling routines have the same prototypes, so we will + be able to handle all chunks via a callback mechanism + Try to fix Linux "setjmp" buffer size problems + Removed png_large_malloc, png_large_free, and png_realloc functions. + +Version 0.95 [March, 1997] + Fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never + Fixed bug in PNG file signature compares when start != 0 + Changed parameter type of png_set_filler(...filler...) from png_byte + to png_uint_32 + Added test for MACOS to ensure that both math.h and fp.h are not #included + Added macros for libpng to be compiled as a Windows DLL (Andreas Kupries) + Added "packswap" transformation, which changes the endianness of + packed-pixel bytes (Kevin Bracey) + Added "strip_alpha" transformation, which removes the alpha channel of + input images without using it (not necessarily a good idea) + Added "swap_alpha" transformation, which puts the alpha channel in front + of the color bytes instead of after + Removed all implicit variable tests which assume NULL == 0 (I think) + Changed several variables to "png_size_t" to show 16/32-bit limitations + Added new pCAL chunk read/write support + Added experimental filter selection weighting (Greg Roelofs) + Removed old png_set_rgbx() and png_set_xrgb() functions that have been + obsolete for about 2 years now (use png_set_filler() instead) + Added macros to read 16- and 32-bit ints directly from buffer, to be + used only on those systems that support it (namely PowerPC and 680x0) + With some testing, this may become the default for MACOS/PPC systems. + Only calculate CRC on data if we are going to use it + Added macros for zTXt compression type PNG_zTXt_COMPRESSION_??? + Added macros for simple libpng debugging output selectable at compile time + Removed PNG_READ_END_MODE in progressive reader (Smarasderagd) + More description of info_struct in libpng.txt and png.h + More instructions in example.c + More chunk types tested in pngtest.c + Renamed pngrcb.c to pngset.c, and all png_read_ functions to be + png_set_. We now have corresponding png_get_ + functions in pngget.c to get information in info_ptr. This isolates + the application from the internal organization of png_info_struct + (good for shared library implementations). + +Version 0.96 [May, 1997] + Fixed serious bug with < 8bpp images introduced in 0.95 + Fixed 256-color transparency bug (Greg Roelofs) + Fixed up documentation (Greg Roelofs, Laszlo Nyul) + Fixed "error" in pngconf.h for Linux setjmp() behaviour + Fixed DOS medium model support (Tim Wegner) + Fixed png_check_keyword() for case with error in static string text + Added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul) + Added typecasts to quiet compiler errors + Added more debugging info + +Version 0.97 [January, 1998] + Removed PNG_USE_OWN_CRC capability + Relocated png_set_crc_action from pngrutil.c to pngrtran.c + Fixed typecasts of "new_key", etc. (Andreas Dilger) + Added RFC 1152 [sic] date support + Fixed bug in gamma handling of 4-bit grayscale + Added 2-bit grayscale gamma handling (Glenn R-P) + Added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P) + Minor corrections in libpng.txt + Added simple sRGB support (Glenn R-P) + Easier conditional compiling, e.g. define PNG_READ/WRITE_NOT_FULLY_SUPPORTED; + all configurable options can be selected from command-line instead + of having to edit pngconf.h (Glenn R-P) + Fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P) + Added more conditions for png_do_background, to avoid changing + black pixels to background when a background is supplied and + no pixels are transparent + Repaired PNG_NO_STDIO behaviour + Tested NODIV support and made it default behaviour (Greg Roelofs) + Added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler) + Regularized version numbering scheme and bumped shared-library major + version number to 2 to avoid problems with libpng 0.89 apps (Greg Roelofs) + +Version 0.98 [January, 1998] + Cleaned up some typos in libpng.txt and in code documentation + Fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler) + Cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c + Changed recommendation about file_gamma for PC images to .51 from .45, + in example.c and libpng.txt, added comments to distinguish between + screen_gamma, viewing_gamma, and display_gamma. + Changed all references to RFC1152 to read RFC1123 and changed the + PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED + Added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent) + Changed srgb_intent from png_byte to int to avoid compiler bugs + +Version 0.99 [January 30, 1998] + Free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler) + Fixed a longstanding "packswap" bug in pngtrans.c + Fixed some inconsistencies in pngconf.h that prevented compiling with + PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined + Fixed some typos and made other minor rearrangement of libpng.txt (Andreas) + Changed recommendation about file_gamma for PC images to .50 from .51 in + example.c and libpng.txt, and changed file_gamma for sRGB images to .45 + Added a number of functions to access information from the png structure + png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit) + Added TARGET_MACOS similar to zlib-1.0.8 + Define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined + Added type casting to all png_malloc() function calls + +Version 0.99a [January 31, 1998] + Added type casts and parentheses to all returns that return a value.(Tim W.) + +Version 0.99b [February 4, 1998] + Added type cast png_uint_32 on malloc function calls where needed. + Changed type of num_hist from png_uint_32 to int (same as num_palette). + Added checks for rowbytes overflow, in case png_size_t is less than 32 bits. + Renamed makefile.elf to makefile.lnx. + +Version 0.99c [February 7, 1998] + More type casting. Removed erroneous overflow test in pngmem.c. + Added png_buffered_memcpy() and png_buffered_memset(), apply them to rowbytes. + Added UNIX manual pages libpng.3 (incorporating libpng.txt) and png.5. + +Version 0.99d [February 11, 1998] + Renamed "far_to_near()" "png_far_to_near()" + Revised libpng.3 + Version 99c "buffered" operations didn't work as intended. Replaced them + with png_memcpy_check() and png_memset_check(). + Added many "if (png_ptr == NULL) return" to quell compiler warnings about + unused png_ptr, mostly in pngget.c and pngset.c. + Check for overlength tRNS chunk present when indexed-color PLTE is read. + Cleaned up spelling errors in libpng.3/libpng.txt + Corrected a problem with png_get_tRNS() which returned undefined trans array + +Version 0.99e [February 28, 1998] + Corrected png_get_tRNS() again. + Add parentheses for easier reading of pngget.c, fixed "||" should be "&&". + Touched up example.c to make more of it compileable, although the entire + file still can't be compiled (Willem van Schaik) + Fixed a bug in png_do_shift() (Bryan Tsai) + Added a space in png.h prototype for png_write_chunk_start() + Replaced pngtest.png with one created with zlib 1.1.1 + Changed pngtest to report PASS even when file size is different (Jean-loup G.) + Corrected some logic errors in png_do_invert_alpha() (Chris Patterson) + +Version 0.99f [March 5, 1998] + Corrected a bug in pngpread() introduced in version 99c (Kevin Bracey) + Moved makefiles into a "scripts" directory, and added INSTALL instruction file + Added makefile.os2 and pngos2.def (A. Zabolotny) and makefile.s2x (W. Sebok) + Added pointers to "note on libpng versions" in makefile.lnx and README + Added row callback feature when reading and writing nonprogressive rows + and added a test of this feature in pngtest.c + Added user transform callbacks, with test of the feature in pngtest.c + +Version 0.99g [March 6, 1998, morning] + Minor changes to pngtest.c to suppress compiler warnings. + Removed "beta" language from documentation. + +Version 0.99h [March 6, 1998, evening] + Minor changes to previous minor changes to pngtest.c + Changed PNG_READ_NOT_FULLY_SUPPORTED to PNG_READ_TRANSFORMS_NOT_SUPPORTED + and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro + Added user transform capability + +Version 1.00 [March 7, 1998] + Changed several typedefs in pngrutil.c + Added makefile.wat (Pawel Mrochen), updated makefile.tc3 (Willem van Schaik) + Replaced "while(1)" with "for(;;)" + Added PNGARG() to prototypes in pngtest.c and removed some prototypes + Updated some of the makefiles (Tom Lane) + Changed some typedefs (s_start, etc.) in pngrutil.c + Fixed dimensions of "short_months" array in pngwrite.c + Replaced ansi2knr.c with the one from jpeg-v6 + +Version 1.0.0 [March 8, 1998] + Changed name from 1.00 to 1.0.0 (Adam Costello) + Added smakefile.ppc (with SCOPTIONS.ppc) for Amiga PPC (Andreas Kleinert) + +Version 1.0.0a [March 9, 1998] + Fixed three bugs in pngrtran.c to make gamma+background handling consistent + (Greg Roelofs) + Changed format of the PNG_LIBPNG_VER integer to xyyzz instead of xyz + for major, minor, and bugfix releases. This is 10001. (Adam Costello, + Tom Lane) + Make months range from 1-12 in png_convert_to_rfc1123 + +Version 1.0.0b [March 13, 1998] + Quieted compiler complaints about two empty "for" loops in pngrutil.c + Minor changes to makefile.s2x + Removed #ifdef/#endif around a png_free() in pngread.c + +Version 1.0.1 [March 14, 1998] + Changed makefile.s2x to reduce security risk of using a relative pathname + Fixed some typos in the documentation (Greg). + Fixed a problem with value of "channels" returned by png_read_update_info() + +Version 1.0.1a [April 21, 1998] + Optimized Paeth calculations by replacing abs() function calls with intrinsics + plus other loop optimizations. Improves avg decoding speed by about 20%. + Commented out i386istic "align" compiler flags in makefile.lnx. + Reduced the default warning level in some makefiles, to make them consistent. + Removed references to IJG and JPEG in the ansi2knr.c copyright statement. + Fixed a bug in png_do_strip_filler with XXRRGGBB => RRGGBB transformation. + Added grayscale and 16-bit capability to png_do_read_filler(). + Fixed a bug in pngset.c, introduced in version 0.99c, that sets rowbytes + too large when writing an image with bit_depth < 8 (Bob Dellaca). + Corrected some bugs in the experimental weighted filtering heuristics. + Moved a misplaced pngrutil code block that truncates tRNS if it has more + than num_palette entries -- test was done before num_palette was defined. + Fixed a png_convert_to_rfc1123() bug that converts day 31 to 0 (Steve Eddins). + Changed compiler flags in makefile.wat for better optimization + (Pawel Mrochen). + +Version 1.0.1b [May 2, 1998] + Relocated png_do_gray_to_rgb() within png_do_read_transformations() (Greg). + Relocated the png_composite macros from pngrtran.c to png.h (Greg). + Added makefile.sco (contributed by Mike Hopkirk). + Fixed two bugs (missing definitions of "istop") introduced in libpng-1.0.1a. + Fixed a bug in pngrtran.c that would set channels=5 under some circumstances. + More work on the Paeth-filtering, achieving imperceptible speedup + (A Kleinert). + More work on loop optimization which may help when compiled with C++ + compilers. + Added warnings when people try to use transforms they've defined out. + Collapsed 4 "i" and "c" loops into single "i" loops in pngrtran and pngwtran. + Revised paragraph about png_set_expand() in libpng.txt and libpng.3 (Greg) + +Version 1.0.1c [May 11, 1998] + Fixed a bug in pngrtran.c (introduced in libpng-1.0.1a) where the masks for + filler bytes should have been 0xff instead of 0xf. + Added max_pixel_depth=32 in pngrutil.c when using FILLER with palette images. + Moved PNG_WRITE_WEIGHTED_FILTER_SUPPORTED and PNG_WRITE_FLUSH_SUPPORTED + out of the PNG_WRITE_TRANSFORMS_NOT_SUPPORTED block of pngconf.h + Added "PNG_NO_WRITE_TRANSFORMS" etc., as alternatives for *_NOT_SUPPORTED, + for consistency, in pngconf.h + Added individual "ifndef PNG_NO_[CAPABILITY]" in pngconf.h to make it easier + to remove unwanted capabilities via the compile line + Made some corrections to grammar (which, it's) in documentation (Greg). + Corrected example.c, use of row_pointers in png_write_image(). + +Version 1.0.1d [May 24, 1998] + Corrected several statements that used side effects illegally in pngrutil.c + and pngtrans.c, that were introduced in version 1.0.1b + Revised png_read_rows() to avoid repeated if-testing for NULL (A Kleinert) + More corrections to example.c, use of row_pointers in png_write_image() + and png_read_rows(). + Added pngdll.mak and pngdef.pas to scripts directory, contributed by + Bob Dellaca, to make a png32bd.dll with Borland C++ 4.5 + Fixed error in example.c with png_set_text: num_text is 3, not 2 (Guido V.) + Changed several loops from count-down to count-up, for consistency. + +Version 1.0.1e [June 6, 1998] + Revised libpng.txt and libpng.3 description of png_set_read|write_fn(), and + added warnings when people try to set png_read_fn and png_write_fn in + the same structure. + Added a test such that png_do_gamma will be done when num_trans==0 + for truecolor images that have defined a background. This corrects an + error that was introduced in libpng-0.90 that can cause gamma processing + to be skipped. + Added tests in png.h to include "trans" and "trans_values" in structures + when PNG_READ_BACKGROUND_SUPPORTED or PNG_READ_EXPAND_SUPPORTED is defined. + Add png_free(png_ptr->time_buffer) in png_destroy_read_struct() + Moved png_convert_to_rfc_1123() from pngwrite.c to png.c + Added capability for user-provided malloc_fn() and free_fn() functions, + and revised pngtest.c to demonstrate their use, replacing the + PNGTEST_DEBUG_MEM feature. + Added makefile.w32, for Microsoft C++ 4.0 and later (Tim Wegner). + +Version 1.0.2 [June 14, 1998] + Fixed two bugs in makefile.bor . + +Version 1.0.2a [December 30, 1998] + Replaced and extended code that was removed from png_set_filler() in 1.0.1a. + Fixed a bug in png_do_filler() that made it fail to write filler bytes in + the left-most pixel of each row (Kevin Bracey). + Changed "static pngcharp tIME_string" to "static char tIME_string[30]" + in pngtest.c (Duncan Simpson). + Fixed a bug in pngtest.c that caused pngtest to try to write a tIME chunk + even when no tIME chunk was present in the source file. + Fixed a problem in pngrutil.c: gray_to_rgb didn't always work with 16-bit. + Fixed a problem in png_read_push_finish_row(), which would not skip some + passes that it should skip, for images that are less than 3 pixels high. + Interchanged the order of calls to png_do_swap() and png_do_shift() + in pngwtran.c (John Cromer). + Added #ifdef PNG_DEBUG/#endif surrounding use of PNG_DEBUG in png.h . + Changed "bad adaptive filter type" from error to warning in pngrutil.c . + Fixed a documentation error about default filtering with 8-bit indexed-color. + Separated the PNG_NO_STDIO macro into PNG_NO_STDIO and PNG_NO_CONSOLE_IO + (L. Peter Deutsch). + Added png_set_rgb_to_gray() and png_get_rgb_to_gray_status() functions. + Added png_get_copyright() and png_get_header_version() functions. + Revised comments on png_set_progressive_read_fn() in libpng.txt and example.c + Added information about debugging in libpng.txt and libpng.3 . + Changed "ln -sf" to "ln -s -f" in makefile.s2x, makefile.lnx, and + makefile.sco. + Removed lines after Dynamic Dependencies" in makefile.aco . + Revised makefile.dec to make a shared library (Jeremie Petit). + Removed trailing blanks from all files. + +Version 1.0.2a [January 6, 1999] + Removed misplaced #endif and #ifdef PNG_NO_EXTERN near the end of png.h + Added "if" tests to silence complaints about unused png_ptr in png.h and png.c + Changed "check_if_png" function in example.c to return true (nonzero) if PNG. + Changed libpng.txt to demonstrate png_sig_cmp() instead of png_check_sig() + which is obsolete. + +Version 1.0.3 [January 14, 1999] + Added makefile.hux, for Hewlett Packard HPUX 10.20 and 11.00 (Jim Rice) + Added a statement of Y2K compliance in png.h, libpng.3, and Y2KINFO. + +Version 1.0.3a [August 12, 1999] + Added check for PNG_READ_INTERLACE_SUPPORTED in pngread.c; issue a warning + if an attempt is made to read an interlaced image when it's not supported. + Added check if png_ptr->trans is defined before freeing it in pngread.c + Modified the Y2K statement to include versions back to version 0.71 + Fixed a bug in the check for valid IHDR bit_depth/color_types in pngrutil.c + Modified makefile.wat (added -zp8 flag, ".symbolic", changed some comments) + Replaced leading blanks with tab characters in makefile.hux + Changed "dworkin.wustl.edu" to "ccrc.wustl.edu" in various documents. + Changed (float)red and (float)green to (double)red, (double)green + in png_set_rgb_to_gray() to avoid "promotion" problems in AIX. + Fixed a bug in pngconf.h that omitted when PNG_DEBUG==0 (K Bracey). + Reformatted libpng.3 and libpngpf.3 with proper fonts (script by J. vanZandt). + Updated documentation to refer to the PNG-1.2 specification. + Removed ansi2knr.c and left pointers to the latest source for ansi2knr.c + in makefile.knr, INSTALL, and README (L. Peter Deutsch) + Fixed bugs in calculation of the length of rowbytes when adding alpha + channels to 16-bit images, in pngrtran.c (Chris Nokleberg) + Added function png_set_user_transform_info() to store user_transform_ptr, + user_depth, and user_channels into the png_struct, and a function + png_get_user_transform_ptr() to retrieve the pointer (Chris Nokleberg) + Added function png_set_empty_plte_permitted() to make libpng useable + in MNG applications. + Corrected the typedef for png_free_ptr in png.h (Jesse Jones). + Correct gamma with srgb is 45455 instead of 45000 in pngrutil.c, to be + consistent with PNG-1.2, and allow variance of 500 before complaining. + Added assembler code contributed by Intel in file pngvcrd.c and modified + makefile.w32 to use it (Nirav Chhatrapati, INTEL Corporation, + Gilles Vollant) + Changed "ln -s -f" to "ln -f -s" in the makefiles to make Solaris happy. + Added some aliases for png_set_expand() in pngrtran.c, namely + png_set_expand_PLTE(), png_set_expand_depth(), and png_set_expand_tRNS() + (Greg Roelofs, in "PNG: The Definitive Guide"). + Added makefile.beo for BEOS on X86, contributed by Sander Stok. + +Version 1.0.3b [August 26, 1999] + Replaced 2147483647L several places with PNG_MAX_UINT macro, defined in png.h + Changed leading blanks to tabs in all makefiles. + Define PNG_USE_PNGVCRD in makefile.w32, to get MMX assembler code. + Made alternate versions of png_set_expand() in pngrtran.c, namely + png_set_gray_1_2_4_to_8, png_set_palette_to_rgb, and png_set_tRNS_to_alpha + (Greg Roelofs, in "PNG: The Definitive Guide"). Deleted the 1.0.3a aliases. + Relocated start of 'extern "C"' block in png.h so it doesn't include pngconf.h + Revised calculation of num_blocks in pngmem.c to avoid a potentially + negative shift distance, whose results are undefined in the C language. + Added a check in pngset.c to prevent writing multiple tIME chunks. + Added a check in pngwrite.c to detect invalid small window_bits sizes. + +Version 1.0.3d [September 4, 1999] + Fixed type casting of igamma in pngrutil.c + Added new png_expand functions to scripts/pngdef.pas and pngos2.def + Added a demo read_user_transform_fn that examines the row filters in pngtest.c + +Version 1.0.4 [September 24, 1999] + Define PNG_ALWAYS_EXTERN in pngconf.h if __STDC__ is defined + Delete #define PNG_INTERNAL and include "png.h" from pngasmrd.h + Made several minor corrections to pngtest.c + Renamed the makefiles with longer but more user friendly extensions. + Copied the PNG copyright and license to a separate LICENSE file. + Revised documentation, png.h, and example.c to remove reference to + "viewing_gamma" which no longer appears in the PNG specification. + Revised pngvcrd.c to use MMX code for interlacing only on the final pass. + Updated pngvcrd.c to use the faster C filter algorithms from libpng-1.0.1a + Split makefile.win32vc into two versions, makefile.vcawin32 (uses MMX + assembler code) and makefile.vcwin32 (doesn't). + Added a CPU timing report to pngtest.c (enabled by defining PNGTEST_TIMING) + Added a copy of pngnow.png to the distribution. + +Version 1.0.4a [September 25, 1999] + Increase max_pixel_depth in pngrutil.c if a user transform needs it. + Changed several division operations to right-shifts in pngvcrd.c + +Version 1.0.4b [September 30, 1999] + Added parentheses in line 3732 of pngvcrd.c + Added a comment in makefile.linux warning about buggy -O3 in pgcc 2.95.1 + +Version 1.0.4c [October 1, 1999] + Added a "png_check_version" function in png.c and pngtest.c that will generate + a helpful compiler error if an old png.h is found in the search path. + Changed type of png_user_transform_depth|channels from int to png_byte. + +Version 1.0.4d [October 6, 1999] + Changed 0.45 to 0.45455 in png_set_sRGB() + Removed unused PLTE entries from pngnow.png + Re-enabled some parts of pngvcrd.c (png_combine_row) that work properly. + +Version 1.0.4e [October 10, 1999] + Fixed sign error in pngvcrd.c (Greg Roelofs) + Replaced some instances of memcpy with simple assignments in pngvcrd (GR-P) + +Version 1.0.4f [October 15, 1999] + Surrounded example.c code with #if 0 .. #endif to prevent people from + inadvertently trying to compile it. + Changed png_get_header_version() from a function to a macro in png.h + Added type casting mostly in pngrtran.c and pngwtran.c + Removed some pointless "ptr = NULL" in pngmem.c + Added a "contrib" directory containing the source code from Greg's book. + +Version 1.0.5 [October 15, 1999] + Minor editing of the INSTALL and README files. + +Version 1.0.5a [October 23, 1999] + Added contrib/pngsuite and contrib/pngminus (Willem van Schaik) + Fixed a typo in the png_set_sRGB() function call in example.c (Jan Nijtmans) + Further optimization and bugfix of pngvcrd.c + Revised pngset.c so that it does not allocate or free memory in the user's + text_ptr structure. Instead, it makes its own copy. + Created separate write_end_info_struct in pngtest.c for a more severe test. + Added code in pngwrite.c to free info_ptr->text[i].key to stop a memory leak. + +Version 1.0.5b [November 23, 1999] + Moved PNG_FLAG_HAVE_CHUNK_HEADER, PNG_FLAG_BACKGROUND_IS_GRAY and + PNG_FLAG_WROTE_tIME from flags to mode. + Added png_write_info_before_PLTE() function. + Fixed some typecasting in contrib/gregbook/*.c + Updated scripts/makevms.com and added makevms.com to contrib/gregbook + and contrib/pngminus (Martin Zinser) + +Version 1.0.5c [November 26, 1999] + Moved png_get_header_version from png.h to png.c, to accommodate ansi2knr. + Removed all global arrays (according to PNG_NO_GLOBAL_ARRAYS macro), to + accommodate making DLL's: Moved usr_png_ver from global variable to function + png_get_header_ver() in png.c. Moved png_sig to png_sig_bytes in png.c and + eliminated use of png_sig in pngwutil.c. Moved the various png_CHNK arrays + into pngtypes.h. Eliminated use of global png_pass arrays. Declared the + png_CHNK and png_pass arrays to be "const". Made the global arrays + available to applications (although none are used in libpng itself) when + PNG_NO_GLOBAL_ARRAYS is not defined or when PNG_GLOBAL_ARRAYS is defined. + Removed some extraneous "-I" from contrib/pngminus/makefile.std + Changed the PNG_sRGB_INTENT macros in png.h to be consistent with PNG-1.2. + Change PNG_SRGB_INTENT to PNG_sRGB_INTENT in libpng.txt and libpng.3 + +Version 1.0.5d [November 29, 1999] + Add type cast (png_const_charp) two places in png.c + Eliminated pngtypes.h; use macros instead to declare PNG_CHNK arrays. + Renamed "PNG_GLOBAL_ARRAYS" to "PNG_USE_GLOBAL_ARRAYS" and made available + to applications a macro "PNG_USE_LOCAL_ARRAYS". + comment out (with #ifdef) all the new declarations when + PNG_USE_GLOBAL_ARRAYS is defined. + Added PNG_EXPORT_VAR macro to accommodate making DLL's. + +Version 1.0.5e [November 30, 1999] + Added iCCP, iTXt, and sPLT support; added "lang" member to the png_text + structure; refactored the inflate/deflate support to make adding new chunks + with trailing compressed parts easier in the future, and added new functions + png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP, + png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond). + NOTE: Applications that write text chunks MUST define png_text->lang + before calling png_set_text(). It must be set to NULL if you want to + write tEXt or zTXt chunks. If you want your application to be able to + run with older versions of libpng, use + + #ifdef PNG_iTXt_SUPPORTED + png_text[i].lang = NULL; + #endif + + Changed png_get_oFFs() and png_set_oFFs() to use signed rather than unsigned + offsets (Eric S. Raymond). + Combined PNG_READ_cHNK_SUPPORTED and PNG_WRITE_cHNK_SUPPORTED macros into + PNG_cHNK_SUPPORTED and combined the three types of PNG_text_SUPPORTED + macros, leaving the separate macros also available. + Removed comments on #endifs at the end of many short, non-nested #if-blocks. + +Version 1.0.5f [December 6, 1999] + Changed makefile.solaris to issue a warning about potential problems when + the ucb "ld" is in the path ahead of the ccs "ld". + Removed "- [date]" from the "synopsis" line in libpng.3 and libpngpf.3. + Added sCAL chunk support (Eric S. Raymond). + +Version 1.0.5g [December 7, 1999] + Fixed "png_free_spallettes" typo in png.h + Added code to handle new chunks in pngpread.c + Moved PNG_CHNK string macro definitions outside of PNG_NO_EXTERN block + Added "translated_key" to png_text structure and png_write_iTXt(). + Added code in pngwrite.c to work around a newly discovered zlib bug. + +Version 1.0.5h [December 10, 1999] + NOTE: regarding the note for version 1.0.5e, the following must also + be included in your code: + png_text[i].translated_key = NULL; + Unknown chunk handling is now supported. + Option to eliminate all floating point support was added. Some new + fixed-point functions such as png_set_gAMA_fixed() were added. + Expanded tabs and removed trailing blanks in source files. + +Version 1.0.5i [December 13, 1999] + Added some type casts to silence compiler warnings. + Renamed "png_free_spalette" to "png_free_spalettes" for consistency. + Removed leading blanks from a #define in pngvcrd.c + Added some parameters to the new png_set_keep_unknown_chunks() function. + Added a test for up->location != 0 in the first instance of writing + unknown chunks in pngwrite.c + Changed "num" to "i" in png_free_spalettes() and png_free_unknowns() to + prevent recursion. + Added png_free_hIST() function. + Various patches to fix bugs in the sCAL and integer cHRM processing, + and to add some convenience macros for use with sCAL. + +Version 1.0.5j [December 21, 1999] + Changed "unit" parameter of png_write_sCAL from png_byte to int, to work + around buggy compilers. + Added new type "png_fixed_point" for integers that hold float*100000 values + Restored backward compatibility of tEXt/zTXt chunk processing: + Restored the first four members of png_text to the same order as v.1.0.5d. + Added members "lang_key" and "itxt_length" to png_text struct. Set + text_length=0 when "text" contains iTXt data. Use the "compression" + member to distinguish among tEXt/zTXt/iTXt types. Added + PNG_ITXT_COMPRESSION_NONE (1) and PNG_ITXT_COMPRESSION_zTXt(2) macros. + The "Note" above, about backward incompatibility of libpng-1.0.5e, no + longer applies. + Fixed png_read|write_iTXt() to read|write parameters in the right order, + and to write the iTXt chunk after IDAT if it appears in the end_ptr. + Added pnggccrd.c, version of pngvcrd.c Intel assembler for gcc (Greg Roelofs) + Reversed the order of trying to write floating-point and fixed-point gAMA. + +Version 1.0.5k [December 27, 1999] + Added many parentheses, e.g., "if (a && b & c)" becomes "if (a && (b & c))" + Added png_handle_as_unknown() function (Glenn) + Added png_free_chunk_list() function and chunk_list and num_chunk_list members + of png_ptr. + Eliminated erroneous warnings about multiple sPLT chunks and sPLT-after-PLTE. + Fixed a libpng-1.0.5h bug in pngrutil.c that was issuing erroneous warnings + about ignoring incorrect gAMA with sRGB (gAMA was in fact not ignored) + Added png_free_tRNS(); png_set_tRNS() now malloc's its own trans array (ESR). + Define png_get_int_32 when oFFs chunk is supported as well as when pCAL is. + Changed type of proflen from png_int_32 to png_uint_32 in png_get_iCCP(). + +Version 1.0.5l [January 1, 2000] + Added functions png_set_read_user_chunk_fn() and png_get_user_chunk_ptr() + for setting a callback function to handle unknown chunks and for + retrieving the associated user pointer (Glenn). + +Version 1.0.5m [January 7, 2000] + Added high-level functions png_read_png(), png_write_png(), png_free_pixels(). + +Version 1.0.5n [January 9, 2000] + Added png_free_PLTE() function, and modified png_set_PLTE() to malloc its + own memory for info_ptr->palette. This makes it safe for the calling + application to free its copy of the palette any time after it calls + png_set_PLTE(). + +Version 1.0.5o [January 20, 2000] + Cosmetic changes only (removed some trailing blanks and TABs) + +Version 1.0.5p [January 31, 2000] + Renamed pngdll.mak to makefile.bd32 + Cosmetic changes in pngtest.c + +Version 1.0.5q [February 5, 2000] + Relocated the makefile.solaris warning about PATH problems. + Fixed pngvcrd.c bug by pushing/popping registers in mmxsupport (Bruce Oberg) + Revised makefile.gcmmx + Added PNG_SETJMP_SUPPORTED, PNG_SETJMP_NOT_SUPPORTED, and PNG_ABORT() macros + +Version 1.0.5r [February 7, 2000] + Removed superfluous prototype for png_get_itxt from png.h + Fixed a bug in pngrtran.c that improperly expanded the background color. + Return *num_text=0 from png_get_text() when appropriate, and fix documentation + of png_get_text() in libpng.txt/libpng.3. + +Version 1.0.5s [February 18, 2000] + Added "png_jmp_env()" macro to pngconf.h, to help people migrate to the + new error handler that's planned for the next libpng release, and changed + example.c, pngtest.c, and contrib programs to use this macro. + Revised some of the DLL-export macros in pngconf.h (Greg Roelofs) + Fixed a bug in png_read_png() that caused it to fail to expand some images + that it should have expanded. + Fixed some mistakes in the unused and undocumented INCH_CONVERSIONS functions + in pngget.c + Changed the allocation of palette, history, and trans arrays back to + the version 1.0.5 method (linking instead of copying) which restores + backward compatibility with version 1.0.5. Added some remarks about + that in example.c. Added "free_me" member to info_ptr and png_ptr + and added png_free_data() function. + Updated makefile.linux and makefile.gccmmx to make directories conditionally. + Made cosmetic changes to pngasmrd.h + Added png_set_rows() and png_get_rows(), for use with png_read|write_png(). + Modified png_read_png() to allocate info_ptr->row_pointers only if it + hasn't already been allocated. + +Version 1.0.5t [March 4, 2000] + Changed png_jmp_env() migration aiding macro to png_jmpbuf(). + Fixed "interlace" typo (should be "interlaced") in contrib/gregbook/read2-x.c + Fixed bug with use of PNG_BEFORE_IHDR bit in png_ptr->mode, introduced when + PNG_FLAG_HAVE_CHUNK_HEADER was moved into png_ptr->mode in version 1.0.5b + Files in contrib/gregbook were revised to use png_jmpbuf() and to select + a 24-bit visual if one is available, and to allow abbreviated options. + Files in contrib/pngminus were revised to use the png_jmpbuf() macro. + Removed spaces in makefile.linux and makefile.gcmmx, introduced in 1.0.5s + +Version 1.0.5u [March 5, 2000] + Simplified the code that detects old png.h in png.c and pngtest.c + Renamed png_spalette (_p, _pp) to png_sPLT_t (_tp, _tpp) + Increased precision of rgb_to_gray calculations from 8 to 15 bits and + added png_set_rgb_to_gray_fixed() function. + Added makefile.bc32 (32-bit Borland C++, C mode) + +Version 1.0.5v [March 11, 2000] + Added some parentheses to the png_jmpbuf macro definition. + Updated references to the zlib home page, which has moved to freesoftware.com. + Corrected bugs in documentation regarding png_read_row() and png_write_row(). + Updated documentation of png_rgb_to_gray calculations in libpng.3/libpng.txt. + Renamed makefile.borland,turboc3 back to makefile.bor,tc3 as in version 1.0.3, + revised borland makefiles; added makefile.ibmvac3 and makefile.gcc (Cosmin) + +Version 1.0.6 [March 20, 2000] + Minor revisions of makefile.bor, libpng.txt, and gregbook/rpng2-win.c + Added makefile.sggcc (SGI IRIX with gcc) + +Version 1.0.6d [April 7, 2000] + Changed sprintf() to strcpy() in png_write_sCAL_s() to work without STDIO + Added data_length parameter to png_decompress_chunk() function + Revised documentation to remove reference to abandoned png_free_chnk functions + Fixed an error in png_rgb_to_gray_fixed() + Revised example.c, usage of png_destroy_write_struct(). + Renamed makefile.ibmvac3 to makefile.ibmc, added libpng.icc IBM project file + Added a check for info_ptr->free_me&PNG_FREE_TEXT when freeing text in png.c + Simplify png_sig_bytes() function to remove use of non-ISO-C strdup(). + +Version 1.0.6e [April 9, 2000] + Added png_data_freer() function. + In the code that checks for over-length tRNS chunks, added check of + info_ptr->num_trans as well as png_ptr->num_trans (Matthias Benckmann) + Minor revisions of libpng.txt/libpng.3. + Check for existing data and free it if the free_me flag is set, in png_set_*() + and png_handle_*(). + Only define PNG_WEIGHTED_FILTERS_SUPPORTED when PNG_FLOATING_POINT_SUPPORTED + is defined. + Changed several instances of PNG_NO_CONSOLE_ID to PNG_NO_STDIO in pngrutil.c + and mentioned the purposes of the two macros in libpng.txt/libpng.3. + +Version 1.0.6f [April 14, 2000] + Revised png_set_iCCP() and png_set_rows() to avoid prematurely freeing data. + Add checks in png_set_text() for NULL members of the input text structure. + Revised libpng.txt/libpng.3. + Removed superfluous prototype for png_set_iTXt from png.h + Removed "else" from pngread.c, after png_error(), and changed "0" to "length". + Changed several png_errors about malformed ancillary chunks to png_warnings. + +Version 1.0.6g [April 24, 2000] + Added png_pass-* arrays to pnggccrd.c when PNG_USE_LOCAL_ARRAYS is defined. + Relocated paragraph about png_set_background() in libpng.3/libpng.txt + and other revisions (Matthias Benckmann) + Relocated info_ptr->free_me, png_ptr->free_me, and other info_ptr and + png_ptr members to restore binary compatibility with libpng-1.0.5 + (breaks compatibility with libpng-1.0.6). + +Version 1.0.6h [April 24, 2000] + Changed shared library so-number pattern from 2.x.y.z to xy.z (this builds + libpng.so.10 & libpng.so.10.6h instead of libpng.so.2 & libpng.so.2.1.0.6h) + This is a temporary change for test purposes. + +Version 1.0.6i [May 2, 2000] + Rearranged some members at the end of png_info and png_struct, to put + unknown_chunks_num and free_me within the original size of the png_structs + and free_me, png_read_user_fn, and png_free_fn within the original png_info, + because some old applications allocate the structs directly instead of + using png_create_*(). + Added documentation of user memory functions in libpng.txt/libpng.3 + Modified png_read_png so that it will use user_allocated row_pointers + if present, unless free_me directs that it be freed, and added description + of the use of png_set_rows() and png_get_rows() in libpng.txt/libpng.3. + Added PNG_LEGACY_SUPPORTED macro, and #ifdef out all new (since version + 1.00) members of png_struct and png_info, to regain binary compatibility + when you define this macro. Capabilities lost in this event + are user transforms (new in version 1.0.0),the user transform pointer + (new in version 1.0.2), rgb_to_gray (new in 1.0.5), iCCP, sCAL, sPLT, + the high-level interface, and unknown chunks support (all new in 1.0.6). + This was necessary because of old applications that allocate the structs + directly as authors were instructed to do in libpng-0.88 and earlier, + instead of using png_create_*(). + Added modes PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT which + can be used to detect codes that directly allocate the structs, and + code to check these modes in png_read_init() and png_write_init() and + generate a libpng error if the modes aren't set and PNG_LEGACY_SUPPORTED + was not defined. + Added makefile.intel and updated makefile.watcom (Pawel Mrochen) + +Version 1.0.6j [May 3, 2000] + Overloaded png_read_init() and png_write_init() with macros that convert + calls to png_read_init_2() or png_write_init_2() that check the version + and structure sizes. + +Version 1.0.7beta11 [May 7, 2000] + Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes + which are no longer used. + Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is + defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED + is defined. + Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory + overrun when old applications fill the info_ptr->text structure directly. + Added PNGAPI macro, and added it to the definitions of all exported functions. + Relocated version macro definitions ahead of the includes of zlib.h and + pngconf.h in png.h. + +Version 1.0.7beta12 [May 12, 2000] + Revised pngset.c to avoid a problem with expanding the png_debug macro. + Deleted some extraneous defines from pngconf.h + Made PNG_NO_CONSOLE_IO the default condition when PNG_BUILD_DLL is defined. + Use MSC _RPTn debugging instead of fprintf if _MSC_VER is defined. + Added png_access_version_number() function. + Check for mask&PNG_FREE_CHNK (for TEXT, SCAL, PCAL) in png_free_data(). + Expanded libpng.3/libpng.txt information about png_data_freer(). + +Version 1.0.7beta14 [May 17, 2000] (beta13 was not published) + Changed pnggccrd.c and pngvcrd.c to handle bad adaptive filter types as + warnings instead of errors, as pngrutil.c does. + Set the PNG_INFO_IDAT valid flag in png_set_rows() so png_write_png() + will actually write IDATs. + Made the default PNG_USE_LOCAL_ARRAYS depend on PNG_DLL instead of WIN32. + Make png_free_data() ignore its final parameter except when freeing data + that can have multiple instances (text, sPLT, unknowns). + Fixed a new bug in png_set_rows(). + Removed info_ptr->valid tests from png_free_data(), as in version 1.0.5. + Added png_set_invalid() function. + Fixed incorrect illustrations of png_destroy_write_struct() in example.c. + +Version 1.0.7beta15 [May 30, 2000] + Revised the deliberately erroneous Linux setjmp code in pngconf.h to produce + fewer error messages. + Rearranged checks for Z_OK to check the most likely path first in pngpread.c + and pngwutil.c. + Added checks in pngtest.c for png_create_*() returning NULL, and mentioned + in libpng.txt/libpng.3 the need for applications to check this. + Changed names of png_default_*() functions in pngtest to pngtest_*(). + Changed return type of png_get_x|y_offset_*() from png_uint_32 to png_int_32. + Fixed some bugs in the unused PNG_INCH_CONVERSIONS functions in pngget.c + Set each pointer to NULL after freeing it in png_free_data(). + Worked around a problem in pngconf.h; AIX's strings.h defines an "index" + macro that conflicts with libpng's png_color_16.index. (Dimitri + Papadapoulos) + Added "msvc" directory with MSVC++ project files (Simon-Pierre Cadieux). + +Version 1.0.7beta16 [June 4, 2000] + Revised the workaround of AIX string.h "index" bug. + Added a check for overlength PLTE chunk in pngrutil.c. + Added PNG_NO_POINTER_INDEXING macro to use array-indexing instead of pointer + indexing in pngrutil.c and pngwutil.c to accommodate a buggy compiler. + Added a warning in png_decompress_chunk() when it runs out of data, e.g. + when it tries to read an erroneous PhotoShop iCCP chunk. + Added PNG_USE_DLL macro. + Revised the copyright/disclaimer/license notice. + Added contrib/msvctest directory + +Version 1.0.7rc1 [June 9, 2000] + Corrected the definition of PNG_TRANSFORM_INVERT_ALPHA (0x0400 not 0x0200) + Added contrib/visupng directory (Willem van Schaik) + +Version 1.0.7beta18 [June 23, 2000] + Revised PNGAPI definition, and pngvcrd.c to work with __GCC__ + and do not redefine PNGAPI if it is passed in via a compiler directive. + Revised visupng/PngFile.c to remove returns from within the Try block. + Removed leading underscores from "_PNG_H" and "_PNG_SAVE_BSD_SOURCE" macros. + Updated contrib/visupng/cexcept.h to version 1.0.0. + Fixed bugs in pngwrite.c and pngwutil.c that prevented writing iCCP chunks. + +Version 1.0.7rc2 [June 28, 2000] + Updated license to include disclaimers required by UCITA. + Fixed "DJBPP" typo in pnggccrd.c introduced in beta18. + +Version 1.0.7 [July 1, 2000] + Revised the definition of "trans_values" in libpng.3/libpng.txt + +Version 1.0.8beta1 [July 8, 2000] + Added png_free(png_ptr, key) two places in pngpread.c to stop memory leaks. + Changed PNG_NO_STDIO to PNG_NO_CONSOLE_IO, several places in pngrutil.c and + pngwutil.c. + Changed PNG_EXPORT_VAR to use PNG_IMPEXP, in pngconf.h. + Removed unused "#include " from png.c + Added WindowsCE support. + Revised pnggccrd.c to work with gcc-2.95.2 and in the Cygwin environment. + +Version 1.0.8beta2 [July 10, 2000] + Added project files to the wince directory and made further revisions + of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE. + +Version 1.0.8beta3 [July 11, 2000] + Only set the PNG_FLAG_FREE_TRNS or PNG_FREE_TRNS flag in png_handle_tRNS() + for indexed-color input files to avoid potential double-freeing trans array + under some unusual conditions; problem was introduced in version 1.0.6f. + Further revisions to pngtest.c and files in the wince subdirectory. + +Version 1.0.8beta4 [July 14, 2000] + Added the files pngbar.png and pngbar.jpg to the distribution. + Added makefile.cygwin, and cygwin support in pngconf.h + Added PNG_NO_ZALLOC_ZERO macro (makes png_zalloc skip zeroing memory) + +Version 1.0.8rc1 [July 16, 2000] + Revised png_debug() macros and statements to eliminate compiler warnings. + +Version 1.0.8 [July 24, 2000] + Added png_flush() in pngwrite.c, after png_write_IEND(). + Updated makefile.hpux to build a shared library. + +Version 1.0.9beta1 [November 10, 2000] + Fixed typo in scripts/makefile.hpux + Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser) + Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser) + Changed "cdrom.com" in documentation to "libpng.org" + Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg). + Changed type of "params" from voidp to png_voidp in png_read|write_png(). + Make sure PNGAPI and PNG_IMPEXP are defined in pngconf.h. + Revised the 3 instances of WRITEFILE in pngtest.c. + Relocated "msvc" and "wince" project subdirectories into "dll" subdirectory. + Updated png.rc in dll/msvc project + Revised makefile.dec to define and use LIBPATH and INCPATH + Increased size of global png_libpng_ver[] array from 12 to 18 chars. + Made global png_libpng_ver[], png_sig[] and png_pass_*[] arrays const. + Removed duplicate png_crc_finish() from png_handle_bKGD() function. + Added a warning when application calls png_read_update_info() multiple times. + Revised makefile.cygwin + Fixed bugs in iCCP support in pngrutil.c and pngwutil.c. + Replaced png_set_empty_plte_permitted() with png_permit_mng_features(). + +Version 1.0.9beta2 [November 19, 2000] + Renamed the "dll" subdirectory "projects". + Added borland project files to "projects" subdirectory. + Set VS_FF_PRERELEASE and VS_FF_PATCHED flags in msvc/png.rc when appropriate. + Add error message in png_set_compression_buffer_size() when malloc fails. + +Version 1.0.9beta3 [November 23, 2000] + Revised PNG_LIBPNG_BUILD_TYPE macro in png.h, used in the msvc project. + Removed the png_flush() in pngwrite.c that crashes some applications + that don't set png_output_flush_fn. + Added makefile.macosx and makefile.aix to scripts directory. + +Version 1.0.9beta4 [December 1, 2000] + Change png_chunk_warning to png_warning in png_check_keyword(). + Increased the first part of msg buffer from 16 to 18 in png_chunk_error(). + +Version 1.0.9beta5 [December 15, 2000] + Added support for filter method 64 (for PNG datastreams embedded in MNG). + +Version 1.0.9beta6 [December 18, 2000] + Revised png_set_filter() to accept filter method 64 when appropriate. + Added new PNG_HAVE_PNG_SIGNATURE bit to png_ptr->mode and use it to + help prevent applications from using MNG features in PNG datastreams. + Added png_permit_mng_features() function. + Revised libpng.3/libpng.txt. Changed "filter type" to "filter method". + +Version 1.0.9rc1 [December 23, 2000] + Revised test for PNG_HAVE_PNG_SIGNATURE in pngrutil.c + Fixed error handling of unknown compression type in png_decompress_chunk(). + In pngconf.h, define __cdecl when _MSC_VER is defined. + +Version 1.0.9beta7 [December 28, 2000] + Changed PNG_TEXT_COMPRESSION_zTXt to PNG_COMPRESSION_TYPE_BASE several places. + Revised memory management in png_set_hIST and png_handle_hIST in a backward + compatible manner. PLTE and tRNS were revised similarly. + Revised the iCCP chunk reader to ignore trailing garbage. + +Version 1.0.9beta8 [January 12, 2001] + Moved pngasmrd.h into pngconf.h. + Improved handling of out-of-spec garbage iCCP chunks generated by PhotoShop. + +Version 1.0.9beta9 [January 15, 2001] + Added png_set_invalid, png_permit_mng_features, and png_mmx_supported to + wince and msvc project module definition files. + Minor revision of makefile.cygwin. + Fixed bug with progressive reading of narrow interlaced images in pngpread.c + +Version 1.0.9beta10 [January 16, 2001] + Do not typedef png_FILE_p in pngconf.h when PNG_NO_STDIO is defined. + Fixed "png_mmx_supported" typo in project definition files. + +Version 1.0.9beta11 [January 19, 2001] + Updated makefile.sgi to make shared library. + Removed png_mmx_support() function and disabled PNG_MNG_FEATURES_SUPPORTED + by default, for the benefit of DLL forward compatibility. These will + be re-enabled in version 1.2.0. + +Version 1.0.9rc2 [January 22, 2001] + Revised cygwin support. + +Version 1.0.9 [January 31, 2001] + Added check of cygwin's ALL_STATIC in pngconf.h + Added "-nommx" parameter to contrib/gregbook/rpng2-win and rpng2-x demos. + +Version 1.0.10beta1 [March 14, 2001] + Revised makefile.dec, makefile.sgi, and makefile.sggcc; added makefile.hpgcc. + Reformatted libpng.3 to eliminate bad line breaks. + Added checks for _mmx_supported in the read_filter_row function of pnggccrd.c + Added prototype for png_mmx_support() near the top of pnggccrd.c + Moved some error checking from png_handle_IHDR to png_set_IHDR. + Added PNG_NO_READ_SUPPORTED and PNG_NO_WRITE_SUPPORTED macros. + Revised png_mmx_support() function in pnggccrd.c + Restored version 1.0.8 PNG_WRITE_EMPTY_PLTE_SUPPORTED behavior in pngwutil.c + Fixed memory leak in contrib/visupng/PngFile.c + Fixed bugs in png_combine_row() in pnggccrd.c and pngvcrd.c (C version) + Added warnings when retrieving or setting gamma=0. + Increased the first part of msg buffer from 16 to 18 in png_chunk_warning(). + +Version 1.0.10rc1 [March 23, 2001] + Changed all instances of memcpy, strcpy, and strlen to png_memcpy, png_strcpy, + and png_strlen. + Revised png_mmx_supported() function in pnggccrd.c to return proper value. + Fixed bug in progressive reading (pngpread.c) with small images (height < 8). + +Version 1.0.10 [March 30, 2001] + Deleted extraneous space (introduced in 1.0.9) from line 42 of makefile.cygwin + Added beos project files (Chris Herborth) + +Version 1.0.11beta1 [April 3, 2001] + Added type casts on several png_malloc() calls (Dimitri Papadapoulos). + Removed a no-longer needed AIX work-around from pngconf.h + Changed several "//" single-line comments to C-style in pnggccrd.c + +Version 1.0.11beta2 [April 11, 2001] + Removed PNGAPI from several functions whose prototypes did not have PNGAPI. + Updated scripts/pngos2.def + +Version 1.0.11beta3 [April 14, 2001] + Added checking the results of many instances of png_malloc() for NULL + +Version 1.0.11beta4 [April 20, 2001] + Undid the changes from version 1.0.11beta3. Added a check for NULL return + from user's malloc_fn(). + Removed some useless type casts of the NULL pointer. + Added makefile.netbsd + +Version 1.0.11 [April 27, 2001] + Revised makefile.netbsd + +Version 1.0.12beta1 [May 14, 2001] + Test for Windows platform in pngconf.h when including malloc.h (Emmanuel Blot) + Updated makefile.cygwin and handling of Cygwin's ALL_STATIC in pngconf.h + Added some never-to-be-executed code in pnggccrd.c to quiet compiler warnings. + Eliminated the png_error about apps using png_read|write_init(). Instead, + libpng will reallocate the png_struct and info_struct if they are too small. + This retains future binary compatibility for old applications written for + libpng-0.88 and earlier. + +Version 1.2.0beta1 [May 6, 2001] + Bumped DLLNUM to 2. + Re-enabled PNG_MNG_FEATURES_SUPPORTED and enabled PNG_ASSEMBLER_CODE_SUPPORTED + by default. + Added runtime selection of MMX features. + Added png_set_strip_error_numbers function and related macros. + +Version 1.2.0beta2 [May 7, 2001] + Finished merging 1.2.0beta1 with version 1.0.11 + Added a check for attempts to read or write PLTE in grayscale PNG datastreams. + +Version 1.2.0beta3 [May 17, 2001] + Enabled user memory function by default. + Modified png_create_struct so it passes user mem_ptr to user memory allocator. + Increased png_mng_features flag from png_byte to png_uint_32. + Bumped shared-library (so-number) and dll-number to 3. + +Version 1.2.0beta4 [June 23, 2001] + Check for missing profile length field in iCCP chunk and free chunk_data + in case of truncated iCCP chunk. + Bumped shared-library number to 3 in makefile.sgi and makefile.sggcc + Bumped dll-number from 2 to 3 in makefile.cygwin + Revised contrib/gregbook/rpng*-x.c to avoid a memory leak and to exit cleanly + if user attempts to run it on an 8-bit display. + Updated contrib/gregbook + Use png_malloc instead of png_zalloc to allocate palette in pngset.c + Updated makefile.ibmc + Added some typecasts to eliminate gcc 3.0 warnings. Changed prototypes + of png_write_oFFS width and height from png_uint_32 to png_int_32. + Updated example.c + Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c + +Version 1.2.0beta5 [August 8, 2001] + Revised contrib/gregbook + Revised makefile.gcmmx + Revised pnggccrd.c to conditionally compile some thread-unsafe code only + when PNG_THREAD_UNSAFE_OK is defined. + Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with + value exceeding 2^bit_depth-1 + Revised makefile.sgi and makefile.sggcc + Replaced calls to fprintf(stderr,...) with png_warning() in pnggccrd.c + Removed restriction that do_invert_mono only operate on 1-bit opaque files + +Version 1.2.0 [September 1, 2001] + Changed a png_warning() to png_debug() in pnggccrd.c + Fixed contrib/gregbook/rpng-x.c, rpng2-x.c to avoid crash with XFreeGC(). + +Version 1.2.1beta1 [October 19, 2001] + Revised makefile.std in contrib/pngminus + Include background_1 in png_struct regardless of gamma support. + Revised makefile.netbsd and makefile.macosx, added makefile.darwin. + Revised example.c to provide more details about using row_callback(). + +Version 1.2.1beta2 [October 25, 2001] + Added type cast to each NULL appearing in a function call, except for + WINCE functions. + Added makefile.so9. + +Version 1.2.1beta3 [October 27, 2001] + Removed type casts from all NULLs. + Simplified png_create_struct_2(). + +Version 1.2.1beta4 [November 7, 2001] + Revised png_create_info_struct() and png_creat_struct_2(). + Added error message if png_write_info() was omitted. + Type cast NULLs appearing in function calls when _NO_PROTO or + PNG_TYPECAST_NULL is defined. + +Version 1.2.1rc1 [November 24, 2001] + Type cast NULLs appearing in function calls except when PNG_NO_TYPECAST_NULL + is defined. + Changed typecast of "size" argument to png_size_t in pngmem.c calls to + the user malloc_fn, to agree with the prototype in png.h + Added a pop/push operation to pnggccrd.c, to preserve Eflag (Maxim Sobolev) + Updated makefile.sgi to recognize LIBPATH and INCPATH. + Updated various makefiles so "make clean" does not remove previous major + version of the shared library. + +Version 1.2.1rc2 [December 4, 2001] + Always allocate 256-entry internal palette, hist, and trans arrays, to + avoid out-of-bounds memory reference caused by invalid PNG datastreams. + Added a check for prefix_length > data_length in iCCP chunk handler. + +Version 1.2.1 [December 7, 2001] + None. + +Version 1.2.2beta1 [February 22, 2002] + Fixed a bug with reading the length of iCCP profiles (Larry Reeves). + Revised makefile.linux, makefile.gcmmx, and makefile.sgi to generate + libpng.a, libpng12.so (not libpng.so.3), and libpng12/png.h + Revised makefile.darwin to remove "-undefined suppress" option. + Added checks for gamma and chromaticity values over 21474.83, which exceed + the limit for PNG unsigned 32-bit integers when encoded. + Revised calls to png_create_read_struct() and png_create_write_struct() + for simpler debugging. + Revised png_zalloc() so zlib handles errors (uses PNG_FLAG_MALLOC_NULL_MEM_OK) + +Version 1.2.2beta2 [February 23, 2002] + Check chunk_length and idat_size for invalid (over PNG_MAX_UINT) lengths. + Check for invalid image dimensions in png_get_IHDR. + Added missing "fi;" in the install target of the SGI makefiles. + Added install-static to all makefiles that make shared libraries. + Always do gamma compensation when image is partially transparent. + +Version 1.2.2beta3 [March 7, 2002] + Compute background.gray and background_1.gray even when color_type is RGB + in case image gets reduced to gray later. + Modified shared-library makefiles to install pkgconfig/libpngNN.pc. + Export (with PNGAPI) png_zalloc, png_zfree, and png_handle_as_unknown + Removed unused png_write_destroy_info prototype from png.h + Eliminated incorrect use of width_mmx from pnggccrd.c in pixel_bytes == 8 case + Added install-shared target to all makefiles that make shared libraries. + Stopped a double free of palette, hist, and trans when not using free_me. + Added makefile.32sunu for Sun Ultra 32 and makefile.64sunu for Sun Ultra 64. + +Version 1.2.2beta4 [March 8, 2002] + Compute background.gray and background_1.gray even when color_type is RGB + in case image gets reduced to gray later (Jason Summers). + Relocated a misplaced /bin/rm in the "install-shared" makefile targets + Added PNG_1_0_X macro which can be used to build a 1.0.x-compatible library. + +Version 1.2.2beta5 [March 26, 2002] + Added missing PNGAPI to several function definitions. + Check for invalid bit_depth or color_type in png_get_IHDR(), and + check for missing PLTE or IHDR in png_push_read_chunk() (Matthias Clasen). + Revised iTXt support to accept NULL for lang and lang_key. + Compute gamma for color components of background even when color_type is gray. + Changed "()" to "{}" in scripts/libpng.pc.in. + Revised makefiles to put png.h and pngconf.h only in $prefix/include/libpngNN + Revised makefiles to make symlink to libpng.so.NN in addition to libpngNN.so + +Version 1.2.2beta6 [March 31, 2002] + +Version 1.0.13beta1 [March 31, 2002] + Prevent png_zalloc() from trying to memset memory that it failed to acquire. + Add typecasts of PNG_MAX_UINT in pngset_cHRM_fixed() (Matt Holgate). + Ensure that the right function (user or default) is used to free the + png_struct after an error in png_create_read_struct_2(). + +Version 1.2.2rc1 [April 7, 2002] + +Version 1.0.13rc1 [April 7, 2002] + Save the ebx register in pnggccrd.c (Sami Farin) + Add "mem_ptr = png_ptr->mem_ptr" in png_destroy_write_struct() (Paul Gardner). + Updated makefiles to put headers in include/libpng and remove old include/*.h. + +Version 1.2.2 [April 15, 2002] + +Version 1.0.13 [April 15, 2002] + Revised description of png_set_filter() in libpng.3/libpng.txt. + Revised makefile.netbsd and added makefile.neNNbsd and makefile.freebsd + +Version 1.0.13patch01 [April 17, 2002] + +Version 1.2.2patch01 [April 17, 2002] + Changed ${PNGMAJ}.${PNGVER} bug to ${PNGVER} in makefile.sgi and + makefile.sggcc + Fixed VER -> PNGVER typo in makefile.macosx and added install-static to + install + Added install: target to makefile.32sunu and makefile.64sunu + +Version 1.0.13patch03 [April 18, 2002] + +Version 1.2.2patch03 [April 18, 2002] + Revised 15 makefiles to link libpng.a to libpngNN.a and the include libpng + subdirectory to libpngNN subdirectory without the full pathname. + Moved generation of libpng.pc from "install" to "all" in 15 makefiles. + +Version 1.2.3rc1 [April 28, 2002] + Added install-man target to 15 makefiles (Dimitri Papadopolous-Orfanos). + Added $(DESTDIR) feature to 24 makefiles (Tim Mooney) + Fixed bug with $prefix, should be $(prefix) in makefile.hpux. + Updated cygwin-specific portion of pngconf.h and revised makefile.cygwin + Added a link from libpngNN.pc to libpng.pc in 15 makefiles. + Added links from include/libpngNN/*.h to include/*.h in 24 makefiles. + Revised makefile.darwin to make relative links without full pathname. + Added setjmp() at the end of png_create_*_struct_2() in case user forgets + to put one in their application. + Restored png_zalloc() and png_zfree() prototypes to version 1.2.1 and + removed them from module definition files. + +Version 1.2.3rc2 [May 1, 2002] + Fixed bug in reporting number of channels in pngget.c and pngset.c, + that was introduced in version 1.2.2beta5. + Exported png_zalloc(), png_zfree(), png_default_read(), png_default_write(), + png_default_flush(), and png_push_fill_buffer() and included them in + module definition files. + Added "libpng.pc" dependency to the "install-shared" target in 15 makefiles. + +Version 1.2.3rc3 [May 1, 2002] + Revised prototype for png_default_flush() + Remove old libpng.pc and libpngNN.pc before installing new ones. + +Version 1.2.3rc4 [May 2, 2002] + Typos in *.def files (png_default_read|write -> png_default_read|write_data) + In makefiles, changed rm libpng.NN.pc to rm libpngNN.pc + Added libpng-config and libpngNN-config and modified makefiles to install + them. + Changed $(MANPATH) to $(DESTDIR)$(MANPATH) in makefiles + Added "Win32 DLL VB" configuration to projects/msvc/libpng.dsp + +Version 1.2.3rc5 [May 11, 2002] + Changed "error" and "message" in prototypes to "error_message" and + "warning_message" to avoid namespace conflict. + Revised 15 makefiles to build libpng-config from libpng-config-*.in + Once more restored png_zalloc and png_zfree to regular nonexported form. + Restored png_default_read|write_data, png_default_flush, png_read_fill_buffer + to nonexported form, but with PNGAPI, and removed them from module def + files. + +Version 1.2.3rc6 [May 14, 2002] + Removed "PNGAPI" from png_zalloc() and png_zfree() in png.c + Changed "Gz" to "Gd" in projects/msvc/libpng.dsp and zlib.dsp. + Removed leftover libpng-config "sed" script from four makefiles. + Revised libpng-config creating script in 16 makefiles. + +Version 1.2.3 [May 22, 2002] + Revised libpng-config target in makefile.cygwin. + Removed description of png_set_mem_fn() from documentation. + Revised makefile.freebsd. + Minor cosmetic changes to 15 makefiles, e.g., $(DI) = $(DESTDIR)/$(INCDIR). + Revised projects/msvc/README.txt + Changed -lpng to -lpngNN in LDFLAGS in several makefiles. + +Version 1.2.4beta1 [May 24, 2002] + Added libpng.pc and libpng-config to "all:" target in 16 makefiles. + Fixed bug in 16 makefiles: $(DESTDIR)/$(LIBPATH) to $(DESTDIR)$(LIBPATH) + Added missing "\" before closing double quote in makefile.gcmmx. + Plugged various memory leaks; added png_malloc_warn() and png_set_text_2() + functions. + +Version 1.2.4beta2 [June 25, 2002] + Plugged memory leak of png_ptr->current_text (Matt Holgate). + Check for buffer overflow before reading CRC in pngpread.c (Warwick Allison) + Added -soname to the loader flags in makefile.dec, makefile.sgi, and + makefile.sggcc. + Added "test-installed" target to makefile.linux, makefile.gcmmx, + makefile.sgi, and makefile.sggcc. + +Version 1.2.4beta3 [June 28, 2002] + Plugged memory leak of row_buf in pngtest.c when there is a png_error(). + Detect buffer overflow in pngpread.c when IDAT is corrupted with extra data. + Added "test-installed" target to makefile.32sunu, makefile.64sunu, + makefile.beos, makefile.darwin, makefile.dec, makefile.macosx, + makefile.solaris, makefile.hpux, makefile.hpgcc, and makefile.so9. + +Version 1.2.4rc1 and 1.0.14rc1 [July 2, 2002] + Added "test-installed" target to makefile.cygwin and makefile.sco. + Revised pnggccrd.c to be able to back out version 1.0.x via PNG_1_0_X macro. + +Version 1.2.4 and 1.0.14 [July 8, 2002] + Changed png_warning() to png_error() when width is too large to process. + +Version 1.2.4patch01 [July 20, 2002] + Revised makefile.cygwin to use DLL number 12 instead of 13. + +Version 1.2.5beta1 [August 6, 2002] + Added code to contrib/gregbook/readpng2.c to ignore unused chunks. + Replaced toucan.png in contrib/gregbook (it has been corrupt since 1.0.11) + Removed some stray *.o files from contrib/gregbook. + Changed png_error() to png_warning() about "Too much data" in pngpread.c + and about "Extra compressed data" in pngrutil.c. + Prevent png_ptr->pass from exceeding 7 in png_push_finish_row(). + Updated makefile.hpgcc + Updated png.c and pnggccrd.c handling of return from png_mmx_support() + +Version 1.2.5beta2 [August 15, 2002] + Only issue png_warning() about "Too much data" in pngpread.c when avail_in + is nonzero. + Updated makefiles to install a separate libpng.so.3 with its own rpath. + +Version 1.2.5rc1 and 1.0.15rc1 [August 24, 2002] + Revised makefiles to not remove previous minor versions of shared libraries. + +Version 1.2.5rc2 and 1.0.15rc2 [September 16, 2002] + Revised 13 makefiles to remove "-lz" and "-L$(ZLIBLIB)", etc., from shared + library loader directive. + Added missing "$OBJSDLL" line to makefile.gcmmx. + Added missing "; fi" to makefile.32sunu. + +Version 1.2.5rc3 and 1.0.15rc3 [September 18, 2002] + Revised libpng-config script. + +Version 1.2.5 and 1.0.15 [October 3, 2002] + Revised makefile.macosx, makefile.darwin, makefile.hpgcc, and makefile.hpux, + and makefile.aix. + Relocated two misplaced PNGAPI lines in pngtest.c + +Version 1.2.6beta1 [October 22, 2002] + Commented out warning about uninitialized mmx_support in pnggccrd.c. + Changed "IBMCPP__" flag to "__IBMCPP__" in pngconf.h. + Relocated two more misplaced PNGAPI lines in pngtest.c + Fixed memory overrun bug in png_do_read_filler() with 16-bit datastreams, + introduced in version 1.0.2. + Revised makefile.macosx, makefile.dec, makefile.aix, and makefile.32sunu. + +Version 1.2.6beta2 [November 1, 2002] + Added libpng-config "--ldopts" output. + Added "AR=ar" and "ARFLAGS=rc" and changed "ar rc" to "$(AR) $(ARFLAGS)" + in makefiles. + +Version 1.2.6beta3 [July 18, 2004] + Reverted makefile changes from version 1.2.6beta2 and some of the changes + from version 1.2.6beta1; these will be postponed until version 1.2.7. + Version 1.2.6 is going to be a simple bugfix release. + Changed the one instance of "ln -sf" to "ln -f -s" in each Sun makefile. + Fixed potential overrun in pngerror.c by using strncpy instead of memcpy. + Added "#!/bin/sh" at the top of configure, for recognition of the + 'x' flag under Cygwin (Cosmin). + Optimized vacuous tests that silence compiler warnings, in png.c (Cosmin). + Added support for PNG_USER_CONFIG, in pngconf.h (Cosmin). + Fixed the special memory handler for Borland C under DOS, in pngmem.c + (Cosmin). + Removed some spurious assignments in pngrutil.c (Cosmin). + Replaced 65536 with 65536L, and 0xffff with 0xffffL, to silence warnings + on 16-bit platforms (Cosmin). + Enclosed shift op expressions in parentheses, to silence warnings (Cosmin). + Used proper type png_fixed_point, to avoid problems on 16-bit platforms, + in png_handle_sRGB() (Cosmin). + Added compression_type to png_struct, and optimized the window size + inside the deflate stream (Cosmin). + Fixed definition of isnonalpha(), in pngerror.c and pngrutil.c (Cosmin). + Fixed handling of unknown chunks that come after IDAT (Cosmin). + Allowed png_error() and png_warning() to work even if png_ptr == NULL + (Cosmin). + Replaced row_info->rowbytes with row_bytes in png_write_find_filter() + (Cosmin). + Fixed definition of PNG_LIBPNG_VER_DLLNUM (Simon-Pierre). + Used PNG_LIBPNG_VER and PNG_LIBPNG_VER_STRING instead of the hardcoded + values in png.c (Simon-Pierre, Cosmin). + Initialized png_libpng_ver[] with PNG_LIBPNG_VER_STRING (Simon-Pierre). + Replaced PNG_LIBPNG_VER_MAJOR with PNG_LIBPNG_VER_DLLNUM in png.rc + (Simon-Pierre). + Moved the definition of PNG_HEADER_VERSION_STRING near the definitions + of the other PNG_LIBPNG_VER_... symbols in png.h (Cosmin). + Relocated #ifndef PNGAPI guards in pngconf.h (Simon-Pierre, Cosmin). + Updated scripts/makefile.vc(a)win32 (Cosmin). + Updated the MSVC project (Simon-Pierre, Cosmin). + Updated the Borland C++ Builder project (Cosmin). + Avoided access to asm_flags in pngvcrd.c, if PNG_1_0_X is defined (Cosmin). + Commented out warning about uninitialized mmx_support in pngvcrd.c (Cosmin). + Removed scripts/makefile.bd32 and scripts/pngdef.pas (Cosmin). + Added extra guard around inclusion of Turbo C memory headers, in pngconf.h + (Cosmin). + Renamed projects/msvc/ to projects/visualc6/, and projects/borland/ to + projects/cbuilder5/ (Cosmin). + Moved projects/visualc6/png32ms.def to scripts/pngw32.def, + and projects/visualc6/png.rc to scripts/pngw32.rc (Cosmin). + Added projects/visualc6/pngtest.dsp; removed contrib/msvctest/ (Cosmin). + Changed line endings to DOS style in cbuilder5 and visualc6 files, even + in the tar.* distributions (Cosmin). + Updated contrib/visupng/VisualPng.dsp (Cosmin). + Updated contrib/visupng/cexcept.h to version 2.0.0 (Cosmin). + Added a separate distribution with "configure" and supporting files (Junichi). + +Version 1.2.6beta4 [July 28, 2004] + Added user ability to change png_size_t via a PNG_SIZE_T macro. + Added png_sizeof() and png_convert_size() functions. + Added PNG_SIZE_MAX (maximum value of a png_size_t variable. + Added check in png_malloc_default() for (size_t)size != (png_uint_32)size + which would indicate an overflow. + Changed sPLT failure action from png_error to png_warning and abandon chunk. + Changed sCAL and iCCP failures from png_error to png_warning and abandon. + Added png_get_uint_31(png_ptr, buf) function. + Added PNG_UINT_32_MAX macro. + Renamed PNG_MAX_UINT to PNG_UINT_31_MAX. + Made png_zalloc() issue a png_warning and return NULL on potential + overflow. + Turn on PNG_NO_ZALLOC_ZERO by default in version 1.2.x + Revised "clobber list" in pnggccrd.c so it will compile under gcc-3.4. + Revised Borland portion of png_malloc() to return NULL or issue + png_error() according to setting of PNG_FLAG_MALLOC_NULL_MEM_OK. + Added PNG_NO_SEQUENTIAL_READ_SUPPORTED macro to conditionally remove + sequential read support. + Added some "#if PNG_WRITE_SUPPORTED" blocks. + Added #ifdef to remove some redundancy in png_malloc_default(). + Use png_malloc instead of png_zalloc to allocate the pallete. + +Version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] + Fixed buffer overflow vulnerability in png_handle_tRNS() + Fixed integer arithmetic overflow vulnerability in png_read_png(). + Fixed some harmless bugs in png_handle_sBIT, etc, that would cause + duplicate chunk types to go undetected. + Fixed some timestamps in the -config version + Rearranged order of processing of color types in png_handle_tRNS(). + Added ROWBYTES macro to calculate rowbytes without integer overflow. + Updated makefile.darwin and removed makefile.macosx from scripts directory. + Imposed default one million column, one-million row limits on the image + dimensions, and added png_set_user_limits() function to override them. + Revised use of PNG_SET_USER_LIMITS_SUPPORTED macro. + Fixed wrong cast of returns from png_get_user_width|height_max(). + Changed some "keep the compiler happy" from empty statements to returns, + Revised libpng.txt to remove 1.2.x stuff from the 1.0.x distribution + +Version 1.0.16rc2 and 1.2.6rc2 [August 7, 2004] + Revised makefile.darwin and makefile.solaris. Removed makefile.macosx. + Revised pngtest's png_debug_malloc() to use png_malloc() instead of + png_malloc_default() which is not supposed to be exported. + Fixed off-by-one error in one of the conversions to PNG_ROWBYTES() in + pngpread.c. Bug was introduced in 1.2.6rc1. + Fixed bug in RGB to RGBX transformation introduced in 1.2.6rc1. + Fixed old bug in RGB to Gray transformation. + Fixed problem with 64-bit compilers by casting arguments to abs() + to png_int_32. + Changed "ln -sf" to "ln -f -s" in three makefiles (solaris, sco, so9). + Changed "HANDLE_CHUNK_*" to "PNG_HANDLE_CHUNK_*" (Cosmin) + Added "-@/bin/rm -f $(DL)/$(LIBNAME).so.$(PNGMAJ)" to 15 *NIX makefiles. + Added code to update the row_info->colortype in png_do_read_filler() (MSB). + +Version 1.0.16rc3 and 1.2.6rc3 [August 9, 2004] + Eliminated use of "abs()" in testing cHRM and gAMA values, to avoid + trouble with some 64-bit compilers. Created PNG_OUT_OF_RANGE() macro. + Revised documentation of png_set_keep_unknown_chunks(). + Check handle_as_unknown status in pngpread.c, as in pngread.c previously. + Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_INTERNAL section of png.h + Added "rim" definitions for CONST4 and CONST6 in pnggccrd.c + +Version 1.0.16rc4 and 1.2.6rc4 [August 10, 2004] + Fixed mistake in pngtest.c introduced in 1.2.6rc2 (declaration of + "pinfo" was out of place). + +Version 1.0.16rc5 and 1.2.6rc5 [August 10, 2004] + Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_ASSEMBLER_CODE_SUPPORTED + section of png.h where they were inadvertently placed in version rc3. + +Version 1.2.6 and 1.0.16 [August 15, 2004] + Revised pngtest so memory allocation testing is only done when PNG_DEBUG==1. + +Version 1.2.7beta1 [August 26, 2004] + Removed unused pngasmrd.h file. + Removed references to uu.net for archived files. Added references to + PNG Spec (second edition) and the PNG ISO/IEC Standard. + Added "test-dd" target in 15 makefiles, to run pngtest in DESTDIR. + Fixed bug with "optimized window size" in the IDAT datastream, that + causes libpng to write PNG files with incorrect zlib header bytes. + +Version 1.2.7beta2 [August 28, 2004] + Fixed bug with sCAL chunk and big-endian machines (David Munro). + Undid new code added in 1.2.6rc2 to update the color_type in + png_set_filler(). + Added png_set_add_alpha() that updates color type. + +Version 1.0.17rc1 and 1.2.7rc1 [September 4, 2004] + Revised png_set_strip_filler() to not remove alpha if color_type has alpha. + +Version 1.2.7 and 1.0.17 [September 12, 2004] + Added makefile.hp64 + Changed projects/msvc/png32ms.def to scripts/png32ms.def in makefile.cygwin + +Version 1.2.8beta1 [November 1, 2004] + Fixed bug in png_text_compress() that would fail to complete a large block. + Fixed bug, introduced in libpng-1.2.7, that overruns a buffer during + strip alpha operation in png_do_strip_filler(). + Added PNG_1_2_X definition in pngconf.h + Use #ifdef to comment out png_info_init in png.c and png_read_init in + pngread.c (as of 1.3.0) + +Version 1.2.8beta2 [November 2, 2004] + Reduce color_type to a nonalpha type after strip alpha operation in + png_do_strip_filler(). + +Version 1.2.8beta3 [November 3, 2004] + Revised definitions of PNG_MAX_UINT_32, PNG_MAX_SIZE, and PNG_MAXSUM + +Version 1.2.8beta4 [November 12, 2004] + Fixed (again) definition of PNG_LIBPNG_VER_DLLNUM in png.h (Cosmin). + Added PNG_LIBPNG_BUILD_PRIVATE in png.h (Cosmin). + Set png_ptr->zstream.data_type to Z_BINARY, to avoid unnecessary detection + of data type in deflate (Cosmin). + Deprecated but continue to support SPECIALBUILD and PRIVATEBUILD in favor of + PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. + +Version 1.2.8beta5 [November 20, 2004] + Use png_ptr->flags instead of png_ptr->transformations to pass + PNG_STRIP_ALPHA info to png_do_strip_filler(), to preserve ABI + compatibility. + Revised handling of SPECIALBUILD, PRIVATEBUILD, + PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. + +Version 1.2.8rc1 [November 24, 2004] + Moved handling of BUILD macros from pngconf.h to png.h + Added definition of PNG_LIBPNG_BASE_TYPE in png.h, inadvertently + omitted from beta5. + Revised scripts/pngw32.rc + Despammed mailing addresses by masking "@" with "at". + Inadvertently installed a supposedly faster test version of pngrutil.c + +Version 1.2.8rc2 [November 26, 2004] + Added two missing "\" in png.h + Change tests in pngread.c and pngpread.c to + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +Version 1.2.8rc3 [November 28, 2004] + Reverted pngrutil.c to version libpng-1.2.8beta5. + Added scripts/makefile.elf with supporting code in pngconf.h for symbol + versioning (John Bowler). + +Version 1.2.8rc4 [November 29, 2004] + Added projects/visualc7 (Simon-pierre). + +Version 1.2.8rc5 [November 29, 2004] + Fixed new typo in scripts/pngw32.rc + +Version 1.2.8 [December 3, 2004] + Removed projects/visualc7, added projects/visualc71. + +Version 1.2.9beta1 [February 21, 2006] + Initialized some structure members in pngwutil.c to avoid gcc-4.0.0 complaints + Revised man page and libpng.txt to make it clear that one should not call + png_read_end or png_write_end after png_read_png or png_write_png. + Updated references to png-mng-implement mailing list. + Fixed an incorrect typecast in pngrutil.c + Added PNG_NO_READ_SUPPORTED conditional for making a write-only library. + Added PNG_NO_WRITE_INTERLACING_SUPPORTED conditional. + Optimized alpha-inversion loops in pngwtran.c + Moved test for nonzero gamma outside of png_build_gamma_table() in pngrtran.c + Make sure num_trans is <= 256 before copying data in png_set_tRNS(). + Make sure num_palette is <= 256 before copying data in png_set_PLTE(). + Interchanged order of write_swap_alpha and write_invert_alpha transforms. + Added parentheses in the definition of PNG_LIBPNG_BUILD_TYPE (Cosmin). + Optimized zlib window flag (CINFO) in contrib/pngsuite/*.png (Cosmin). + Updated scripts/makefile.bc32 for Borland C++ 5.6 (Cosmin). + Exported png_get_uint_32, png_save_uint_32, png_get_uint_16, png_save_uint_16, + png_get_int_32, png_save_int_32, png_get_uint_31 (Cosmin). + Added type cast (png_byte) in png_write_sCAL() (Cosmin). + Fixed scripts/makefile.cygwin (Christian Biesinger, Cosmin). + Default iTXt support was inadvertently enabled. + +Version 1.2.9beta2 [February 21, 2006] + Check for png_rgb_to_gray and png_gray_to_rgb read transformations before + checking for png_read_dither in pngrtran.c + Revised checking of chromaticity limits to accommodate extended RGB + colorspace (John Denker). + Changed line endings in some of the project files to CRLF, even in the + "Unix" tar distributions (Cosmin). + Made png_get_int_32 and png_save_int_32 always available (Cosmin). + Updated scripts/pngos2.def, scripts/pngw32.def and projects/wince/png32ce.def + with the newly exported functions. + Eliminated distributions without the "configure" script. + Updated INSTALL instructions. + +Version 1.2.9beta3 [February 24, 2006] + Fixed CRCRLF line endings in contrib/visupng/VisualPng.dsp + Made libpng.pc respect EXEC_PREFIX (D. P. Kreil, J. Bowler) + Removed reference to pngasmrd.h from Makefile.am + Renamed CHANGES to ChangeLog. + Renamed LICENSE to COPYING. + Renamed ANNOUNCE to NEWS. + Created AUTHORS file. + +Version 1.2.9beta4 [March 3, 2006] + Changed definition of PKGCONFIG from $prefix/lib to $libdir in configure.ac + Reverted to filenames LICENSE and ANNOUNCE; removed AUTHORS and COPYING. + Removed newline from the end of some error and warning messages. + Removed test for sqrt() from configure.ac and configure. + Made swap tables in pngtrans.c PNG_CONST (Carlo Bramix). + Disabled default iTXt support that was inadvertently enabled in + libpng-1.2.9beta1. + Added "OS2" to list of systems that don't need underscores, in pnggccrd.c + Removed libpng version and date from *.c files. + +Version 1.2.9beta5 [March 4, 2006] + Removed trailing blanks from source files. + Put version and date of latest change in each source file, and changed + copyright year accordingly. + More cleanup of configure.ac, Makefile.am, and associated scripts. + Restored scripts/makefile.elf which was inadvertently deleted. + +Version 1.2.9beta6 [March 6, 2006] + Fixed typo (RELEASE) in configuration files. + +Version 1.2.9beta7 [March 7, 2006] + Removed libpng.vers and libpng.sym from libpng12_la_SOURCES in Makefile.am + Fixed inconsistent #ifdef's around png_sig_bytes() and png_set_sCAL_s() + in png.h. + Updated makefile.elf as suggested by debian. + Made cosmetic changes to some makefiles, adding LN_SF and other macros. + Made some makefiles accept "exec_prefix". + +Version 1.2.9beta8 [March 9, 2006] + Fixed some "#if defined (..." which should be "#if defined(..." + Bug introduced in libpng-1.2.8. + Fixed inconsistency in definition of png_default_read_data() + Restored blank that was lost from makefile.sggcc "clean" target in beta7. + Revised calculation of "current" and "major" for irix in ltmain.sh + Changed "mkdir" to "MKDIR_P" in some makefiles. + Separated PNG_EXPAND and PNG_EXPAND_tRNS. + Added png_set_expand_gray_1_2_4_to_8() and deprecated + png_set_gray_1_2_4_to_8() which also expands tRNS to alpha. + +Version 1.2.9beta9 [March 10, 2006] + Include "config.h" in pngconf.h when available. + Added some checks for NULL png_ptr or NULL info_ptr (timeless) + +Version 1.2.9beta10 [March 20, 2006] + Removed extra CR from contrib/visualpng/VisualPng.dsw (Cosmin) + Made pnggccrd.c PIC-compliant (Christian Aichinger). + Added makefile.mingw (Wolfgang Glas). + Revised pngconf.h MMX checking. + +Version 1.2.9beta11 [March 22, 2006] + Fixed out-of-order declaration in pngwrite.c that was introduced in beta9 + Simplified some makefiles by using LIBSO, LIBSOMAJ, and LIBSOVER macros. + +Version 1.2.9rc1 [March 31, 2006] + Defined PNG_USER_PRIVATEBUILD when including "pngusr.h" (Cosmin). + Removed nonsensical assertion check from pngtest.c (Cosmin). + +Version 1.2.9 [April 14, 2006] + Revised makefile.beos and added "none" selector in ltmain.sh + +Version 1.2.10beta1 [April 15, 2006] + Renamed "config.h" to "png_conf.h" and revised Makefile.am to add + -DPNG_BUILDING_LIBPNG to compile directive, and modified pngconf.h + to include png_conf.h only when PNG_BUILDING_LIBPNG is defined. + +Version 1.2.10beta2 [April 15, 2006] + Manually updated Makefile.in and configure. Changed png_conf.h.in + back to config.h. + +Version 1.2.10beta3 [April 15, 2006] + Change png_conf.h back to config.h in pngconf.h. + +Version 1.2.10beta4 [April 16, 2006] + Change PNG_BUILDING_LIBPNG to PNG_CONFIGURE_LIBPNG in config/Makefile*. + +Version 1.2.10beta5 [April 16, 2006] + Added a configure check for compiling assembler code in pnggccrd.c + +Version 1.2.10beta6 [April 17, 2006] + Revised the configure check for pnggccrd.c + Moved -DPNG_CONFIGURE_LIBPNG into @LIBPNG_DEFINES@ + Added @LIBPNG_DEFINES@ to arguments when building libpng.sym + +Version 1.2.10beta7 [April 18, 2006] + Change "exec_prefix=$prefix" to "exec_prefix=$(prefix)" in makefiles. + +Version 1.2.10rc1 [April 19, 2006] + Ensure pngconf.h doesn't define both PNG_USE_PNGGCCRD and PNG_USE_PNGVCRD + Fixed "LN_FS" typo in makefile.sco and makefile.solaris. + +Version 1.2.10rc2 [April 20, 2006] + Added a backslash between -DPNG_CONFIGURE_LIBPNG and -DPNG_NO_ASSEMBLER_CODE + in configure.ac and configure + Made the configure warning about versioned symbols less arrogant. + +Version 1.2.10rc3 [April 21, 2006] + Added a note in libpng.txt that png_set_sig_bytes(8) can be used when + writing an embedded PNG without the 8-byte signature. + Revised makefiles and configure to avoid making links to libpng.so.* + +Version 1.2.10 [April 23, 2006] + Reverted configure to "rc2" state. + +Version 1.2.11beta1 [May 31, 2006] + scripts/libpng.pc.in contained "configure" style version info and would + not work with makefiles. + The shared-library makefiles were linking to libpng.so.0 instead of + libpng.so.3 compatibility as the library. + +Version 1.2.11beta2 [June 2, 2006] + Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + Fixed bug in example.c (png_set_palette_rgb -> png_set_palette_to_rgb) + +Version 1.2.11beta3 [June 5, 2006] + Prepended "#! /bin/sh" to ltmail.sh and contrib/pngminus/*.sh (Cosmin). + Removed the accidental leftover Makefile.in~ (Cosmin). + Avoided potential buffer overflow and optimized buffer in + png_write_sCAL(), png_write_sCAL_s() (Cosmin). + Removed the include directories and libraries from CFLAGS and LDFLAGS + in scripts/makefile.gcc (Nelson A. de Oliveira, Cosmin). + +Version 1.2.11beta4 [June 6, 2006] + Allow zero-length IDAT chunks after the entire zlib datastream, but not + after another intervening chunk type. + +Version 1.0.19rc1, 1.2.11rc1 [June 13, 2006] + Deleted extraneous square brackets from [config.h] in configure.ac + +Version 1.0.19rc2, 1.2.11rc2 [June 14, 2006] + Added prototypes for PNG_INCH_CONVERSIONS functions to png.h + Revised INSTALL and autogen.sh + Fixed typo in several makefiles (-W1 should be -Wl) + Added typedef for png_int_32 and png_uint_32 on 64-bit systems. + +Version 1.0.19rc3, 1.2.11rc3 [June 15, 2006] + Removed the new typedefs for 64-bit systems (delay until version 1.4.0) + Added one zero element to png_gamma_shift[] array in pngrtran.c to avoid + reading out of bounds. + +Version 1.0.19rc4, 1.2.11rc4 [June 15, 2006] + Really removed the new typedefs for 64-bit systems. + +Version 1.0.19rc5, 1.2.11rc5 [June 22, 2006] + Removed png_sig_bytes entry from scripts/pngw32.def + +Version 1.0.19, 1.2.11 [June 26, 2006] + None. + +Version 1.0.20, 1.2.12 [June 27, 2006] + Really increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + +Version 1.2.13beta1 [October 2, 2006] + Removed AC_FUNC_MALLOC from configure.ac + Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h + Change "logical" to "bitwise" throughout documentation. + Detect and fix attempt to write wrong iCCP profile length. + +Version 1.0.21, 1.2.13 [November 14, 2006] + Fix potential buffer overflow in sPLT chunk handler. + Fix Makefile.am to not try to link to noexistent files. + Check all exported functions for NULL png_ptr. + +Version 1.2.14beta1 [November 17, 2006] + Relocated three misplaced tests for NULL png_ptr. + Built Makefile.in with automake-1.9.6 instead of 1.9.2. + Build configure with autoconf-2.60 instead of 2.59 + +Version 1.2.14beta2 [November 17, 2006] + Added some typecasts in png_zalloc(). + +Version 1.2.14rc1 [November 20, 2006] + Changed "strtod" to "png_strtod" in pngrutil.c + +Version 1.0.22, 1.2.14 [November 27, 2006] + Added missing "$(srcdir)" in Makefile.am and Makefile.in + +Version 1.2.15beta1 [December 3, 2006] + Generated configure with autoconf-2.61 instead of 2.60 + Revised configure.ac to update libpng.pc and libpng-config. + +Version 1.2.15beta2 [December 3, 2006] + Always export MMX asm functions, just stubs if not building pnggccrd.c + +Version 1.2.15beta3 [December 4, 2006] + Add "png_bytep" typecast to profile while calculating length in pngwutil.c + +Version 1.2.15beta4 [December 7, 2006] + Added scripts/CMakeLists.txt + Changed PNG_NO_ASSEMBLER_CODE to PNG_NO_MMX_CODE in scripts, like 1.4.0beta + +Version 1.2.15beta5 [December 7, 2006] + Changed some instances of PNG_ASSEMBLER_* to PNG_MMX_* in pnggccrd.c + Revised scripts/CMakeLists.txt + +Version 1.2.15beta6 [December 13, 2006] + Revised scripts/CMakeLists.txt and configure.ac + +Version 1.2.15rc1 [December 18, 2006] + Revised scripts/CMakeLists.txt + +Version 1.2.15rc2 [December 21, 2006] + Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. + Added scripts/makefile.nommx + +Version 1.2.15rc3 [December 25, 2006] + Fixed shared library numbering error that was introduced in 1.2.15beta6. + +Version 1.2.15rc4 [December 27, 2006] + Fixed handling of rgb_to_gray when png_ptr->color.gray isn't set. + +Version 1.2.15rc5 [December 31, 2006] + Revised handling of rgb_to_gray. + +Version 1.2.15 [January 5, 2007] + Added some (unsigned long) typecasts in pngtest.c to avoid printing errors. + +Version 1.2.16beta1 [January 6, 2007] + Fix bugs in makefile.nommx + +Version 1.2.16beta2 [January 16, 2007] + Revised scripts/CMakeLists.txt + +Version 1.2.16 [January 31, 2007] + No changes. + +Version 1.2.17beta1 [March 6, 2007] + Revised scripts/CMakeLists.txt to install both shared and static libraries. + Deleted a redundant line from pngset.c. + +Version 1.2.17beta2 [April 26, 2007] + Relocated misplaced test for png_ptr == NULL in pngpread.c + Change "==" to "&" for testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN + flags. + Changed remaining instances of PNG_ASSEMBLER_* to PNG_MMX_* + Added pngerror() when write_IHDR fails in deflateInit2(). + Added "const" to some array declarations. + Mention examples of libpng usage in the libpng*.txt and libpng.3 documents. + +Version 1.2.17rc1 [May 4, 2007] + No changes. + +Version 1.2.17rc2 [May 8, 2007] + Moved several PNG_HAVE_* macros out of PNG_INTERNAL because applications + calling set_unknown_chunk_location() need them. + Changed transformation flag from PNG_EXPAND_tRNS to PNG_EXPAND in + png_set_expand_gray_1_2_4_to_8(). + Added png_ptr->unknown_chunk to hold working unknown chunk data, so it + can be free'ed in case of error. Revised unknown chunk handling in + pngrutil.c and pngpread.c to use this structure. + +Version 1.2.17rc3 [May 8, 2007] + Revised symbol-handling in configure script. + +Version 1.2.17rc4 [May 10, 2007] + Revised unknown chunk handling to avoid storing unknown critical chunks. + +Version 1.0.25 [May 15, 2007] +Version 1.2.17 [May 15, 2007] + Added "png_ptr->num_trans=0" before error return in png_handle_tRNS, + to eliminate a vulnerability (CVE-2007-2445, CERT VU#684664) + +Version 1.0.26 [May 15, 2007] +Version 1.2.18 [May 15, 2007] + Reverted the libpng-1.2.17rc3 change to symbol-handling in configure script + +Version 1.2.19beta1 [May 18, 2007] + Changed "const static" to "static PNG_CONST" everywhere, mostly undoing + change of libpng-1.2.17beta2. Changed other "const" to "PNG_CONST" + Changed some handling of unused parameters, to avoid compiler warnings. + "if (unused == NULL) return;" becomes "unused = unused". + +Version 1.2.19beta2 [May 18, 2007] + Only use the valid bits of tRNS value in png_do_expand() (Brian Cartier) + +Version 1.2.19beta3 [May 19, 2007] + Add some "png_byte" typecasts in png_check_keyword() and write new_key + instead of key in zTXt chunk (Kevin Ryde). + +Version 1.2.19beta4 [May 21, 2007] + Add png_snprintf() function and use it in place of sprint() for improved + defense against buffer overflows. + +Version 1.2.19beta5 [May 21, 2007] + Fixed png_handle_tRNS() to only use the valid bits of tRNS value. + Changed handling of more unused parameters, to avoid compiler warnings. + Removed some PNG_CONST in pngwutil.c to avoid compiler warnings. + +Version 1.2.19beta6 [May 22, 2007] + Added some #ifdef PNG_MMX_CODE_SUPPORTED where needed in pngvcrd.c + Added a special "_MSC_VER" case that defines png_snprintf to _snprintf + +Version 1.2.19beta7 [May 22, 2007] + Squelched png_squelch_warnings() in pnggccrd.c and added + an #ifdef PNG_MMX_CODE_SUPPORTED block around the declarations that caused + the warnings that png_squelch_warnings was squelching. + +Version 1.2.19beta8 [May 22, 2007] + Removed __MMX__ from test in pngconf.h. + +Version 1.2.19beta9 [May 23, 2007] + Made png_squelch_warnings() available via PNG_SQUELCH_WARNINGS macro. + Revised png_squelch_warnings() so it might work. + Updated makefile.sgcc and makefile.solaris; added makefile.solaris-x86. + +Version 1.2.19beta10 [May 24, 2007] + Resquelched png_squelch_warnings(), use "__attribute__((used))" instead. + +Version 1.4.0beta1 [April 20, 2006] + Enabled iTXt support (changes png_struct, thus requires so-number change). + Cleaned up PNG_ASSEMBLER_CODE_SUPPORTED vs PNG_MMX_CODE_SUPPORTED + Eliminated PNG_1_0_X and PNG_1_2_X macros. + Removed deprecated functions png_read_init, png_write_init, png_info_init, + png_permit_empty_plte, png_set_gray_1_2_4_to_8, png_check_sig, and + removed the deprecated macro PNG_MAX_UINT. + Moved "PNG_INTERNAL" parts of png.h and pngconf.h into pngintrn.h + Removed many WIN32_WCE #ifdefs (Cosmin). + Reduced dependency on C-runtime library when on Windows (Simon-Pierre) + Replaced sprintf() with png_sprintf() (Simon-Pierre) + +Version 1.4.0beta2 [April 20, 2006] + Revised makefiles and configure to avoid making links to libpng.so.* + Moved some leftover MMX-related defines from pngconf.h to pngintrn.h + Updated scripts/pngos2.def, pngw32.def, and projects/wince/png32ce.def + +Version 1.4.0beta3 [May 10, 2006] + Updated scripts/pngw32.def to comment out MMX functions. + Added PNG_NO_GET_INT_32 and PNG_NO_SAVE_INT_32 macros. + Scripts/libpng.pc.in contained "configure" style version info and would + not work with makefiles. + Revised pngconf.h and added pngconf.h.in, so makefiles and configure can + pass defines to libpng and applications. + +Version 1.4.0beta4 [May 11, 2006] + Revised configure.ac, Makefile.am, and many of the makefiles to write + their defines in pngconf.h. + +Version 1.4.0beta5 [May 15, 2006] + Added a missing semicolon in Makefile.am and Makefile.in + Deleted extraneous square brackets from configure.ac + +Version 1.4.0beta6 [June 2, 2006] + Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + Changed sonum from 0 to 1. + Removed unused prototype for png_check_sig() from png.h + +Version 1.4.0beta7 [June 16, 2006] + Exported png_write_sig (Cosmin). + Optimized buffer in png_handle_cHRM() (Cosmin). + Set pHYs = 2835 x 2835 pixels per meter, and added + sCAL = 0.352778e-3 x 0.352778e-3 meters, in pngtest.png (Cosmin). + Added png_set_benign_errors(), png_benign_error(), png_chunk_benign_error(). + Added typedef for png_int_32 and png_uint_32 on 64-bit systems. + Added "(unsigned long)" typecast on png_uint_32 variables in printf lists. + +Version 1.4.0beta8 [June 22, 2006] + Added demonstration of user chunk support in pngtest.c, to support the + public sTER chunk and a private vpAg chunk. + +Version 1.4.0beta9 [July 3, 2006] + Removed ordinals from scripts/pngw32.def and removed png_info_int and + png_set_gray_1_2_4_to_8 entries. + Inline call of png_get_uint_32() in png_get_uint_31(). + Use png_get_uint_31() to get vpAg width and height in pngtest.c + Removed WINCE and Netware projects. + Removed standalone Y2KINFO file. + +Version 1.4.0beta10 [July 12, 2006] + Eliminated automatic copy of pngconf.h to pngconf.h.in from configure and + some makefiles, because it was not working reliably. Instead, distribute + pngconf.h.in along with pngconf.h and cause configure and some of the + makefiles to update pngconf.h from pngconf.h.in. + Added pngconf.h to DEPENDENCIES in Makefile.am + +Version 1.4.0beta11 [August 19, 2006] + Removed AC_FUNC_MALLOC from configure.ac. + Added a warning when writing iCCP profile with mismatched profile length. + Patched pnggccrd.c to assemble on x86_64 platforms. + Moved chunk header reading into a separate function png_read_chunk_header() + in pngrutil.c. The chunk header (len+sig) is now serialized in a single + operation (Cosmin). + Implemented support for I/O states. Added png_ptr member io_state, and + functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + (Cosmin). + Added png_get_io_chunk_name and png_get_io_state to scripts/*.def (Cosmin). + Renamed scripts/pngw32.* to scripts/pngwin.* (Cosmin). + Removed the include directories and libraries from CFLAGS and LDFLAGS + in scripts/makefile.gcc (Cosmin). + Used png_save_uint_32() to set vpAg width and height in pngtest.c (Cosmin). + Cast to proper type when getting/setting vpAg units in pngtest.c (Cosmin). + Added pngintrn.h to the Visual C++ projects (Cosmin). + Removed scripts/list (Cosmin). + Updated copyright year in scripts/pngwin.def (Cosmin). + Removed PNG_TYPECAST_NULL and used standard NULL consistently (Cosmin). + Disallowed the user to redefine png_size_t, and enforced a consistent use + of png_size_t across libpng (Cosmin). + Changed the type of png_ptr->rowbytes, PNG_ROWBYTES() and friends + to png_size_t (Cosmin). + Removed png_convert_size() and replaced png_sizeof with sizeof (Cosmin). + Removed some unnecessary type casts (Cosmin). + Changed prototype of png_get_compression_buffer_size() and + png_set_compression_buffer_size() to work with png_size_t instead of + png_uint_32 (Cosmin). + Removed png_memcpy_check() and png_memset_check() (Cosmin). + Fixed a typo (png_byte --> png_bytep) in libpng.3 and libpng.txt (Cosmin). + Clarified that png_zalloc() does not clear the allocated memory, + and png_zalloc() and png_zfree() cannot be PNGAPI (Cosmin). + Renamed png_mem_size_t to png_alloc_size_t, fixed its definition in + pngconf.h, and used it in all memory allocation functions (Cosmin). + Renamed pngintrn.h to pngpriv.h, added a comment at the top of the file + mentioning that the symbols declared in that file are private, and + updated the scripts and the Visual C++ projects accordingly (Cosmin). + Removed circular references between pngconf.h and pngconf.h.in in + scripts/makefile.vc*win32 (Cosmin). + Removing trailing '.' from the warning and error messages (Cosmin). + Added pngdefs.h that is built by makefile or configure, instead of + pngconf.h.in (Glenn). + Detect and fix attempt to write wrong iCCP profile length. + +Version 1.4.0beta12 [October 19, 2006] + Changed "logical" to "bitwise" in the documentation. + Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h + Add a typecast to stifle compiler warning in pngrutil.c + +Version 1.4.0beta13 [November 10, 2006] + Fix potential buffer overflow in sPLT chunk handler. + Fix Makefile.am to not try to link to noexistent files. + +Version 1.4.0beta14 [November 15, 2006] + Check all exported functions for NULL png_ptr. + +Version 1.4.0beta15 [November 17, 2006] + Relocated two misplaced tests for NULL png_ptr. + Built Makefile.in with automake-1.9.6 instead of 1.9.2. + Build configure with autoconf-2.60 instead of 2.59 + Add "install: all" in Makefile.am so "configure; make install" will work. + +Version 1.4.0beta16 [November 17, 2006] + Added a typecast in png_zalloc(). + +Version 1.4.0beta17 [December 4, 2006] + Changed "new_key[79] = '\0';" to "(*new_key)[79] = '\0';" in pngwutil.c + Add "png_bytep" typecast to profile while calculating length in pngwutil.c + +Version 1.4.0beta18 [December 7, 2006] + Added scripts/CMakeLists.txt + +Version 1.4.0beta19 [May 16, 2007] + Revised scripts/CMakeLists.txt + Rebuilt configure and Makefile.in with newer tools. + Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. + Added scripts/makefile.nommx + +Version 1.4.0beta20 [July 9, 2008] + Moved several PNG_HAVE_* macros from pngpriv.h to png.h because applications + calling set_unknown_chunk_location() need them. + Moved several macro definitions from pngpriv.h to pngconf.h + Merge with changes to the 1.2.X branch, as of 1.2.30beta04. + Deleted all use of the MMX assembler code and Intel-licensed optimizations. + Revised makefile.mingw + +Version 1.4.0beta21 [July 21, 2008] + Moved local array "chunkdata" from pngrutil.c to the png_struct, so + it will be freed by png_read_destroy() in case of a read error (Kurt + Christensen). + +Version 1.4.0beta22 [July 21, 2008] + Change "purpose" and "buffer" to png_ptr->chunkdata to avoid memory leaking. + +Version 1.4.0beta23 [July 22, 2008] + Change "chunkdata = NULL" to "png_ptr->chunkdata = NULL" several places in + png_decompress_chunk(). + +Version 1.4.0beta24 [July 25, 2008] + Change all remaining "chunkdata" to "png_ptr->chunkdata" in + png_decompress_chunk(), and remove "chunkdata" from parameter list. + Put a call to png_check_chunk_name() in png_read_chunk_header(). + Revised png_check_chunk_name() to reject a name with a lowercase 3rd byte. + Removed two calls to png_check_chunk_name() occuring later in the process. + Define PNG_NO_ERROR_NUMBERS by default in pngconf.h + +Version 1.4.0beta25 [July 30, 2008] + Added a call to png_check_chunk_name() in pngpread.c + Reverted png_check_chunk_name() to accept a name with a lowercase 3rd byte. + Added png_push_have_buffer() function to pngpread.c + Eliminated PNG_BIG_ENDIAN_SUPPORTED and associated png_get_* macros. + Made inline expansion of png_get_*() optional with PNG_USE_READ_MACROS. + Eliminated all PNG_USELESS_TESTS and PNG_CORRECT_PALETTE_SUPPORTED code. + Synced contrib directory and configure files with libpng-1.2.30beta06. + Eliminated no-longer-used pngdefs.h (but it's still built in the makefiles) + Relocated a misplaced "#endif /* PNG_NO_WRITE_FILTER */" in pngwutil.c + +Version 1.4.0beta26 [August 4, 2008] + Removed png_push_have_buffer() function in pngpread.c. It increased the + compiled library size slightly. + Changed "-Wall" to "-W -Wall" in the CFLAGS in all makefiles (Cosmin Truta) + Declared png_ptr "volatile" in pngread.c and pngwrite.c to avoid warnings. + Updated contrib/visupng/cexcept.h to version 2.0.1 + Added PNG_LITERAL_CHARACTER macros for #, [, and ]. + +Version 1.4.0beta27 [August 5, 2008] + Revised usage of PNG_LITERAL_SHARP in pngerror.c. + Moved newline character from individual png_debug messages into the + png_debug macros. + Allow user to #define their own png_debug, png_debug1, and png_debug2. + +Version 1.4.0beta28 [August 5, 2008] + Revised usage of PNG_LITERAL_SHARP in pngerror.c. + Added PNG_STRING_NEWLINE macro + +Version 1.4.0beta29 [August 9, 2008] + Revised usage of PNG_STRING_NEWLINE to work on non-ISO compilers. + Added PNG_STRING_COPYRIGHT macro. + Added non-ISO versions of png_debug macros. + +Version 1.4.0beta30 [August 14, 2008] + Added premultiplied alpha feature (Volker Wiendl). + +Version 1.4.0beta31 [August 18, 2008] + Moved png_set_premultiply_alpha from pngtrans.c to pngrtran.c + Removed extra crc check at the end of png_handle_cHRM(). Bug introduced + in libpng-1.4.0beta20. + +Version 1.4.0beta32 [August 19, 2008] + Added PNG_WRITE_FLUSH_SUPPORTED block around new png_flush() call. + Revised PNG_NO_STDIO version of png_write_flush() + +Version 1.4.0beta33 [August 20, 2008] + Added png_get|set_chunk_cache_max() to limit the total number of sPLT, + text, and unknown chunks that can be stored. + +Version 1.4.0beta34 [September 6, 2008] + Shortened tIME_string to 29 bytes in pngtest.c + Fixed off-by-one error introduced in png_push_read_zTXt() function in + libpng-1.2.30beta04/pngpread.c (Harald van Dijk) + +Version 1.4.0beta35 [October 6, 2008] + Changed "trans_values" to "trans_color". + Changed so-number from 0 to 14. Some OS do not like 0. + Revised makefile.darwin to fix shared library numbering. + Change png_set_gray_1_2_4_to_8() to png_set_expand_gray_1_2_4_to_8() + in example.c (debian bug report) + +Version 1.4.0beta36 [October 25, 2008] + Sync with tEXt vulnerability fix in libpng-1.2.33rc02. + +Version 1.4.0beta37 [November 13, 2008] + Added png_check_cHRM in png.c and moved checking from pngget.c, pngrutil.c, + and pngwrite.c + +Version 1.4.0beta38 [November 22, 2008] + Added check for zero-area RGB cHRM triangle in png_check_cHRM() and + png_check_cHRM_fixed(). + +Version 1.4.0beta39 [November 23, 2008] + Revised png_warning() to write its message on standard output by default + when warning_fn is NULL. + +Version 1.4.0beta40 [November 24, 2008] + Eliminated png_check_cHRM(). Instead, always use png_check_cHRM_fixed(). + In png_check_cHRM_fixed(), ensure white_y is > 0, and removed redundant + check for all-zero coordinates that is detected by the triangle check. + +Version 1.4.0beta41 [November 26, 2008] + Fixed string vs pointer-to-string error in png_check_keyword(). + Rearranged test expressions in png_check_cHRM_fixed() to avoid internal + overflows. + Added PNG_NO_CHECK_cHRM conditional. + +Version 1.4.0beta42, 43 [December 1, 2008] + Merge png_debug with version 1.2.34beta04. + +Version 1.4.0beta44 [December 6, 2008] + Removed redundant check for key==NULL before calling png_check_keyword() + to ensure that new_key gets initialized and removed extra warning + (Merge with version 1.2.34beta05 -- Arvan Pritchard). + +Version 1.4.0beta45 [December 9, 2008] + In png_write_png(), respect the placement of the filler bytes in an earlier + call to png_set_filler() (Jim Barry). + +Version 1.4.0beta46 [December 10, 2008] + Undid previous change and added PNG_TRANSFORM_STRIP_FILLER_BEFORE and + PNG_TRANSFORM_STRIP_FILLER_AFTER conditionals and deprecated + PNG_TRANSFORM_STRIP_FILLER (Jim Barry). + +Version 1.4.0beta47 [December 15, 2008] + Support for dithering was disabled by default, because it has never + been well tested and doesn't work very well. The code has not + been removed, however, and can be enabled by building libpng with + PNG_READ_DITHER_SUPPORTED defined. + +Version 1.4.0beta48 [February 14, 2009] + Added new exported function png_calloc(). + Combined several instances of png_malloc(); png_memset() into png_calloc(). + Removed prototype for png_freeptr() that was added in libpng-1.4.0beta24 + but was never defined. + +Version 1.4.0beta49 [February 28, 2009] + Added png_fileno() macro to pngconf.h, used in pngwio.c + Corrected order of #ifdef's in png_debug definition in png.h + Fixed bug introduced in libpng-1.4.0beta48 with the memset arguments + for pcal_params. + Fixed order of #ifdef directives in the png_debug defines in png.h + (bug introduced in libpng-1.2.34/1.4.0beta29). + Revised comments in png_set_read_fn() and png_set_write_fn(). + +Version 1.4.0beta50 [March 18, 2009] + Use png_calloc() instead of png_malloc() to allocate big_row_buf when + reading an interlaced file, to avoid a possible UMR. + Undid revision of PNG_NO_STDIO version of png_write_flush(). Users + having trouble with fflush() can build with PNG_NO_WRITE_FLUSH defined + or supply their own flush_fn() replacement. + Revised libpng*.txt and png.h documentation about use of png_write_flush() + and png_set_write_fn(). + Removed fflush() from pngtest.c. + Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h + +Version 1.4.0beta51 [March 21, 2009] + Removed new png_fileno() macro from pngconf.h . + +Version 1.4.0beta52 [March 27, 2009] + Relocated png_do_chop() ahead of building gamma tables in pngrtran.c + This avoids building 16-bit gamma tables unnecessarily. + Removed fflush() from pngtest.c. + Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h + Added a section on differences between 1.0.x and 1.2.x to libpng.3/libpng.txt + +Version 1.4.0beta53 [April 1, 2009] + Removed some remaining MMX macros from pngpriv.h + Fixed potential memory leak of "new_name" in png_write_iCCP() (Ralph Giles) + +Version 1.4.0beta54 [April 13, 2009] + Added "ifndef PNG_SKIP_SETJMP_CHECK" block in pngconf.h to allow + application code writers to bypass the check for multiple inclusion + of setjmp.h when they know that it is safe to ignore the situation. + Eliminated internal use of setjmp() in pngread.c and pngwrite.c + Reordered ancillary chunks in pngtest.png to be the same as what + pngtest now produces, and made some cosmetic changes to pngtest output. + Eliminated deprecated png_read_init_3() and png_write_init_3() functions. + +Version 1.4.0beta55 [April 15, 2009] + Simplified error handling in pngread.c and pngwrite.c by putting + the new png_read_cleanup() and png_write_cleanup() functions inline. + +Version 1.4.0beta56 [April 25, 2009] + Renamed "user_chunk_data" to "my_user_chunk_data" in pngtest.c to suppress + "shadowed declaration" warning from gcc-4.3.3. + Renamed "gamma" to "png_gamma" in pngset.c to avoid "shadowed declaration" + warning about a global "gamma" variable in math.h on some platforms. + +Version 1.4.0beta57 [May 2, 2009] + Removed prototype for png_freeptr() that was added in libpng-1.4.0beta24 + but was never defined (again). + Rebuilt configure scripts with autoconf-2.63 instead of 2.62 + Removed pngprefs.h and MMX from makefiles + +Version 1.4.0beta58 [May 14, 2009] + Changed pngw32.def to pngwin.def in makefile.mingw (typo was introduced + in beta57). + Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri) + +Version 1.4.0beta59 [May 15, 2009] + Reformated sources in libpng style (3-space intentation, comment format) + Fixed typo in libpng docs (PNG_FILTER_AVE should be PNG_FILTER_AVG) + Added sections about the git repository and our coding style to the + documentation + Relocated misplaced #endif in pngwrite.c, sCAL chunk handler. + +Version 1.4.0beta60 [May 19, 2009] + Conditionally compile png_read_finish_row() which is not used by + progressive readers. + Added contrib/pngminim/preader to demonstrate building minimal progressive + decoder, based on contrib/gregbook with embedded libpng and zlib. + +Version 1.4.0beta61 [May 20, 2009] + In contrib/pngminim/*, renamed "makefile.std" to "makefile", since there + is only one makefile in those directories, and revised the README files + accordingly. + More reformatting of comments, mostly to capitalize sentences. + +Version 1.4.0beta62 [June 2, 2009] + Added "#define PNG_NO_WRITE_SWAP" to contrib/pngminim/encoder/pngusr.h + and "define PNG_NO_READ_SWAP" to decoder/pngusr.h and preader/pngusr.h + Reformatted several remaining "else statement" into two lines. + Added a section to the libpng documentation about using png_get_io_ptr() + in configure scripts to detect the presence of libpng. + +Version 1.4.0beta63 [June 15, 2009] + Revised libpng*.txt and libpng.3 to mention calling png_set_IHDR() + multiple times and to specify the sample order in the tRNS chunk, + because the ISO PNG specification has a typo in the tRNS table. + Changed several PNG_UNKNOWN_CHUNK_SUPPORTED to + PNG_HANDLE_AS_UNKNOWN_SUPPORTED, to make the png_set_keep mechanism + available for ignoring known chunks even when not saving unknown chunks. + Adopted preference for consistent use of "#ifdef" and "#ifndef" versus + "#if defined()" and "if !defined()" where possible. + +Version 1.4.0beta64 [June 24, 2009] + Eliminated PNG_LEGACY_SUPPORTED code. + Moved the various unknown chunk macro definitions outside of the + PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks. + +Version 1.4.0beta65 [June 26, 2009] + Added a reference to the libpng license in each file. + +Version 1.4.0beta66 [June 27, 2009] + Refer to the libpng license instead of the libpng license in each file. + +Version 1.4.0beta67 [July 6, 2009] + Relocated INVERT_ALPHA within png_read_png() and png_write_png(). + Added high-level API transform PNG_TRANSFORM_GRAY_TO_RGB. + Added an "xcode" project to the projects directory (Alam Arias). + +Version 1.4.0beta68 [July 19, 2009] + Avoid some tests in filter selection in pngwutil.c + +Version 1.4.0beta69 [July 25, 2009] + Simplified the new filter-selection test. This runs faster in the + common "PNG_ALL_FILTERS" and PNG_FILTER_NONE cases. + Removed extraneous declaration from the new call to png_read_gray_to_rgb() + (bug introduced in libpng-1.4.0beta67). + Fixed up xcode project (Alam Arias) + Added a prototype for png_64bit_product() in png.c + +Version 1.4.0beta70 [July 27, 2009] + Avoid a possible NULL dereference in debug build, in png_set_text_2(). + (bug introduced in libpng-0.95, discovered by Evan Rouault) + +Version 1.4.0beta71 [July 29, 2009] + Rebuilt configure scripts with autoconf-2.64. + +Version 1.4.0beta72 [August 1, 2009] + Replaced *.tar.lzma with *.tar.xz in distribution. Get the xz codec + from . + +Version 1.4.0beta73 [August 1, 2009] + Reject attempt to write iCCP chunk with negative embedded profile length + (JD Chen) + +Version 1.4.0beta74 [August 8, 2009] + Changed png_ptr and info_ptr member "trans" to "trans_alpha". + +Version 1.4.0beta75 [August 21, 2009] + Removed an extra png_debug() recently added to png_write_find_filter(). + Fixed incorrect #ifdef in pngset.c regarding unknown chunk support. + +Version 1.4.0beta76 [August 22, 2009] + Moved an incorrectly located test in png_read_row() in pngread.c + +Version 1.4.0beta77 [August 27, 2009] + Removed lpXYZ.tar.bz2 (with CRLF), KNOWNBUG, libpng-x.y.z-KNOWNBUG.txt, + and the "noconfig" files from the distribution. + Moved CMakeLists.txt from scripts into the main libpng directory. + Various bugfixes and improvements to CMakeLists.txt (Philip Lowman) + +Version 1.4.0beta78 [August 31, 2009] + Converted all PNG_NO_* tests to PNG_*_SUPPORTED everywhere except pngconf.h + Eliminated PNG_NO_FREE_ME and PNG_FREE_ME_SUPPORTED macros. + Use png_malloc plus a loop instead of png_calloc() to initialize + row_pointers in png_read_png(). + +Version 1.4.0beta79 [September 1, 2009] + Eliminated PNG_GLOBAL_ARRAYS and PNG_LOCAL_ARRAYS; always use local arrays. + Eliminated PNG_CALLOC_SUPPORTED macro and always provide png_calloc(). + +Version 1.4.0beta80 [September 17, 2009] + Removed scripts/libpng.icc + Changed typecast of filler from png_byte to png_uint_16 in png_set_filler(). + (Dennis Gustafsson) + Fixed typo introduced in beta78 in pngtest.c ("#if def " should be "#ifdef ") + +Version 1.4.0beta81 [September 23, 2009] + Eliminated unused PNG_FLAG_FREE_* defines from pngpriv.h + Expanded TAB characters in pngrtran.c + Removed PNG_CONST from all "PNG_CONST PNG_CHNK" declarations to avoid + compiler complaints about doubly declaring things "const". + Changed all "#if [!]defined(X)" to "if[n]def X" where possible. + Eliminated unused png_ptr->row_buf_size + +Version 1.4.0beta82 [September 25, 2009] + Moved redundant IHDR checking into new png_check_IHDR() in png.c + and report all errors found in the IHDR data. + Eliminated useless call to png_check_cHRM() from pngset.c + +Version 1.4.0beta83 [September 25, 2009] + Revised png_check_IHDR() to eliminate bogus complaint about filter_type. + +Version 1.4.0beta84 [September 30, 2009] + Fixed some inconsistent indentation in pngconf.h + Revised png_check_IHDR() to add a test for width variable less than 32-bit. + +Version 1.4.0beta85 [October 1, 2009] + Revised png_check_IHDR() again, to check info_ptr members instead of + the contents of the returned parameters. + +Version 1.4.0beta86 [October 9, 2009] + Updated the "xcode" project (Alam Arias). + Eliminated a shadowed declaration of "pp" in png_handle_sPLT(). + +Version 1.4.0rc01 [October 19, 2009] + Trivial cosmetic changes. + +Version 1.4.0beta87 [October 30, 2009] + Moved version 1.4.0 back into beta. + +Version 1.4.0beta88 [October 30, 2009] + Revised libpng*.txt section about differences between 1.2.x and 1.4.0 + because most of the new features have now been ported back to 1.2.41 + +Version 1.4.0beta89 [November 1, 2009] + More bugfixes and improvements to CMakeLists.txt (Philip Lowman) + Removed a harmless extra png_set_invert_alpha() from pngwrite.c + Apply png_user_chunk_cache_max within png_decompress_chunk(). + Merged libpng-1.2.41.txt with libpng-1.4.0.txt where appropriate. + +Version 1.4.0beta90 [November 2, 2009] + Removed all remaining WIN32_WCE #ifdefs except those involving the + time.h "tm" structure + +Version 1.4.0beta91 [November 3, 2009] + Updated scripts/pngw32.def and projects/wince/png32ce.def + Copied projects/wince/png32ce.def to the scripts directory. + Added scripts/makefile.wce + Patched ltmain.sh for wince support. + Added PNG_CONVERT_tIME_SUPPORTED macro. + +Version 1.4.0beta92 [November 4, 2009] + Make inclusion of time.h in pngconf.h depend on PNG_CONVERT_tIME_SUPPORTED + Make #define PNG_CONVERT_tIME_SUPPORTED depend on PNG_WRITE_tIME_SUPPORTED + Revised libpng*.txt to describe differences from 1.2.40 to 1.4.0 (instead + of differences from 1.2.41 to 1.4.0) + +Version 1.4.0beta93 [November 7, 2009] + Added PNG_DEPSTRUCT, PNG_DEPRECATED, PNG_USE_RESULT, PNG_NORETURN, and + PNG_ALLOCATED macros to detect deprecated direct access to the + png_struct or info_struct members and other deprecated usage in + applications (John Bowler). + Updated scripts/makefile* to add "-DPNG_CONFIGURE_LIBPNG" to CFLAGS, + to prevent warnings about direct access to png structs by libpng + functions while building libpng. They need to be tested, especially + those using compilers other than gcc. + Updated projects/visualc6 and visualc71 with "/d PNG_CONFIGURE_LIBPNG". + They should work but still need to be updated to remove + references to pnggccrd.c or pngvcrd.c and ASM building. + Added README.txt to the beos, cbuilder5, netware, and xcode projects warning + that they need to be updated, to remove references to pnggccrd.c and + pngvcrd.c and to depend on pngpriv.h + Removed three direct references to read_info_ptr members in pngtest.c + that were detected by the new PNG_DEPSTRUCT macro. + Moved the png_debug macro definitions and the png_read_destroy(), + png_write_destroy() and png_far_to_near() prototypes from png.h + to pngpriv.h (John Bowler) + Moved the synopsis lines for png_read_destroy(), png_write_destroy() + png_debug(), png_debug1(), and png_debug2() from libpng.3 to libpngpf.3. + +Version 1.4.0beta94 [November 9, 2009] + Removed the obsolete, unused pnggccrd.c and pngvcrd.c files. + Updated CMakeLists.txt to add "-DPNG_CONFIGURE_LIBPNG" to the definitions. + Removed dependency of pngtest.o on pngpriv.h in the makefiles. + Only #define PNG_DEPSTRUCT, etc. in pngconf.h if not already defined. + +Version 1.4.0beta95 [November 10, 2009] + Changed png_check_sig() to !png_sig_cmp() in contrib programs. + Added -DPNG_CONFIGURE_LIBPNG to contrib/pngminm/*/makefile + Changed png_check_sig() to !png_sig_cmp() in contrib programs. + Corrected the png_get_IHDR() call in contrib/gregbook/readpng2.c + Changed pngminim/*/gather.sh to stop trying to remove pnggccrd.c and pngvcrd.c + Added dependency on pngpriv.h in contrib/pngminim/*/makefile + +Version 1.4.0beta96 [November 12, 2009] + Renamed scripts/makefile.wce to scripts/makefile.cegcc + Revised Makefile.am to use libpng.sys while building libpng.so + so that only PNG_EXPORT functions are exported. + Removed the deprecated png_check_sig() function/macro. + Removed recently removed function names from scripts/*.def + Revised pngtest.png to put chunks in the same order written by pngtest + (evidently the same change made in libpng-1.0beta54 was lost). + Added PNG_PRIVATE macro definition in pngconf.h for possible future use. + +Version 1.4.0beta97 [November 13, 2009] + Restored pngtest.png to the libpng-1.4.0beta7 version. + Removed projects/beos and netware.txt; no one seems to be supporting them. + Revised Makefile.in + +Version 1.4.0beta98 [November 13, 2009] + Added the "xcode" project to zip distributions, + Fixed a typo in scripts/pngwin.def introduced in beta97. + +Version 1.4.0beta99 [November 14, 2009] + Moved libpng-config.in and libpng.pc-configure.in out of the scripts + directory, to libpng-config.in and libpng-pc.in, respectively, and + modified Makefile.am and configure.ac accordingly. Now "configure" + needs nothing from the "scripts" directory. + Avoid redefining PNG_CONST in pngconf.h + +Version 1.4.0beta100 [November 14, 2009] + Removed ASM builds from projects/visualc6 and projects/visualc71 + Removed scripts/makefile.nommx and makefile.vcawin32 + Revised CMakeLists.txt to account for new location of libpng-config.in + and libpng-pc.in + Updated INSTALL to reflect removal and relocation of files. + +Version 1.4.0beta101 [November 14, 2009] + Restored the binary files (*.jpg, *.png, some project files) that were + accidentally deleted from the zip and 7z distributions when the xcode + project was added. + +Version 1.4.0beta102 [November 18, 2009] + Added libpng-config.in and libpng-pc.in to the zip and 7z distributions. + Fixed a typo in projects/visualc6/pngtest.dsp, introduced in beta100. + Moved descriptions of makefiles and other scripts out of INSTALL into + scripts/README.txt + Updated the copyright year in scripts/pngwin.rc from 2006 to 2009. + +Version 1.4.0beta103 [November 21, 2009] + Removed obsolete comments about ASM from projects/visualc71/README_zlib.txt + Align row_buf on 16-byte boundary in memory. + Restored the PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED guard around the call + to png_flush() after png_write_IEND(). See 1.4.0beta32, 1.4.0beta50 + changes above and 1.2.30, 1.2.30rc01 and rc03 in 1.2.41 CHANGES. Someone + needs this feature. + Make the 'png_jmpbuf' macro expand to a call that records the correct + longjmp function as well as returning a pointer to the setjmp + jmp_buf buffer, and marked direct access to jmpbuf 'deprecated'. + (John Bowler) + +Version 1.4.0beta104 [November 22, 2009] + Removed png_longjmp_ptr from scripts/*.def and libpng.3 + Rebuilt configure scripts with autoconf-2.65 + +Version 1.4.0beta105 [November 25, 2009] + Use fast integer PNG_DIVIDE_BY_255() or PNG_DIVIDE_BY_65535() + to accomplish alpha premultiplication when + PNG_READ_COMPOSITE_NODIV_SUPPORTED is defined. + Changed "/255" to "/255.0" in background calculations to make it clear + that the 255 is used as a double. + +Version 1.4.0beta106 [November 27, 2009] + Removed premultiplied alpha feature. + +Version 1.4.0beta107 [December 4, 2009] + Updated README + Added "#define PNG_NO_PEDANTIC_WARNINGS" in the libpng source files. + Removed "-DPNG_CONFIGURE_LIBPNG" from the makefiles and projects. + Revised scripts/makefile.netbsd, makefile.openbsd, and makefile.sco + to put png.h and pngconf.h in $prefix/include, like the other scripts, + instead of in $prefix/include/libpng. Also revised makefile.sco + to put them in $prefix/include/libpng15 instead of in + $prefix/include/libpng/libpng15. + +Version 1.4.0beta108 [December 11, 2009] + Removed leftover "-DPNG_CONFIGURE_LIBPNG" from contrib/pngminim/*/makefile + Relocated png_do_chop() to its original position in pngrtran.c; the + change in version 1.2.41beta08 caused transparency to be handled wrong + in some 16-bit datastreams (Yusaku Sugai). + +Version 1.4.0beta109 [December 13, 2009] + Added "bit_depth" parameter to the private png_build_gamma_table() function. + Pass bit_depth=8 to png_build_gamma_table() when bit_depth is 16 but the + PNG_16_TO_8 transform has been set, to avoid unnecessary build of 16-bit + tables. + +Version 1.4.0rc02 [December 20, 2009] + Declared png_cleanup_needed "volatile" in pngread.c and pngwrite.c + +Version 1.4.0rc03 [December 22, 2009] + Renamed libpng-pc.in back to libpng.pc.in and revised CMakeLists.txt + (revising the change in 1.4.0beta99) + +Version 1.4.0rc04 [December 25, 2009] + Swapped PNG_UNKNOWN_CHUNKS_SUPPORTED and PNG_HANDLE_AS_UNKNOWN_SUPPORTED + in pngset.c to be consistent with other changes in version 1.2.38. + +Version 1.4.0rc05 [December 25, 2009] + Changed "libpng-pc.in" to "libpng.pc.in" in configure.ac, configure, and + Makefile.in to be consistent with changes in libpng-1.4.0rc03 + +Version 1.4.0rc06 [December 29, 2009] + Reverted the gamma_table changes from libpng-1.4.0beta109. + Fixed some indentation errors. + +Version 1.4.0rc07 [January 1, 2010] + Revised libpng*.txt and libpng.3 about 1.2.x->1.4.x differences. + Use png_calloc() instead of png_malloc(); png_memset() in pngrutil.c + Update copyright year to 2010. + +Version 1.4.0rc08 [January 2, 2010] + Avoid deprecated references to png_ptr-io_ptr and png_ptr->error_ptr + in pngtest.c + +Version 1.4.0 [January 3, 2010] + No changes. + +Version 1.4.1beta01 [January 8, 2010] + Updated CMakeLists.txt for consistent indentation and to avoid an + unclosed if-statement warning (Philip Lowman). + Revised Makefile.am and Makefile.in to remove references to Y2KINFO, + KNOWNBUG, and libpng.la (Robert Schwebel). + Revised the makefiles to install the same files and symbolic + links as configure, except for libpng.la and libpng14.la. + Make png_set|get_compression_buffer_size() available even when + PNG_WRITE_SUPPORTED is not enabled. + Revised Makefile.am and Makefile.in to simplify their maintenance. + Revised scripts/makefile.linux to install a link to libpng14.so.14.1 + +Version 1.4.1beta02 [January 9, 2010] + Revised the rest of the makefiles to install a link to libpng14.so.14.1 + +Version 1.4.1beta03 [January 10, 2010] + Removed png_set_premultiply_alpha() from scripts/*.def + +Version 1.4.1rc01 [January 16, 2010] + No changes. + +Version 1.4.1beta04 [January 23, 2010] + Revised png_decompress_chunk() to improve speed and memory usage when + decoding large chunks. + Added png_set|get_chunk_malloc_max() functions. + +Version 1.4.1beta05 [January 26, 2010] + Relocated "int k" declaration in pngtest.c to minimize its scope. + +Version 1.4.1beta06 [January 28, 2010] + Revised png_decompress_chunk() to use a two-pass method suggested by + John Bowler. + +Version 1.4.1beta07 [February 6, 2010] + Folded some long lines in the source files. + Added defineable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX, + and a PNG_USER_LIMITS_SUPPORTED flag. + Eliminated use of png_ptr->irowbytes and reused the slot in png_ptr as + png_ptr->png_user_chunk_malloc_max. + Revised png_push_save_buffer() to do fewer but larger png_malloc() calls. + +Version 1.4.1beta08 [February 6, 2010] + Minor cleanup and updating of dates and copyright year. + +Version 1.5.0beta01 [February 7, 2010] + Moved declaration of png_struct into private pngstruct.h and png_info + into pnginfo.h + +Version 1.4.1beta09 and 1.5.0beta02 [February 7, 2010] + Reverted to original png_push_save_buffer() code. + +Version 1.4.1beta10 and 1.5.0beta03 [February 8, 2010] + Return allocated "old_buffer" in png_push_save_buffer() before + calling png_error(), to avoid a potential memory leak. + Updated configure script to use SO number 15. + +Version 1.5.0beta04 [February 9, 2010] + Removed malformed "incomplete struct declaration" of png_info from png.h + +Version 1.5.0beta05 [February 12, 2010] + Removed PNG_DEPSTRUCT markup in pngstruct.h and pnginfo.h, and undid the + linewrapping that it entailed. + Revised comments in pngstruct.h and pnginfo.h and added pointers to + the libpng license. + Changed PNG_INTERNAL to PNG_EXPOSE_INTERNAL_STRUCTURES + Removed the cbuilder5 project, which has not been updated to 1.4.0. + +Version 1.4.1beta12 and 1.5.0beta06 [February 14, 2010] + Fixed type declaration of png_get_chunk_malloc_max() in pngget.c (Daisuke + Nishikawa) + +Version 1.5.0beta07 [omitted] + +Version 1.5.0beta08 [February 19, 2010] + Changed #ifdef PNG_NO_STDIO_SUPPORTED to #ifdef PNG_NO_CONSOLE_IO_SUPPORTED + wherever png_snprintf() is used to construct error and warning messages. + Noted in scripts/makefile.mingw that it expects to be run under MSYS. + Removed obsolete unused MMX-querying support from contrib/gregbook + Added exported png_longjmp() function. + Removed the AIX redefinition of jmpbuf in png.h + Added -D_ALLSOURCE in configure.ac, makefile.aix, and CMakeLists.txt + when building on AIX. + +Version 1.5.0beta09 [February 19, 2010] + Removed -D_ALLSOURCE from configure.ac, makefile.aix, and CMakeLists.txt. + Changed the name of png_ptr->jmpbuf to png_ptr->png_jmpbuf in pngstruct.h + +Version 1.5.0beta10 [February 25, 2010] + Removed unused gzio.c from contrib/pngminim gather and makefile scripts + Removed replacement error handlers from contrib/gregbook. Because of + the new png_longjmp() function they are no longer needed. + +Version 1.5.0beta11 [March 6, 2010] + Removed checking for already-included setjmp.h from pngconf.h + Fixed inconsistent indentations and made numerous cosmetic changes. + Revised the "SEE ALSO" style of libpng.3, libpngpf.3, and png.5 + +Version 1.5.0beta12 [March 9, 2010] + Moved "#include png.h" inside pngpriv.h and removed "#include png.h" from + the source files, along with "#define PNG_EXPOSE_INTERNAL_STRUCTURES" + and "#define PNG_NO_PEDANTIC_WARNINGS" (John Bowler). + Created new pngdebug.h and moved debug definitions there. + +Version 1.5.0beta13 [March 10, 2010] + Protect pngstruct.h, pnginfo.h, and pngdebug.h from being included twice. + Revise the "#ifdef" blocks in png_inflate() so it will compile when neither + PNG_USER_CHUNK_MALLOC_MAX nor PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + is defined. + Removed unused png_measure_compressed_chunk() from pngpriv.h and libpngpf.3 + Moved the 'config.h' support from pngconf.h to pngpriv.h + Removed PNGAPI from the png_longjmp_ptr typedef. + Eliminated dependence of pngtest.c on the private pngdebug.h file. + Make all png_debug macros into *unterminated* statements or + expressions (i.e. a trailing ';' must always be added) and correct + the format statements in various png_debug messages. + +Version 1.5.0beta14 [March 14, 2010] + Removed direct access to png_ptr->io_ptr from the Windows code in pngtest.c + Revised Makefile.am to account for recent additions and replacements. + Corrected CE and OS/2 DEF files (scripts/png*def) for symbols removed and + added ordinal numbers to the Windows DEF file and corrected the duplicated + ordinal numbers on CE symbols that are commented out. + Added back in export symbols that can be present in the Windows build but + are disabled by default. + PNG_EXPORT changed to include an 'ordinal' field for DEF file generation. + PNG_CALLBACK added to make callback definitions uniform. PNGAPI split + into PNGCAPI (base C form), PNGAPI (exports) and PNGCBAPI (callbacks), + and appropriate changes made to all files. Cygwin builds re-hinged to + allow procedure call standard changes and to remove the need for the DEF + file (fixes build on Cygwin). + Enabled 'attribute' warnings that are relevant to library APIs and callbacks. + Changed rules for generation of the various symbol files and added a new + rule for a DEF file (which is also added to the distribution). + Updated the symbol file generation to stop it adding spurious spaces + to EOL (coming from preprocessor macro expansion). Added a facility + to join tokens in the output and rewrite *.dfn to use this. + Eliminated scripts/*.def in favor of libpng.def; updated projects/visualc71 + and removed scripts/makefile.cygwin. + Made PNG_BUILD_DLL safe: it can be set whenever a DLL is being built. + Removed the include of sys/types.h - apparently unnecessary now on the + platforms on which it happened (all but Mac OS and RISC OS). + Moved the Mac OS test into pngpriv.h (the only place it is used.) + +Version 1.5.0beta15 [March 17, 2010] + Added symbols.chk target to Makefile.am to validate the symbols in png.h + against the new DEF file scripts/symbols.def. + Changed the default DEF file back to pngwin.def. + Removed makefile.mingw. + Eliminated PNG_NO_EXTERN and PNG_ALL_EXTERN + +Version 1.5.0beta16 [April 1, 2010] + Make png_text_struct independent of PNG_iTXt_SUPPORTED, so that + fields are initialized in all configurations. The READ/WRITE + macros (PNG_(READ|WRITE)_iTXt_SUPPORTED) still function as + before to disable code to actually read or write iTXt chunks + and iTXt_SUPPORTED can be used to detect presence of either + read or write support (but it is probably better to check for + the one actually required - read or write.) + Combined multiple png_warning() calls for a single error. + Restored the macro definition of png_check_sig(). + +Version 1.5.0beta17 [April 17, 2010] + Added some "(long)" typecasts to printf calls in png_handle_cHRM(). + Documented the fact that png_set_dither() was disabled since libpng-1.4.0. + Reenabled png_set_dither() but renamed it to png_set_quantize() to reflect + more accurately what it actually does. At the same time, renamed + the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros to + PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS. + Added some "(long)" typecasts to printf calls in png_handle_cHRM(). + Freeze build-time only configuration in the build. + In all prior versions of libpng most configuration options + controlled by compiler #defines had to be repeated by the + application code that used libpng. This patch changes this + so that compilation options that can only be changed at build + time are frozen in the build. Options that are compiler + dependent (and those that are system dependent) are evaluated + each time - pngconf.h holds these. Options that can be changed + per-file in the application are in png.h. Frozen options are + in the new installed header file pnglibconf.h (John Bowler) + Removed the xcode project because it has not been updated to work + with libpng-1.5.0. + Removed the ability to include optional pngusr.h + +Version 1.5.0beta18 [April 17, 2010] + Restored the ability to include optional pngusr.h + Moved replacements for png_error() and png_warning() from the + contrib/pngminim project to pngerror.c, for use when warnings or + errors are disabled via PNG_NO_WARN or PNG_NO_ERROR_TEXT, to avoid + storing unneeded error/warning text. + Updated contrib/pngminim project to work with the new pnglibconf.h + Added some PNG_NO_* defines to contrib/pngminim/*/pngusr.h to save space. + +Version 1.5.0beta19 [April 24, 2010] + Added PNG_{READ,WRITE}_INT_FUNCTIONS_SUPPORTED. This allows the functions + to read and write ints to be disabled independently of PNG_USE_READ_MACROS, + which allows libpng to be built with the functions even though the default + is to use the macros - this allows applications to choose at app build + time whether or not to use macros (previously impossible because the + functions weren't in the default build.) + Changed Windows calling convention back to __cdecl for API functions. + For Windows/x86 platforms only: + __stdcall is no longer needed for Visual Basic, so libpng-1.5.0 uses + __cdecl throughout (both API functions and callbacks) on Windows/x86 + platforms. + Replaced visualc6 and visualc71 projects with new vstudio project + Relaxed the overly-restrictive permissions of some files. + +Version 1.5.0beta20 [April 24, 2010] + Relaxed more overly-restrictive permissions of some files. + +Version 1.5.0beta21 [April 27, 2010] + Removed some unwanted binary bytes and changed CRLF to NEWLINE in the new + vstudio project files, and some trivial editing of some files in the + scripts directory. + Set PNG_NO_READ_BGR, PNG_NO_IO_STATE, and PNG_NO_TIME_RFC1123 in + contrib/pngminim/decoder/pngusr.h to make a smaller decoder application. + +Version 1.5.0beta22 [April 28, 2010] + Fixed dependencies of GET_INT_32 - it does not require READ_INT_FUNCTIONS + because it has a macro equivalent. + Improved the options.awk script; added an "everything off" option. + Revised contrib/pngminim to use the "everything off" option in pngusr.dfa. + +Version 1.5.0beta23 [April 29, 2010] + Corrected PNG_REMOVED macro to take five arguments. + The macro was documented with two arguments (name,ordinal), however + the symbol checking .dfn files assumed five arguments. The five + argument form seems more useful so it is changed to that. + Corrected PNG_UNKNOWN_CHUNKS_SUPPORTED to PNG_HANDLE_AS_UNKNOWN_SUPPORTED + in gregbook/readpng2.c + Corrected protection of png_get_user_transform_ptr. The API declaration in + png.h is removed if both READ and WRITE USER_TRANSFORM are turned off + but was left defined in pngtrans.c + Added logunsupported=1 to cause pnglibconf.h to document disabled options. + This makes the installed pnglibconf.h more readable but causes no + other change. The intention is that users of libpng will find it + easier to understand if an API they need is missing. + Include png_reset_zstream() in png.c only when PNG_READ_SUPPORTED is defined. + Removed dummy_inflate.c from contrib/pngminim/encoder + Removed contrib/pngminim/*/gather.sh; gathering is now done in the makefile. + +Version 1.5.0beta24 [May 7, 2010] + Use bitwise "&" instead of arithmetic mod in pngrutil.c calculation of the + offset of the png_ptr->rowbuf pointer into png_ptr->big_row_buf. + Added more blank lines for readability. + +Version 1.5.0beta25 [June 18, 2010] + In pngpread.c: png_push_have_row() add check for new_row > height + Removed the now-redundant check for out-of-bounds new_row from example.c + +Version 1.5.0beta26 [June 18, 2010] + In pngpread.c: png_push_process_row() add check for too many rows. + +Version 1.5.0beta27 [June 18, 2010] + Removed the check added in beta25 as it is now redundant. + +Version 1.5.0beta28 [June 20, 2010] + Rewrote png_process_IDAT_data to consistently treat extra data as warnings + and handle end conditions more cleanly. + Removed the new (beta26) check in png_push_process_row(). + +Version 1.5.0beta29 [June 21, 2010] + Revised scripts/options.awk to work on Sunos (but still doesn't work) + Added comment to options.awk and contrib/pngminim/*/makefile to try nawk. + +Version 1.5.0beta30 [June 22, 2010] + Stop memory leak when reading a malformed sCAL chunk. + +Version 1.5.0beta31 [June 26, 2010] + Revised pngpread.c patch of beta28 to avoid an endless loop. + Removed some trailing blanks. + +Version 1.5.0beta32 [June 26, 2010] + Removed leftover scripts/options.patch and scripts/options.rej + +Version 1.5.0beta33 [July 6, 3010] + Made FIXED and FLOATING options consistent in the APIs they enable and + disable. Corrected scripts/options.awk to handle both command line + options and options specified in the .dfa files. + Changed char *msg to PNG_CONST char *msg in pngrutil.c + Make png_set_sRGB_gAMA_and_cHRM set values using either the fixed or + floating point APIs, but not both. + Reversed patch to remove error handler when the jmp_buf is stored in the + main program structure, not the png_struct. + The error handler is needed because the default handler in libpng will + always use the jmp_buf in the library control structure; this is never + set. The gregbook code is a useful example because, even though it + uses setjmp/longjmp, it shows how error handling can be implemented + using control mechanisms not directly supported by libpng. The + technique will work correctly with mechanisms such as Microsoft + Structure Exceptions or C++ exceptions (compiler willing - note that gcc + does not by default support interworking of C and C++ error handling.) + Reverted changes to call png_longjmp in contrib/gregbook where it is not + appropriate. If mainprog->jmpbuf is used by setjmp, then png_longjmp + cannot be used. + Changed "extern PNG_EXPORT" to "PNG_EXPORT" in png.h (Jan Nijtmans) + Changed "extern" to "PNG_EXTERN" in pngpriv.h (except for the 'extern "C" {') + +Version 1.5.0beta34 [July 12, 2010] + Put #ifndef PNG_EXTERN, #endif around the define PNG_EXTERN in pngpriv.h + +Version 1.5.0beta35 [July 24, 2010] + Removed some newly-added TAB characters. + Added -DNO_PNG_SNPRINTF to CFLAGS in scripts/makefile.dj2 + Moved the definition of png_snprintf() outside of the enclosing + #ifdef blocks in pngconf.h + +Version 1.5.0beta36 [July 29, 2010] + Patches by John Bowler: + Fixed point APIs are now supported throughout (no missing APIs). + Internal fixed point arithmetic support exists for all internal floating + point operations. + sCAL validates the floating point strings it is passed. + Safe, albeit rudimentary, Watcom support is provided by PNG_API_RULE==2 + Two new APIs exist to get the number of passes without turning on the + PNG_INTERLACE transform and to get the number of rows in the current + pass. + A new test program, pngvalid.c, validates the gamma code. + Errors in the 16 bit gamma correction (overflows) have been corrected. + cHRM chunk testing is done consistently (previously the floating point + API bypassed it, because the test really didn't work on FP, now the test + is performed on the actual values to be stored in the PNG file so it + works in the FP case too.) + Most floating point APIs now simply call the fixed point APIs after + converting the values to the fixed point form used in the PNG file. + The standard headers no longer include zlib.h, which is currently only + required for pngstruct.h and can therefore be internal. + Revised png_get_int_32 to undo the PNG two's complement representation of + negative numbers. + +Version 1.5.0beta37 [July 30, 2010] + Added a typecast in png_get_int_32() in png.h and pngrutil.h to avoid + a compiler warning. + Replaced oFFs 0,0 with oFFs -10,20 in pngtest.png + +Version 1.5.0beta38 [July 31, 2010] + Implemented remaining "_fixed" functions. + Corrected a number of recently introduced warnings mostly resulting from + safe but uncast assignments to shorter integers. Also added a zlib + VStudio release library project because the latest zlib Official Windows + build does not include such a thing. + Revised png_get_int_16() to be similar to png_get_int_32(). + Restored projects/visualc71. + +Version 1.5.0beta39 [August 2, 2010] + VisualC/GCC warning fixes, VisualC build fixes + The changes include support for function attributes in VC in addition to + those already present in GCC - necessary because without these some + warnings are unavoidable. Fixes include signed/unsigned fixes in + pngvalid and checks with gcc -Wall -Wextra -Wunused. + VC requires function attributes on function definitions as well as + declarations, PNG_FUNCTION has been added to enable this and the + relevant function definitions changed. + +Version 1.5.0beta40 [August 6, 2010] + Correct use of _WINDOWS_ in pngconf.h + Removed png_mem_ #defines; they are no longer used. + Added the sRGB chunk to pngtest.png + +Version 1.5.0beta41 [August 11, 2010] + Added the cHRM chunk to pngtest.png + Don't try to use version-script with cygwin/mingw. + Revised contrib/gregbook to work under cygwin/mingw. + +Version 1.5.0beta42 [August 18, 2010] + Add .dll.a to the list of extensions to be symlinked by Makefile.am (Yaakov) + Made all API functions that have const arguments and constant string + literal pointers declare them (John Bowler). + +Version 1.5.0beta43 [August 20, 2010] + Removed spurious tabs, shorten long lines (no source change) + Also added scripts/chkfmt to validate the format of all the files that can + reasonably be validated (it is suggested to run "make distclean" before + checking, because some machine generated files have long lines.) + Reformatted the CHANGES file to be more consistent throughout. + Made changes to address various issues identified by GCC, mostly + signed/unsigned and shortening problems on assignment but also a few + difficult to optimize (for GCC) loops. + Fixed non-GCC fixed point builds. In png.c a declaration was misplaced + in an earlier update. Fixed to declare the auto variables at the head. + Use cexcept.h in pngvalid.c. + +Version 1.5.0beta44 [August 24, 2010] + Updated CMakeLists.txt to use CMAKE_INSTALL_LIBDIR variable; useful for + installing libpng in /usr/lib64 (Funda Wang). + Revised CMakeLists.txt to put the man pages in share/man/man* not man/man* + Revised CMakeLists.txt to make symlinks instead of copies when installing. + Changed PNG_LIB_NAME from pngNN to libpngNN in CMakeLists.txt (Philip Lowman) + Implemented memory checks within pngvalid + Reformatted/rearranged pngvalid.c to assist use of progressive reader. + Check interlaced images in pngvalid + Clarified pngusr.h comments in pnglibconf.dfa + Simplified the pngvalid error-handling code now that cexcept.h is in place. + Implemented progressive reader in pngvalid.c for standard tests + Implemented progressive read in pngvalid.c gamma tests + Turn on progressive reader in pngvalid.c by default and tidy code. + +Version 1.5.0beta45 [August 26, 2010] + Added an explicit make step to projects/vstudio for pnglibconf.h + Also corrected zlib.vcxproj into which Visual Studio had introduced + what it calls an "authoring error". The change to make pnglibconf.h + simply copies the file; in the future it may actually generate the + file from scripts/pnglibconf.dfa as the other build systems do. + Changed pngvalid to work when floating point APIs are disabled + Renamed the prebuilt scripts/pnglibconf.h to scripts/pnglibconf.h.prebuilt + Supply default values for PNG_USER_PRIVATEBUILD and PNG_USER_DLLFNAME_POSTFIX + in pngpriv.h in case the user neglected to define them in their pngusr.h + +Version 1.5.0beta46 [August 28, 2010] + Added new private header files to libpng_sources in CMakeLists.txt + Added PNG_READ_16BIT, PNG_WRITE_16BIT, and PNG_16BIT options. + Added reference to scripts/pnglibconf.h.prebuilt in the visualc71 project. + +Version 1.5.0beta47 [September 11, 2010] + Fixed a number of problems with 64-bit compilation reported by Visual + Studio 2010 (John Bowler). + +Version 1.5.0beta48 [October 4, 2010] + Updated CMakeLists.txt (Philip Lowman). + Revised autogen.sh to recognize and use $AUTOCONF, $AUTOMAKE, $AUTOHEADER, + $AUTOPOINT, $ACLOCAL and $LIBTOOLIZE + Fixed problem with symbols creation in Makefile.am which was assuming that + all versions of ccp write to standard output by default (Martin Banky). The + bug was introduced in libpng-1.2.9beta5. + Removed unused mkinstalldirs. + +Version 1.5.0beta49 [October 8, 2010] + Undid Makefile.am revision of 1.5.0beta48. + +Version 1.5.0beta50 [October 14, 2010] + Revised Makefile.in to account for mkinstalldirs being removed. + Added some "(unsigned long)" typecasts in printf statements in pngvalid.c. + Suppressed a compiler warning in png_handle_sPLT(). + Check for out-of-range text compression mode in png_set_text(). + +Version 1.5.0beta51 [October 15, 2010] + Changed embedded dates to "(PENDING RELEASE) in beta releases (and future + rc releases) to minimize the difference between releases. + +Version 1.5.0beta52 [October 16, 2010] + Restored some of the embedded dates (in png.h, png.c, documentation, etc.) + +Version 1.5.0beta53 [October 18, 2010] + Updated INSTALL to mention using "make maintainer-clean" and to remove + obsolete statement about a custom ltmain.sh + Disabled "color-tests" by default in Makefile.am so it will work with + automake versions earlier than 1.11.1 + Use document name "libpng-manual.txt" instead of "libpng-.txt" + to simplify version differences. + Removed obsolete remarks about setjmp handling from INSTALL. + Revised and renamed the typedef in png.h and png.c that was designed + to catch library and header mismatch. + +Version 1.5.0beta54 [November 10, 2010] + Require 48 bytes, not 64 bytes, for big_row_buf in overflow checks. + Used a consistent structure for the pngget.c functions. + +Version 1.5.0beta55 [November 21, 2010] + Revised png_get_uint_32, png_get_int_32, png_get_uint_16 (Cosmin) + Moved reading of file signature into png_read_sig (Cosmin) + Fixed atomicity of chunk header serialization (Cosmin) + Added test for io_state in pngtest.c (Cosmin) + Added "#!/bin/sh" at the top of contrib/pngminim/*/gather.sh scripts. + Changes to remove gcc warnings (John Bowler) + Certain optional gcc warning flags resulted in warnings in libpng code. + With these changes only -Wconversion and -Wcast-qual cannot be turned on. + Changes are trivial rearrangements of code. -Wconversion is not possible + for pngrutil.c (because of the widespread use of += et al on variables + smaller than (int) or (unsigned int)) and -Wcast-qual is not possible + with pngwio.c and pngwutil.c because the 'write' callback and zlib + compression both fail to declare their input buffers with 'const'. + +Version 1.5.0beta56 [December 7, 2010] + Added the private PNG_UNUSED() macro definition in pngpriv.h. + Added some commentary about PNG_EXPORT in png.h and pngconf.h + Revised PNG_EXPORT() macro and added PNG_EXPORTA() macro, with the + objective of simplifying and improving the cosmetic appearance of png.h. + Fixed some incorrect "=" macro names in pnglibconf.dfa + Included documentation of changes in 1.5.0 from 1.4.x in libpng-manual.txt + +Version 1.5.0beta57 [December 9, 2010] + Documented the pngvalid gamma error summary with additional comments and + print statements. + Improved missing symbol handling in checksym.awk; symbols missing in both + the old and new files can now be optionally ignored, treated as errors + or warnings. + Removed references to pngvcrd.c and pnggccrd.c from the vstudio project. + Updated "libpng14" to "libpng15" in the visualc71 project. + Enabled the strip16 tests in pngvalid.` + Don't display test results (except PASS/FAIL) when running "make test". + Instead put them in pngtest-log.txt + Added "--with-zprefix=" to configure.ac + Updated the prebuilt configuration files to autoconf version 2.68 + +Version 1.5.0beta58 [December 19, 2010] + Fixed interlace image handling and add test cases (John Bowler) + Fixed the clean rule in Makefile.am to remove pngtest-log.txt + Made minor changes to work around warnings in gcc 3.4 + +Version 1.5.0rc01 [December 27, 2010] + No changes. + +Version 1.5.0rc02 [December 27, 2010] + Eliminated references to the scripts/*.def files in project/visualc71. + +Version 1.5.0rc03 [December 28, 2010] + Eliminated scripts/*.def and revised Makefile.am accordingly + +Version 1.5.0rc04 [December 29, 2010] + Fixed bug in background transformation handling in pngrtran.c (it was + looking for the flag in png_ptr->transformations instead of in + png_ptr->flags) (David Raymond). + +Version 1.5.0rc05 [December 31, 2010] + Fixed typo in a comment in CMakeLists.txt (libpng14 => libpng15) (Cosmin) + +Version 1.5.0rc06 [January 4, 2011] + Changed the new configure option "zprefix=string" to "zlib-prefix=string" + +Version 1.5.0rc07 [January 4, 2011] + Updated copyright year. + +Version 1.5.0 [January 6, 2011] + No changes. + +version 1.5.1beta01 [January 8, 2011] + Added description of png_set_crc_action() to the manual. + Added a note in the manual that the type of the iCCP profile was changed + from png_charpp to png_bytepp in png_get_iCCP(). This change happened + in version 1.5.0beta36 but is not noted in the CHANGES. Similarly, + it was changed from png_charpp to png_const_bytepp in png_set_iCCP(). + Ensure that png_rgb_to_gray ignores palette mapped images, if libpng + internally happens to call it with one. + Fixed a failure to handle palette mapped images correctly. + +Version 1.5.1beta02 [January 14, 2011] + Fixed a bug in handling of interlaced images (bero at arklinux.org). + Updated CMakeLists.txt (Clifford Yapp) + +Version 1.5.1beta03 [January 14, 2011] + Fixed typecasting of some png_debug() statements (Cosmin) + +Version 1.5.1beta04 [January 16, 2011] + Updated documentation of png_set|get_tRNS() (Thomas Klausner). + Mentioned in the documentation that applications must #include "zlib.h" + if they need access to anything in zlib.h, and that a number of + macros such as png_memset() are no longer accessible by applications. + Corrected pngvalid gamma test "sample" function to access all of the color + samples of each pixel, instead of sampling the red channel three times. + Prefixed variable names index, div, exp, gamma with "png_" to avoid "shadow" + warnings, and (mistakenly) changed png_exp() to exp(). + +Version 1.5.1beta05 [January 16, 2011] + Changed variable names png_index, png_div, png_exp, and png_gamma to + char_index, divisor, exp_b10, and gamma_val, respectively, and + changed exp() back to png_exp(). + +Version 1.5.1beta06 [January 20, 2011] + Prevent png_push_crc_skip() from hanging while reading an unknown chunk + or an over-large compressed zTXt chunk with the progressive reader. + Eliminated more GCC "shadow" warnings. + Revised png_fixed() in png.c to avoid compiler warning about reaching the + end without returning anything. + +Version 1.5.1beta07 [January 22, 2011] + In the manual, describe the png_get_IHDR() arguments in the correct order. + Added const_png_structp and const_png_infop types, and used them in + prototypes for most png_get_*() functions. + +Version 1.5.1beta08 [January 23, 2011] + Added png_get_io_chunk_type() and deprecated png_get_io_chunk_name() + Added synopses for the IO_STATE functions and other missing synopses + to the manual. Removed the synopses from libpngpf.3 because they + were out of date and no longer useful. Better information can be + obtained by reading the prototypes and comments in pngpriv.h + Attempted to fix cpp on Solaris with S. Studio 12 cc, fix build + Added a make macro DFNCPP that is a CPP that will accept the tokens in + a .dfn file and adds configure stuff to test for such a CPP. ./configure + should fail if one is not available. + Corrected const_png_ in png.h to png_const_ to avoid polluting the namespace. + Added png_get_current_row_number and png_get_current_pass_number for the + benefit of the user transform callback. + Added png_process_data_pause and png_process_data_skip for the benefit of + progressive readers that need to stop data processing or want to optimize + skipping of unread data (e.g., if the reader marks a chunk to be skipped.) + +Version 1.5.1beta09 [January 24, 2011] + Enhanced pngvalid, corrected an error in gray_to_rgb, corrected doc error. + pngvalid contains tests of transforms, which tests are currently disabled + because they are incompletely tested. gray_to_rgb was failing to expand + the bit depth for smaller bit depth images; this seems to be a long + standing error and resulted, apparently, in invalid output. The + documentation did not accurately describe what libpng really does when + converting RGB to gray. + +Version 1.5.1beta10 [January 27, 2010] + Fixed incorrect examples of callback prototypes in the manual, that were + introduced in libpng-1.0.0. + In addition the order of the png_get_uint macros with respect to the + relevant function definitions has been reversed. This helps the + preprocessing of the symbol files be more robust. Furthermore, the + symbol file preprocessing now uses -DPNG_NO_USE_READ_MACROS even when + the library may actually be built with PNG_USE_READ_MACROS; this stops + the read macros interfering with the symbol file format. + Made the manual, synopses, and function prototypes use the function + argument names file_gamma, int_file_gamma, and srgb_intent consistently. + +Version 1.5.1beta11 [January 28, 2011] + Changed PNG_UNUSED from "param=param;" to "{if(param){}}". + Corrected local variable type in new API png_process_data_skip() + The type was self-evidently incorrect but only causes problems on 64 bit + architectures. + Added transform tests to pngvalid and simplified the arguments. + +Version 1.5.1rc01 [January 29, 2011] + No changes. + +Version 1.5.1rc02 [January 31, 2011] + Added a request in the manual that applications do not use "png_" or + "PNG_" to begin any of their own symbols. + Changed PNG_UNUSED to "(void)param;" and updated the commentary in pngpriv.h + +Version 1.5.1 [February 3, 2011] + No changes. + +Send comments/corrections/commendations to png-mng-implement at lists.sf.net +(subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe) +or to glennrp at users.sourceforge.net + +Glenn R-P +*/ } +#endif diff --git a/contrib/libpng/CMakeLists.txt b/contrib/libpng/CMakeLists.txt new file mode 100644 index 0000000..36a55dc --- /dev/null +++ b/contrib/libpng/CMakeLists.txt @@ -0,0 +1,303 @@ +cmake_minimum_required(VERSION 2.4.4) +set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) + +if(UNIX AND NOT DEFINED CMAKE_BUILD_TYPE) + if(CMAKE_MAJOR_VERSION EQUAL 2 AND CMAKE_MINOR_VERSION EQUAL 4) + # workaround CMake 2.4.x bug + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING + "Choose the type of build, options are: + None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) + Debug + Release + RelWithDebInfo + MinSizeRel.") + else() + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING + "Choose the type of build, options are: + None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) + Debug + Release + RelWithDebInfo + MinSizeRel.") + endif() +endif() + +project(libpng C) +enable_testing() + +# Copyright (C) 2007-2011 Glenn Randers-Pehrson + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +set(PNGLIB_MAJOR 1) +set(PNGLIB_MINOR 5) +set(PNGLIB_RELEASE 1) +set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR}) +set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE}) + +if(NOT WIN32) + find_library(M_LIBRARY + NAMES m + PATHS /usr/lib /usr/local/lib + ) + if(NOT M_LIBRARY) + message(STATUS + "math library 'libm' not found - floating point support disabled") + endif() +else() + # not needed on windows + set(M_LIBRARY "") +endif() + +# COMMAND LINE OPTIONS +if(DEFINED PNG_SHARED) + option(PNG_SHARED "Build shared lib" ${PNG_SHARED}) +else() + option(PNG_SHARED "Build shared lib" ON) +endif() +if(DEFINED PNG_STATIC) + option(PNG_STATIC "Build static lib" ${PNG_STATIC}) +else() + option(PNG_STATIC "Build static lib" ON) +endif() + +if(MINGW) + option(PNG_TESTS "Build pngtest" NO) +else() + option(PNG_TESTS "Build pngtest" YES) +endif() + +option(PNG_NO_CONSOLE_IO "FIXME" YES) +option(PNG_NO_STDIO "FIXME" YES) +option(PNG_DEBUG "Build with debug output" NO) +option(PNGARG "FIXME" YES) +#TODO: +# PNG_CONSOLE_IO_SUPPORTED + +# maybe needs improving, but currently I don't know when we can enable what :) +set(png_asm_tmp "OFF") +if(NOT WIN32) + find_program(uname_executable NAMES uname PATHS /bin /usr/bin /usr/local/bin) + if(uname_executable) + exec_program(${uname_executable} + ARGS --machine OUTPUT_VARIABLE uname_output) + if("uname_output" MATCHES "^.*i[1-9]86.*$") + set(png_asm_tmp "ON") + else("uname_output" MATCHES "^.*i[1-9]86.*$") + set(png_asm_tmp "OFF") + endif("uname_output" MATCHES "^.*i[1-9]86.*$") + endif(uname_executable) +else() + # this env var is normally only set on win64 + set(TEXT "ProgramFiles(x86)") + if("$ENV{${TEXT}}" STREQUAL "") + set(png_asm_tmp "ON") + endif("$ENV{${TEXT}}" STREQUAL "") +endif() + +# SET LIBNAME +set(PNG_LIB_NAME png${PNGLIB_MAJOR}${PNGLIB_MINOR}) + +# to distinguish between debug and release lib +set(CMAKE_DEBUG_POSTFIX "d") + +# Use the prebuilt pnglibconf.h file from the scripts folder +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt + ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# OUR SOURCES +set(libpng_public_hdrs + png.h + pngconf.h + ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h +) +set(libpng_sources + ${libpng_public_hdrs} + pngdebug.h + pnginfo.h + pngpriv.h + pngstruct.h + png.c + pngerror.c + pngget.c + pngmem.c + pngpread.c + pngread.c + pngrio.c + pngrtran.c + pngrutil.c + pngset.c + pngtrans.c + pngwio.c + pngwrite.c + pngwtran.c + pngwutil.c +) +set(pngtest_sources + pngtest.c +) +# SOME NEEDED DEFINITIONS + +add_definitions(-DPNG_CONFIGURE_LIBPNG) + +if(_AIX) + add_definitions(-D_ALL_SOURCE) +endif(_AIX) + +if(MSVC) + add_definitions(-DPNG_NO_MODULEDEF -D_CRT_SECURE_NO_DEPRECATE) +endif(MSVC) + +if(PNG_SHARED OR NOT MSVC) + #if building msvc static this has NOT to be defined + add_definitions(-DZLIB_DLL) +endif() + + +if(PNG_CONSOLE_IO_SUPPORTED) + add_definitions(-DPNG_CONSOLE_IO_SUPPORTED) +endif() + +if(PNG_NO_CONSOLE_IO) + add_definitions(-DPNG_NO_CONSOLE_IO) +endif() + +if(PNG_NO_STDIO) + add_definitions(-DPNG_NO_STDIO) +endif() + +if(PNG_DEBUG) + add_definitions(-DPNG_DEBUG) +endif() + +if(NOT M_LIBRARY AND NOT WIN32) + add_definitions(-DPNG_NO_FLOATING_POINT_SUPPORTED) +endif() + +# NOW BUILD OUR TARGET +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +if(PNG_SHARED) + add_library(${PNG_LIB_NAME} SHARED ${libpng_sources}) + if(MSVC) + # msvc does not append 'lib' - do it here to have consistent name + set_target_properties(${PNG_LIB_NAME} PROPERTIES PREFIX "lib") + set_target_properties(${PNG_LIB_NAME} PROPERTIES IMPORT_PREFIX "lib") + endif() + target_link_libraries(${PNG_LIB_NAME} Zlib::zlib ${M_LIBRARY}) + target_include_directories(${PNG_LIB_NAME} PUBLIC . ${CMAKE_CURRENT_BINARY_DIR}) + add_library(Png::png ALIAS ${PNG_LIB_NAME}) +endif() + +if(PNG_STATIC) +# does not work without changing name + set(PNG_LIB_NAME_STATIC ${PNG_LIB_NAME}_static) + add_library(${PNG_LIB_NAME_STATIC} STATIC ${libpng_sources}) + if(MSVC) + # msvc does not append 'lib' - do it here to have consistent name + set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES PREFIX "lib") + endif() + target_link_libraries(${PNG_LIB_NAME_STATIC} Zlib::zlib ${M_LIBRARY}) + target_include_directories(${PNG_LIB_NAME_STATIC} PUBLIC . ${CMAKE_CURRENT_BINARY_DIR}) + add_library(Png::pngstatic ALIAS ${PNG_LIB_NAME}_static) +endif() + + +if(PNG_SHARED AND WIN32) + set_target_properties(${PNG_LIB_NAME} PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL) +endif() + +if(PNG_TESTS AND PNG_SHARED) + # does not work with msvc due to png_lib_ver issue + add_executable(pngtest ${pngtest_sources}) + target_link_libraries(pngtest ${PNG_LIB_NAME}) + add_test(pngtest ./pngtest ${CMAKE_CURRENT_SOURCE_DIR}/pngtest.png) +endif() + +# +# Set a variable with CMake code which: +# Creates a symlink from src to dest (if possible) or alternatively +# copies if different. +macro(_png_generate_symlink_code CODE SRC DEST) + if(WIN32 AND NOT CYGWIN) + set(_png_gsc_message "Copying ${SRC} to ${DEST} if needed") + set(_png_gsc_operation "copy_if_different") + else() + set(_png_gsc_message "Symlinking ${SRC} to ${DEST}") + set(_png_gsc_operation "create_symlink") + endif() + + set(${CODE} " + message(STATUS \"${_png_gsc_message}\") + execute_process(COMMAND \${CMAKE_COMMAND} -E ${_png_gsc_operation} + \"${SRC}\" \"${DEST}\") + ") +endmacro() + +# CREATE PKGCONFIG FILES +# we use the same files like ./configure, so we have to set its vars +if(NOT DEFINED CMAKE_INSTALL_LIBDIR) + set(CMAKE_INSTALL_LIBDIR lib) +endif(NOT DEFINED CMAKE_INSTALL_LIBDIR) +set(prefix ${CMAKE_INSTALL_PREFIX}) +set(exec_prefix ${CMAKE_INSTALL_PREFIX}) +set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) +set(includedir ${CMAKE_INSTALL_PREFIX}/include) +set(LIBS "-lz -lm") +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc @ONLY) +_png_generate_symlink_code(PNG_PC_INSTALL_CODE + ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc + ${CMAKE_CURRENT_BINARY_DIR}/libpng.pc) + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng-config.in + ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config @ONLY) +_png_generate_symlink_code(PNG_CONFIG_INSTALL_CODE + ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config + ${CMAKE_CURRENT_BINARY_DIR}/libpng-config) + +# SET UP LINKS +if(PNG_SHARED) + set_target_properties(${PNG_LIB_NAME} PROPERTIES +# VERSION 15.${PNGLIB_RELEASE}.1.5.1 + VERSION 15.${PNGLIB_RELEASE}.0 + SOVERSION 15 + CLEAN_DIRECT_OUTPUT 1) +endif() +if(PNG_STATIC) + # MSVC doesn't use a different file extension for shared vs. static + # libs. We are able to change OUTPUT_NAME to remove the _static + # for all other platforms. + if(NOT MSVC) + set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES + OUTPUT_NAME ${PNG_LIB_NAME} + CLEAN_DIRECT_OUTPUT 1) + endif() +endif() + +# If CMake > 2.4.x, we set a variable used below to export +# targets to an export file. +# TODO: Use VERSION_GREATER after our cmake_minimum_required >= 2.6.2 +if(CMAKE_MAJOR_VERSION GREATER 1 AND CMAKE_MINOR_VERSION GREATER 4) + set(PNG_EXPORT_RULE EXPORT libpng) +elseif(CMAKE_MAJOR_VERSION GREATER 2) # future proof + set(PNG_EXPORT_RULE EXPORT libpng) +endif() + +# what's with libpng-$VER%.txt and all the extra files? + + +# UNINSTALL +# do we need this? + + +# DIST +# do we need this? + +# to create msvc import lib for mingw compiled shared lib +# pexports libpng.dll > libpng.def +# lib /def:libpng.def /machine:x86 + diff --git a/contrib/libpng/INSTALL b/contrib/libpng/INSTALL new file mode 100644 index 0000000..353bfff --- /dev/null +++ b/contrib/libpng/INSTALL @@ -0,0 +1,135 @@ + +Installing libpng + +On Unix/Linux and similar systems, you can simply type + + ./configure [--prefix=/path] + make check + make install + +and ignore the rest of this document. + +If configure does not work on your system and you have a reasonably +up-to-date set of tools, running ./autogen.sh before running ./configure +may fix the problem. You can also run the individual commands in +autogen.sh with the --force option, if supported by your version of +the tools. To be really sure that you aren't using any of the included +pre-built scripts, you can do this: + + ./configure --enable-maintainer-mode + make maintainer-clean + ./autogen.sh + ./configure [--prefix=/path] [other options] + make + make install + make check + +Instead, you can use one of the custom-built makefiles in the +"scripts" directory + + cp scripts/makefile.system makefile + make test + make install + +The files that are presently available in the scripts directory +are listed and described in scripts/README.txt. + +Or you can use one of the "projects" in the "projects" directory. + +Before installing libpng, you must first install zlib, if it +is not already on your system. zlib can usually be found +wherever you got libpng. zlib can be placed in another directory, +at the same level as libpng. + +If you want to use "cmake" (see www.cmake.org), type + + cmake . -DCMAKE_INSTALL_PREFIX=/path + make + make install + +If your system already has a preinstalled zlib you will still need +to have access to the zlib.h and zconf.h include files that +correspond to the version of zlib that's installed. + +You can rename the directories that you downloaded (they +might be called "libpng-x.y.z" or "libpngNN" and "zlib-1.2.5" +or "zlib125") so that you have directories called "zlib" and "libpng". + +Your directory structure should look like this: + + .. (the parent directory) + libpng (this directory) + INSTALL (this file) + README + *.h + *.c + CMakeLists.txt => "cmake" script + configuration files: + configure.ac, configure, Makefile.am, Makefile.in, + autogen.sh, config.guess, ltmain.sh, missing, libpng.pc.in, + libpng-config.in, aclocal.m4, config.h.in, config.sub, + depcomp, install-sh, mkinstalldirs, test-pngtest.sh + contrib + gregbook + pngminim + pngminus + pngsuite + visupng + projects + visualc71 + vstudio + scripts + makefile.* + *.def (module definition files) + etc. + pngtest.png + etc. + zlib + README + *.h + *.c + contrib + etc. + +If the line endings in the files look funny, you may wish to get the other +distribution of libpng. It is available in both tar.gz (UNIX style line +endings) and zip (DOS style line endings) formats. + +If you are building libpng with MSVC, you can enter the +libpng projects\visualc6 or visualc71 directory and follow the instructions +in README.txt. + +Otherwise enter the zlib directory and follow the instructions in zlib/README, +then come back here and run "configure" or choose the appropriate +makefile.sys in the scripts directory. + +Copy the file (or files) that you need from the +scripts directory into this directory, for example + + MSDOS example: copy scripts\makefile.msc makefile + UNIX example: cp scripts/makefile.std makefile + +Read the makefile to see if you need to change any source or +target directories to match your preferences. + +Then read pnglibconf.dfa to see if you want to make any configuration +changes. + +Then just run "make" which will create the libpng library in +this directory and "make test" which will run a quick test that reads +the "pngtest.png" file and writes a "pngout.png" file that should be +identical to it. Look for "9782 zero samples" in the output of the +test. For more confidence, you can run another test by typing +"pngtest pngnow.png" and looking for "289 zero samples" in the output. +Also, you can run "pngtest -m contrib/pngsuite/*.png" and compare +your output with the result shown in contrib/pngsuite/README. + +Most of the makefiles will allow you to run "make install" to +put the library in its final resting place (if you want to +do that, run "make install" in the zlib directory first if necessary). +Some also allow you to run "make test-installed" after you have +run "make install". + +Further information can be found in the README and libpng-manual.txt +files, in the individual makefiles, in png.h, and the manual pages +libpng.3 and png.5. diff --git a/contrib/libpng/LICENSE b/contrib/libpng/LICENSE new file mode 100644 index 0000000..b28f15c --- /dev/null +++ b/contrib/libpng/LICENSE @@ -0,0 +1,111 @@ + +This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail. + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.1, February 3, 2011, are +Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +February 3, 2011 diff --git a/contrib/libpng/Makefile.am b/contrib/libpng/Makefile.am new file mode 100644 index 0000000..142a4ce --- /dev/null +++ b/contrib/libpng/Makefile.am @@ -0,0 +1,211 @@ +# Makefile.am: +# Source file for Makefile.in (and hence Makefile) +# + +PNGLIB_BASENAME= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ + +# libpng does not follow GNU file name conventions + +# "color-tests" requires automake 1.11.1 or later. Enable it if you like, +# to get red "FAIL" and green "PASS" notations during tests. +# AUTOMAKE_OPTIONS = foreign color-tests +AUTOMAKE_OPTIONS = foreign + +# test programs - run on make check, make distcheck +check_PROGRAMS= pngtest pngvalid +pngtest_SOURCES = pngtest.c +pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +pngvalid_SOURCES = pngvalid.c +pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +TESTS = test-pngtest.sh test-pngvalid-simple.sh test-pngvalid-full.sh +TESTS_ENVIRONMENT= srcdir=$(srcdir) + +# man pages +dist_man_MANS= libpng.3 libpngpf.3 png.5 + +# generate the -config scripts if required +binconfigs= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config +EXTRA_SCRIPTS= libpng-config libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config +bin_SCRIPTS= @binconfigs@ + +# rules to build libpng, only build the old library on request +lib_LTLIBRARIES=libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +# EXTRA_LTLIBRARIES= libpng.la +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c\ + pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c pngrutil.c\ + pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\ + png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h + +nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS = @LIBPNG_DEFINES@ + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined -export-dynamic \ + -version-number @PNGLIB_MAJOR@@PNGLIB_MINOR@:@PNGLIB_RELEASE@:0 + +if HAVE_LD_VERSION_SCRIPT + # Versioned symbols and restricted exports + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -Wl,--version-script=libpng.vers + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.vers +else + # Only restricted exports when possible + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -export-symbols libpng.sym + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.sym +endif + +#distribute headers in /usr/include/libpng/* +pkgincludedir= $(includedir)/$(PNGLIB_BASENAME) +pkginclude_HEADERS= png.h pngconf.h +nodist_pkginclude_HEADERS= pnglibconf.h + +# pkg-config stuff, note that libpng.pc is always required in order +# to get the correct library +pkgconfigdir = @pkgconfigdir@ +pkgconfig_DATA = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc + +#extra source distribution files. +EXTRA_DIST= \ + ANNOUNCE CHANGES INSTALL LICENSE README TODO \ + pngtest.png pngbar.png pngnow.png pngbar.jpg autogen.sh \ + ${srcdir}/contrib ${srcdir}/projects ${srcdir}/scripts \ + $(TESTS) \ + CMakeLists.txt example.c libpng-manual.txt + +SCRIPT_CLEANFILES=scripts/*.out scripts/*.chk scripts/pnglibconf.dfn + +CLEANFILES= dfn.c dfn?.out pngout.png libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config libpng.vers libpng.sym \ + check.new pnglibconf.* symbols.new pngtest-log.txt \ + $(SCRIPT_CLEANFILES) + +MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in \ +config.sub configure depcomp install-sh ltmain.sh missing + +# DFNCPP is normally just CPP - the C preprocessor - but on Solaris and maybe +# other operating systems (NeXT?) the C preprocessor selected by configure +# checks input tokens for validity - effectively it performs part of the ANSI-C +# parsing - and therefore fails with the .df files. configure.ac has special +# checks for this and sets DFNCPP appropriately. +DFNCPP = @DFNCPP@ + +SUFFIXES = .chk .dfn .out + +$(PNGLIB_BASENAME).pc: libpng.pc + cp libpng.pc $@ + +$(PNGLIB_BASENAME)-config: libpng-config + cp libpng-config $@ + +scripts/sym.out scripts/vers.out: png.h pngconf.h pnglibconf.h +scripts/symbols.out: png.h pngconf.h scripts/pnglibconf.h.prebuilt + +libpng.sym: scripts/sym.out + rm -f $@ + cp $? $@ +libpng.vers: scripts/vers.out + rm -f $@ + cp $? $@ +pnglibconf.h: pnglibconf.out + rm -f $@ + cp $? $@ +scripts/pnglibconf.h.prebuilt: + @echo "This is a machine generated file, but if you want to make" >&2 + @echo "a new one simply make 'scripts/pnglibconf.out' and copy that" >&2 + @exit 1 + +# The following is necessary to ensure that the local pnglibconf.h is used, not +# an installed one (this can happen immediately after on a clean system if +# 'make test' is the first thing the user does.) +pngvalid.o pngtest.o: pnglibconf.h + +# We must use -DPNG_NO_USE_READ_MACROS here even when the library may actually +# be built with PNG_USE_READ_MACROS; this stops the read macros interfering +# with the symbol file format. +SYMBOL_CFLAGS = -DPNGLIB_LIBNAME='PNG@PNGLIB_MAJOR@@PNGLIB_MINOR@_0'\ + -DPNGLIB_VERSION='@PNGLIB_VERSION@'\ + -DSYMBOL_PREFIX='$(SYMBOL_PREFIX)'\ + -DPNG_NO_USE_READ_MACROS + +.dfn.out: + rm -f $@ dfn.c dfn?.out + test -d scripts || mkdir scripts + echo '#include "$<"' >dfn.c + $(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) @LIBPNG_DEFINES@\ + $(CPPFLAGS) $(SYMBOL_CFLAGS) dfn.c > dfn1.out + $(SED) -n -e 's|^.*PNG_DEFN_MAGIC-\(.*\)-PNG_DEFN_END.*$$|\1|p'\ + dfn1.out >dfn2.out + $(SED) -e 's| *@@@ *||g' -e 's| *$$||' dfn2.out >dfn3.out + rm -f dfn.c dfn[12].out + mv dfn3.out $@ + +# The .dfn file for pnglibconf.h is machine generated +pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk + rm -f $@ dfn?.out + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn1.out\ + ${srcdir}/scripts/pnglibconf.dfa $(DFA_XTRA) 1>&2 + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn2.out dfn1.out 1>&2 + rm dfn1.out + mv dfn2.out $@ + +# Symbol checks (.def and .out files should match) +scripts/symbols.chk: scripts/checksym.awk scripts/symbols.def scripts/symbols.out +.out.chk: + rm -f $@ symbols.new + $(AWK) -f ${srcdir}/scripts/checksym.awk ${srcdir}/scripts/${*F}.def\ + $< >&2 + mv symbols.new $@ + +# used on demand to regenerate the standard header, CPPFLAGS should +# be empty - no non-standard defines +scripts/pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk + rm -f $@ dfn?.out + test -z "$(CPPFLAGS)" + echo "com @PNGLIB_VERSION@ STANDARD API DEFINITION" |\ + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn1.out\ + logunsupported=1 - ${srcdir}/scripts/pnglibconf.dfa 1>&2 + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn2.out dfn1.out 1>&2 + rm dfn1.out + mv dfn2.out $@ + +$(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS): png.h pngconf.h \ + pnglibconf.h pngpriv.h pngdebug.h pnginfo.h pngstruct.h + +test: check-am + +# Extra checks +check: scripts/symbols.chk + +# Don't distribute the generated script files +dist-hook: + cd '$(top_distdir)'; rm -f $(SCRIPT_CLEANFILES) + +# install the .../include headers as links to the new ones +install-data-hook: + cd $(DESTDIR)$(includedir); rm -f png.h pngconf.h pnglibconf.h + cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/png.h png.h + cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/pngconf.h \ + pngconf.h + cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/pnglibconf.h \ + pnglibconf.h + cd $(DESTDIR)$(pkgconfigdir); rm -f libpng.pc + cd $(DESTDIR)$(pkgconfigdir); $(LN_S) $(PNGLIB_BASENAME).pc libpng.pc + +# do evil things to libpng to cause libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ to be used +install-exec-hook: + cd $(DESTDIR)$(bindir); rm -f libpng-config + cd $(DESTDIR)$(bindir); $(LN_S) $(PNGLIB_BASENAME)-config libpng-config + @set -x;\ + cd $(DESTDIR)$(libdir);\ + for ext in a la so so.@PNGLIB_MAJOR@@PNGLIB_MINOR@.@PNGLIB_RELEASE@ sl dylib dll.a; do\ + rm -f libpng.$$ext;\ + if test -f $(PNGLIB_BASENAME).$$ext; then\ + $(LN_S) $(PNGLIB_BASENAME).$$ext libpng.$$ext;\ + fi;\ + done + +uninstall-hook: + cd $(DESTDIR)$(includedir); rm -f png.h pngconf.h pnglibconf.h + rm -f $(DESTDIR)$(pkgconfigdir)/libpng.pc + rm -f $(DESTDIR)$(bindir)/libpng-config + rm -f $(DESTDIR)$(libdir)/libpng.a + rm -f $(DESTDIR)$(libdir)/libpng.la diff --git a/contrib/libpng/Makefile.in b/contrib/libpng/Makefile.in new file mode 100644 index 0000000..d2febdd --- /dev/null +++ b/contrib/libpng/Makefile.in @@ -0,0 +1,1375 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Makefile.am: +# Source file for Makefile.in (and hence Makefile) +# + + + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +check_PROGRAMS = pngtest$(EXEEXT) pngvalid$(EXEEXT) +@HAVE_LD_VERSION_SCRIPT_TRUE@am__append_1 = -Wl,--version-script=libpng.vers +@HAVE_LD_VERSION_SCRIPT_FALSE@am__append_2 = -export-symbols libpng.sym +subdir = . +DIST_COMMON = README $(am__configure_deps) $(dist_man_MANS) \ + $(pkginclude_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/libpng-config.in $(srcdir)/libpng.pc.in \ + $(top_srcdir)/configure INSTALL TODO config.guess config.sub \ + depcomp install-sh ltmain.sh missing +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = libpng.pc libpng-config +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ + "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man5dir)" \ + "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgincludedir)" \ + "$(DESTDIR)$(pkgincludedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LIBADD = +am_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS = \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrio.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwrite.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.lo \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo +nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS = +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS = \ + $(am_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) \ + $(nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LINK = $(LIBTOOL) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) \ + $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS) $(LDFLAGS) -o \ + $@ +am_pngtest_OBJECTS = pngtest.$(OBJEXT) +pngtest_OBJECTS = $(am_pngtest_OBJECTS) +pngtest_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +am_pngvalid_OBJECTS = pngvalid.$(OBJEXT) +pngvalid_OBJECTS = $(am_pngvalid_OBJECTS) +pngvalid_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +SCRIPTS = $(bin_SCRIPTS) +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ + $(LDFLAGS) -o $@ +SOURCES = $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES) \ + $(nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES) \ + $(pngtest_SOURCES) $(pngvalid_SOURCES) +DIST_SOURCES = $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES) \ + $(pngtest_SOURCES) $(pngvalid_SOURCES) +man3dir = $(mandir)/man3 +man5dir = $(mandir)/man5 +NROFF = nroff +MANS = $(dist_man_MANS) +DATA = $(pkgconfig_DATA) +HEADERS = $(nodist_pkginclude_HEADERS) $(pkginclude_HEADERS) +ETAGS = etags +CTAGS = ctags +am__tty_colors = \ +red=; grn=; lgn=; blu=; std= +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + { test ! -d "$(distdir)" \ + || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr "$(distdir)"; }; } +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +distcleancheck_listfiles = find . -type f -print + +#distribute headers in /usr/include/libpng/* +pkgincludedir = $(includedir)/$(PNGLIB_BASENAME) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ + +# DFNCPP is normally just CPP - the C preprocessor - but on Solaris and maybe +# other operating systems (NeXT?) the C preprocessor selected by configure +# checks input tokens for validity - effectively it performs part of the ANSI-C +# parsing - and therefore fails with the .df files. configure.ac has special +# checks for this and sets DFNCPP appropriately. +DFNCPP = @DFNCPP@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBPNG_DEFINES = @LIBPNG_DEFINES@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PNGLIB_MAJOR = @PNGLIB_MAJOR@ +PNGLIB_MINOR = @PNGLIB_MINOR@ +PNGLIB_RELEASE = @PNGLIB_RELEASE@ +PNGLIB_VERSION = @PNGLIB_VERSION@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYMBOL_PREFIX = @SYMBOL_PREFIX@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ + +# generate the -config scripts if required +binconfigs = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ + +# pkg-config stuff, note that libpng.pc is always required in order +# to get the correct library +pkgconfigdir = @pkgconfigdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +PNGLIB_BASENAME = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ + +# libpng does not follow GNU file name conventions + +# "color-tests" requires automake 1.11.1 or later. Enable it if you like, +# to get red "FAIL" and green "PASS" notations during tests. +# AUTOMAKE_OPTIONS = foreign color-tests +AUTOMAKE_OPTIONS = foreign +pngtest_SOURCES = pngtest.c +pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +pngvalid_SOURCES = pngvalid.c +pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +TESTS = test-pngtest.sh test-pngvalid-simple.sh test-pngvalid-full.sh +TESTS_ENVIRONMENT = srcdir=$(srcdir) + +# man pages +dist_man_MANS = libpng.3 libpngpf.3 png.5 +EXTRA_SCRIPTS = libpng-config libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config +bin_SCRIPTS = @binconfigs@ + +# rules to build libpng, only build the old library on request +lib_LTLIBRARIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +# EXTRA_LTLIBRARIES= libpng.la +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c\ + pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c pngrutil.c\ + pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\ + png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h + +nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS = @LIBPNG_DEFINES@ +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined \ + -export-dynamic -version-number \ + @PNGLIB_MAJOR@@PNGLIB_MINOR@:@PNGLIB_RELEASE@:0 \ + $(am__append_1) $(am__append_2) +@HAVE_LD_VERSION_SCRIPT_FALSE@libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.sym +@HAVE_LD_VERSION_SCRIPT_TRUE@libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.vers +pkginclude_HEADERS = png.h pngconf.h +nodist_pkginclude_HEADERS = pnglibconf.h +pkgconfig_DATA = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc + +#extra source distribution files. +EXTRA_DIST = \ + ANNOUNCE CHANGES INSTALL LICENSE README TODO \ + pngtest.png pngbar.png pngnow.png pngbar.jpg autogen.sh \ + ${srcdir}/contrib ${srcdir}/projects ${srcdir}/scripts \ + $(TESTS) \ + CMakeLists.txt example.c libpng-manual.txt + +SCRIPT_CLEANFILES = scripts/*.out scripts/*.chk scripts/pnglibconf.dfn +CLEANFILES = dfn.c dfn?.out pngout.png libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config libpng.vers libpng.sym \ + check.new pnglibconf.* symbols.new pngtest-log.txt \ + $(SCRIPT_CLEANFILES) + +MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in \ +config.sub configure depcomp install-sh ltmain.sh missing + +SUFFIXES = .chk .dfn .out + +# We must use -DPNG_NO_USE_READ_MACROS here even when the library may actually +# be built with PNG_USE_READ_MACROS; this stops the read macros interfering +# with the symbol file format. +SYMBOL_CFLAGS = -DPNGLIB_LIBNAME='PNG@PNGLIB_MAJOR@@PNGLIB_MINOR@_0'\ + -DPNGLIB_VERSION='@PNGLIB_VERSION@'\ + -DSYMBOL_PREFIX='$(SYMBOL_PREFIX)'\ + -DPNG_NO_USE_READ_MACROS + +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .chk .dfn .out .c .lo .o .obj +am--refresh: + @: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +libpng.pc: $(top_builddir)/config.status $(srcdir)/libpng.pc.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +libpng-config: $(top_builddir)/config.status $(srcdir)/libpng-config.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la: $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES) + $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LINK) -rpath $(libdir) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LIBADD) $(LIBS) + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +pngtest$(EXEEXT): $(pngtest_OBJECTS) $(pngtest_DEPENDENCIES) + @rm -f pngtest$(EXEEXT) + $(LINK) $(pngtest_OBJECTS) $(pngtest_LDADD) $(LIBS) +pngvalid$(EXEEXT): $(pngvalid_OBJECTS) $(pngvalid_DEPENDENCIES) + @rm -f pngvalid$(EXEEXT) + $(LINK) $(pngvalid_OBJECTS) $(pngvalid_LDADD) $(LIBS) +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwrite.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngtest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngvalid.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c $< + +.c.obj: +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.lo: png.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.lo `test -f 'png.c' || echo '$(srcdir)/'`png.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='png.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-png.lo `test -f 'png.c' || echo '$(srcdir)/'`png.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo: pngerror.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo `test -f 'pngerror.c' || echo '$(srcdir)/'`pngerror.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngerror.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngerror.lo `test -f 'pngerror.c' || echo '$(srcdir)/'`pngerror.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.lo: pngget.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.lo `test -f 'pngget.c' || echo '$(srcdir)/'`pngget.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngget.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngget.lo `test -f 'pngget.c' || echo '$(srcdir)/'`pngget.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo: pngmem.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo `test -f 'pngmem.c' || echo '$(srcdir)/'`pngmem.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngmem.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngmem.lo `test -f 'pngmem.c' || echo '$(srcdir)/'`pngmem.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo: pngpread.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo `test -f 'pngpread.c' || echo '$(srcdir)/'`pngpread.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngpread.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngpread.lo `test -f 'pngpread.c' || echo '$(srcdir)/'`pngpread.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.lo: pngread.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.lo `test -f 'pngread.c' || echo '$(srcdir)/'`pngread.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngread.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngread.lo `test -f 'pngread.c' || echo '$(srcdir)/'`pngread.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrio.lo: pngrio.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrio.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrio.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrio.lo `test -f 'pngrio.c' || echo '$(srcdir)/'`pngrio.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrio.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrio.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngrio.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrio.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrio.lo `test -f 'pngrio.c' || echo '$(srcdir)/'`pngrio.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo: pngrtran.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo `test -f 'pngrtran.c' || echo '$(srcdir)/'`pngrtran.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngrtran.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrtran.lo `test -f 'pngrtran.c' || echo '$(srcdir)/'`pngrtran.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo: pngrutil.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo `test -f 'pngrutil.c' || echo '$(srcdir)/'`pngrutil.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngrutil.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngrutil.lo `test -f 'pngrutil.c' || echo '$(srcdir)/'`pngrutil.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo: pngset.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo `test -f 'pngset.c' || echo '$(srcdir)/'`pngset.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngset.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngset.lo `test -f 'pngset.c' || echo '$(srcdir)/'`pngset.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo: pngtrans.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo `test -f 'pngtrans.c' || echo '$(srcdir)/'`pngtrans.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngtrans.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngtrans.lo `test -f 'pngtrans.c' || echo '$(srcdir)/'`pngtrans.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.lo: pngwio.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.lo `test -f 'pngwio.c' || echo '$(srcdir)/'`pngwio.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngwio.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwio.lo `test -f 'pngwio.c' || echo '$(srcdir)/'`pngwio.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwrite.lo: pngwrite.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwrite.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwrite.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwrite.lo `test -f 'pngwrite.c' || echo '$(srcdir)/'`pngwrite.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwrite.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwrite.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngwrite.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwrite.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwrite.lo `test -f 'pngwrite.c' || echo '$(srcdir)/'`pngwrite.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.lo: pngwtran.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.lo `test -f 'pngwtran.c' || echo '$(srcdir)/'`pngwtran.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngwtran.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwtran.lo `test -f 'pngwtran.c' || echo '$(srcdir)/'`pngwtran.c + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo: pngwutil.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo -MD -MP -MF $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.Tpo -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo `test -f 'pngwutil.c' || echo '$(srcdir)/'`pngwutil.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.Tpo $(DEPDIR)/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngwutil.c' object='libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la-pngwutil.lo `test -f 'pngwutil.c' || echo '$(srcdir)/'`pngwutil.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool config.lt +install-man3: $(dist_man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" + @list=''; test -n "$(man3dir)" || exit 0; \ + { for i in $$list; do echo "$$i"; done; \ + l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.3[a-z]*$$/p'; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man3dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man3dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man3dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man3dir)" || exit $$?; }; \ + done; } + +uninstall-man3: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man3dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.3[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + test -z "$$files" || { \ + echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(man3dir)" && rm -f $$files; } +install-man5: $(dist_man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man5dir)" || $(MKDIR_P) "$(DESTDIR)$(man5dir)" + @list=''; test -n "$(man5dir)" || exit 0; \ + { for i in $$list; do echo "$$i"; done; \ + l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.5[a-z]*$$/p'; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ + done; } + +uninstall-man5: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man5dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.5[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + test -z "$$files" || { \ + echo " ( cd '$(DESTDIR)$(man5dir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(man5dir)" && rm -f $$files; } +install-pkgconfigDATA: $(pkgconfig_DATA) + @$(NORMAL_INSTALL) + test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ + done + +uninstall-pkgconfigDATA: + @$(NORMAL_UNINSTALL) + @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files +install-nodist_pkgincludeHEADERS: $(nodist_pkginclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" + @list='$(nodist_pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ + done + +uninstall-nodist_pkgincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(pkgincludedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pkgincludedir)" && rm -f $$files +install-pkgincludeHEADERS: $(pkginclude_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ + done + +uninstall-pkgincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(pkgincludedir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(pkgincludedir)" && rm -f $$files + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; skip=0; \ + srcdir=$(srcdir); export srcdir; \ + list=' $(TESTS) '; \ + $(am__tty_colors); \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + col=$$red; res=XPASS; \ + ;; \ + *) \ + col=$$grn; res=PASS; \ + ;; \ + esac; \ + elif test $$? -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$tst[\ \ ]*) \ + xfail=`expr $$xfail + 1`; \ + col=$$lgn; res=XFAIL; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + col=$$red; res=FAIL; \ + ;; \ + esac; \ + else \ + skip=`expr $$skip + 1`; \ + col=$$blu; res=SKIP; \ + fi; \ + echo "$${col}$$res$${std}: $$tst"; \ + done; \ + if test "$$all" -eq 1; then \ + tests="test"; \ + All=""; \ + else \ + tests="tests"; \ + All="All "; \ + fi; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="$$All$$all $$tests passed"; \ + else \ + if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ + banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all $$tests failed"; \ + else \ + if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ + banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + fi; \ + fi; \ + dashes="$$banner"; \ + skipped=""; \ + if test "$$skip" -ne 0; then \ + if test "$$skip" -eq 1; then \ + skipped="($$skip test was not run)"; \ + else \ + skipped="($$skip tests were not run)"; \ + fi; \ + test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$skipped"; \ + fi; \ + report=""; \ + if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ + report="Please report to $(PACKAGE_BUGREPORT)"; \ + test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ + dashes="$$report"; \ + fi; \ + dashes=`echo "$$dashes" | sed s/./=/g`; \ + if test "$$failed" -eq 0; then \ + echo "$$grn$$dashes"; \ + else \ + echo "$$red$$dashes"; \ + fi; \ + echo "$$banner"; \ + test -z "$$skipped" || echo "$$skipped"; \ + test -z "$$report" || echo "$$report"; \ + echo "$$dashes$$std"; \ + test "$$failed" -eq 0; \ + else :; fi + +distdir: $(DISTFILES) + @list='$(MANS)'; if test -n "$$list"; then \ + list=`for p in $$list; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ + if test -n "$$list" && \ + grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ + echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ + grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ + echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ + echo " typically \`make maintainer-clean' will remove them" >&2; \ + exit 1; \ + else :; fi; \ + else :; fi + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @$(am__cd) '$(distuninstallcheck_dir)' \ + && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(LTLIBRARIES) $(SCRIPTS) $(MANS) $(DATA) $(HEADERS) \ + config.h +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgincludedir)" "$(DESTDIR)$(pkgincludedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man install-nodist_pkgincludeHEADERS \ + install-pkgconfigDATA install-pkgincludeHEADERS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binSCRIPTS install-libLTLIBRARIES + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man3 install-man5 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binSCRIPTS uninstall-libLTLIBRARIES \ + uninstall-man uninstall-nodist_pkgincludeHEADERS \ + uninstall-pkgconfigDATA uninstall-pkgincludeHEADERS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook +uninstall-man: uninstall-man3 uninstall-man5 + +.MAKE: all check-am install-am install-data-am install-exec-am \ + install-strip uninstall-am + +.PHONY: CTAGS GTAGS all all-am am--refresh check check-TESTS check-am \ + clean clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ + clean-libtool ctags dist dist-all dist-bzip2 dist-gzip \ + dist-hook dist-lzma dist-shar dist-tarZ dist-xz dist-zip \ + distcheck distclean distclean-compile distclean-generic \ + distclean-hdr distclean-libtool distclean-tags distcleancheck \ + distdir distuninstallcheck dvi dvi-am html html-am info \ + info-am install install-am install-binSCRIPTS install-data \ + install-data-am install-data-hook install-dvi install-dvi-am \ + install-exec install-exec-am install-exec-hook install-html \ + install-html-am install-info install-info-am \ + install-libLTLIBRARIES install-man install-man3 install-man5 \ + install-nodist_pkgincludeHEADERS install-pdf install-pdf-am \ + install-pkgconfigDATA install-pkgincludeHEADERS install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-binSCRIPTS uninstall-hook \ + uninstall-libLTLIBRARIES uninstall-man uninstall-man3 \ + uninstall-man5 uninstall-nodist_pkgincludeHEADERS \ + uninstall-pkgconfigDATA uninstall-pkgincludeHEADERS + + +@HAVE_LD_VERSION_SCRIPT_TRUE@ # Versioned symbols and restricted exports +@HAVE_LD_VERSION_SCRIPT_FALSE@ # Only restricted exports when possible + +$(PNGLIB_BASENAME).pc: libpng.pc + cp libpng.pc $@ + +$(PNGLIB_BASENAME)-config: libpng-config + cp libpng-config $@ + +scripts/sym.out scripts/vers.out: png.h pngconf.h pnglibconf.h +scripts/symbols.out: png.h pngconf.h scripts/pnglibconf.h.prebuilt + +libpng.sym: scripts/sym.out + rm -f $@ + cp $? $@ +libpng.vers: scripts/vers.out + rm -f $@ + cp $? $@ +pnglibconf.h: pnglibconf.out + rm -f $@ + cp $? $@ +scripts/pnglibconf.h.prebuilt: + @echo "This is a machine generated file, but if you want to make" >&2 + @echo "a new one simply make 'scripts/pnglibconf.out' and copy that" >&2 + @exit 1 + +# The following is necessary to ensure that the local pnglibconf.h is used, not +# an installed one (this can happen immediately after on a clean system if +# 'make test' is the first thing the user does.) +pngvalid.o pngtest.o: pnglibconf.h + +.dfn.out: + rm -f $@ dfn.c dfn?.out + test -d scripts || mkdir scripts + echo '#include "$<"' >dfn.c + $(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) @LIBPNG_DEFINES@\ + $(CPPFLAGS) $(SYMBOL_CFLAGS) dfn.c > dfn1.out + $(SED) -n -e 's|^.*PNG_DEFN_MAGIC-\(.*\)-PNG_DEFN_END.*$$|\1|p'\ + dfn1.out >dfn2.out + $(SED) -e 's| *@@@ *||g' -e 's| *$$||' dfn2.out >dfn3.out + rm -f dfn.c dfn[12].out + mv dfn3.out $@ + +# The .dfn file for pnglibconf.h is machine generated +pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk + rm -f $@ dfn?.out + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn1.out\ + ${srcdir}/scripts/pnglibconf.dfa $(DFA_XTRA) 1>&2 + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn2.out dfn1.out 1>&2 + rm dfn1.out + mv dfn2.out $@ + +# Symbol checks (.def and .out files should match) +scripts/symbols.chk: scripts/checksym.awk scripts/symbols.def scripts/symbols.out +.out.chk: + rm -f $@ symbols.new + $(AWK) -f ${srcdir}/scripts/checksym.awk ${srcdir}/scripts/${*F}.def\ + $< >&2 + mv symbols.new $@ + +# used on demand to regenerate the standard header, CPPFLAGS should +# be empty - no non-standard defines +scripts/pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk + rm -f $@ dfn?.out + test -z "$(CPPFLAGS)" + echo "com @PNGLIB_VERSION@ STANDARD API DEFINITION" |\ + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn1.out\ + logunsupported=1 - ${srcdir}/scripts/pnglibconf.dfa 1>&2 + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn2.out dfn1.out 1>&2 + rm dfn1.out + mv dfn2.out $@ + +$(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS): png.h pngconf.h \ + pnglibconf.h pngpriv.h pngdebug.h pnginfo.h pngstruct.h + +test: check-am + +# Extra checks +check: scripts/symbols.chk + +# Don't distribute the generated script files +dist-hook: + cd '$(top_distdir)'; rm -f $(SCRIPT_CLEANFILES) + +# install the .../include headers as links to the new ones +install-data-hook: + cd $(DESTDIR)$(includedir); rm -f png.h pngconf.h pnglibconf.h + cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/png.h png.h + cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/pngconf.h \ + pngconf.h + cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/pnglibconf.h \ + pnglibconf.h + cd $(DESTDIR)$(pkgconfigdir); rm -f libpng.pc + cd $(DESTDIR)$(pkgconfigdir); $(LN_S) $(PNGLIB_BASENAME).pc libpng.pc + +# do evil things to libpng to cause libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ to be used +install-exec-hook: + cd $(DESTDIR)$(bindir); rm -f libpng-config + cd $(DESTDIR)$(bindir); $(LN_S) $(PNGLIB_BASENAME)-config libpng-config + @set -x;\ + cd $(DESTDIR)$(libdir);\ + for ext in a la so so.@PNGLIB_MAJOR@@PNGLIB_MINOR@.@PNGLIB_RELEASE@ sl dylib dll.a; do\ + rm -f libpng.$$ext;\ + if test -f $(PNGLIB_BASENAME).$$ext; then\ + $(LN_S) $(PNGLIB_BASENAME).$$ext libpng.$$ext;\ + fi;\ + done + +uninstall-hook: + cd $(DESTDIR)$(includedir); rm -f png.h pngconf.h pnglibconf.h + rm -f $(DESTDIR)$(pkgconfigdir)/libpng.pc + rm -f $(DESTDIR)$(bindir)/libpng-config + rm -f $(DESTDIR)$(libdir)/libpng.a + rm -f $(DESTDIR)$(libdir)/libpng.la + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/libpng/README b/contrib/libpng/README new file mode 100644 index 0000000..9dd6745 --- /dev/null +++ b/contrib/libpng/README @@ -0,0 +1,205 @@ +README for libpng version 1.5.1 - February 3, 2011 (shared library 15.0) +See the note about version numbers near the top of png.h + +See INSTALL for instructions on how to install libpng. + +Libpng comes in several distribution formats. Get libpng-*.tar.gz, +libpng-*.tar.xz or libpng-*.tar.bz2 if you want UNIX-style line endings +in the text files, or lpng*.zip if you want DOS-style line endings. + +Version 0.89 was the first official release of libpng. Don't let the +fact that it's the first release fool you. The libpng library has been in +extensive use and testing since mid-1995. By late 1997 it had +finally gotten to the stage where there hadn't been significant +changes to the API in some time, and people have a bad feeling about +libraries with versions < 1.0. Version 1.0.0 was released in +March 1998. + +**** +Note that some of the changes to the png_info structure render this +version of the library binary incompatible with libpng-0.89 or +earlier versions if you are using a shared library. The type of the +"filler" parameter for png_set_filler() has changed from png_byte to +png_uint_32, which will affect shared-library applications that use +this function. + +To avoid problems with changes to the internals of png_info_struct, +new APIs have been made available in 0.95 to avoid direct application +access to info_ptr. These functions are the png_set_ and +png_get_ functions. These functions should be used when +accessing/storing the info_struct data, rather than manipulating it +directly, to avoid such problems in the future. + +It is important to note that the APIs do not make current programs +that access the info struct directly incompatible with the new +library. However, it is strongly suggested that new programs use +the new APIs (as shown in example.c and pngtest.c), and older programs +be converted to the new format, to facilitate upgrades in the future. +**** + +Additions since 0.90 include the ability to compile libpng as a +Windows DLL, and new APIs for accessing data in the info struct. +Experimental functions include the ability to set weighting and cost +factors for row filter selection, direct reads of integers from buffers +on big-endian processors that support misaligned data access, faster +methods of doing alpha composition, and more accurate 16->8 bit color +conversion. + +The additions since 0.89 include the ability to read from a PNG stream +which has had some (or all) of the signature bytes read by the calling +application. This also allows the reading of embedded PNG streams that +do not have the PNG file signature. As well, it is now possible to set +the library action on the detection of chunk CRC errors. It is possible +to set different actions based on whether the CRC error occurred in a +critical or an ancillary chunk. + +The changes made to the library, and bugs fixed are based on discussions +on the PNG-implement mailing list and not on material submitted +privately to Guy, Andreas, or Glenn. They will forward any good +suggestions to the list. + +For a detailed description on using libpng, read libpng-manual.txt. For +examples of libpng in a program, see example.c and pngtest.c. For usage +information and restrictions (what little they are) on libpng, see +png.h. For a description on using zlib (the compression library used by +libpng) and zlib's restrictions, see zlib.h + +I have included a general makefile, as well as several machine and +compiler specific ones, but you may have to modify one for your own needs. + +You should use zlib 1.0.4 or later to run this, but it MAY work with +versions as old as zlib 0.95. Even so, there are bugs in older zlib +versions which can cause the output of invalid compression streams for +some images. You will definitely need zlib 1.0.4 or later if you are +taking advantage of the MS-DOS "far" structure allocation for the small +and medium memory models. You should also note that zlib is a +compression library that is useful for more things than just PNG files. +You can use zlib as a drop-in replacement for fread() and fwrite() if +you are so inclined. + +zlib should be available at the same place that libpng is, or at. +ftp://ftp.info-zip.org/pub/infozip/zlib + +You may also want a copy of the PNG specification. It is available +as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find +these at http://www.libpng.org/pub/png/documents/ + +This code is currently being archived at libpng.sf.net in the +[DOWNLOAD] area, and on CompuServe, Lib 20 (PNG SUPPORT) +at GO GRAPHSUP. If you can't find it in any of those places, +e-mail me, and I'll help you find it. + +If you have any code changes, requests, problems, etc., please e-mail +them to me. Also, I'd appreciate any make files or project files, +and any modifications you needed to make to get libpng to compile, +along with a #define variable to tell what compiler/system you are on. +If you needed to add transformations to libpng, or wish libpng would +provide the image in a different way, drop me a note (and code, if +possible), so I can consider supporting the transformation. +Finally, if you get any warning messages when compiling libpng +(note: not zlib), and they are easy to fix, I'd appreciate the +fix. Please mention "libpng" somewhere in the subject line. Thanks. + +This release was created and will be supported by myself (of course +based in a large way on Guy's and Andreas' earlier work), and the PNG +development group. + +Send comments/corrections/commendations to png-mng-implement at +lists.sourceforge.net (subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe) or to glennrp at users.sourceforge.net + +You can't reach Guy, the original libpng author, at the addresses +given in previous versions of this document. He and Andreas will +read mail addressed to the png-implement list, however. + +Please do not send general questions about PNG. Send them to +the (png-list at ccrc.wustl.edu, subscription required, write to +majordomo at ccrc.wustl.edu with "subscribe png-list" in your message). +On the other hand, +please do not send libpng questions to that address, send them to me +or to the png-implement list. I'll +get them in the end anyway. If you have a question about something +in the PNG specification that is related to using libpng, send it +to me. Send me any questions that start with "I was using libpng, +and ...". If in doubt, send questions to me. I'll bounce them +to others, if necessary. + +Please do not send suggestions on how to change PNG. We have +been discussing PNG for nine years now, and it is official and +finished. If you have suggestions for libpng, however, I'll +gladly listen. Even if your suggestion is not used immediately, +it may be used later. + +Files in this distribution: + + ANNOUNCE => Announcement of this version, with recent changes + CHANGES => Description of changes between libpng versions + KNOWNBUG => List of known bugs and deficiencies + LICENSE => License to use and redistribute libpng + README => This file + TODO => Things not implemented in the current library + Y2KINFO => Statement of Y2K compliance + example.c => Example code for using libpng functions + libpng.3 => manual page for libpng (includes libpng-manual.txt) + libpng-manual.txt => Description of libpng and its functions + libpngpf.3 => manual page for libpng's private functions + png.5 => manual page for the PNG format + png.c => Basic interface functions common to library + png.h => Library function and interface declarations (public) + pngpriv.h => Library function and interface declarations (private) + pngconf.h => System specific library configuration (public) + pngstruct.h => png_struct declaration (private) + pnginfo.h => png_info struct declaration (private) + pngdebug.h => debugging macros (private) + pngerror.c => Error/warning message I/O functions + pngget.c => Functions for retrieving info from struct + pngmem.c => Memory handling functions + pngbar.png => PNG logo, 88x31 + pngnow.png => PNG logo, 98x31 + pngpread.c => Progressive reading functions + pngread.c => Read data/helper high-level functions + pngrio.c => Lowest-level data read I/O functions + pngrtran.c => Read data transformation functions + pngrutil.c => Read data utility functions + pngset.c => Functions for storing data into the info_struct + pngtest.c => Library test program + pngtest.png => Library test sample image + pngtrans.c => Common data transformation functions + pngwio.c => Lowest-level write I/O functions + pngwrite.c => High-level write functions + pngwtran.c => Write data transformations + pngwutil.c => Write utility functions + contrib => Contributions + gregbook => source code for PNG reading and writing, from + Greg Roelofs' "PNG: The Definitive Guide", + O'Reilly, 1999 + msvctest => Builds and runs pngtest using a MSVC workspace + pngminus => Simple pnm2png and png2pnm programs + pngsuite => Test images + visupng => Contains a MSVC workspace for VisualPng + projects => Contains project files and workspaces for + building a DLL + cbuilder5 => Contains a Borland workspace for building + libpng and zlib + visualc6 => Contains a Microsoft Visual C++ (MSVC) + workspace for building libpng and zlib + visualc71 => Contains a Microsoft Visual C++ (MSVC) + workspace for building libpng and zlib + xcode => Contains an Apple xcode + workspace for building libpng and zlib + scripts => Directory containing scripts for building libpng: + (see scripts/README.txt for the list of scripts) + +Good luck, and happy coding. + +-Glenn Randers-Pehrson (current maintainer, since 1998) + Internet: glennrp at users.sourceforge.net + +-Andreas Eric Dilger (former maintainer, 1996-1997) + Internet: adilger at enel.ucalgary.ca + Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/ + +-Guy Eric Schalnat (original author and former maintainer, 1995-1996) + (formerly of Group 42, Inc) + Internet: gschal at infinet.com diff --git a/contrib/libpng/TODO b/contrib/libpng/TODO new file mode 100644 index 0000000..6e1f028 --- /dev/null +++ b/contrib/libpng/TODO @@ -0,0 +1,27 @@ +/* +TODO - list of things to do for libpng: + +Final bug fixes. +Better C++ wrapper/full C++ implementation? +Fix problem with C++ and EXTERN "C". +cHRM transformation. +Remove setjmp/longjmp usage in favor of returning error codes. +Add "grayscale->palette" transformation and "palette->grayscale" detection. +Improved dithering. +Multi-lingual error and warning message support. +Complete sRGB transformation (presently it simply uses gamma=0.45455). +Man pages for function calls. +Better documentation. +Better filter selection + (counting huffman bits/precompression? filter inertia? filter costs?). +Histogram creation. +Text conversion between different code pages (Latin-1 -> Mac and DOS). +Avoid building gamma tables whenever possible. +Use greater precision when changing to linear gamma for compositing against + background and doing rgb-to-gray transformation. +Investigate pre-incremented loop counters and other loop constructions. +Add interpolated method of handling interlacing. +Switch to the simpler zlib (zlib/libpng) license if legally possible. +Extend pngvalid.c to validate more of the libpng transformations. + +*/ diff --git a/contrib/libpng/aclocal.m4 b/contrib/libpng/aclocal.m4 new file mode 100644 index 0000000..e788a89 --- /dev/null +++ b/contrib/libpng/aclocal.m4 @@ -0,0 +1,9430 @@ +# generated automatically by aclocal 1.11.1 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],, +[m4_warning([this file was generated for autoconf 2.68. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +m4_define([_LT_COPYING], [dnl +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +]) + +# serial 57 LT_INIT + + +# LT_PREREQ(VERSION) +# ------------------ +# Complain and exit if this libtool version is less that VERSION. +m4_defun([LT_PREREQ], +[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, + [m4_default([$3], + [m4_fatal([Libtool version $1 or higher is required], + 63)])], + [$2])]) + + +# _LT_CHECK_BUILDDIR +# ------------------ +# Complain if the absolute build directory name contains unusual characters +m4_defun([_LT_CHECK_BUILDDIR], +[case `pwd` in + *\ * | *\ *) + AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; +esac +]) + + +# LT_INIT([OPTIONS]) +# ------------------ +AC_DEFUN([LT_INIT], +[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +AC_BEFORE([$0], [LT_LANG])dnl +AC_BEFORE([$0], [LT_OUTPUT])dnl +AC_BEFORE([$0], [LTDL_INIT])dnl +m4_require([_LT_CHECK_BUILDDIR])dnl + +dnl Autoconf doesn't catch unexpanded LT_ macros by default: +m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl +m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl +dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 +dnl unless we require an AC_DEFUNed macro: +AC_REQUIRE([LTOPTIONS_VERSION])dnl +AC_REQUIRE([LTSUGAR_VERSION])dnl +AC_REQUIRE([LTVERSION_VERSION])dnl +AC_REQUIRE([LTOBSOLETE_VERSION])dnl +m4_require([_LT_PROG_LTMAIN])dnl + +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + +dnl Parse OPTIONS +_LT_SET_OPTIONS([$0], [$1]) + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +_LT_SETUP + +# Only expand once: +m4_define([LT_INIT]) +])# LT_INIT + +# Old names: +AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) +AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PROG_LIBTOOL], []) +dnl AC_DEFUN([AM_PROG_LIBTOOL], []) + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +m4_defun([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +]) + + +# _LT_FILEUTILS_DEFAULTS +# ---------------------- +# It is okay to use these file commands and assume they have been set +# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. +m4_defun([_LT_FILEUTILS_DEFAULTS], +[: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} +])# _LT_FILEUTILS_DEFAULTS + + +# _LT_SETUP +# --------- +m4_defun([_LT_SETUP], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + +_LT_DECL([], [host_alias], [0], [The host system])dnl +_LT_DECL([], [host], [0])dnl +_LT_DECL([], [host_os], [0])dnl +dnl +_LT_DECL([], [build_alias], [0], [The build system])dnl +_LT_DECL([], [build], [0])dnl +_LT_DECL([], [build_os], [0])dnl +dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +dnl +AC_REQUIRE([AC_PROG_LN_S])dnl +test -z "$LN_S" && LN_S="ln -s" +_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl +dnl +AC_REQUIRE([LT_CMD_MAX_LEN])dnl +_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl +_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl +dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl +m4_require([_LT_CMD_RELOAD])dnl +m4_require([_LT_CHECK_MAGIC_METHOD])dnl +m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl +m4_require([_LT_CMD_OLD_ARCHIVE])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_WITH_SYSROOT])dnl + +_LT_CONFIG_LIBTOOL_INIT([ +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi +]) +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +_LT_CHECK_OBJDIR + +m4_require([_LT_TAG_COMPILER])dnl + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + _LT_PATH_MAGIC + fi + ;; +esac + +# Use C for the default configuration in the libtool script +LT_SUPPORTED_TAG([CC]) +_LT_LANG_C_CONFIG +_LT_LANG_DEFAULT_CONFIG +_LT_CONFIG_COMMANDS +])# _LT_SETUP + + +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + +# _LT_PROG_LTMAIN +# --------------- +# Note that this code is called both from `configure', and `config.status' +# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, +# `config.status' has no value for ac_aux_dir unless we are using Automake, +# so we pass a copy along to make sure it has a sensible value anyway. +m4_defun([_LT_PROG_LTMAIN], +[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl +_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) +ltmain="$ac_aux_dir/ltmain.sh" +])# _LT_PROG_LTMAIN + + + +# So that we can recreate a full libtool script including additional +# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS +# in macros and then make a single call at the end using the `libtool' +# label. + + +# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) +# ---------------------------------------- +# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL_INIT], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_INIT], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_INIT]) + + +# _LT_CONFIG_LIBTOOL([COMMANDS]) +# ------------------------------ +# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. +m4_define([_LT_CONFIG_LIBTOOL], +[m4_ifval([$1], + [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], + [$1 +])])]) + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) + + +# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) +# ----------------------------------------------------- +m4_defun([_LT_CONFIG_SAVE_COMMANDS], +[_LT_CONFIG_LIBTOOL([$1]) +_LT_CONFIG_LIBTOOL_INIT([$2]) +]) + + +# _LT_FORMAT_COMMENT([COMMENT]) +# ----------------------------- +# Add leading comment marks to the start of each line, and a trailing +# full-stop to the whole comment if one is not present already. +m4_define([_LT_FORMAT_COMMENT], +[m4_ifval([$1], [ +m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], + [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) +)]) + + + + + +# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) +# ------------------------------------------------------------------- +# CONFIGNAME is the name given to the value in the libtool script. +# VARNAME is the (base) name used in the configure script. +# VALUE may be 0, 1 or 2 for a computed quote escaped value based on +# VARNAME. Any other value will be used directly. +m4_define([_LT_DECL], +[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], + [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], + [m4_ifval([$1], [$1], [$2])]) + lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) + m4_ifval([$4], + [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) + lt_dict_add_subkey([lt_decl_dict], [$2], + [tagged?], [m4_ifval([$5], [yes], [no])])]) +]) + + +# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) +# -------------------------------------------------------- +m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) + + +# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_tag_varnames], +[_lt_decl_filter([tagged?], [yes], $@)]) + + +# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) +# --------------------------------------------------------- +m4_define([_lt_decl_filter], +[m4_case([$#], + [0], [m4_fatal([$0: too few arguments: $#])], + [1], [m4_fatal([$0: too few arguments: $#: $1])], + [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], + [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], + [lt_dict_filter([lt_decl_dict], $@)])[]dnl +]) + + +# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) +# -------------------------------------------------- +m4_define([lt_decl_quote_varnames], +[_lt_decl_filter([value], [1], $@)]) + + +# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_dquote_varnames], +[_lt_decl_filter([value], [2], $@)]) + + +# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) +# --------------------------------------------------- +m4_define([lt_decl_varnames_tagged], +[m4_assert([$# <= 2])dnl +_$0(m4_quote(m4_default([$1], [[, ]])), + m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), + m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) +m4_define([_lt_decl_varnames_tagged], +[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) + + +# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) +# ------------------------------------------------ +m4_define([lt_decl_all_varnames], +[_$0(m4_quote(m4_default([$1], [[, ]])), + m4_if([$2], [], + m4_quote(lt_decl_varnames), + m4_quote(m4_shift($@))))[]dnl +]) +m4_define([_lt_decl_all_varnames], +[lt_join($@, lt_decl_varnames_tagged([$1], + lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl +]) + + +# _LT_CONFIG_STATUS_DECLARE([VARNAME]) +# ------------------------------------ +# Quote a variable value, and forward it to `config.status' so that its +# declaration there will have the same value as in `configure'. VARNAME +# must have a single quote delimited value for this to work. +m4_define([_LT_CONFIG_STATUS_DECLARE], +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) + + +# _LT_CONFIG_STATUS_DECLARATIONS +# ------------------------------ +# We delimit libtool config variables with single quotes, so when +# we write them to config.status, we have to be sure to quote all +# embedded single quotes properly. In configure, this macro expands +# each variable declared with _LT_DECL (and _LT_TAGDECL) into: +# +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' +m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], +[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), + [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAGS +# ---------------- +# Output comment and list of tags supported by the script +m4_defun([_LT_LIBTOOL_TAGS], +[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl +available_tags="_LT_TAGS"dnl +]) + + +# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) +# ----------------------------------- +# Extract the dictionary values for VARNAME (optionally with TAG) and +# expand to a commented shell variable setting: +# +# # Some comment about what VAR is for. +# visible_name=$lt_internal_name +m4_define([_LT_LIBTOOL_DECLARE], +[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], + [description])))[]dnl +m4_pushdef([_libtool_name], + m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl +m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), + [0], [_libtool_name=[$]$1], + [1], [_libtool_name=$lt_[]$1], + [2], [_libtool_name=$lt_[]$1], + [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl +m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl +]) + + +# _LT_LIBTOOL_CONFIG_VARS +# ----------------------- +# Produce commented declarations of non-tagged libtool config variables +# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' +# script. Tagged libtool config variables (even for the LIBTOOL CONFIG +# section) are produced by _LT_LIBTOOL_TAG_VARS. +m4_defun([_LT_LIBTOOL_CONFIG_VARS], +[m4_foreach([_lt_var], + m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) + + +# _LT_LIBTOOL_TAG_VARS(TAG) +# ------------------------- +m4_define([_LT_LIBTOOL_TAG_VARS], +[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), + [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) + + +# _LT_TAGVAR(VARNAME, [TAGNAME]) +# ------------------------------ +m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) + + +# _LT_CONFIG_COMMANDS +# ------------------- +# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of +# variables for single and double quote escaping we saved from calls +# to _LT_DECL, we can put quote escaped variables declarations +# into `config.status', and then the shell code to quote escape them in +# for loops in `config.status'. Finally, any additional code accumulated +# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. +m4_defun([_LT_CONFIG_COMMANDS], +[AC_PROVIDE_IFELSE([LT_OUTPUT], + dnl If the libtool generation code has been placed in $CONFIG_LT, + dnl instead of duplicating it all over again into config.status, + dnl then we will have config.status run $CONFIG_LT later, so it + dnl needs to know what name is stored there: + [AC_CONFIG_COMMANDS([libtool], + [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], + dnl If the libtool generation code is destined for config.status, + dnl expand the accumulated commands and init code now: + [AC_CONFIG_COMMANDS([libtool], + [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) +])#_LT_CONFIG_COMMANDS + + +# Initialize. +m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], +[ + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +_LT_CONFIG_STATUS_DECLARATIONS +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_quote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in lt_decl_all_varnames([[ \ +]], lt_decl_dquote_varnames); do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[[\\\\\\\`\\"\\\$]]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +_LT_OUTPUT_LIBTOOL_INIT +]) + +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# `#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test $lt_write_fail = 0 && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT + +# LT_OUTPUT +# --------- +# This macro allows early generation of the libtool script (before +# AC_OUTPUT is called), incase it is used in configure for compilation +# tests. +AC_DEFUN([LT_OUTPUT], +[: ${CONFIG_LT=./config.lt} +AC_MSG_NOTICE([creating $CONFIG_LT]) +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) + +cat >>"$CONFIG_LT" <<\_LTEOF +lt_cl_silent=false +exec AS_MESSAGE_LOG_FD>>config.log +{ + echo + AS_BOX([Running $as_me.]) +} >&AS_MESSAGE_LOG_FD + +lt_cl_help="\ +\`$as_me' creates a local libtool stub from the current configuration, +for use in further configure time tests before the real libtool is +generated. + +Usage: $[0] [[OPTIONS]] + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + +Report bugs to ." + +lt_cl_version="\ +m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl +m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) +configured by $[0], generated by m4_PACKAGE_STRING. + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.lt script is free software; the Free Software Foundation +gives unlimited permision to copy, distribute and modify it." + +while test $[#] != 0 +do + case $[1] in + --version | --v* | -V ) + echo "$lt_cl_version"; exit 0 ;; + --help | --h* | -h ) + echo "$lt_cl_help"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --quiet | --q* | --silent | --s* | -q ) + lt_cl_silent=: ;; + + -*) AC_MSG_ERROR([unrecognized option: $[1] +Try \`$[0] --help' for more information.]) ;; + + *) AC_MSG_ERROR([unrecognized argument: $[1] +Try \`$[0] --help' for more information.]) ;; + esac + shift +done + +if $lt_cl_silent; then + exec AS_MESSAGE_FD>/dev/null +fi +_LTEOF + +cat >>"$CONFIG_LT" <<_LTEOF +_LT_OUTPUT_LIBTOOL_COMMANDS_INIT +_LTEOF + +cat >>"$CONFIG_LT" <<\_LTEOF +AC_MSG_NOTICE([creating $ofile]) +_LT_OUTPUT_LIBTOOL_COMMANDS +AS_EXIT(0) +_LTEOF +chmod +x "$CONFIG_LT" + +# configure is writing to config.log, but config.lt does its own redirection, +# appending to config.log, which fails on DOS, as config.log is still kept +# open by configure. Here we exec the FD to /dev/null, effectively closing +# config.log, so it can be properly (re)opened and appended to by config.lt. +lt_cl_success=: +test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) +])# LT_OUTPUT + + +# _LT_CONFIG(TAG) +# --------------- +# If TAG is the built-in tag, create an initial libtool script with a +# default configuration from the untagged config vars. Otherwise add code +# to config.status for appending the configuration named by TAG from the +# matching tagged config vars. +m4_defun([_LT_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_CONFIG_SAVE_COMMANDS([ + m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl + m4_if(_LT_TAG, [C], [ + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +_LT_COPYING +_LT_LIBTOOL_TAGS + +# ### BEGIN LIBTOOL CONFIG +_LT_LIBTOOL_CONFIG_VARS +_LT_LIBTOOL_TAG_VARS +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + _LT_PROG_LTMAIN + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + _LT_PROG_REPLACE_SHELLFNS + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +], +[cat <<_LT_EOF >> "$ofile" + +dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded +dnl in a comment (ie after a #). +# ### BEGIN LIBTOOL TAG CONFIG: $1 +_LT_LIBTOOL_TAG_VARS(_LT_TAG) +# ### END LIBTOOL TAG CONFIG: $1 +_LT_EOF +])dnl /m4_if +], +[m4_if([$1], [], [ + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile'], []) +])dnl /_LT_CONFIG_SAVE_COMMANDS +])# _LT_CONFIG + + +# LT_SUPPORTED_TAG(TAG) +# --------------------- +# Trace this macro to discover what tags are supported by the libtool +# --tag option, using: +# autoconf --trace 'LT_SUPPORTED_TAG:$1' +AC_DEFUN([LT_SUPPORTED_TAG], []) + + +# C support is built-in for now +m4_define([_LT_LANG_C_enabled], []) +m4_define([_LT_TAGS], []) + + +# LT_LANG(LANG) +# ------------- +# Enable libtool support for the given language if not already enabled. +AC_DEFUN([LT_LANG], +[AC_BEFORE([$0], [LT_OUTPUT])dnl +m4_case([$1], + [C], [_LT_LANG(C)], + [C++], [_LT_LANG(CXX)], + [Java], [_LT_LANG(GCJ)], + [Fortran 77], [_LT_LANG(F77)], + [Fortran], [_LT_LANG(FC)], + [Windows Resource], [_LT_LANG(RC)], + [m4_ifdef([_LT_LANG_]$1[_CONFIG], + [_LT_LANG($1)], + [m4_fatal([$0: unsupported language: "$1"])])])dnl +])# LT_LANG + + +# _LT_LANG(LANGNAME) +# ------------------ +m4_defun([_LT_LANG], +[m4_ifdef([_LT_LANG_]$1[_enabled], [], + [LT_SUPPORTED_TAG([$1])dnl + m4_append([_LT_TAGS], [$1 ])dnl + m4_define([_LT_LANG_]$1[_enabled], [])dnl + _LT_LANG_$1_CONFIG($1)])dnl +])# _LT_LANG + + +# _LT_LANG_DEFAULT_CONFIG +# ----------------------- +m4_defun([_LT_LANG_DEFAULT_CONFIG], +[AC_PROVIDE_IFELSE([AC_PROG_CXX], + [LT_LANG(CXX)], + [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) + +AC_PROVIDE_IFELSE([AC_PROG_F77], + [LT_LANG(F77)], + [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) + +AC_PROVIDE_IFELSE([AC_PROG_FC], + [LT_LANG(FC)], + [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) + +dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal +dnl pulling things in needlessly. +AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [LT_LANG(GCJ)], + [AC_PROVIDE_IFELSE([LT_PROG_GCJ], + [LT_LANG(GCJ)], + [m4_ifdef([AC_PROG_GCJ], + [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([A][M_PROG_GCJ], + [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) + m4_ifdef([LT_PROG_GCJ], + [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) + +AC_PROVIDE_IFELSE([LT_PROG_RC], + [LT_LANG(RC)], + [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) +])# _LT_LANG_DEFAULT_CONFIG + +# Obsolete macros: +AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) +AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) +AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) +AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_CXX], []) +dnl AC_DEFUN([AC_LIBTOOL_F77], []) +dnl AC_DEFUN([AC_LIBTOOL_FC], []) +dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) + + +# _LT_TAG_COMPILER +# ---------------- +m4_defun([_LT_TAG_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl +_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl +_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl +_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_TAG_COMPILER + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +m4_defun([_LT_COMPILER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +m4_defun([_LT_LINKER_BOILERPLATE], +[m4_require([_LT_DECL_SED])dnl +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* +])# _LT_LINKER_BOILERPLATE + +# _LT_REQUIRED_DARWIN_CHECKS +# ------------------------- +m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ + case $host_os in + rhapsody* | darwin*) + AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) + AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) + AC_CHECK_TOOL([LIPO], [lipo], [:]) + AC_CHECK_TOOL([OTOOL], [otool], [:]) + AC_CHECK_TOOL([OTOOL64], [otool64], [:]) + _LT_DECL([], [DSYMUTIL], [1], + [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) + _LT_DECL([], [NMEDIT], [1], + [Tool to change global to local symbols on Mac OS X]) + _LT_DECL([], [LIPO], [1], + [Tool to manipulate fat objects and archives on Mac OS X]) + _LT_DECL([], [OTOOL], [1], + [ldd/readelf like tool for Mach-O binaries on Mac OS X]) + _LT_DECL([], [OTOOL64], [1], + [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) + + AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], + [lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi]) + AC_CACHE_CHECK([for -exported_symbols_list linker flag], + [lt_cv_ld_exported_symbols_list], + [lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [lt_cv_ld_exported_symbols_list=yes], + [lt_cv_ld_exported_symbols_list=no]) + LDFLAGS="$save_LDFLAGS" + ]) + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) + case $host_os in + rhapsody* | darwin1.[[012]]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[[012]]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac +]) + + +# _LT_DARWIN_LINKER_FEATURES +# -------------------------- +# Checks for linker and compiler features on darwin +m4_defun([_LT_DARWIN_LINKER_FEATURES], +[ + m4_require([_LT_REQUIRED_DARWIN_CHECKS]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_automatic, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + m4_if([$1], [CXX], +[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then + _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi +],[]) + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi +]) + +# _LT_SYS_MODULE_PATH_AIX([TAGNAME]) +# ---------------------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +# Store the results from the different compilers for each TAGNAME. +# Allow to override them for all tags through lt_cv_aix_libpath. +m4_defun([_LT_SYS_MODULE_PATH_AIX], +[m4_require([_LT_DECL_SED])dnl +if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], + [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ + lt_aix_libpath_sed='[ + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }]' + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi],[]) + if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then + _LT_TAGVAR([lt_cv_aix_libpath_], [$1])="/usr/lib:/lib" + fi + ]) + aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) +fi +])# _LT_SYS_MODULE_PATH_AIX + + +# _LT_SHELL_INIT(ARG) +# ------------------- +m4_define([_LT_SHELL_INIT], +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + + + +# _LT_PROG_ECHO_BACKSLASH +# ----------------------- +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script which will find a shell with a builtin +# printf (which we can use as an echo command). +m4_defun([_LT_PROG_ECHO_BACKSLASH], +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +case "$ECHO" in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac + +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) + +_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) +])# _LT_PROG_ECHO_BACKSLASH + + +# _LT_WITH_SYSROOT +# ---------------- +AC_DEFUN([_LT_WITH_SYSROOT], +[AC_MSG_CHECKING([for sysroot]) +AC_ARG_WITH([sysroot], +[ --with-sysroot[=DIR] Search for dependent libraries within DIR + (or the compiler's sysroot if not specified).], +[], [with_sysroot=no]) + +dnl lt_sysroot will always be passed unquoted. We quote it here +dnl in case the user passed a directory name. +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + AC_MSG_RESULT([${with_sysroot}]) + AC_MSG_ERROR([The sysroot must be an absolute path.]) + ;; +esac + + AC_MSG_RESULT([${lt_sysroot:-no}]) +_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl +[dependent libraries, and in which our libraries should be installed.])]) + +# _LT_ENABLE_LOCK +# --------------- +m4_defun([_LT_ENABLE_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AS_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" +])# _LT_ENABLE_LOCK + + +# _LT_PROG_AR +# ----------- +m4_defun([_LT_PROG_AR], +[AC_CHECK_TOOLS(AR, [ar], false) +: ${AR=ar} +: ${AR_FLAGS=cru} +_LT_DECL([], [AR], [1], [The archiver]) +_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) + +AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], + [lt_cv_ar_at_file=no + AC_COMPILE_IFELSE([AC_LANG_PROGRAM], + [echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + AC_TRY_EVAL([lt_ar_try]) + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + ]) + ]) + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi +_LT_DECL([], [archiver_list_spec], [1], + [How to feed a file listing to the archiver]) +])# _LT_PROG_AR + + +# _LT_CMD_OLD_ARCHIVE +# ------------------- +m4_defun([_LT_CMD_OLD_ARCHIVE], +[_LT_PROG_AR + +AC_CHECK_TOOL(STRIP, strip, :) +test -z "$STRIP" && STRIP=: +_LT_DECL([], [STRIP], [1], [A symbol stripping program]) + +AC_CHECK_TOOL(RANLIB, ranlib, :) +test -z "$RANLIB" && RANLIB=: +_LT_DECL([], [RANLIB], [1], + [Commands used to install an old-style archive]) + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac +_LT_DECL([], [old_postinstall_cmds], [2]) +_LT_DECL([], [old_postuninstall_cmds], [2]) +_LT_TAGDECL([], [old_archive_cmds], [2], + [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) +])# _LT_CMD_OLD_ARCHIVE + + +# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([_LT_COMPILER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $RM conftest* +]) + +if test x"[$]$2" = xyes; then + m4_if([$5], , :, [$5]) +else + m4_if([$6], , :, [$6]) +fi +])# _LT_COMPILER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) + + +# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------- +# Check whether the given linker option works +AC_DEFUN([_LT_LINKER_OPTION], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_SED])dnl +AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + m4_if([$4], , :, [$4]) +else + m4_if([$5], , :, [$5]) +fi +])# _LT_LINKER_OPTION + +# Old name: +AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) + + +# LT_CMD_MAX_LEN +#--------------- +AC_DEFUN([LT_CMD_MAX_LEN], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +max_cmd_len=$lt_cv_sys_max_cmd_len +_LT_DECL([], [max_cmd_len], [0], + [What is the maximum length of a command?]) +])# LT_CMD_MAX_LEN + +# Old name: +AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) + + +# _LT_HEADER_DLFCN +# ---------------- +m4_defun([_LT_HEADER_DLFCN], +[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl +])# _LT_HEADER_DLFCN + + +# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ---------------------------------------------------------------- +m4_defun([_LT_TRY_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +[#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +}] +_LT_EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_TRY_DLOPEN_SELF + + +# LT_SYS_DLOPEN_SELF +# ------------------ +AC_DEFUN([LT_SYS_DLOPEN_SELF], +[m4_require([_LT_HEADER_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +_LT_DECL([dlopen_support], [enable_dlopen], [0], + [Whether dlopen is supported]) +_LT_DECL([dlopen_self], [enable_dlopen_self], [0], + [Whether dlopen of programs is supported]) +_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], + [Whether dlopen of statically linked programs is supported]) +])# LT_SYS_DLOPEN_SELF + +# Old name: +AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) + + +# _LT_COMPILER_C_O([TAGNAME]) +# --------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler. +# This macro does not hard code the compiler like AC_PROG_CC_C_O. +m4_defun([_LT_COMPILER_C_O], +[m4_require([_LT_DECL_SED])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* +]) +_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], + [Does compiler simultaneously support -c and -o options?]) +])# _LT_COMPILER_C_O + + +# _LT_COMPILER_FILE_LOCKS([TAGNAME]) +# ---------------------------------- +# Check to see if we can do hard links to lock some files if needed +m4_defun([_LT_COMPILER_FILE_LOCKS], +[m4_require([_LT_ENABLE_LOCK])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +_LT_COMPILER_C_O([$1]) + +hard_links="nottested" +if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) +])# _LT_COMPILER_FILE_LOCKS + + +# _LT_CHECK_OBJDIR +# ---------------- +m4_defun([_LT_CHECK_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +_LT_DECL([], [objdir], [0], + [The name of the directory that contains temporary libtool files])dnl +m4_pattern_allow([LT_OBJDIR])dnl +AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", + [Define to the sub-directory in which libtool stores uninstalled libraries.]) +])# _LT_CHECK_OBJDIR + + +# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) +# -------------------------------------- +# Check hardcoding attributes. +m4_defun([_LT_LINKER_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || + test -n "$_LT_TAGVAR(runpath_var, $1)" || + test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || + test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +_LT_TAGDECL([], [hardcode_action], [0], + [How to hardcode a shared library path into an executable]) +])# _LT_LINKER_HARDCODE_LIBPATH + + +# _LT_CMD_STRIPLIB +# ---------------- +m4_defun([_LT_CMD_STRIPLIB], +[m4_require([_LT_DECL_EGREP]) +striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) +_LT_DECL([], [striplib], [1]) +])# _LT_CMD_STRIPLIB + + +# _LT_SYS_DYNAMIC_LINKER([TAG]) +# ----------------------------- +# PORTME Fill in your ld.so characteristics +m4_defun([_LT_SYS_DYNAMIC_LINKER], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_OBJDUMP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl +AC_MSG_CHECKING([dynamic linker characteristics]) +m4_if([$1], + [], [ +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[[lt_foo]]++; } + if (lt_freq[[lt_foo]] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[[4-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[[3-9]]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + +_LT_DECL([], [variables_saved_for_relink], [1], + [Variables whose values should be saved in libtool wrapper scripts and + restored at link time]) +_LT_DECL([], [need_lib_prefix], [0], + [Do we need the "lib" prefix for modules?]) +_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) +_LT_DECL([], [version_type], [0], [Library versioning type]) +_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) +_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) +_LT_DECL([], [shlibpath_overrides_runpath], [0], + [Is shlibpath searched before the hard-coded library search path?]) +_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) +_LT_DECL([], [library_names_spec], [1], + [[List of archive names. First name is the real one, the rest are links. + The last name is the one that the linker finds with -lNAME]]) +_LT_DECL([], [soname_spec], [1], + [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) +_LT_DECL([], [postinstall_cmds], [2], + [Command to use after installation of a shared archive]) +_LT_DECL([], [postuninstall_cmds], [2], + [Command to use after uninstallation of a shared archive]) +_LT_DECL([], [finish_cmds], [2], + [Commands used to finish a libtool library installation in a directory]) +_LT_DECL([], [finish_eval], [1], + [[As "finish_cmds", except a single script fragment to be evaled but + not shown]]) +_LT_DECL([], [hardcode_into_libs], [0], + [Whether we should hardcode library paths into libraries]) +_LT_DECL([], [sys_lib_search_path_spec], [2], + [Compile-time system search path for libraries]) +_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], + [Run-time system search path for libraries]) +])# _LT_SYS_DYNAMIC_LINKER + + +# _LT_PATH_TOOL_PREFIX(TOOL) +# -------------------------- +# find a file program which can recognize shared library +AC_DEFUN([_LT_PATH_TOOL_PREFIX], +[m4_require([_LT_DECL_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="m4_if([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +_LT_DECL([], [MAGIC_CMD], [0], + [Used to examine libraries when file_magic_cmd begins with "file"])dnl +])# _LT_PATH_TOOL_PREFIX + +# Old name: +AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) + + +# _LT_PATH_MAGIC +# -------------- +# find a file program which can recognize a shared library +m4_defun([_LT_PATH_MAGIC], +[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# _LT_PATH_MAGIC + + +# LT_PATH_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([LT_PATH_LD], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl + +AC_ARG_WITH([gnu-ld], + [AS_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no])dnl + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[[3-9]]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + +_LT_DECL([], [deplibs_check_method], [1], + [Method to check whether dependent libraries are shared objects]) +_LT_DECL([], [file_magic_cmd], [1], + [Command to use when deplibs_check_method = "file_magic"]) +_LT_DECL([], [file_magic_glob], [1], + [How to find potential files when deplibs_check_method = "file_magic"]) +_LT_DECL([], [want_nocaseglob], [1], + [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) +])# _LT_CHECK_MAGIC_METHOD + + +# LT_PATH_NM +# ---------- +# find the pathname to a BSD- or MS-compatible name lister +AC_DEFUN([LT_PATH_NM], +[AC_REQUIRE([AC_PROG_CC])dnl +AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi]) +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + AC_SUBST([DUMPBIN]) + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm +AC_SUBST([NM]) +_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl + +AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], + [lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&AS_MESSAGE_LOG_FD + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) + cat conftest.out >&AS_MESSAGE_LOG_FD + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest*]) +])# LT_PATH_NM + +# Old names: +AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) +AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_PROG_NM], []) +dnl AC_DEFUN([AC_PROG_NM], []) + +# _LT_CHECK_SHAREDLIB_FROM_LINKLIB +# -------------------------------- +# how to determine the name of the shared library +# associated with a specific link library. +# -- PORTME fill in with the dynamic library characteristics +m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], +[m4_require([_LT_DECL_EGREP]) +m4_require([_LT_DECL_OBJDUMP]) +m4_require([_LT_DECL_DLLTOOL]) +AC_CACHE_CHECK([how to associate runtime and link libraries], +lt_cv_sharedlib_from_linklib_cmd, +[lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac +]) +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + +_LT_DECL([], [sharedlib_from_linklib_cmd], [1], + [Command to associate shared and link libraries]) +])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB + + +# _LT_PATH_MANIFEST_TOOL +# ---------------------- +# locate the manifest tool +m4_defun([_LT_PATH_MANIFEST_TOOL], +[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], + [lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&AS_MESSAGE_LOG_FD + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest*]) +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi +_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl +])# _LT_PATH_MANIFEST_TOOL + + +# LT_LIB_M +# -------- +# check for math library +AC_DEFUN([LT_LIB_M], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +AC_SUBST([LIBM]) +])# LT_LIB_M + +# Old name: +AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_CHECK_LIBM], []) + + +# _LT_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------- +m4_defun([_LT_COMPILER_NO_RTTI], +[m4_require([_LT_TAG_COMPILER])dnl + +_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac + + _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], + [Compiler flag to turn off builtin functions]) +])# _LT_COMPILER_NO_RTTI + + +# _LT_CMD_GLOBAL_SYMBOLS +# ---------------------- +m4_defun([_LT_CMD_GLOBAL_SYMBOLS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([LT_PATH_NM])dnl +AC_REQUIRE([LT_PATH_LD])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_TAG_COMPILER])dnl + +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\)[[ ]]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK ['"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx]" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT@&t@_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT@&t@_DLSYM_CONST +#else +# define LT@&t@_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT@&t@_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[[]] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + +_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], + [Take the output of nm and produce a listing of raw symbols and C names]) +_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], + [Transform the output of nm in a proper C declaration]) +_LT_DECL([global_symbol_to_c_name_address], + [lt_cv_sys_global_symbol_to_c_name_address], [1], + [Transform the output of nm in a C name address pair]) +_LT_DECL([global_symbol_to_c_name_address_lib_prefix], + [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], + [Transform the output of nm in a C name address pair when lib prefix is needed]) +_LT_DECL([], [nm_file_list_spec], [1], + [Specify filename containing input files for $NM]) +]) # _LT_CMD_GLOBAL_SYMBOLS + + +# _LT_COMPILER_PIC([TAGNAME]) +# --------------------------- +m4_defun([_LT_COMPILER_PIC], +[m4_require([_LT_TAG_COMPILER])dnl +_LT_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_TAGVAR(lt_prog_compiler_static, $1)= + +m4_if([$1], [CXX], [ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix[[4-9]]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + interix[[3-9]]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Xcompiler -fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + m4_if([$1], [GCJ], [], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) + ;; + + hpux9* | hpux10* | hpux11*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' + _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' + ;; + nagfor*) + # NAG Fortran compiler + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + ;; + *Sun\ C*) + # Sun C 5.9 + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + esac + ;; + + newsos6) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + rdos*) + _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +AC_CACHE_CHECK([for $compiler option to produce PIC], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], + [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) +_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then + _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], + [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], + [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], + [Additional compiler flags for building library objects]) + +_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], + [How to pass a linker flag through the compiler]) +# +# Check to make sure the static flag actually works. +# +wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" +_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) +_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], + [Compiler flag to prevent dynamic linking]) +])# _LT_COMPILER_PIC + + +# _LT_LINKER_SHLIBS([TAGNAME]) +# ---------------------------- +# See if the linker supports building shared libraries. +m4_defun([_LT_LINKER_SHLIBS], +[AC_REQUIRE([LT_PATH_LD])dnl +AC_REQUIRE([LT_PATH_NM])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl +m4_require([_LT_TAG_COMPILER])dnl +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +m4_if([$1], [CXX], [ + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + case $host_os in + aix[[4-9]]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + ;; + esac + ;; + *) + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +], [ + runpath_var= + _LT_TAGVAR(allow_undefined_flag, $1)= + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(archive_cmds, $1)= + _LT_TAGVAR(archive_expsym_cmds, $1)= + _LT_TAGVAR(compiler_needs_object, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(hardcode_automatic, $1)=no + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_TAGVAR(hardcode_libdir_separator, $1)= + _LT_TAGVAR(hardcode_minus_L, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_TAGVAR(inherit_rpath, $1)=no + _LT_TAGVAR(link_all_deplibs, $1)=unknown + _LT_TAGVAR(module_cmds, $1)= + _LT_TAGVAR(module_expsym_cmds, $1)= + _LT_TAGVAR(old_archive_from_new_cmds, $1)= + _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_TAGVAR(thread_safe_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. +dnl Note also adjust exclude_expsyms for C++ above. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[[3-9]]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' + _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + _LT_TAGVAR(whole_archive_flag_spec, $1)= + tmp_sharedflag='--shared' ;; + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='' + ;; + m68k) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + ;; + + bsdi[[45]]*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + esac + ;; + + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], + [lt_cv_irix_exported_symbol], + [save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + AC_LINK_IFELSE( + [AC_LANG_SOURCE( + [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], + [C++], [[int foo (void) { return 0; }]], + [Fortran 77], [[ + subroutine foo + end]], + [Fortran], [[ + subroutine foo + end]])])], + [lt_cv_irix_exported_symbol=yes], + [lt_cv_irix_exported_symbol=no]) + LDFLAGS="$save_LDFLAGS"]) + if test "$lt_cv_irix_exported_symbol" = yes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + os2*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)='no' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + fi + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' + ;; + esac + fi + fi +]) +AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) +test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld + +_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl +_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl +_LT_DECL([], [extract_expsyms_cmds], [2], + [The commands to extract the exported symbol list from a shared archive]) + +# +# Do we need to explicitly link libc? +# +case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) + ;; + esac + fi + ;; +esac + +_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], + [Whether or not to add -lc for building shared libraries]) +_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], + [enable_shared_with_static_runtimes], [0], + [Whether or not to disallow shared libs when runtime libs are static]) +_LT_TAGDECL([], [export_dynamic_flag_spec], [1], + [Compiler flag to allow reflexive dlopens]) +_LT_TAGDECL([], [whole_archive_flag_spec], [1], + [Compiler flag to generate shared objects directly from archives]) +_LT_TAGDECL([], [compiler_needs_object], [1], + [Whether the compiler copes with passing no objects directly]) +_LT_TAGDECL([], [old_archive_from_new_cmds], [2], + [Create an old-style archive from a shared archive]) +_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], + [Create a temporary old-style archive to link instead of a shared archive]) +_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) +_LT_TAGDECL([], [archive_expsym_cmds], [2]) +_LT_TAGDECL([], [module_cmds], [2], + [Commands used to build a loadable module if different from building + a shared archive.]) +_LT_TAGDECL([], [module_expsym_cmds], [2]) +_LT_TAGDECL([], [with_gnu_ld], [1], + [Whether we are building with GNU ld or not]) +_LT_TAGDECL([], [allow_undefined_flag], [1], + [Flag that allows shared libraries with undefined symbols to be built]) +_LT_TAGDECL([], [no_undefined_flag], [1], + [Flag that enforces no undefined symbols]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], + [Flag to hardcode $libdir into a binary during linking. + This must work even if $libdir does not exist]) +_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], + [[If ld is used when linking, flag to hardcode $libdir into a binary + during linking. This must work even if $libdir does not exist]]) +_LT_TAGDECL([], [hardcode_libdir_separator], [1], + [Whether we need a single "-rpath" flag with a separated argument]) +_LT_TAGDECL([], [hardcode_direct], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary]) +_LT_TAGDECL([], [hardcode_direct_absolute], [0], + [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes + DIR into the resulting binary and the resulting library dependency is + "absolute", i.e impossible to change by setting ${shlibpath_var} if the + library is relocated]) +_LT_TAGDECL([], [hardcode_minus_L], [0], + [Set to "yes" if using the -LDIR flag during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_shlibpath_var], [0], + [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR + into the resulting binary]) +_LT_TAGDECL([], [hardcode_automatic], [0], + [Set to "yes" if building a shared library automatically hardcodes DIR + into the library and all subsequent libraries and executables linked + against it]) +_LT_TAGDECL([], [inherit_rpath], [0], + [Set to yes if linker adds runtime paths of dependent libraries + to runtime path list]) +_LT_TAGDECL([], [link_all_deplibs], [0], + [Whether libtool must link a program against all its dependency libraries]) +_LT_TAGDECL([], [always_export_symbols], [0], + [Set to "yes" if exported symbols are required]) +_LT_TAGDECL([], [export_symbols_cmds], [2], + [The commands to list exported symbols]) +_LT_TAGDECL([], [exclude_expsyms], [1], + [Symbols that should not be listed in the preloaded symbols]) +_LT_TAGDECL([], [include_expsyms], [1], + [Symbols that must always be exported]) +_LT_TAGDECL([], [prelink_cmds], [2], + [Commands necessary for linking programs (against libraries) with templates]) +_LT_TAGDECL([], [postlink_cmds], [2], + [Commands necessary for finishing linking programs]) +_LT_TAGDECL([], [file_list_spec], [1], + [Specify filename containing input files]) +dnl FIXME: Not yet implemented +dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], +dnl [Compiler flag to generate thread safe objects]) +])# _LT_LINKER_SHLIBS + + +# _LT_LANG_C_CONFIG([TAG]) +# ------------------------ +# Ensure that the configuration variables for a C compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_C_CONFIG], +[m4_require([_LT_DECL_EGREP])dnl +lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + +_LT_TAG_COMPILER +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + LT_SYS_DLOPEN_SELF + _LT_CMD_STRIPLIB + + # Report which library types will actually be built + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_CONFIG($1) +fi +AC_LANG_POP +CC="$lt_save_CC" +])# _LT_LANG_C_CONFIG + + +# _LT_LANG_CXX_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a C++ compiler are suitably +# defined. These variables are subsequently used by _LT_CONFIG to write +# the compiler configuration to `libtool'. +m4_defun([_LT_LANG_CXX_CONFIG], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PATH_MANIFEST_TOOL])dnl +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi + +AC_LANG_PUSH(C++) +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(compiler_needs_object, $1)=no +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + else + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + LT_PATH_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) + _LT_TAGVAR(ld_shlibs, $1)=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aix[[4-9]]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_TAGVAR(archive_cmds, $1)='' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + _LT_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_TAGVAR(hardcode_minus_L, $1)=yes + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + _LT_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + _LT_SYS_MODULE_PATH_AIX([$1]) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi + _LT_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=yes + _LT_TAGVAR(file_list_spec, $1)='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + # Don't use ranlib + _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' + _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' + _LT_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_TAGVAR(always_export_symbols, $1)=no + _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + _LT_DARWIN_LINKER_FEATURES($1) + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + freebsd-elf*) + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + gnu*) + ;; + + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + + hpux9*) + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + interix[[3-9]]*) + _LT_TAGVAR(hardcode_direct, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + fi + fi + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_TAGVAR(inherit_rpath, $1)=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) + _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + _LT_TAGVAR(ld_shlibs, $1)=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + _LT_TAGVAR(hardcode_direct, $1)=yes + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_direct_absolute, $1)=yes + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + case $host in + osf3*) + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + ;; + *) + _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' + ;; + esac + _LT_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' + _LT_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_TAGVAR(link_all_deplibs, $1)=yes + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" + ;; + *) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + + *) + # FIXME: insert proper C++ library support + _LT_TAGVAR(ld_shlibs, $1)=no + ;; + esac + + AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) + test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + + _LT_TAGVAR(GCC, $1)="$GXX" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +AC_LANG_POP +])# _LT_LANG_CXX_CONFIG + + +# _LT_FUNC_STRIPNAME_CNF +# ---------------------- +# func_stripname_cnf prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# +# This function is identical to the (non-XSI) version of func_stripname, +# except this one can be used by m4 code that may be executed by configure, +# rather than the libtool script. +m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl +AC_REQUIRE([_LT_DECL_SED]) +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf +])# _LT_FUNC_STRIPNAME_CNF + +# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) +# --------------------------------- +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +m4_defun([_LT_SYS_HIDDEN_LIBDEPS], +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl +AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl +# Dependencies to place before and after the object being linked: +_LT_TAGVAR(predep_objects, $1)= +_LT_TAGVAR(postdep_objects, $1)= +_LT_TAGVAR(predeps, $1)= +_LT_TAGVAR(postdeps, $1)= +_LT_TAGVAR(compiler_lib_search_path, $1)= + +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF +int a; +void foo (void) { a = 0; } +_LT_EOF +], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF +], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +_LT_EOF +], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF + subroutine foo + implicit none + integer a + a=0 + return + end +_LT_EOF +], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +_LT_EOF +]) + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +esac + +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case ${prev}${p} in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test "$pre_test_object_deps_done" = no; then + case ${prev} in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_TAGVAR(postdeps, $1)"; then + _LT_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_TAGVAR(predep_objects, $1)"; then + _LT_TAGVAR(predep_objects, $1)="$p" + else + _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then + _LT_TAGVAR(postdep_objects, $1)="$p" + else + _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +m4_if([$1], [CXX], +[case $host_os in +interix[[3-9]]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + _LT_TAGVAR(predep_objects,$1)= + _LT_TAGVAR(postdep_objects,$1)= + _LT_TAGVAR(postdeps,$1)= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac +]) + +case " $_LT_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac + _LT_TAGVAR(compiler_lib_search_dirs, $1)= +if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then + _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi +_LT_TAGDECL([], [compiler_lib_search_dirs], [1], + [The directories searched by this compiler when creating a shared library]) +_LT_TAGDECL([], [predep_objects], [1], + [Dependencies to place before and after the objects being linked to + create a shared library]) +_LT_TAGDECL([], [postdep_objects], [1]) +_LT_TAGDECL([], [predeps], [1]) +_LT_TAGDECL([], [postdeps], [1]) +_LT_TAGDECL([], [compiler_lib_search_path], [1], + [The library search path used internally by the compiler when linking + a shared library]) +])# _LT_SYS_HIDDEN_LIBDEPS + + +# _LT_LANG_F77_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for a Fortran 77 compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_F77_CONFIG], +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the F77 compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_F77" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${F77-"f77"} + CFLAGS=$FFLAGS + compiler=$CC + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + GCC=$G77 + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$G77" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC="$lt_save_CC" + CFLAGS="$lt_save_CFLAGS" +fi # test "$_lt_disable_F77" != yes + +AC_LANG_POP +])# _LT_LANG_F77_CONFIG + + +# _LT_LANG_FC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for a Fortran compiler are +# suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_FC_CONFIG], +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi + +_LT_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_TAGVAR(allow_undefined_flag, $1)= +_LT_TAGVAR(always_export_symbols, $1)=no +_LT_TAGVAR(archive_expsym_cmds, $1)= +_LT_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_TAGVAR(hardcode_direct, $1)=no +_LT_TAGVAR(hardcode_direct_absolute, $1)=no +_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_TAGVAR(hardcode_libdir_separator, $1)= +_LT_TAGVAR(hardcode_minus_L, $1)=no +_LT_TAGVAR(hardcode_automatic, $1)=no +_LT_TAGVAR(inherit_rpath, $1)=no +_LT_TAGVAR(module_cmds, $1)= +_LT_TAGVAR(module_expsym_cmds, $1)= +_LT_TAGVAR(link_all_deplibs, $1)=unknown +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds +_LT_TAGVAR(no_undefined_flag, $1)= +_LT_TAGVAR(whole_archive_flag_spec, $1)= +_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for fc test sources. +ac_ext=${ac_fc_srcext-f} + +# Object file extension for compiled fc test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# No sense in running all these tests if we already determined that +# the FC compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_disable_FC" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="\ + subroutine t + return + end +" + + # Code to be used in simple link tests + lt_simple_link_test_code="\ + program t + end +" + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + _LT_TAG_COMPILER + + # save warnings/boilerplate of simple test code + _LT_COMPILER_BOILERPLATE + _LT_LINKER_BOILERPLATE + + # Allow CC to be a program name with arguments. + lt_save_CC="$CC" + lt_save_GCC=$GCC + lt_save_CFLAGS=$CFLAGS + CC=${FC-"f95"} + CFLAGS=$FCFLAGS + compiler=$CC + GCC=$ac_cv_fc_compiler_gnu + + _LT_TAGVAR(compiler, $1)=$CC + _LT_CC_BASENAME([$compiler]) + + if test -n "$compiler"; then + AC_MSG_CHECKING([if libtool supports shared libraries]) + AC_MSG_RESULT([$can_build_shared]) + + AC_MSG_CHECKING([whether to build shared libraries]) + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + aix[[4-9]]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + AC_MSG_RESULT([$enable_shared]) + + AC_MSG_CHECKING([whether to build static libraries]) + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + AC_MSG_RESULT([$enable_static]) + + _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" + _LT_TAGVAR(LD, $1)="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + _LT_SYS_HIDDEN_LIBDEPS($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_SYS_DYNAMIC_LINKER($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) + fi # test -n "$compiler" + + GCC=$lt_save_GCC + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS +fi # test "$_lt_disable_FC" != yes + +AC_LANG_POP +])# _LT_LANG_FC_CONFIG + + +# _LT_LANG_GCJ_CONFIG([TAG]) +# -------------------------- +# Ensure that the configuration variables for the GNU Java Compiler compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_GCJ_CONFIG], +[AC_REQUIRE([LT_PROG_GCJ])dnl +AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC=yes +CC=${GCJ-"gcj"} +CFLAGS=$GCJFLAGS +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_TAGVAR(LD, $1)="$LD" +_LT_CC_BASENAME([$compiler]) + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_TAGVAR(archive_cmds_need_lc, $1)=no + +_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds + +if test -n "$compiler"; then + _LT_COMPILER_NO_RTTI($1) + _LT_COMPILER_PIC($1) + _LT_COMPILER_C_O($1) + _LT_COMPILER_FILE_LOCKS($1) + _LT_LINKER_SHLIBS($1) + _LT_LINKER_HARDCODE_LIBPATH($1) + + _LT_CONFIG($1) +fi + +AC_LANG_RESTORE + +GCC=$lt_save_GCC +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_GCJ_CONFIG + + +# _LT_LANG_RC_CONFIG([TAG]) +# ------------------------- +# Ensure that the configuration variables for the Windows resource compiler +# are suitably defined. These variables are subsequently used by _LT_CONFIG +# to write the compiler configuration to `libtool'. +m4_defun([_LT_LANG_RC_CONFIG], +[AC_REQUIRE([LT_PROG_RC])dnl +AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_TAG_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +lt_save_CFLAGS=$CFLAGS +lt_save_GCC=$GCC +GCC= +CC=${RC-"windres"} +CFLAGS= +compiler=$CC +_LT_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) +_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +if test -n "$compiler"; then + : + _LT_CONFIG($1) +fi + +GCC=$lt_save_GCC +AC_LANG_RESTORE +CC=$lt_save_CC +CFLAGS=$lt_save_CFLAGS +])# _LT_LANG_RC_CONFIG + + +# LT_PROG_GCJ +# ----------- +AC_DEFUN([LT_PROG_GCJ], +[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], + [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], + [AC_CHECK_TOOL(GCJ, gcj,) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS)])])[]dnl +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_GCJ], []) + + +# LT_PROG_RC +# ---------- +AC_DEFUN([LT_PROG_RC], +[AC_CHECK_TOOL(RC, windres,) +]) + +# Old name: +AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_RC], []) + + +# _LT_DECL_EGREP +# -------------- +# If we don't have a new enough Autoconf to choose the best grep +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_EGREP], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_REQUIRE([AC_PROG_FGREP])dnl +test -z "$GREP" && GREP=grep +_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) +_LT_DECL([], [EGREP], [1], [An ERE matcher]) +_LT_DECL([], [FGREP], [1], [A literal string matcher]) +dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too +AC_SUBST([GREP]) +]) + + +# _LT_DECL_OBJDUMP +# -------------- +# If we don't have a new enough Autoconf to choose the best objdump +# available, choose the one first in the user's PATH. +m4_defun([_LT_DECL_OBJDUMP], +[AC_CHECK_TOOL(OBJDUMP, objdump, false) +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) +AC_SUBST([OBJDUMP]) +]) + +# _LT_DECL_DLLTOOL +# ---------------- +# Ensure DLLTOOL variable is set. +m4_defun([_LT_DECL_DLLTOOL], +[AC_CHECK_TOOL(DLLTOOL, dlltool, false) +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program]) +AC_SUBST([DLLTOOL]) +]) + +# _LT_DECL_SED +# ------------ +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +m4_defun([_LT_DECL_SED], +[AC_PROG_SED +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" +_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) +_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], + [Sed that helps us avoid accidentally triggering echo(1) options like -n]) +])# _LT_DECL_SED + +m4_ifndef([AC_PROG_SED], [ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # + +m4_defun([AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +IFS=$as_save_IFS +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_SUBST([SED]) +AC_MSG_RESULT([$SED]) +])#AC_PROG_SED +])#m4_ifndef + +# Old name: +AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([LT_AC_PROG_SED], []) + + +# _LT_CHECK_SHELL_FEATURES +# ------------------------ +# Find out whether the shell is Bourne or XSI compatible, +# or has some other useful features. +m4_defun([_LT_CHECK_SHELL_FEATURES], +[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +AC_MSG_RESULT([$xsi_shell]) +_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) + +AC_MSG_CHECKING([whether the shell understands "+="]) +lt_shell_append=no +( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +AC_MSG_RESULT([$lt_shell_append]) +_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi +_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac +_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl +_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl +])# _LT_CHECK_SHELL_FEATURES + + +# _LT_PROG_FUNCTION_REPLACE (FUNCNAME, REPLACEMENT-BODY) +# ------------------------------------------------------ +# In `$cfgfile', look for function FUNCNAME delimited by `^FUNCNAME ()$' and +# '^} FUNCNAME ', and replace its body with REPLACEMENT-BODY. +m4_defun([_LT_PROG_FUNCTION_REPLACE], +[dnl { +sed -e '/^$1 ()$/,/^} # $1 /c\ +$1 ()\ +{\ +m4_bpatsubsts([$2], [$], [\\], [^\([ ]\)], [\\\1]) +} # Extended-shell $1 implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: +]) + + +# _LT_PROG_REPLACE_SHELLFNS +# ------------------------- +# Replace existing portable implementations of several shell functions with +# equivalent extended shell implementations where those features are available.. +m4_defun([_LT_PROG_REPLACE_SHELLFNS], +[if test x"$xsi_shell" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_dirname], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_basename], [dnl + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_dirname_and_basename], [dnl + case ${1} in + */*) func_dirname_result="${1%/*}${2}" ;; + * ) func_dirname_result="${3}" ;; + esac + func_basename_result="${1##*/}"]) + + _LT_PROG_FUNCTION_REPLACE([func_stripname], [dnl + # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are + # positional parameters, so assign one to ordinary parameter first. + func_stripname_result=${3} + func_stripname_result=${func_stripname_result#"${1}"} + func_stripname_result=${func_stripname_result%"${2}"}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_long_opt], [dnl + func_split_long_opt_name=${1%%=*} + func_split_long_opt_arg=${1#*=}]) + + _LT_PROG_FUNCTION_REPLACE([func_split_short_opt], [dnl + func_split_short_opt_arg=${1#??} + func_split_short_opt_name=${1%"$func_split_short_opt_arg"}]) + + _LT_PROG_FUNCTION_REPLACE([func_lo2o], [dnl + case ${1} in + *.lo) func_lo2o_result=${1%.lo}.${objext} ;; + *) func_lo2o_result=${1} ;; + esac]) + + _LT_PROG_FUNCTION_REPLACE([func_xform], [ func_xform_result=${1%.*}.lo]) + + _LT_PROG_FUNCTION_REPLACE([func_arith], [ func_arith_result=$(( $[*] ))]) + + _LT_PROG_FUNCTION_REPLACE([func_len], [ func_len_result=${#1}]) +fi + +if test x"$lt_shell_append" = xyes; then + _LT_PROG_FUNCTION_REPLACE([func_append], [ eval "${1}+=\\${2}"]) + + _LT_PROG_FUNCTION_REPLACE([func_append_quoted], [dnl + func_quote_for_eval "${2}" +dnl m4 expansion turns \\\\ into \\, and then the shell eval turns that into \ + eval "${1}+=\\\\ \\$func_quote_for_eval_result"]) + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([[a-zA-Z_]]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + AC_MSG_WARN([Unable to substitute extended shell functions in $ofile]) +fi +]) + +# _LT_PATH_CONVERSION_FUNCTIONS +# ----------------------------- +# Determine which file name conversion functions should be used by +# func_to_host_file (and, implicitly, by func_to_host_path). These are needed +# for certain cross-compile configurations and native mingw. +m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_MSG_CHECKING([how to convert $build file names to $host format]) +AC_CACHE_VAL(lt_cv_to_host_file_cmd, +[case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac +]) +to_host_file_cmd=$lt_cv_to_host_file_cmd +AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) +_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], + [0], [convert $build file names to $host format])dnl + +AC_MSG_CHECKING([how to convert $build file names to toolchain format]) +AC_CACHE_VAL(lt_cv_to_tool_file_cmd, +[#assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac +]) +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) +_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], + [0], [convert $build files to toolchain format])dnl +])# _LT_PATH_CONVERSION_FUNCTIONS + +# Helper functions for option handling. -*- Autoconf -*- +# +# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 7 ltoptions.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) + + +# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) +# ------------------------------------------ +m4_define([_LT_MANGLE_OPTION], +[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) + + +# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) +# --------------------------------------- +# Set option OPTION-NAME for macro MACRO-NAME, and if there is a +# matching handler defined, dispatch to it. Other OPTION-NAMEs are +# saved as a flag. +m4_define([_LT_SET_OPTION], +[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl +m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), + _LT_MANGLE_DEFUN([$1], [$2]), + [m4_warning([Unknown $1 option `$2'])])[]dnl +]) + + +# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) +# ------------------------------------------------------------ +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +m4_define([_LT_IF_OPTION], +[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) + + +# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) +# ------------------------------------------------------- +# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME +# are set. +m4_define([_LT_UNLESS_OPTIONS], +[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), + [m4_define([$0_found])])])[]dnl +m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 +])[]dnl +]) + + +# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) +# ---------------------------------------- +# OPTION-LIST is a space-separated list of Libtool options associated +# with MACRO-NAME. If any OPTION has a matching handler declared with +# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about +# the unknown option and exit. +m4_defun([_LT_SET_OPTIONS], +[# Set options +m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), + [_LT_SET_OPTION([$1], _LT_Option)]) + +m4_if([$1],[LT_INIT],[ + dnl + dnl Simply set some default values (i.e off) if boolean options were not + dnl specified: + _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no + ]) + _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no + ]) + dnl + dnl If no reference was made to various pairs of opposing options, then + dnl we run the default mode handler for the pair. For example, if neither + dnl `shared' nor `disable-shared' was passed, we enable building of shared + dnl archives by default: + _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) + _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) + _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], + [_LT_ENABLE_FAST_INSTALL]) + ]) +])# _LT_SET_OPTIONS + + + +# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) +# ----------------------------------------- +m4_define([_LT_MANGLE_DEFUN], +[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) + + +# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) +# ----------------------------------------------- +m4_define([LT_OPTION_DEFINE], +[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl +])# LT_OPTION_DEFINE + + +# dlopen +# ------ +LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes +]) + +AU_DEFUN([AC_LIBTOOL_DLOPEN], +[_LT_SET_OPTION([LT_INIT], [dlopen]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `dlopen' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) + + +# win32-dll +# --------- +# Declare package support for building win32 dll's. +LT_OPTION_DEFINE([LT_INIT], [win32-dll], +[enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; +esac + +test -z "$AS" && AS=as +_LT_DECL([], [AS], [1], [Assembler program])dnl + +test -z "$DLLTOOL" && DLLTOOL=dlltool +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl + +test -z "$OBJDUMP" && OBJDUMP=objdump +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl +])# win32-dll + +AU_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +_LT_SET_OPTION([LT_INIT], [win32-dll]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `win32-dll' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) + + +# _LT_ENABLE_SHARED([DEFAULT]) +# ---------------------------- +# implement the --enable-shared flag, and supports the `shared' and +# `disable-shared' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_SHARED], +[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([shared], + [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) + + _LT_DECL([build_libtool_libs], [enable_shared], [0], + [Whether or not to build shared libraries]) +])# _LT_ENABLE_SHARED + +LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) +]) + +AC_DEFUN([AC_DISABLE_SHARED], +[_LT_SET_OPTION([LT_INIT], [disable-shared]) +]) + +AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_SHARED], []) +dnl AC_DEFUN([AM_DISABLE_SHARED], []) + + + +# _LT_ENABLE_STATIC([DEFAULT]) +# ---------------------------- +# implement the --enable-static flag, and support the `static' and +# `disable-static' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_STATIC], +[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([static], + [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]_LT_ENABLE_STATIC_DEFAULT) + + _LT_DECL([build_old_libs], [enable_static], [0], + [Whether or not to build static libraries]) +])# _LT_ENABLE_STATIC + +LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) + +# Old names: +AC_DEFUN([AC_ENABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) +]) + +AC_DEFUN([AC_DISABLE_STATIC], +[_LT_SET_OPTION([LT_INIT], [disable-static]) +]) + +AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AM_ENABLE_STATIC], []) +dnl AC_DEFUN([AM_DISABLE_STATIC], []) + + + +# _LT_ENABLE_FAST_INSTALL([DEFAULT]) +# ---------------------------------- +# implement the --enable-fast-install flag, and support the `fast-install' +# and `disable-fast-install' LT_INIT options. +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +m4_define([_LT_ENABLE_FAST_INSTALL], +[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl +AC_ARG_ENABLE([fast-install], + [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) + +_LT_DECL([fast_install], [enable_fast_install], [0], + [Whether or not to optimize for fast installation])dnl +])# _LT_ENABLE_FAST_INSTALL + +LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) +LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) + +# Old names: +AU_DEFUN([AC_ENABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `fast-install' option into LT_INIT's first parameter.]) +]) + +AU_DEFUN([AC_DISABLE_FAST_INSTALL], +[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you put +the `disable-fast-install' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) +dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) + + +# _LT_WITH_PIC([MODE]) +# -------------------- +# implement the --with-pic flag, and support the `pic-only' and `no-pic' +# LT_INIT options. +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +m4_define([_LT_WITH_PIC], +[AC_ARG_WITH([pic], + [AS_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) + +test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) + +_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl +])# _LT_WITH_PIC + +LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) +LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) + +# Old name: +AU_DEFUN([AC_LIBTOOL_PICMODE], +[_LT_SET_OPTION([LT_INIT], [pic-only]) +AC_DIAGNOSE([obsolete], +[$0: Remove this warning and the call to _LT_SET_OPTION when you +put the `pic-only' option into LT_INIT's first parameter.]) +]) + +dnl aclocal-1.4 backwards compatibility: +dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) + + +m4_define([_LTDL_MODE], []) +LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], + [m4_define([_LTDL_MODE], [nonrecursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [recursive], + [m4_define([_LTDL_MODE], [recursive])]) +LT_OPTION_DEFINE([LTDL_INIT], [subproject], + [m4_define([_LTDL_MODE], [subproject])]) + +m4_define([_LTDL_TYPE], []) +LT_OPTION_DEFINE([LTDL_INIT], [installable], + [m4_define([_LTDL_TYPE], [installable])]) +LT_OPTION_DEFINE([LTDL_INIT], [convenience], + [m4_define([_LTDL_TYPE], [convenience])]) + +# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Written by Gary V. Vaughan, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 6 ltsugar.m4 + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) + + +# lt_join(SEP, ARG1, [ARG2...]) +# ----------------------------- +# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their +# associated separator. +# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier +# versions in m4sugar had bugs. +m4_define([lt_join], +[m4_if([$#], [1], [], + [$#], [2], [[$2]], + [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) +m4_define([_lt_join], +[m4_if([$#$2], [2], [], + [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) + + +# lt_car(LIST) +# lt_cdr(LIST) +# ------------ +# Manipulate m4 lists. +# These macros are necessary as long as will still need to support +# Autoconf-2.59 which quotes differently. +m4_define([lt_car], [[$1]]) +m4_define([lt_cdr], +[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], + [$#], 1, [], + [m4_dquote(m4_shift($@))])]) +m4_define([lt_unquote], $1) + + +# lt_append(MACRO-NAME, STRING, [SEPARATOR]) +# ------------------------------------------ +# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. +# Note that neither SEPARATOR nor STRING are expanded; they are appended +# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). +# No SEPARATOR is output if MACRO-NAME was previously undefined (different +# than defined and empty). +# +# This macro is needed until we can rely on Autoconf 2.62, since earlier +# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. +m4_define([lt_append], +[m4_define([$1], + m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) + + + +# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) +# ---------------------------------------------------------- +# Produce a SEP delimited list of all paired combinations of elements of +# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list +# has the form PREFIXmINFIXSUFFIXn. +# Needed until we can rely on m4_combine added in Autoconf 2.62. +m4_define([lt_combine], +[m4_if(m4_eval([$# > 3]), [1], + [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl +[[m4_foreach([_Lt_prefix], [$2], + [m4_foreach([_Lt_suffix], + ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, + [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) + + +# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) +# ----------------------------------------------------------------------- +# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited +# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. +m4_define([lt_if_append_uniq], +[m4_ifdef([$1], + [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], + [lt_append([$1], [$2], [$3])$4], + [$5])], + [lt_append([$1], [$2], [$3])$4])]) + + +# lt_dict_add(DICT, KEY, VALUE) +# ----------------------------- +m4_define([lt_dict_add], +[m4_define([$1($2)], [$3])]) + + +# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) +# -------------------------------------------- +m4_define([lt_dict_add_subkey], +[m4_define([$1($2:$3)], [$4])]) + + +# lt_dict_fetch(DICT, KEY, [SUBKEY]) +# ---------------------------------- +m4_define([lt_dict_fetch], +[m4_ifval([$3], + m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), + m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) + + +# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) +# ----------------------------------------------------------------- +m4_define([lt_if_dict_fetch], +[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], + [$5], + [$6])]) + + +# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) +# -------------------------------------------------------------- +m4_define([lt_dict_filter], +[m4_if([$5], [], [], + [lt_join(m4_quote(m4_default([$4], [[, ]])), + lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), + [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl +]) + +# ltversion.m4 -- version numbers -*- Autoconf -*- +# +# Copyright (C) 2004 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004 +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# @configure_input@ + +# serial 3293 ltversion.m4 +# This file is part of GNU Libtool + +m4_define([LT_PACKAGE_VERSION], [2.4]) +m4_define([LT_PACKAGE_REVISION], [1.3293]) + +AC_DEFUN([LTVERSION_VERSION], +[macro_version='2.4' +macro_revision='1.3293' +_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) +_LT_DECL(, macro_revision, 0) +]) + +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 5 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) + +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.11' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.11.1], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.11.1])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 9 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 10 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +#serial 5 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 8 + +# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. +AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 16 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Add --enable-maintainer-mode option to configure. -*- Autoconf -*- +# From Jim Meyering + +# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_MAINTAINER_MODE([DEFAULT-MODE]) +# ---------------------------------- +# Control maintainer-specific portions of Makefiles. +# Default is to disable them, unless `enable' is passed literally. +# For symmetry, `disable' may be passed as well. Anyway, the user +# can override the default with the --enable/--disable switch. +AC_DEFUN([AM_MAINTAINER_MODE], +[m4_case(m4_default([$1], [disable]), + [enable], [m4_define([am_maintainer_other], [disable])], + [disable], [m4_define([am_maintainer_other], [enable])], + [m4_define([am_maintainer_other], [enable]) + m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) +AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles]) + dnl maintainer-mode's default is 'disable' unless 'enable' is passed + AC_ARG_ENABLE([maintainer-mode], +[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful + (and sometimes confusing) to the casual installer], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + AC_MSG_RESULT([$USE_MAINTAINER_MODE]) + AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) + MAINT=$MAINTAINER_MODE_TRUE + AC_SUBST([MAINT])dnl +] +) + +AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006, 2008 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. +AM_MISSING_PROG([AMTAR], [tar]) +m4_if([$1], [v7], + [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + diff --git a/contrib/libpng/autogen.sh b/contrib/libpng/autogen.sh new file mode 100755 index 0000000..5be104e --- /dev/null +++ b/contrib/libpng/autogen.sh @@ -0,0 +1,34 @@ +#! /bin/sh +# a quick hack script to generate necessary files from +# auto* tools. +# +# WARNING: if you run this you will change the versions +# of the tools which are used and, maybe, required! + +# You can define your own replacements in your environment. +# $AUTOCONF, $AUTOMAKE, $AUTOHEADER, $AUTOPOINT, $ACLOCAL and $LIBTOOLIZE + +touch Makefile.am configure.ac +{ + LT=${LIBTOOLIZE-libtoolize} + echo "running $LT" >&2 + $LT --force --copy --automake +} && { + AL=${ACLOCAL-aclocal} + echo "running $AL" >&2 + $AL +} && { + AH=${AUTOHEADER-autoheader} + echo "running $AH [ignore the warnings]" >&2 + $AH +} && { + AM=${AUTOMAKE-automake} + echo "running $AM" >&2 + $AM --force-missing --foreign -a -c +} && { + AC=${AUTOCONF-autoconf} + echo "running $AC" >&2 + $AC +} && + echo "autogen complete" >&2 || + echo "ERROR: autogen.sh failed, autogen is incomplete" >&2 diff --git a/contrib/libpng/config.guess b/contrib/libpng/config.guess new file mode 100644 index 0000000..dc84c68 --- /dev/null +++ b/contrib/libpng/config.guess @@ -0,0 +1,1501 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-11-20' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[456]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/contrib/libpng/config.h.in b/contrib/libpng/config.h.in new file mode 100644 index 0000000..fb23495 --- /dev/null +++ b/contrib/libpng/config.h.in @@ -0,0 +1,86 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `z' library (-lz). */ +#undef HAVE_LIBZ + +/* Define to 1 if you have the header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the `pow' function. */ +#undef HAVE_POW + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `unsigned int' if does not define. */ +#undef size_t diff --git a/contrib/libpng/config.sub b/contrib/libpng/config.sub new file mode 100644 index 0000000..2a55a50 --- /dev/null +++ b/contrib/libpng/config.sub @@ -0,0 +1,1705 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 +# Free Software Foundation, Inc. + +timestamp='2009-11-20' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/contrib/libpng/configure b/contrib/libpng/configure new file mode 100755 index 0000000..1f5ad92 --- /dev/null +++ b/contrib/libpng/configure @@ -0,0 +1,14885 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.68 for libpng 1.5.1. +# +# Report bugs to . +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software +# Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: png-mng-implement@lists.sourceforge.net about your +$0: system, including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='libpng' +PACKAGE_TARNAME='libpng' +PACKAGE_VERSION='1.5.1' +PACKAGE_STRING='libpng 1.5.1' +PACKAGE_BUGREPORT='png-mng-implement@lists.sourceforge.net' +PACKAGE_URL='' + +ac_unique_file="pngget.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +binconfigs +pkgconfigdir +PNGLIB_RELEASE +PNGLIB_MINOR +PNGLIB_MAJOR +PNGLIB_VERSION +SYMBOL_PREFIX +HAVE_LD_VERSION_SCRIPT_FALSE +HAVE_LD_VERSION_SCRIPT_TRUE +LIBPNG_DEFINES +LIBOBJS +POW_LIB +DFNCPP +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +RANLIB +ac_ct_AR +AR +NM +ac_ct_DUMPBIN +DUMPBIN +LIBTOOL +OBJDUMP +DLLTOOL +AS +LN_S +CPP +LD +FGREP +EGREP +GREP +SED +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +MAINT +MAINTAINER_MODE_FALSE +MAINTAINER_MODE_TRUE +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_maintainer_mode +enable_dependency_tracking +with_gnu_ld +enable_shared +enable_static +with_pic +enable_fast_install +with_sysroot +enable_libtool_lock +with_zlib_prefix +with_pkgconfigdir +with_binconfigs +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CPP +CPPFLAGS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used" >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures libpng 1.5.1 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/libpng] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of libpng 1.5.1:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-maintainer-mode enable make rules and dependencies not useful + (and sometimes confusing) to the casual installer + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-sysroot=DIR Search for dependent libraries within DIR + (or the compiler's sysroot if not specified). + --with-zlib-prefix prefix that may have been used in installed zlib + --with-pkgconfigdir Use the specified pkgconfig dir (default is + libdir/pkgconfig) + --with-binconfigs Generate shell libpng-config scripts as well as + pkg-config data [default=yes] + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +libpng configure 1.5.1 +generated by GNU Autoconf 2.68 + +Copyright (C) 2010 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ------------------------------------------------------ ## +## Report this to png-mng-implement@lists.sourceforge.net ## +## ------------------------------------------------------ ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_type LINENO TYPE VAR INCLUDES +# ------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_c_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by libpng $as_me 1.5.1, which was +generated by GNU Autoconf 2.68. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +am__api_version='1.11' + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken +alias in your environment" "$LINENO" 5 + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='libpng' + VERSION='1.5.1' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 +$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } + # Check whether --enable-maintainer-mode was given. +if test "${enable_maintainer_mode+set}" = set; then : + enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval +else + USE_MAINTAINER_MODE=no +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 +$as_echo "$USE_MAINTAINER_MODE" >&6; } + if test $USE_MAINTAINER_MODE = yes; then + MAINTAINER_MODE_TRUE= + MAINTAINER_MODE_FALSE='#' +else + MAINTAINER_MODE_TRUE='#' + MAINTAINER_MODE_FALSE= +fi + + MAINT=$MAINTAINER_MODE_TRUE + + + +PNGLIB_VERSION=1.5.1 +PNGLIB_MAJOR=1 +PNGLIB_MINOR=5 +PNGLIB_RELEASE=1 + + + +ac_config_headers="$ac_config_headers config.h" + + +# Checks for programs. +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}sed", so it can be a program name with args. +set dummy ${ac_tool_prefix}sed; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$SED"; then + ac_cv_prog_SED="$SED" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_SED="${ac_tool_prefix}sed" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +SED=$ac_cv_prog_SED +if test -n "$SED"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 +$as_echo "$SED" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_SED"; then + ac_ct_SED=$SED + # Extract the first word of "sed", so it can be a program name with args. +set dummy sed; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_SED"; then + ac_cv_prog_ac_ct_SED="$ac_ct_SED" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_SED="sed" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_SED=$ac_cv_prog_ac_ct_SED +if test -n "$ac_ct_SED"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_SED" >&5 +$as_echo "$ac_ct_SED" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_SED" = x; then + SED=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + SED=$ac_ct_SED + fi +else + SED="$ac_cv_prog_SED" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}awk", so it can be a program name with args. +set dummy ${ac_tool_prefix}awk; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="${ac_tool_prefix}awk" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AWK"; then + ac_ct_AWK=$AWK + # Extract the first word of "awk", so it can be a program name with args. +set dummy awk; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AWK"; then + ac_cv_prog_ac_ct_AWK="$ac_ct_AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AWK="awk" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AWK=$ac_cv_prog_ac_ct_AWK +if test -n "$ac_ct_AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AWK" >&5 +$as_echo "$ac_ct_AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AWK" = x; then + AWK=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AWK=$ac_ct_AWK + fi +else + AWK="$ac_cv_prog_AWK" +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4' +macro_revision='1.3293' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 +$as_echo "${with_sysroot}" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + + + +# Set options +enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. +set dummy ${ac_tool_prefix}as; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AS="${ac_tool_prefix}as" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AS=$ac_cv_prog_AS +if test -n "$AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 +$as_echo "$AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AS"; then + ac_ct_AS=$AS + # Extract the first word of "as", so it can be a program name with args. +set dummy as; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AS"; then + ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AS="as" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AS=$ac_cv_prog_ac_ct_AS +if test -n "$ac_ct_AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 +$as_echo "$ac_ct_AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AS" = x; then + AS="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AS=$ac_ct_AS + fi +else + AS="$ac_cv_prog_AS" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + + ;; +esac + +test -z "$AS" && AS=as + + + + + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + enable_dlopen=no + + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; pic_mode="$withval" +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + lt_prog_compiler_pic='-Xcompiler -fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld='-rpath $libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test "$lt_cv_irix_exported_symbol" = yes; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + +# On Solaris 10 and 12 CPP gets set to cc -E, however this still +# does some input parsing. We need strict ANSI-C style tokenization, +# check this: + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a C preprocessor that does not parse its input" >&5 +$as_echo_n "checking for a C preprocessor that does not parse its input... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +1.5.0 16BIT +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + DFNCPP="$CPP" +else + DFNCPP="" + sav_CPP="$CPP" + for CPP in "${CC-cc} -E" "${CC-cc} -E -traditional-cpp" "/lib/cpp" "cpp"; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +1.5.0 16BIT +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + DFNCPP="$CPP" + break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + done + CPP="$sav_CPP" +fi +rm -f conftest.err conftest.i conftest.$ac_ext +if test -n "$DFNCPP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DFNCPP" >&5 +$as_echo "$DFNCPP" >&6; } + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 1 "not found +See \`config.log' for more details" "$LINENO" 5; } +fi + +# Checks for header files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +for ac_header in malloc.h stdlib.h string.h strings.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +# Checks for typedefs, structures, and compiler characteristics. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset cs; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 +$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } +if ${ac_cv_struct_tm+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include + +int +main () +{ +struct tm tm; + int *p = &tm.tm_sec; + return !p; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_struct_tm=time.h +else + ac_cv_struct_tm=sys/time.h +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 +$as_echo "$ac_cv_struct_tm" >&6; } +if test $ac_cv_struct_tm = sys/time.h; then + +$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h + +fi + + +# Checks for library functions. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working strtod" >&5 +$as_echo_n "checking for working strtod... " >&6; } +if ${ac_cv_func_strtod+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_strtod=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +$ac_includes_default +#ifndef strtod +double strtod (); +#endif +int +main() +{ + { + /* Some versions of Linux strtod mis-parse strings with leading '+'. */ + char *string = " +69"; + char *term; + double value; + value = strtod (string, &term); + if (value != 69 || term != (string + 4)) + return 1; + } + + { + /* Under Solaris 2.4, strtod returns the wrong value for the + terminating character under some conditions. */ + char *string = "NaN"; + char *term; + strtod (string, &term); + if (term != string && *(term - 1) == 0) + return 1; + } + return 0; +} + +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_func_strtod=yes +else + ac_cv_func_strtod=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strtod" >&5 +$as_echo "$ac_cv_func_strtod" >&6; } +if test $ac_cv_func_strtod = no; then + case " $LIBOBJS " in + *" strtod.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strtod.$ac_objext" + ;; +esac + +ac_fn_c_check_func "$LINENO" "pow" "ac_cv_func_pow" +if test "x$ac_cv_func_pow" = xyes; then : + +fi + +if test $ac_cv_func_pow = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pow in -lm" >&5 +$as_echo_n "checking for pow in -lm... " >&6; } +if ${ac_cv_lib_m_pow+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pow (); +int +main () +{ +return pow (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_pow=yes +else + ac_cv_lib_m_pow=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_pow" >&5 +$as_echo "$ac_cv_lib_m_pow" >&6; } +if test "x$ac_cv_lib_m_pow" = xyes; then : + POW_LIB=-lm +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot find library containing definition of pow" >&5 +$as_echo "$as_me: WARNING: cannot find library containing definition of pow" >&2;} +fi + +fi + +fi + +for ac_func in memset +do : + ac_fn_c_check_func "$LINENO" "memset" "ac_cv_func_memset" +if test "x$ac_cv_func_memset" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_MEMSET 1 +_ACEOF + +else + as_fn_error $? "memset not found in libc" "$LINENO" 5 +fi +done + +for ac_func in pow +do : + ac_fn_c_check_func "$LINENO" "pow" "ac_cv_func_pow" +if test "x$ac_cv_func_pow" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_POW 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pow in -lm" >&5 +$as_echo_n "checking for pow in -lm... " >&6; } +if ${ac_cv_lib_m_pow+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pow (); +int +main () +{ +return pow (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_pow=yes +else + ac_cv_lib_m_pow=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_pow" >&5 +$as_echo "$ac_cv_lib_m_pow" >&6; } +if test "x$ac_cv_lib_m_pow" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +else + as_fn_error $? "cannot find pow" "$LINENO" 5 +fi + +fi +done + + +# Check whether --with-zlib-prefix was given. +if test "${with_zlib_prefix+set}" = set; then : + withval=$with_zlib_prefix; ZPREFIX=${withval} +else + ZPREFIX='z_' +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for zlibVersion in -lz" >&5 +$as_echo_n "checking for zlibVersion in -lz... " >&6; } +if ${ac_cv_lib_z_zlibVersion+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char zlibVersion (); +int +main () +{ +return zlibVersion (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_z_zlibVersion=yes +else + ac_cv_lib_z_zlibVersion=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_zlibVersion" >&5 +$as_echo "$ac_cv_lib_z_zlibVersion" >&6; } +if test "x$ac_cv_lib_z_zlibVersion" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBS="-lz $LIBS" + +else + as_ac_Lib=`$as_echo "ac_cv_lib_z_${ZPREFIX}zlibVersion" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ZPREFIX}zlibVersion in -lz" >&5 +$as_echo_n "checking for ${ZPREFIX}zlibVersion in -lz... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ${ZPREFIX}zlibVersion (); +int +main () +{ +return ${ZPREFIX}zlibVersion (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBS="-lz $LIBS" + +else + as_fn_error $? "zlib not installed" "$LINENO" 5 +fi + +fi + + + +LIBPNG_DEFINES=-DPNG_CONFIGURE_LIBPNG +LIBPNG_DEFINES=$LIBPNG_DEFINES + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if libraries can be versioned" >&5 +$as_echo_n "checking if libraries can be versioned... " >&6; } +# Special case for PE/COFF platforms: ld reports +# support for version-script, but doesn't actually +# DO anything with it. +case $host in +*cygwin* | *mingw32* | *interix* ) + have_ld_version_script=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +;; +* ) +GLD=`$LD --help < /dev/null 2>/dev/null | grep version-script` +if test "$GLD"; then + have_ld_version_script=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + have_ld_version_script=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** You have not enabled versioned symbols." >&5 +$as_echo "$as_me: WARNING: *** You have not enabled versioned symbols." >&2;} +fi +;; +esac + + if test "$have_ld_version_script" = "yes"; then + HAVE_LD_VERSION_SCRIPT_TRUE= + HAVE_LD_VERSION_SCRIPT_FALSE='#' +else + HAVE_LD_VERSION_SCRIPT_TRUE='#' + HAVE_LD_VERSION_SCRIPT_FALSE= +fi + + +if test "$have_ld_version_script" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for symbol prefix" >&5 +$as_echo_n "checking for symbol prefix... " >&6; } + SYMBOL_PREFIX=`echo "PREFIX=__USER_LABEL_PREFIX__" \ + | ${CPP-${CC-gcc} -E} - 2>&1 \ + | ${EGREP-grep} "^PREFIX=" \ + | ${SED-sed} "s:^PREFIX=::"` + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SYMBOL_PREFIX" >&5 +$as_echo "$SYMBOL_PREFIX" >&6; } +fi + +# Substitutions for .in files + + + + + +# Additional arguments (and substitutions) +# Allow the pkg-config directory to be set + +# Check whether --with-pkgconfigdir was given. +if test "${with_pkgconfigdir+set}" = set; then : + withval=$with_pkgconfigdir; pkgconfigdir=${withval} +else + pkgconfigdir='${libdir}/pkgconfig' +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: pkgconfig directory is ${pkgconfigdir}" >&5 +$as_echo "$as_me: pkgconfig directory is ${pkgconfigdir}" >&6;} + +# Make the *-config binary config scripts optional + +# Check whether --with-binconfigs was given. +if test "${with_binconfigs+set}" = set; then : + withval=$with_binconfigs; if test "${withval}" = no; then + binconfigs= + { $as_echo "$as_me:${as_lineno-$LINENO}: libpng-config scripts will not be built" >&5 +$as_echo "$as_me: libpng-config scripts will not be built" >&6;} + else + binconfigs='${binconfigs}' + fi +else + binconfigs='${binconfigs}' +fi + + + +# Config files, substituting as above +ac_config_files="$ac_config_files Makefile libpng.pc:libpng.pc.in" + +ac_config_files="$ac_config_files libpng-config:libpng-config.in" + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_LD_VERSION_SCRIPT_TRUE}" && test -z "${HAVE_LD_VERSION_SCRIPT_FALSE}"; then + as_fn_error $? "conditional \"HAVE_LD_VERSION_SCRIPT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by libpng $as_me 1.5.1, which was +generated by GNU Autoconf 2.68. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +libpng config.status 1.5.1 +configured by $0, generated by GNU Autoconf 2.68, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SED \ +GREP \ +EGREP \ +FGREP \ +SHELL \ +ECHO \ +LD \ +AS \ +DLLTOOL \ +OBJDUMP \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +nm_file_list_spec \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_flag_spec_ld \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "libpng.pc") CONFIG_FILES="$CONFIG_FILES libpng.pc:libpng.pc.in" ;; + "libpng-config") CONFIG_FILES="$CONFIG_FILES libpng-config:libpng-config.in" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="" + +# ### BEGIN LIBTOOL CONFIG + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Assembler program. +AS=$lt_AS + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Object dumper program. +OBJDUMP=$lt_OBJDUMP + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and in which our libraries should be installed. +lt_sysroot=$lt_sysroot + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + if test x"$xsi_shell" = xyes; then + sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ +func_dirname ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_basename ()$/,/^} # func_basename /c\ +func_basename ()\ +{\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ +func_dirname_and_basename ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ +func_stripname ()\ +{\ +\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ +\ # positional parameters, so assign one to ordinary parameter first.\ +\ func_stripname_result=${3}\ +\ func_stripname_result=${func_stripname_result#"${1}"}\ +\ func_stripname_result=${func_stripname_result%"${2}"}\ +} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ +func_split_long_opt ()\ +{\ +\ func_split_long_opt_name=${1%%=*}\ +\ func_split_long_opt_arg=${1#*=}\ +} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ +func_split_short_opt ()\ +{\ +\ func_split_short_opt_arg=${1#??}\ +\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ +} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ +func_lo2o ()\ +{\ +\ case ${1} in\ +\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ +\ *) func_lo2o_result=${1} ;;\ +\ esac\ +} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_xform ()$/,/^} # func_xform /c\ +func_xform ()\ +{\ + func_xform_result=${1%.*}.lo\ +} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_arith ()$/,/^} # func_arith /c\ +func_arith ()\ +{\ + func_arith_result=$(( $* ))\ +} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_len ()$/,/^} # func_len /c\ +func_len ()\ +{\ + func_len_result=${#1}\ +} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + +fi + +if test x"$lt_shell_append" = xyes; then + sed -e '/^func_append ()$/,/^} # func_append /c\ +func_append ()\ +{\ + eval "${1}+=\\${2}"\ +} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ +func_append_quoted ()\ +{\ +\ func_quote_for_eval "${2}"\ +\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ +} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 +$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} +fi + + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + ;; + "libpng-config":F) chmod +x libpng-config ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/contrib/libpng/configure.ac b/contrib/libpng/configure.ac new file mode 100644 index 0000000..ff277a4 --- /dev/null +++ b/contrib/libpng/configure.ac @@ -0,0 +1,167 @@ +# configure.ac + +dnl Process this file with autoconf to produce a configure script. +dnl +dnl Minor upgrades (compatible ABI): increment the package version +dnl (third field in two places below) and set the PNGLIB_RELEASE +dnl variable. +dnl +dnl Major upgrades (incompatible ABI): increment the package major +dnl version (second field, or first if desired), set the minor +dnl to 0, set PNGLIB_MAJOR below *and* follow the instructions in +dnl Makefile.am to upgrade the package name. + +dnl This is here to prevent earlier autoconf from being used, it +dnl should not be necessary to regenerate configure if the time +dnl stamps are correct +AC_PREREQ(2.59) + +dnl Version number stuff here: + +AC_INIT([libpng], [1.5.1], [png-mng-implement@lists.sourceforge.net]) +AM_INIT_AUTOMAKE +dnl stop configure from automagically running automake +AM_MAINTAINER_MODE + +PNGLIB_VERSION=1.5.1 +PNGLIB_MAJOR=1 +PNGLIB_MINOR=5 +PNGLIB_RELEASE=1 + +dnl End of version number stuff + +AC_CONFIG_SRCDIR([pngget.c]) +AM_CONFIG_HEADER(config.h) + +# Checks for programs. +AC_LANG([C]) +AC_PROG_CC +AC_PROG_LD +AC_PROG_CPP +AC_CHECK_TOOL(SED, sed, :) +AC_CHECK_TOOL(AWK, awk, :) +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +LT_INIT([win32-dll]) + +# On Solaris 10 and 12 CPP gets set to cc -E, however this still +# does some input parsing. We need strict ANSI-C style tokenization, +# check this: +AC_REQUIRE_CPP +AC_MSG_CHECKING([for a C preprocessor that does not parse its input]) +AC_TRY_CPP([1.5.0 16BIT], + [DFNCPP="$CPP"], + [DFNCPP="" + sav_CPP="$CPP" + for CPP in "${CC-cc} -E" "${CC-cc} -E -traditional-cpp" "/lib/cpp" "cpp"; do + AC_TRY_CPP([1.5.0 16BIT], + [DFNCPP="$CPP"] + [break],,) + done + CPP="$sav_CPP"]) +if test -n "$DFNCPP"; then + AC_MSG_RESULT([$DFNCPP]) + AC_SUBST(DFNCPP) +else + AC_MSG_FAILURE([not found], 1) +fi + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([malloc.h stdlib.h string.h strings.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T +AC_STRUCT_TM + +# Checks for library functions. +AC_FUNC_STRTOD +AC_CHECK_FUNCS([memset], , AC_ERROR([memset not found in libc])) +AC_CHECK_FUNCS([pow], , AC_CHECK_LIB(m, pow, , AC_ERROR([cannot find pow])) ) +AC_ARG_WITH(zlib-prefix, + AC_HELP_STRING([--with-zlib-prefix], + [prefix that may have been used in installed zlib]), + [ZPREFIX=${withval}], + [ZPREFIX='z_']) +AC_CHECK_LIB(z, zlibVersion, , + AC_CHECK_LIB(z, ${ZPREFIX}zlibVersion, , + AC_ERROR([zlib not installed]))) + + +LIBPNG_DEFINES=-DPNG_CONFIGURE_LIBPNG +LIBPNG_DEFINES=$LIBPNG_DEFINES +AC_SUBST(LIBPNG_DEFINES) + +AC_MSG_CHECKING([if libraries can be versioned]) +# Special case for PE/COFF platforms: ld reports +# support for version-script, but doesn't actually +# DO anything with it. +case $host in +*cygwin* | *mingw32* | *interix* ) + have_ld_version_script=no + AC_MSG_RESULT(no) +;; +* ) +GLD=`$LD --help < /dev/null 2>/dev/null | grep version-script` +if test "$GLD"; then + have_ld_version_script=yes + AC_MSG_RESULT(yes) +else + have_ld_version_script=no + AC_MSG_RESULT(no) + AC_MSG_WARN(*** You have not enabled versioned symbols.) +fi +;; +esac + +AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes") + +if test "$have_ld_version_script" = "yes"; then + AC_MSG_CHECKING([for symbol prefix]) + SYMBOL_PREFIX=`echo "PREFIX=__USER_LABEL_PREFIX__" \ + | ${CPP-${CC-gcc} -E} - 2>&1 \ + | ${EGREP-grep} "^PREFIX=" \ + | ${SED-sed} "s:^PREFIX=::"` + AC_SUBST(SYMBOL_PREFIX) + AC_MSG_RESULT($SYMBOL_PREFIX) +fi + +# Substitutions for .in files +AC_SUBST(PNGLIB_VERSION) +AC_SUBST(PNGLIB_MAJOR) +AC_SUBST(PNGLIB_MINOR) +AC_SUBST(PNGLIB_RELEASE) + +# Additional arguments (and substitutions) +# Allow the pkg-config directory to be set +AC_ARG_WITH(pkgconfigdir, + AC_HELP_STRING([--with-pkgconfigdir], + [Use the specified pkgconfig dir (default is libdir/pkgconfig)]), + [pkgconfigdir=${withval}], + [pkgconfigdir='${libdir}/pkgconfig']) + +AC_SUBST([pkgconfigdir]) +AC_MSG_NOTICE([pkgconfig directory is ${pkgconfigdir}]) + +# Make the *-config binary config scripts optional +AC_ARG_WITH(binconfigs, + AC_HELP_STRING([--with-binconfigs], + [Generate shell libpng-config scripts as well as pkg-config data] + [@<:@default=yes@:>@]), + [if test "${withval}" = no; then + binconfigs= + AC_MSG_NOTICE([libpng-config scripts will not be built]) + else + binconfigs='${binconfigs}' + fi], + [binconfigs='${binconfigs}']) +AC_SUBST([binconfigs]) + +# Config files, substituting as above +AC_CONFIG_FILES([Makefile libpng.pc:libpng.pc.in]) +AC_CONFIG_FILES([libpng-config:libpng-config.in], + [chmod +x libpng-config]) + +AC_OUTPUT diff --git a/contrib/libpng/contrib/gregbook/COPYING b/contrib/libpng/contrib/gregbook/COPYING new file mode 100644 index 0000000..a3e9774 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/contrib/libpng/contrib/gregbook/LICENSE b/contrib/libpng/contrib/gregbook/LICENSE new file mode 100644 index 0000000..d956717 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/LICENSE @@ -0,0 +1,50 @@ + --------------------------------------------------------------------------- + + Copyright (c) 1998-2008 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + --------------------------------------------------------------------------- diff --git a/contrib/libpng/contrib/gregbook/Makefile.mingw32 b/contrib/libpng/contrib/gregbook/Makefile.mingw32 new file mode 100644 index 0000000..e70a59a --- /dev/null +++ b/contrib/libpng/contrib/gregbook/Makefile.mingw32 @@ -0,0 +1,130 @@ +# Sample makefile for rpng-win / rpng2-win / wpng using mingw32-gcc and make. +# Greg Roelofs +# Last modified: 2 June 2007 +# +# 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? Well, OK, it's not +# generally for sale anymore, but it's the thought that counts, +# right? (Hint: http://www.libpng.org/pub/png/book/ ) +# +# Invoke this makefile from a DOS-prompt window via: +# +# make -f Makefile.mingw32 +# +# 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 PNGDIR and ZDIR macros below). It makes no assumptions +# at all about the mingw32 installation tree (W32DIR). 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 both statically and dynamically linked executables by default. +# (You need only one set, but for testing it can be handy to have both.) + + +# macros -------------------------------------------------------------------- + +#PNGDIR = ../..# for libpng-x.y.z/contrib/gregbook builds +PNGDIR = ../libpng-win32 +PNGINC = -I$(PNGDIR) +PNGLIBd = $(PNGDIR)/libpng.dll.a # dynamically linked +PNGLIBs = $(PNGDIR)/libpng.a # statically linked, local libpng + +#ZDIR = ../../../zlib-win32# for libpng-x.y.z/contrib/gregbook builds +ZDIR = ../zlib-win32 +ZINC = -I$(ZDIR) +ZLIBd = $(ZDIR)/libzdll.a +ZLIBs = $(ZDIR)/libz.a + +# change this to be the path where mingw32 installs its stuff: +W32DIR = +#W32DIR = /usr/local/cross-tools/i386-mingw32msvc +W32INC = -I$(W32DIR)/include +W32LIB = $(W32DIR)/lib/libuser32.a $(W32DIR)/lib/libgdi32.a + +CC = gcc +#CC = i386-mingw32msvc-gcc # e.g., Linux -> Win32 cross-compilation +LD = $(CC) +RM = rm -f +CFLAGS = -O -Wall $(INCS) $(MINGW_CCFLAGS) +# [note that -Wall is a gcc-specific compilation flag ("most warnings on")] +# [-ansi, -pedantic and -W can also be used] +LDFLAGS = $(MINGW_LDFLAGS) +O = .o +E = .exe + +INCS = $(PNGINC) $(ZINC) $(W32INC) +RLIBSd = $(PNGLIBd) $(ZLIBd) $(W32LIB) -lm +RLIBSs = $(PNGLIBs) $(ZLIBs) $(W32LIB) -lm +WLIBSd = $(PNGLIBd) $(ZLIBd) +WLIBSs = $(PNGLIBs) $(ZLIBs) + +RPNG = rpng-win +RPNG2 = rpng2-win +WPNG = wpng + +ROBJSd = $(RPNG)$(O) readpng.pic$(O) +ROBJS2d = $(RPNG2)$(O) readpng2.pic$(O) +WOBJSd = $(WPNG)$(O) writepng.pic$(O) + +RPNGs = $(RPNG)-static +RPNG2s = $(RPNG2)-static +WPNGs = $(WPNG)-static + +ROBJSs = $(RPNG)$(O) readpng$(O) +ROBJS2s = $(RPNG2)$(O) readpng2$(O) +WOBJSs = $(WPNG)$(O) writepng$(O) + +STATIC_EXES = $(RPNGs)$(E) $(RPNG2s)$(E) $(WPNGs)$(E) +DYNAMIC_EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E) + +EXES = $(STATIC_EXES) $(DYNAMIC_EXES) + + +# implicit make rules ------------------------------------------------------- + +.c$(O): + $(CC) -c $(CFLAGS) $< + +%.pic$(O): %.c + $(CC) -c $(CFLAGS) -DPNG_BUILD_DLL -o $@ $< + + +# dependencies -------------------------------------------------------------- + +all: $(EXES) + +$(RPNGs)$(E): $(ROBJSs) + $(LD) $(LDFLAGS) -o $@ $(ROBJSs) $(RLIBSs) + +$(RPNG)$(E): $(ROBJSd) + $(LD) $(LDFLAGS) -o $@ $(ROBJSd) $(RLIBSd) + +$(RPNG2s)$(E): $(ROBJS2s) + $(LD) $(LDFLAGS) -o $@ $(ROBJS2s) $(RLIBSs) + +$(RPNG2)$(E): $(ROBJS2d) + $(LD) $(LDFLAGS) -o $@ $(ROBJS2d) $(RLIBSd) + +$(WPNGs)$(E): $(WOBJSs) + $(LD) $(LDFLAGS) -o $@ $(WOBJSs) $(WLIBSs) + +$(WPNG)$(E): $(WOBJSd) + $(LD) $(LDFLAGS) -o $@ $(WOBJSd) $(WLIBSd) + +$(RPNG)$(O): $(RPNG).c readpng.h +$(RPNG2)$(O): $(RPNG2).c readpng2.h +$(WPNG)$(O): $(WPNG).c writepng.h + +readpng$(O) readpng.pic$(O): readpng.c readpng.h +readpng2$(O) readpng2.pic$(O): readpng2.c readpng2.h +writepng$(O) writepng.pic$(O): writepng.c writepng.h + + +# maintenance --------------------------------------------------------------- + +clean: + $(RM) $(EXES) + $(RM) $(ROBJSs) $(ROBJS2s) $(WOBJSs) + $(RM) $(ROBJSd) $(ROBJS2d) $(WOBJSd) diff --git a/contrib/libpng/contrib/gregbook/Makefile.sgi b/contrib/libpng/contrib/gregbook/Makefile.sgi new file mode 100644 index 0000000..91623ac --- /dev/null +++ b/contrib/libpng/contrib/gregbook/Makefile.sgi @@ -0,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/libpng15 +PNGLIB = -L/usr/local/lib -lpng15 # dynamically linked against libpng +#PNGLIB = /usr/local/lib/libpng15.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) diff --git a/contrib/libpng/contrib/gregbook/Makefile.unx b/contrib/libpng/contrib/gregbook/Makefile.unx new file mode 100644 index 0000000..b52d8b6 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/Makefile.unx @@ -0,0 +1,132 @@ +# Sample makefile for rpng-x / rpng2-x / wpng using gcc and make. +# Greg Roelofs +# Last modified: 2 June 2007 +# +# 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? Well, OK, it's not +# generally for sale anymore, but it's the thought that counts, +# right? (Hint: http://www.libpng.org/pub/png/book/ ) +# +# 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 installed in /usr/local/{include,lib} or as otherwise indicated by +# the PNG* and Z* macros below. Edit as appropriate--choose only ONE each of +# the PNGINC, PNGLIBd, PNGLIBs, ZINC, ZLIBd and ZLIBs lines. +# +# This makefile builds both dynamically and statically linked executables +# (against libpng and zlib, that is), but that can be changed by modifying +# the "EXES =" line. (You need only one set, but for testing it can be handy +# to have both.) + + +# macros -------------------------------------------------------------------- + +#PNGDIR = /usr/local/lib +#PNGINC = -I/usr/local/include/libpng15 +#PNGLIBd = -L$(PNGDIR) -lpng15 # dynamically linked, installed libpng +#PNGLIBs = $(PNGDIR)/libpng15.a # statically linked, installed libpng +# or: +PNGDIR = ../..# this one is for libpng-x.y.z/contrib/gregbook builds +#PNGDIR = ../libpng +PNGINC = -I$(PNGDIR) +PNGLIBd = -Wl,-rpath,$(PNGDIR) -L$(PNGDIR) -lpng15 # dynamically linked +PNGLIBs = $(PNGDIR)/libpng.a # statically linked, local libpng + +ZDIR = /usr/local/lib +#ZDIR = /usr/lib64 +ZINC = -I/usr/local/include +ZLIBd = -L$(ZDIR) -lz # dynamically linked against zlib +ZLIBs = $(ZDIR)/libz.a # statically linked against zlib +# or: +#ZDIR = ../zlib +#ZINC = -I$(ZDIR) +#ZLIBd = -Wl,-rpath,$(ZDIR) -L$(ZDIR) -lz # -rpath allows in-place testing +#ZLIBs = $(ZDIR)/libz.a + +#XINC = -I/usr/include # old-style, stock X distributions +#XLIB = -L/usr/lib/X11 -lX11 # (including SGI IRIX) +#XINC = -I/usr/openwin/include # Sun workstations (OpenWindows) +#XLIB = -L/usr/openwin/lib -lX11 +XINC = -I/usr/X11R6/include # new X distributions (X.org, etc.) +XLIB = -L/usr/X11R6/lib -lX11 +#XLIB = -L/usr/X11R6/lib64 -lX11 # e.g., Red Hat on AMD64 + +INCS = $(PNGINC) $(ZINC) $(XINC) +RLIBSd = $(PNGLIBd) $(ZLIBd) $(XLIB) -lm +RLIBSs = $(PNGLIBs) $(ZLIBs) $(XLIB) -lm +WLIBSd = $(PNGLIBd) $(ZLIBd) -lm +WLIBSs = $(PNGLIBs) $(ZLIBs) + +CC = gcc +LD = gcc +RM = rm -f +CFLAGS = -O -Wall $(INCS) -DFEATURE_LOOP +# [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 + +RPNGs = $(RPNG)-static +RPNG2s = $(RPNG2)-static +WPNGs = $(WPNG)-static + +ROBJS = $(RPNG)$(O) readpng$(O) +ROBJS2 = $(RPNG2)$(O) readpng2$(O) +WOBJS = $(WPNG)$(O) writepng$(O) + +STATIC_EXES = $(RPNGs)$(E) $(RPNG2s)$(E) $(WPNGs)$(E) +DYNAMIC_EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E) + +EXES = $(STATIC_EXES) $(DYNAMIC_EXES) + + +# implicit make rules ------------------------------------------------------- + +.c$(O): + $(CC) -c $(CFLAGS) $< + + +# dependencies -------------------------------------------------------------- + +all: $(EXES) + +$(RPNGs)$(E): $(ROBJS) + $(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBSs) + +$(RPNG)$(E): $(ROBJS) + $(LD) $(LDFLAGS) -o $@ $(ROBJS) $(RLIBSd) + +$(RPNG2s)$(E): $(ROBJS2) + $(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBSs) + +$(RPNG2)$(E): $(ROBJS2) + $(LD) $(LDFLAGS) -o $@ $(ROBJS2) $(RLIBSd) + +$(WPNGs)$(E): $(WOBJS) + $(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBSs) + +$(WPNG)$(E): $(WOBJS) + $(LD) $(LDFLAGS) -o $@ $(WOBJS) $(WLIBSd) + +$(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) diff --git a/contrib/libpng/contrib/gregbook/Makefile.w32 b/contrib/libpng/contrib/gregbook/Makefile.w32 new file mode 100644 index 0000000..3c08085 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/Makefile.w32 @@ -0,0 +1,113 @@ +# Sample makefile for rpng-win / rpng2-win / wpng using MSVC and NMAKE. +# Greg Roelofs +# Last modified: 2 June 2007 +# +# 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? Well, OK, it's not +# generally for sale anymore, but it's the thought that counts, +# right? (Hint: http://www.libpng.org/pub/png/book/ ) +# +# 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 + + +# 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 -W3 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) diff --git a/contrib/libpng/contrib/gregbook/README b/contrib/libpng/contrib/gregbook/README new file mode 100644 index 0000000..6f8e079 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/README @@ -0,0 +1,186 @@ + =========================== + 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@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 or GNU GPL) + COPYING GNU General Public License (GPL) + + 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 +http://pobox.com/~newt/greg_contact.html +16 March 2008 + + +BUILD INSTRUCTIONS + + - Prerequisites (in order of compilation): + + - zlib http://zlib.net/ + - 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-notrans.ppm > toucan-notrans.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. diff --git a/contrib/libpng/contrib/gregbook/makevms.com b/contrib/libpng/contrib/gregbook/makevms.com new file mode 100644 index 0000000..bd37dc0 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/makevms.com @@ -0,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 diff --git a/contrib/libpng/contrib/gregbook/readpng.c b/contrib/libpng/contrib/gregbook/readpng.c new file mode 100644 index 0000000..d72309f --- /dev/null +++ b/contrib/libpng/contrib/gregbook/readpng.c @@ -0,0 +1,305 @@ +/*--------------------------------------------------------------------------- + + rpng - simple PNG display program readpng.c + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#include +#include + +#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_sig_cmp(sig, 0, 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; + } +} diff --git a/contrib/libpng/contrib/gregbook/readpng.h b/contrib/libpng/contrib/gregbook/readpng.h new file mode 100644 index 0000000..fad9fe3 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/readpng.h @@ -0,0 +1,88 @@ +/*--------------------------------------------------------------------------- + + rpng - simple PNG display program readpng.h + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#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); diff --git a/contrib/libpng/contrib/gregbook/readpng2.c b/contrib/libpng/contrib/gregbook/readpng2.c new file mode 100644 index 0000000..1772a90 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/readpng2.c @@ -0,0 +1,505 @@ +/*--------------------------------------------------------------------------- + + rpng2 - progressive-model PNG display program readpng2.c + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + + +#include /* for exit() prototype */ +#include + +#include +#include "png.h" /* libpng header from the local directory */ +#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) +{ + fprintf(stderr, " Compiled with libpng %s; using libpng %s\n", + PNG_LIBPNG_VER_STRING, png_libpng_ver); + + fprintf(stderr, " and with zlib %s; using zlib %s.\n", + ZLIB_VERSION, zlib_version); +} + + + + +int readpng2_check_sig(uch *sig, int num) +{ + return !png_sig_cmp(sig, 0, 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; + } + + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + /* prepare the reader to ignore all recognized chunks whose data won't be + * used, i.e., all chunks recognized by libpng except for IHDR, PLTE, IDAT, + * IEND, tRNS, bKGD, gAMA, and sRGB (small performance improvement) */ + { + /* 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. */ + static /* const */ png_byte chunks_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 */ + 112, 72, 89, 115, '\0', /* pHYs */ + 115, 66, 73, 84, '\0', /* sBIT */ + 115, 67, 65, 76, '\0', /* sCAL */ + 115, 80, 76, 84, '\0', /* sPLT */ + 115, 84, 69, 82, '\0', /* sTER */ + 116, 69, 88, 116, '\0', /* tEXt */ + 116, 73, 77, 69, '\0', /* tIME */ + 122, 84, 88, 116, '\0' /* zTXt */ + }; + + png_set_keep_unknown_chunks(png_ptr, 1 /* PNG_HANDLE_CHUNK_NEVER */, + chunks_to_ignore, sizeof(chunks_to_ignore)/5); + } +#endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */ + + + /* 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); + + + /* 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; + png_uint_32 width, height; +#ifdef PNG_FLOATING_POINT_SUPPORTED + double gamma; +#else + png_fixed_point gamma; +#endif + + + /* 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, &width, &height, &bit_depth, &color_type, + NULL, NULL, NULL); + mainprog_ptr->width = (ulg)width; + mainprog_ptr->height = (ulg)height; + + + /* 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. */ + +#ifdef PNG_FLOATING_POINT_SUPPORTED + 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); +#else + if (png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) + png_set_gamma_fixed(png_ptr, + (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), gamma); + else + png_set_gamma_fixed(png_ptr, + (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), 45455); +#endif + + /* 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); + } + + /* Now we have our data structure we can use the information in it + * to return control to our own higher level code (all the points + * where 'setjmp' is called in this file.) This will work with other + * error handling mechanisms as well - libpng always calls png_error + * when it can proceed no further, thus, so long as the error handler + * is intercepted, application code can do its own error recovery. + */ + longjmp(mainprog_ptr->jmpbuf, 1); +} diff --git a/contrib/libpng/contrib/gregbook/readpng2.h b/contrib/libpng/contrib/gregbook/readpng2.h new file mode 100644 index 0000000..6b3660d --- /dev/null +++ b/contrib/libpng/contrib/gregbook/readpng2.h @@ -0,0 +1,116 @@ +/*--------------------------------------------------------------------------- + + rpng2 - progressive-model PNG display program readpng2.h + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2008 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#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 + +enum rpng2_states { + kPreInit = 0, + kWindowInit, + kDone +}; + +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; + int state; + 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); diff --git a/contrib/libpng/contrib/gregbook/readppm.c b/contrib/libpng/contrib/gregbook/readppm.c new file mode 100644 index 0000000..be9a56d --- /dev/null +++ b/contrib/libpng/contrib/gregbook/readppm.c @@ -0,0 +1,179 @@ +/*--------------------------------------------------------------------------- + + rpng - simple PNG display program readppm.c + + --------------------------------------------------------------------------- + + This is a special-purpose replacement for readpng.c that allows binary + PPM files to be used in place of PNG images. + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#include +#include + +#include "readpng.h" /* typedefs, common macros, public prototypes */ + + +ulg width, height; +int bit_depth, color_type, channels; +uch *image_data = NULL; +FILE *saved_infile; + + +void readpng_version_info() +{ + fprintf(stderr, " Compiled without libpng, zlib or PBMPLUS/NetPBM.\n"); +} + + +/* 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) +{ + static uch ppmline[256]; + int maxval; + + + saved_infile = infile; + + fgets(ppmline, 256, infile); + if (ppmline[0] != 'P' || ppmline[1] != '6') { + fprintf(stderr, "ERROR: not a PPM file\n"); + return 1; + } + /* possible color types: P5 = grayscale (0), P6 = RGB (2), P8 = RGBA (6) */ + if (ppmline[1] == '6') { + color_type = 2; + channels = 3; + } else if (ppmline[1] == '8') { + color_type = 6; + channels = 4; + } else /* if (ppmline[1] == '5') */ { + color_type = 0; + channels = 1; + } + + do { + fgets(ppmline, 256, infile); + } while (ppmline[0] == '#'); + sscanf(ppmline, "%lu %lu", &width, &height); + + do { + fgets(ppmline, 256, infile); + } while (ppmline[0] == '#'); + sscanf(ppmline, "%d", &maxval); + if (maxval != 255) { + fprintf(stderr, "ERROR: maxval = %d\n", maxval); + return 2; + } + bit_depth = 8; + + *pWidth = width; + *pHeight = height; + + 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) +{ + return 1; +} + + + + +/* display_exponent == LUT_exponent * CRT_exponent */ + +uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) +{ + ulg rowbytes; + + + /* 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] */ + + /* GRR WARNING: grayscale needs to be expanded and channels reset! */ + + *pRowbytes = rowbytes = channels*width; + *pChannels = channels; + + if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) { + return NULL; + } + + Trace((stderr, "readpng_get_image: rowbytes = %ld, height = %ld\n", rowbytes, height)); + + + /* now we can go ahead and just read the whole image */ + + fread(image_data, 1L, rowbytes*height, saved_infile); + + + return image_data; +} + + +void readpng_cleanup(int free_image_data) +{ + if (free_image_data && image_data) { + free(image_data); + image_data = NULL; + } +} diff --git a/contrib/libpng/contrib/gregbook/rpng-win.c b/contrib/libpng/contrib/gregbook/rpng-win.c new file mode 100644 index 0000000..f53ddc8 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/rpng-win.c @@ -0,0 +1,728 @@ +/*--------------------------------------------------------------------------- + + 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) + - 2.00: dual-licensed (added GNU GPL) + - 2.01: fixed improper display of usage screen on PNG error(s) + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2008 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#define PROGNAME "rpng-win" +#define LONGNAME "Simple PNG Viewer for Windows" +#define VERSION "2.01 of 16 March 2008" + +#include +#include +#include +#include +#include +#ifdef __CYGWIN__ +/* getch replacement. Turns out, we don't really need this, + * but leave it here if we ever enable any of the uses of + * _getch in the main code + */ +#include +#include +#include +int repl_getch( void ) +{ + char ch; + int fd = fileno(stdin); + struct termio old_tty, new_tty; + + ioctl(fd, TCGETA, &old_tty); + new_tty = old_tty; + new_tty.c_lflag &= ~(ICANON | ECHO | ISIG); + ioctl(fd, TCSETA, &new_tty); + fread(&ch, 1, sizeof(ch), stdin); + ioctl(fd, TCSETA, &old_tty); + + return ch; +} +#define _getch repl_getch +#else +#include /* only for _getch() */ +#endif + +/* #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]; +static char *progname = PROGNAME; +static char *appname = LONGNAME; +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; + +#ifndef __CYGWIN__ + /* 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@realviz.com for supplying the magical + * incantation. */ + + AllocConsole(); + freopen("CONOUT$", "a", stderr); + freopen("CONOUT$", "a", stdout); +#endif + + + /* 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; + + + /* print usage screen if any errors up to this point */ + + if (error) { +#ifndef __CYGWIN__ + int ch; +#endif + + 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" +#ifndef __CYGWIN__ + "Press Q or Esc to quit this usage screen.\n" +#endif + "\n", PROGNAME, default_display_exponent); +#ifndef __CYGWIN__ + do + ch = _getch(); + while (ch != 'q' && ch != 'Q' && ch != 0x1B); +#endif + exit(1); + } + + + 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); + } + + + if (error) { +#ifndef __CYGWIN__ + int ch; +#endif + + fprintf(stderr, PROGNAME ": aborting.\n"); +#ifndef __CYGWIN__ + do + ch = _getch(); + while (ch != 'q' && ch != 'Q' && ch != 0x1B); +#endif + exit(2); + } else { + fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname); +#ifndef __CYGWIN__ + fprintf(stderr, + "\n [console window: closing this window will terminate %s]\n\n", + PROGNAME); +#endif + } + + + /* 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 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( +#ifndef __CYGWIN__ + "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n" +#else + "Done. Press mouse button 1 (within image window) to quit.\n" +#endif + ); + 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); +} diff --git a/contrib/libpng/contrib/gregbook/rpng-x.c b/contrib/libpng/contrib/gregbook/rpng-x.c new file mode 100644 index 0000000..e821cfb --- /dev/null +++ b/contrib/libpng/contrib/gregbook/rpng-x.c @@ -0,0 +1,904 @@ +/*--------------------------------------------------------------------------- + + 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 (colormapped) X 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 some small X memory leaks (thanks to François Petitjean) + - 1.13: fixed XFreeGC() crash bug (thanks to Patrick Welche) + - 1.14: added support for X resources (thanks to Gerhard Niklasch) + - 2.00: dual-licensed (added GNU GPL) + - 2.01: fixed improper display of usage screen on PNG error(s) + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2008 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#define PROGNAME "rpng-x" +#define LONGNAME "Simple PNG Viewer for X" +#define VERSION "2.01 of 16 March 2008" +#define RESNAME "rpng" /* our X resource application name */ +#define RESCLASS "Rpng" /* our X resource class name */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* #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 *res_name = RESNAME; +static char *res_class = RESCLASS; +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; + + + /* print usage screen if any errors up to this point */ + + 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); + } + + + 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); + } + + + if (error) { + fprintf(stderr, PROGNAME ": aborting.\n"); + exit(2); + } + + + /* 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; + XTextProperty windowName, *pWindowName = &windowName; + XTextProperty iconName, *pIconName = &iconName; + XVisualInfo visual_info; + XSizeHints *size_hints; + XWMHints *wm_hints; + XClassHint *class_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 any 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 */ ; + } + + if ((class_hints = XAllocClassHint()) != NULL) { + class_hints->res_name = res_name; + class_hints->res_class = res_class; + } + + XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0, + size_hints, wm_hints, class_hints); + + /* 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); + if (class_hints) + XFree(class_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; +} diff --git a/contrib/libpng/contrib/gregbook/rpng2-win.c b/contrib/libpng/contrib/gregbook/rpng2-win.c new file mode 100644 index 0000000..fbdacb5 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/rpng2-win.c @@ -0,0 +1,1253 @@ +/*--------------------------------------------------------------------------- + + 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 (someday, maybe): + - 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 + - 1.22: added AMD64/EM64T support (__x86_64__) + - 2.00: dual-licensed (added GNU GPL) + - 2.01: fixed 64-bit typo in readpng2.c + - 2.02: fixed improper display of usage screen on PNG error(s); fixed + unexpected-EOF and file-read-error cases + - 2.03: removed runtime MMX-enabling/disabling and obsolete -mmx* options + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2008 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#define PROGNAME "rpng2-win" +#define LONGNAME "Progressive PNG Viewer for Windows" +#define VERSION "2.02 of 16 March 2008" + +#include +#include +#include +#include /* for jmpbuf declaration in readpng2.h */ +#include +#include /* only for PvdM background code */ +#include +#ifdef __CYGWIN__ +/* getch replacement. Turns out, we don't really need this, + * but leave it here if we ever enable any of the uses of + * _getch in the main code + */ +#include +#include +#include +int repl_getch( void ) +{ + char ch; + int fd = fileno(stdin); + struct termio old_tty, new_tty; + + ioctl(fd, TCGETA, &old_tty); + new_tty = old_tty; + new_tty.c_lflag &= ~(ICANON | ECHO | ISIG); + ioctl(fd, TCSETA, &new_tty); + fread(&ch, 1, sizeof(ch), stdin); + ioctl(fd, TCSETA, &old_tty); + + return ch; +} +#define _getch repl_getch +#else +#include /* only for _getch() */ +#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> 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]; +static char *progname = PROGNAME; +static char *appname = LONGNAME; +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)); + +#ifndef __CYGWIN__ + /* 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@realviz.com for supplying the magical + * incantation. */ + + AllocConsole(); + freopen("CONOUT$", "a", stderr); + freopen("CONOUT$", "a", stdout); +#endif + + /* 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; + } 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; + + + /* print usage screen if any errors up to this point */ + + if (error) { +#ifndef __CYGWIN__ + int ch; +#endif + + 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" + " %*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" + "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n" +#ifndef __CYGWIN__ + "Press Q or Esc to quit this usage screen. ", +#else + , +#endif + PROGNAME, +#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) && \ + !(defined(__CYGWIN__) || defined(__MINGW32__)) + (int)strlen(PROGNAME), " ", +#endif + (int)strlen(PROGNAME), " ", default_display_exponent, num_bgpat); + fflush(stderr); +#ifndef __CYGWIN__ + do + ch = _getch(); + while (ch != 'q' && ch != 'Q' && ch != 0x1B); +#endif + exit(1); + } + + + 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); + } + + + if (error) { +#ifndef __CYGWIN__ + int ch; +#endif + + fprintf(stderr, PROGNAME ": aborting.\n"); +#ifndef __CYGWIN__ + do + ch = _getch(); + while (ch != 'q' && ch != 'Q' && ch != 0x1B); +#endif + exit(2); + } else { + fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname); +#ifndef __CYGWIN__ + fprintf(stderr, + "\n [console window: closing this window will terminate %s]\n\n", + PROGNAME); +#endif + 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.state = kPreInit; + 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 || incount != INBUFSIZE || rpng2_info.state == kDone) { + if (rpng2_info.state == kDone) { + Trace((stderr, "done decoding PNG image\n")) + } else if (ferror(infile)) { + fprintf(stderr, PROGNAME + ": error while reading PNG image file\n"); + exit(3); + } else if (feof(infile)) { + fprintf(stderr, PROGNAME ": end of file reached " + "(unexpectedly) while reading PNG image file\n"); + exit(3); + } else /* if (error) */ { + // will print error message below + } + 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 = %d\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; + } + + rpng2_info.state = kWindowInit; +} + + + + + +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.state = kDone; + printf( +#ifndef __CYGWIN__ + "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n" +#else + "Done. Press mouse button 1 (within image window) to quit.\n" +#endif + ); + 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); +} diff --git a/contrib/libpng/contrib/gregbook/rpng2-x.c b/contrib/libpng/contrib/gregbook/rpng2-x.c new file mode 100644 index 0000000..b04c5c6 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/rpng2-x.c @@ -0,0 +1,2107 @@ +/*--------------------------------------------------------------------------- + + 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 (someday, maybe): + - fix expose/redraw code: don't draw entire row if only part exposed + - 8-bit (colormapped) X 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 some small X memory leaks (thanks to François Petitjean) + - 1.22: fixed XFreeGC() crash bug (thanks to Patrick Welche) + - 1.23: added -bgpat 0 mode (std white/gray checkerboard, 8x8 squares) + - 1.30: added -loop option for -bgpat (ifdef FEATURE_LOOP); fixed bpp = + 24; added support for X resources (thanks to Gerhard Niklasch) + - 1.31: added code to skip unused chunks (thanks to Glenn Randers-Pehrson) + - 1.32: added AMD64/EM64T support (__x86_64__); added basic expose/redraw + handling + - 2.00: dual-licensed (added GNU GPL) + - 2.01: fixed 64-bit typo in readpng2.c; fixed -pause usage description + - 2.02: fixed improper display of usage screen on PNG error(s); fixed + unexpected-EOF and file-read-error cases; fixed Trace() cut-and- + paste bugs + - 2.03: deleted runtime MMX-enabling/disabling and obsolete -mmx* options + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2008 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#define PROGNAME "rpng2-x" +#define LONGNAME "Progressive PNG Viewer for X" +#define VERSION "2.03 of 25 February 2010" +#define RESNAME "rpng2" /* our X resource application name */ +#define RESCLASS "Rpng" /* our X resource class name */ + +#include +#include +#include +#include +#include /* for jmpbuf declaration in readpng2.h */ +#include +#include /* only for PvdM background code */ +#include +#include +#include +#include /* defines XK_* macros */ + +#ifdef VMS +# include +#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> 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_redisplay_image (ulg startcol, ulg startrow, + ulg width, ulg height); +#ifdef FEATURE_LOOP +static void rpng2_x_reload_bg_image (void); +static int is_number (char *p); +#endif +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 *res_name = RESNAME; +static char *res_class = RESCLASS; +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, bgscale_default = 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 */ + {192, 192, 192} /* 16: Netscape/Mosaic gray */ +}; +/* 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, 1,1, 16,16}, /* checkered: white vs. light gray (basic) */ + {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; +#ifdef FEATURE_LOOP + int loop = FALSE; + long loop_interval = -1; /* seconds (100,000 max) */ +#endif + 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); + if (pat >= 0 && pat < num_bgpat) { + bg_image = TRUE; + have_bg = FALSE; + } else + ++error; + } + } 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; +#ifdef FEATURE_LOOP + } else if (!strncmp(*argv, "-loop", 2)) { + loop = TRUE; + if (!argv[1] || !is_number(argv[1])) + loop_interval = 2; + else { + ++argv; + loop_interval = atol(*argv); + if (loop_interval < 0) + loop_interval = 2; + else if (loop_interval > 100000) /* bit more than one day */ + loop_interval = 100000; + } +#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; + + + /* print usage screen if any errors up to this point */ + + 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" +#ifdef FEATURE_LOOP + " %*s [-usleep dur | -timing] [-pause] [-loop [sec]] file.png\n\n" +#else + " %*s [-usleep dur | -timing] [-pause] file.png\n\n" +#endif + " 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 (0-%d); used with\n" + "\t\t transparent images; overrides -bgcolor\n" +#ifdef FEATURE_LOOP + " -loop\tloops through background images after initial display\n" + "\t\t is complete (depends on -bgpat)\n" + " sec \tseconds to display each background image (default = 2)\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 mouse clicked\n" + "\nPress Q, Esc or mouse button 1 (within image window, after image\n" + "is displayed) to quit.\n" + "\n", PROGNAME, + (int)strlen(PROGNAME), " ", default_display_exponent, num_bgpat-1); + exit(1); + } + + + 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 { + Trace((stderr, "about to call XOpenDisplay()\n")) + 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); + } + + + if (error) { + fprintf(stderr, PROGNAME ": aborting.\n"); + exit(2); + } + + + /* 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.state = kPreInit; + 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 || incount != INBUFSIZE || rpng2_info.state == kDone) { + if (rpng2_info.state == kDone) { + Trace((stderr, "done decoding PNG image\n")) + } else if (ferror(infile)) { + fprintf(stderr, PROGNAME + ": error while reading PNG image file\n"); + exit(3); + } else if (feof(infile)) { + fprintf(stderr, PROGNAME ": end of file reached " + "(unexpectedly) while reading PNG image file\n"); + exit(3); + } else /* if (error) */ { + // will print error message below + } + 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); + } + + +#ifdef FEATURE_LOOP + + if (loop && bg_image) { + Trace((stderr, "entering -loop loop (FEATURE_LOOP)\n")) + for (;;) { + int i, use_sleep; + struct timeval now, then; + + /* get current time and add loop_interval to get target time */ + if (gettimeofday(&then, NULL) == 0) { + then.tv_sec += loop_interval; + use_sleep = FALSE; + } else + use_sleep = TRUE; + + /* do quick check for a quit event but don't wait for it */ + /* GRR BUG: should also check for Expose events and redraw... */ + if (XCheckMaskEvent(display, KeyPressMask | ButtonPressMask, &e)) + if (QUIT(e,k)) + break; + + /* generate next background image */ + if (++pat >= num_bgpat) + pat = 0; + rpng2_x_reload_bg_image(); + + /* wait for timeout, using whatever means are available */ + if (use_sleep || gettimeofday(&now, NULL) != 0) { + for (i = loop_interval; i > 0; --i) { + sleep(1); + /* GRR BUG: also need to check for Expose (and redraw!) */ + if (XCheckMaskEvent(display, KeyPressMask | ButtonPressMask, + &e) && QUIT(e,k)) + break; + } + } else { + /* Y2038 BUG! */ + if (now.tv_sec < then.tv_sec || + (now.tv_sec == then.tv_sec && now.tv_usec < then.tv_usec)) + { + int quit = FALSE; + long seconds_to_go = then.tv_sec - now.tv_sec; + long usleep_usec; + + /* basically chew up most of remaining loop-interval with + * calls to sleep(1) interleaved with checks for quit + * events, but also recalc time-to-go periodically; when + * done, clean up any remaining time with usleep() call + * (could also use SIGALRM, but signals are a pain...) */ + while (seconds_to_go-- > 1) { + int seconds_done = 0; + + for (i = seconds_to_go; i > 0 && !quit; --i) { + sleep(1); + /* GRR BUG: need to check for Expose and redraw */ + if (XCheckMaskEvent(display, KeyPressMask | + ButtonPressMask, &e) && QUIT(e,k)) + quit = TRUE; + if (++seconds_done > 1000) + break; /* time to redo seconds_to_go meas. */ + } + if (quit) + break; + + /* OK, more than 1000 seconds since last check: + * correct the time-to-go measurement for drift */ + if (gettimeofday(&now, NULL) == 0) { + if (now.tv_sec >= then.tv_sec) + break; + seconds_to_go = then.tv_sec - now.tv_sec; + } else + ++seconds_to_go; /* restore what we subtracted */ + } + if (quit) + break; /* breaks outer do-loop, skips redisplay */ + + /* since difference between "now" and "then" is already + * eaten up to within a couple of seconds, don't need to + * worry about overflow--but might have overshot (neg.) */ + if (gettimeofday(&now, NULL) == 0) { + usleep_usec = 1000000L*(then.tv_sec - now.tv_sec) + + then.tv_usec - now.tv_usec; + if (usleep_usec > 0) + usleep((ulg)usleep_usec); + } + } + } + + /* composite image against new background and display (note that + * we do not take into account the time spent doing this...) */ + rpng2_x_redisplay_image (0, 0, rpng2_info.width, rpng2_info.height); + } + + } else /* FALL THROUGH and do the normal thing */ + +#endif /* FEATURE_LOOP */ + + /* wait for the user to tell us when to quit */ + + if (rpng2_info.state >= kWindowInit) { + Trace((stderr, "entering final wait-for-quit-event loop\n")) + do { + XNextEvent(display, &e); + if (e.type == Expose) { + XExposeEvent *ex = (XExposeEvent *)&e; + rpng2_x_redisplay_image (ex->x, ex->y, ex->width, ex->height); + } + } while (!QUIT(e,k)); + } else { + fprintf(stderr, PROGNAME ": init callback never called: probable " + "libpng error while decoding PNG metadata\n"); + exit(4); + } + + + /* 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 = %d\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 call our error handler to 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 */ + readpng2_cleanup(&rpng2_info); + rpng2_x_cleanup(); + exit(2); + } + + rpng2_info.state = kWindowInit; +} + + + + + +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; + XTextProperty windowName, *pWindowName = &windowName; + XTextProperty iconName, *pIconName = &iconName; + XVisualInfo visual_info; + XSizeHints *size_hints; + XWMHints *wm_hints; + XClassHint *class_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 */ ; + } + + if ((class_hints = XAllocClassHint()) != NULL) { + class_hints->res_name = res_name; + class_hints->res_class = res_class; + } + + XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0, + size_hints, wm_hints, class_hints); + + /* 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); + if (class_hints) + XFree(class_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; + 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; + } + + bgscale = (pat == 0)? 8 : bgscale_default; + yidx_max = bgscale - 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; + int bpp = ximage->bits_per_pixel; + + for (row = 0; row < rpng2_info.height; ++row) { + src = bg_data + row*bg_rowbytes; + dest = ximage->data + row*ximage_rowbytes; + if (bpp == 32) { /* slightly optimized version */ + 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 */ + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } + } else { + 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 == 24 & bits are packed low */ + /* (probably need to use RShift, RMask, etc.) */ + *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 (!QUIT(e,k)); + } + 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; + int bpp = ximage->bits_per_pixel; + + 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 */ + if (bpp == 32) { + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } else { + /* GRR BUG? this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift, RMask, etc.) */ + *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 */ + if (bpp == 32) { + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } else { + /* GRR BUG? this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift, RMask, etc.) */ + *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.state = kDone; + printf( + "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n"); + fflush(stdout); +} + + + + + +static void rpng2_x_redisplay_image(ulg startcol, ulg startrow, + ulg width, ulg height) +{ + 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; + ulg i, row, lastrow = 0; + ulg pixel; + int ximage_rowbytes = ximage->bytes_per_line; + + + Trace((stderr, "beginning display loop (image_channels == %d)\n", + rpng2_info.channels)) + Trace((stderr, " (width = %ld, rowbytes = %d, ximage_rowbytes = %d)\n", + rpng2_info.width, rpng2_info.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"))) + +/*--------------------------------------------------------------------------- + Aside from the use of the rpng2_info struct and of src2 (for background + image), this routine is identical to rpng_x_display_image() in the non- + progressive version of the program--for the simple reason that redisplay + of the image against a new background happens after the image is fully + decoded and therefore is, by definition, non-progressive. + ---------------------------------------------------------------------------*/ + + if (depth == 24 || depth == 32) { + ulg red, green, blue; + int bpp = ximage->bits_per_pixel; + + for (lastrow = row = startrow; row < startrow+height; ++row) { + 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++; +#ifdef NO_24BIT_MASKS + pixel = (red << RShift) | + (green << GShift) | + (blue << BShift); + /* recall that we set ximage->byte_order = MSBFirst above */ + if (bpp == 32) { + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } else { + /* this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift, RMask, etc.) */ + *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 */ + if (bpp == 32) { + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } else { + /* GRR BUG */ + /* this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift/RMask/etc. here, too) */ + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } +#endif + } + + } 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); + } +#ifdef NO_24BIT_MASKS + pixel = (red << RShift) | + (green << GShift) | + (blue << BShift); + /* recall that we set ximage->byte_order = MSBFirst above */ + if (bpp == 32) { + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } else { + /* this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift, RMask, etc.) */ + *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 */ + if (bpp == 32) { + *dest++ = (char)((pixel >> 24) & 0xff); + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } else { + /* GRR BUG */ + /* this assumes bpp == 24 & bits are packed low */ + /* (probably need to use RShift/RMask/etc. here, too) */ + *dest++ = (char)((pixel >> 16) & 0xff); + *dest++ = (char)((pixel >> 8) & 0xff); + *dest++ = (char)( pixel & 0xff); + } +#endif + } + } + /* display after every 16 lines */ + if (((row+1) & 0xf) == 0) { + XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0, + (int)lastrow, rpng2_info.width, 16); + XFlush(display); + lastrow = row + 1; + } + } + + } else if (depth == 16) { + ush red, green, blue; + + for (lastrow = row = startrow; row < startrow+height; ++row) { + 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); + } + } + /* display after every 16 lines */ + if (((row+1) & 0xf) == 0) { + XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0, + (int)lastrow, rpng2_info.width, 16); + XFlush(display); + lastrow = row + 1; + } + } + + } else /* depth == 8 */ { + + /* GRR: add 8-bit support */ + + } + + Trace((stderr, "calling final XPutImage()\n")) + if (lastrow < startrow+height) { + XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0, + (int)lastrow, rpng2_info.width, rpng2_info.height-lastrow); + XFlush(display); + } + +} /* end function rpng2_x_redisplay_image() */ + + + + + +#ifdef FEATURE_LOOP + +static void rpng2_x_reload_bg_image(void) +{ + 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; + int even_odd_vert, even_odd_horiz, even_odd; + int invert_gradient2 = (bg[pat].type & 0x08); + int invert_column; + ulg i, row; + + + bgscale = (pat == 0)? 8 : bgscale_default; + yidx_max = bgscale - 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; + + 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); + } + } + } + } + +} /* end function rpng2_x_reload_bg_image() */ + + + + + +static int is_number(char *p) +{ + while (*p) { + if (!isdigit(*p)) + return FALSE; + ++p; + } + return TRUE; +} + +#endif /* FEATURE_LOOP */ + + + + + +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; +} diff --git a/contrib/libpng/contrib/gregbook/toucan.png b/contrib/libpng/contrib/gregbook/toucan.png new file mode 100644 index 0000000..03960d4 Binary files /dev/null and b/contrib/libpng/contrib/gregbook/toucan.png differ diff --git a/contrib/libpng/contrib/gregbook/wpng.c b/contrib/libpng/contrib/gregbook/wpng.c new file mode 100644 index 0000000..a06e352 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/wpng.c @@ -0,0 +1,853 @@ +/*--------------------------------------------------------------------------- + + 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. Thanks + to Cosmin Truta for Cygwin fixes. + + 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 + - 1.04: fixed DOS/OS2/Win32 detection, including partial Cygwin fix + (see http://home.att.net/~perlspinr/diffs/GregBook_cygwin.diff) + - 2.00: dual-licensed (added GNU GPL) + + [REPORTED BUG (win32 only): "contrib/gregbook/wpng.c - cmd line + dose not work! In order to do something useful I needed to redirect + both input and output, with cygwin and with bcc32 as well. Under + Linux, the same wpng appears to work fine. I don't know what is + the problem."] + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#define PROGNAME "wpng" +#define VERSION "2.00 of 2 June 2007" +#define APPNAME "Simple PGM/PPM/PAM to PNG Converter" + +#if defined(__MSDOS__) || defined(__OS2__) +# define DOS_OS2_W32 +#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +# ifndef __GNUC__ /* treat Win32 native ports of gcc as Unix environments */ +# define DOS_OS2_W32 +# endif +#endif + +#include +#include +#include +#include /* for jmpbuf declaration in writepng.h */ +#include + +#ifdef DOS_OS2_W32 +# include /* for isatty(), setmode() prototypes */ +# include /* 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 +# define getch() getkey() /* GRR: need getche() */ +# else +# include /* for getche() console input */ +# endif +# endif /* ?__EMX__ */ +# define FGETS(buf,len,stream) dos_kbd_gets(buf,len) +#else +# include /* 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 key.\n"); + /* note: just 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 */ diff --git a/contrib/libpng/contrib/gregbook/writepng.c b/contrib/libpng/contrib/gregbook/writepng.c new file mode 100644 index 0000000..f07f4a8 --- /dev/null +++ b/contrib/libpng/contrib/gregbook/writepng.c @@ -0,0 +1,400 @@ +/*--------------------------------------------------------------------------- + + wpng - simple PNG-writing program writepng.c + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + + +#include /* 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 some other method to return control to + * application code, 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); + } + + /* Now we have our data structure we can use the information in it + * to return control to our own higher level code (all the points + * where 'setjmp' is called in this file.) This will work with other + * error handling mechanisms as well - libpng always calls png_error + * when it can proceed no further, thus, so long as the error handler + * is intercepted, application code can do its own error recovery. + */ + longjmp(mainprog_ptr->jmpbuf, 1); +} diff --git a/contrib/libpng/contrib/gregbook/writepng.h b/contrib/libpng/contrib/gregbook/writepng.h new file mode 100644 index 0000000..78b966b --- /dev/null +++ b/contrib/libpng/contrib/gregbook/writepng.h @@ -0,0 +1,133 @@ +/*--------------------------------------------------------------------------- + + wpng - simple PNG-writing program writepng.h + + --------------------------------------------------------------------------- + + Copyright (c) 1998-2007 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. + + The contents of this file are DUAL-LICENSED. You may modify and/or + redistribute this software according to the terms of one of the + following two licenses (at your option): + + + LICENSE 1 ("BSD-like with advertising clause"): + + 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. + + + LICENSE 2 (GNU GPL v2 or later): + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ---------------------------------------------------------------------------*/ + +#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); diff --git a/contrib/libpng/contrib/pngminim/README b/contrib/libpng/contrib/pngminim/README new file mode 100644 index 0000000..51d5a3c --- /dev/null +++ b/contrib/libpng/contrib/pngminim/README @@ -0,0 +1,4 @@ +This demonstrates the use of PNG_USER_CONFIG, pngusr.h and pngusr.dfa +to build minimal decoder, encoder, and progressive reader applications. + +See the individual README and pngusr.dfa files for more explanation. diff --git a/contrib/libpng/contrib/pngminim/decoder/README b/contrib/libpng/contrib/pngminim/decoder/README new file mode 100644 index 0000000..5618cb7 --- /dev/null +++ b/contrib/libpng/contrib/pngminim/decoder/README @@ -0,0 +1,10 @@ +This demonstrates the use of PNG_USER_CONFIG, pngusr.h and pngusr.dfa + +The makefile builds a minimal read-only decoder with embedded libpng +and zlib. + +Specify the location of the zlib source (1.2.1 or later) as ZLIBSRC +on the make command line. + +If you prefer to use the shared libraries, go to contrib/pngminus +and build the png2pnm application there. diff --git a/contrib/libpng/contrib/pngminim/decoder/makefile b/contrib/libpng/contrib/pngminim/decoder/makefile new file mode 100644 index 0000000..43e45bd --- /dev/null +++ b/contrib/libpng/contrib/pngminim/decoder/makefile @@ -0,0 +1,149 @@ +# Makefile for PngMinus (pngm2pnm) +# Linux / Unix + +#CC=cc +CC=gcc +LD=$(CC) +STRIP=strip + +# If awk fails try +# make AWK=nawk + +RM=rm -f +COPY=cp + +CFLAGS=-DPNG_USER_CONFIG -DNO_GZCOMPRESS -DNO_GZIP -I. -O1 + +C=.c +O=.o +L=.a +E= + +# Where to find the source code: +PNGSRC =../../.. +ZLIBSRC=$(PNGSRC)/../zlib +PROGSRC=$(PNGSRC)/contrib/pngminus + +# Zlib (minimal inflate requirements - crc32 is used by libpng) +# zutil can be eliminated if you provide your own zcalloc and zcfree +ZSRCS = adler32$(C) crc32$(C) \ + inffast$(C) inflate$(C) inftrees$(C) \ + zutil$(C) + +# Standard headers +ZH = zlib.h crc32.h inffast.h inffixed.h \ + inflate.h inftrees.h zutil.h + +# Machine generated headers +ZCONF = zconf.h + +# Headers callers use +ZINC = zlib.h $(ZCONF) + +# Headers the Zlib source uses +ZHDRS = $(ZH) $(ZCONF) + +ZOBJS = adler32$(O) crc32$(O) \ + inffast$(O) inflate$(O) inftrees$(O) \ + zutil$(O) + +# libpng +PNGSRCS=png$(C) pngerror$(C) pngget$(C) pngmem$(C) \ + pngread$(C) pngrio$(C) pngrtran$(C) pngrutil$(C) \ + pngset$(C) pngtrans$(C) + +# Standard headers +PNGH =png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h + +# Machine generated headers +PNGCONF=pnglibconf.h + +# Headers callers use +PNGINC= png.h pngconf.h pngusr.h $(PNGCONF) + +# Headers the PNG library uses +PNGHDRS=$(PNGH) $(PNGCONF) pngusr.h + +PNGOBJS=png$(O) pngerror$(O) pngget$(O) pngmem$(O) \ + pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) \ + pngset$(O) pngtrans$(O) + +PROGSRCS= pngm2pnm$(C) +PROGHDRS= +PROGDOCS= +PROGOBJS= pngm2pnm$(O) + +OBJS = $(PROGOBJS) $(PNGOBJS) $(ZOBJS) + +# implicit make rules ------------------------------------------------------- + +# note: dependencies do not work on implicit rule lines +.c$(O): + $(CC) -c $(CFLAGS) $< + +# dependencies + +all: pngm2pnm$(E) + +pngm2pnm$(E): $(OBJS) + $(LD) -o pngm2pnm$(E) $(OBJS) + $(STRIP) pngm2pnm$(E) + +# The DFA_XTRA setting turns all libpng options off then +# turns on those required for this minimal build. +# The CPP_FLAGS setting causes pngusr.h to be included in +# both the build of pnglibconf.h and, subsequently, when +# building libpng itself. +$(PNGCONF): $(PNGSRC)/scripts/pnglibconf.mak\ + $(PNGSRC)/scripts/pnglibconf.dfa \ + $(PNGSRC)/scripts/options.awk pngusr.h pngusr.dfa + $(RM) pnglibconf.h pnglibconf.dfn + $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\ + srcdir=$(PNGSRC) CPPFLAGS="-DPNG_USER_CONFIG"\ + DFA_XTRA="pngusr.dfa" $@ + +clean: + $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\ + srcdir=$(PNGSRC) clean + $(RM) pngm2pnm$(O) + $(RM) pngm2pnm$(E) + $(RM) $(OBJS) + +# distclean also removes the copied source and headers +distclean: clean + $(RM) -r scripts # historical reasons + $(RM) $(PNGSRCS) $(PNGH) + $(RM) $(ZSRCS) $(ZH) $(ZCONF) + $(RM) $(PROGSRCS) $(PROGHDRS) $(PROGDOCS) + +# Header file dependencies: +$(PROGOBJS): $(PROGHDRS) $(PNGINC) $(ZINC) +$(PNGOBJS): $(PNGHDRS) $(ZINC) +$(ZOBJS): $(ZHDRS) + +# Gather the source code from the respective directories +$(PNGSRCS) $(PNGH): $(PNGSRC)/$@ + $(RM) $@ + $(COPY) $(PNGSRC)/$@ $@ + +# No dependency on the ZLIBSRC target so that it only needs +# to be specified once. +$(ZSRCS) $(ZH): + $(RM) $@ + $(COPY) $(ZLIBSRC)/$@ $@ + +# The unconfigured zconf.h varies in name according to the +# zlib release +$(ZCONF): + $(RM) $@ + @for f in zconf.h.in zconf.in.h zconf.h; do\ + test -r $(ZLIBSRC)/$$f &&\ + echo $(COPY) $(ZLIBSRC)/$$f $@ &&\ + $(COPY) $(ZLIBSRC)/$$f $@ && exit 0;\ + done; echo copy: $(ZLIBSRC)/zconf.h not found; exit 1 + +pngm2pnm.c: $(PROGSRC)/png2pnm.c + $(RM) $@ + $(COPY) $(PROGSRC)/png2pnm.c $@ + +# End of makefile for pngm2pnm diff --git a/contrib/libpng/contrib/pngminim/decoder/pngusr.dfa b/contrib/libpng/contrib/pngminim/decoder/pngusr.dfa new file mode 100644 index 0000000..9653cd1 --- /dev/null +++ b/contrib/libpng/contrib/pngminim/decoder/pngusr.dfa @@ -0,0 +1,39 @@ +# pngminim/decoder/pngusr.dfa +# +# Copyright (c) 2010-2011 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# First all the build options off: + +everything = off + +# All that is required is some read code. This example switches +# on the sequential read code (see ../preader for a progressive +# read example). + +option SEQUENTIAL_READ on + +# You must choose fixed or floating point arithmetic: +# option FLOATING_POINT on + +option FIXED_POINT on + +# You must chose the internal fixed point implementation or to +# use the system floating point. The latter is considerably +# smaller (by about 1kbyte on an x86 system): +# option FLOATING_ARITHMETIC on + +option FLOATING_ARITHMETIC off + +# Your program will probably need other options. The example +# program here, pngm2pnm, requires the following. Take a look +# at pnglibconf.h to find out the full set of what has to be +# enabled to make the following work. + +option SETJMP on +option STDIO on +option READ_EXPAND on +option READ_16_TO_8 on diff --git a/contrib/libpng/contrib/pngminim/decoder/pngusr.h b/contrib/libpng/contrib/pngminim/decoder/pngusr.h new file mode 100644 index 0000000..ce85537 --- /dev/null +++ b/contrib/libpng/contrib/pngminim/decoder/pngusr.h @@ -0,0 +1,23 @@ +/* minrdpngconf.h: headers to make a minimal png-read-only library + * + * Copyright (c) 2007, 2010-2011 Glenn Randers-Pehrson + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Derived from pngcrush.h, Copyright 1998-2007, Glenn Randers-Pehrson + */ + +#ifndef MINRDPNGCONF_H +#define MINRDPNGCONF_H + +/* To include pngusr.h set -DPNG_USER_CONFIG in CPPFLAGS */ + +/* List options to turn off features of the build that do not + * affect the API (so are not recorded in pnglibconf.h) + */ + +#define PNG_NO_WARNINGS + +#endif /* MINRDPNGCONF_H */ diff --git a/contrib/libpng/contrib/pngminim/encoder/README b/contrib/libpng/contrib/pngminim/encoder/README new file mode 100644 index 0000000..04fd27f --- /dev/null +++ b/contrib/libpng/contrib/pngminim/encoder/README @@ -0,0 +1,10 @@ +This demonstrates the use of PNG_USER_CONFIG and pngusr.h + +The makefile builds a minimal write-only decoder with embedded libpng +and zlib. + +Specify the location of the zlib source (1.2.1 or later) as ZLIBSRC +on the make command line. + +If you prefer to use the shared libraries, go to contrib/pngminus +and build the pnm2png application there. diff --git a/contrib/libpng/contrib/pngminim/encoder/makefile b/contrib/libpng/contrib/pngminim/encoder/makefile new file mode 100644 index 0000000..a19ae73 --- /dev/null +++ b/contrib/libpng/contrib/pngminim/encoder/makefile @@ -0,0 +1,148 @@ +# Makefile for PngMinus (pnm2pngm) +# Linux / Unix + +#CC=cc +CC=gcc +LD=$(CC) +STRIP=strip + +# If awk fails try +# make AWK=nawk + +RM=rm -f +COPY=cp + +CFLAGS=-DPNG_USER_CONFIG -DNO_GZIP -I. -O1 + +C=.c +O=.o +L=.a +E= + +# Where to find the source code: +PNGSRC =../../.. +ZLIBSRC=$(PNGSRC)/../zlib +PROGSRC=$(PNGSRC)/contrib/pngminus + +# Zlib +ZSRCS = adler32$(C) compress$(C) crc32$(C) deflate$(C) \ + trees$(C) zutil$(C) + +# Standard headers +#ZH = zlib.h crc32.h deflate.h trees.h zutil.h +ZH = zlib.h crc32.h deflate.h trees.h zutil.h + +# Machine generated headers +ZCONF = zconf.h + +# Headers callers use +ZINC = zlib.h $(ZCONF) + +# Headers the Zlib source uses +ZHDRS = $(ZH) $(ZCONF) + +# compress is not required; it is needed to link the zlib +# code because deflate defines an unused API function deflateBound +# which itself calls compressBound from compress. +ZOBJS = adler32$(O) compress$(O) crc32$(O) deflate$(O) \ + trees$(O) zutil$(O) + +# libpng +PNGSRCS=png$(C) pngerror$(C) pngget$(C) pngmem$(C) \ + pngset$(C) pngtrans$(C) pngwio$(C) pngwrite$(C) \ + pngwtran$(C) pngwutil$(C) + +# Standard headers +PNGH =png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h + +# Machine generated headers +PNGCONF=pnglibconf.h + +# Headers callers use +PNGINC= png.h pngconf.h pngusr.h $(PNGCONF) + +# Headers the PNG library uses +PNGHDRS=$(PNGH) $(PNGCONF) pngusr.h + +PNGOBJS=png$(O) pngerror$(O) pngget$(O) pngmem$(O) \ + pngset$(O) pngtrans$(O) pngwio$(O) pngwrite$(O) \ + pngwtran$(O) pngwutil$(O) + +PROGSRCS= pnm2pngm$(C) +PROGHDRS= +PROGDOCS= +PROGOBJS= pnm2pngm$(O) + +OBJS = $(PROGOBJS) $(PNGOBJS) $(ZOBJS) + +# implicit make rules ------------------------------------------------------- + +.c$(O): + $(CC) -c $(CFLAGS) $< + +# dependencies + +all: pnm2pngm$(E) + +pnm2pngm$(E): $(OBJS) + $(LD) -o pnm2pngm$(E) $(OBJS) + $(STRIP) pnm2pngm$(E) + +# The DFA_XTRA setting turns all libpng options off then +# turns on those required for this minimal build. +# The CPP_FLAGS setting causes pngusr.h to be included in +# both the build of pnglibconf.h and, subsequently, when +# building libpng itself. +$(PNGCONF): $(PNGSRC)/scripts/pnglibconf.mak\ + $(PNGSRC)/scripts/pnglibconf.dfa \ + $(PNGSRC)/scripts/options.awk pngusr.h pngusr.dfa + $(RM) pnglibconf.h pnglibconf.dfn + $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\ + srcdir=$(PNGSRC) CPPFLAGS="-DPNG_USER_CONFIG"\ + DFA_XTRA="pngusr.dfa" $@ + +clean: + $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\ + srcdir=$(PNGSRC) clean + $(RM) pnm2pngm$(O) + $(RM) pnm2pngm$(E) + $(RM) $(OBJS) + +# distclean also removes the copied source and headers +distclean: clean + $(RM) -r scripts # historical reasons + $(RM) $(PNGSRCS) $(PNGH) + $(RM) $(ZSRCS) $(ZH) $(ZCONF) + $(RM) $(PROGSRCS) $(PROGHDRS) $(PROGDOCS) + +# Header file dependencies: +$(PROGOBJS): $(PROGHDRS) $(PNGINC) $(ZINC) +$(PNGOBJS): $(PNGHDRS) $(ZINC) +$(ZOBJS): $(ZHDRS) + +# Gather the source code from the respective directories +$(PNGSRCS) $(PNGH): $(PNGSRC)/$@ + $(RM) $@ + $(COPY) $(PNGSRC)/$@ $@ + +# No dependency on the ZLIBSRC target so that it only needs +# to be specified once. +$(ZSRCS) $(ZH): + $(RM) $@ + $(COPY) $(ZLIBSRC)/$@ $@ + +# The unconfigured zconf.h varies in name according to the +# zlib release +$(ZCONF): + $(RM) $@ + @for f in zconf.h.in zconf.in.h zconf.h; do\ + test -r $(ZLIBSRC)/$$f &&\ + echo $(COPY) $(ZLIBSRC)/$$f $@ &&\ + $(COPY) $(ZLIBSRC)/$$f $@ && exit 0;\ + done; echo copy: $(ZLIBSRC)/zconf.h not found; exit 1 + +pnm2pngm.c: $(PROGSRC)/pnm2png.c + $(RM) $@ + $(COPY) $(PROGSRC)/pnm2png.c $@ + +# End of makefile for pnm2pngm diff --git a/contrib/libpng/contrib/pngminim/encoder/pngusr.dfa b/contrib/libpng/contrib/pngminim/encoder/pngusr.dfa new file mode 100644 index 0000000..ee88443 --- /dev/null +++ b/contrib/libpng/contrib/pngminim/encoder/pngusr.dfa @@ -0,0 +1,35 @@ +# pngminim/encoder/pngusr.dfa +# +# Copyright (c) 2010-2011 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# First all the build options off: + +everything = off + +# Switch on the write code - this makes a minimalist encoder + +option WRITE on + +# You must choose fixed or floating point arithmetic: +# option FLOATING_POINT on + +option FIXED_POINT on + +# You must chose the internal fixed point implementation or to +# use the system floating point. The latter is considerably +# smaller (by about 1kbyte on an x86 system): +# option FLOATING_ARITHMETIC on + +option FLOATING_ARITHMETIC off + +# Your program will probably need other options. The example +# program here, pnm2pngm, requires the following. Take a look +# at pnglibconf.h to find out the full set of what has to be +# enabled to make the following work. + +option SETJMP on +option STDIO on diff --git a/contrib/libpng/contrib/pngminim/encoder/pngusr.h b/contrib/libpng/contrib/pngminim/encoder/pngusr.h new file mode 100644 index 0000000..fb35245 --- /dev/null +++ b/contrib/libpng/contrib/pngminim/encoder/pngusr.h @@ -0,0 +1,23 @@ +/* minwrpngconf.h: headers to make a minimal png-write-only library + * + * Copyright (c) 2007, 2010-2011 Glenn Randers-Pehrson + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Derived from pngcrush.h, Copyright 1998-2007, Glenn Randers-Pehrson + */ + +#ifndef MINWRPNGCONF_H +#define MINWRPNGCONF_H + +/* To include pngusr.h set -DPNG_USER_CONFIG in CPPFLAGS */ + +/* List options to turn off features of the build that do not + * affect the API (so are not recorded in pnglibconf.h) + */ + +#define PNG_NO_WARNINGS + +#endif /* MINWRPNGCONF_H */ diff --git a/contrib/libpng/contrib/pngminim/preader/README b/contrib/libpng/contrib/pngminim/preader/README new file mode 100644 index 0000000..6bf1db0 --- /dev/null +++ b/contrib/libpng/contrib/pngminim/preader/README @@ -0,0 +1,15 @@ +This demonstrates the use of PNG_USER_CONFIG and pngusr.h + +The makefile builds a minimal read-only progressive decoder with +embedded libpng, zlib and your system's X library. + +Specify the location of the zlib source (1.2.1 or later) as ZLIBSRC +on the make command line. + +Edit makefile if required, to find your X library and include files, +then + + make ZLIBSRC=directory + +If you prefer to use the shared libraries, go to contrib/gregbook +and build the rpng2-x application there. diff --git a/contrib/libpng/contrib/pngminim/preader/makefile b/contrib/libpng/contrib/pngminim/preader/makefile new file mode 100644 index 0000000..282709e --- /dev/null +++ b/contrib/libpng/contrib/pngminim/preader/makefile @@ -0,0 +1,164 @@ +# Makefile for PngMinus (rpng2) +# Linux / Unix + +#CC=cc +CC=gcc +LD=$(CC) +STRIP=strip + +# If awk fails try +# make AWK=nawk + +RM=rm -f +COPY=cp + +#XINC = -I/usr/include # old-style, stock X distributions +#XLIB = -L/usr/lib/X11 -lX11 # (including SGI IRIX) + +#XINC = -I/usr/openwin/include # Sun workstations (OpenWindows) +#XLIB = -L/usr/openwin/lib -lX11 + +XINC = -I/usr/X11R6/include # new X distributions (X.org, etc.) +XLIB = -L/usr/X11R6/lib -lX11 +#XLIB = -L/usr/X11R6/lib64 -lX11 # e.g., Red Hat on AMD64 + +#XINC = -I/usr/local/include # FreeBSD +#XLIB = -L/usr/local/lib -lX11 + +#LIBS = $(XLIB) +LIBS = $(XLIB) -lm #platforms that need libm + +CFLAGS=-DPNG_USER_CONFIG -DNO_GZCOMPRESS -DNO_GZIP -I. $(XINC) -O1 + +C=.c +O=.o +L=.a +E= + +# Where to find the source code: +PNGSRC =../../.. +ZLIBSRC=$(PNGSRC)/../zlib +PROGSRC=$(PNGSRC)/contrib/gregbook + +# Zlib (minimal inflate requirements - crc32 is used by libpng) +# zutil can be eliminated if you provide your own zcalloc and zcfree +ZSRCS = adler32$(C) crc32$(C) \ + inffast$(C) inflate$(C) inftrees$(C) \ + zutil$(C) + +# Standard headers +ZH = zlib.h crc32.h inffast.h inffixed.h \ + inflate.h inftrees.h zutil.h + +# Machine generated headers +ZCONF = zconf.h + +# Headers callers use +ZINC = zlib.h $(ZCONF) + +# Headers the Zlib source uses +ZHDRS = $(ZH) $(ZCONF) + +ZOBJS = adler32$(O) crc32$(O) \ + inffast$(O) inflate$(O) inftrees$(O) \ + zutil$(O) + +# libpng +PNGSRCS=png$(C) pngerror$(C) pngget$(C) pngmem$(C) \ + pngpread$(C) pngread$(C) pngrio$(C) pngrtran$(C) pngrutil$(C) \ + pngset$(C) pngtrans$(C) + +# Standard headers +PNGH =png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h + +# Machine generated headers +PNGCONF=pnglibconf.h + +# Headers callers use +PNGINC= png.h pngconf.h pngusr.h $(PNGCONF) + +# Headers the PNG library uses +PNGHDRS=$(PNGH) $(PNGCONF) pngusr.h + +PNGOBJS=png$(O) pngerror$(O) pngget$(O) pngmem$(O) \ + pngpread$(O) pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) \ + pngset$(O) pngtrans$(O) + +PROGSRCS= rpng2-x$(C) readpng2$(C) +PROGHDRS= readpng2.h +PROGDOCS= COPYING LICENSE +PROGOBJS= rpng2-x$(O) readpng2$(O) + +OBJS = $(PROGOBJS) $(PNGOBJS) $(ZOBJS) + +# implicit make rules ------------------------------------------------------- + +.c$(O): + $(CC) -c $(CFLAGS) $< + +# dependencies + +all: $(PROGDOCS) rpng2-x$(E) + +rpng2-x$(E): $(OBJS) + $(LD) -o rpng2-x$(E) $(OBJS) $(LIBS) + $(STRIP) rpng2-x$(E) + +# The DFA_XTRA setting turns all libpng options off then +# turns on those required for this minimal build. +# The CPP_FLAGS setting causes pngusr.h to be included in +# both the build of pnglibconf.h and, subsequently, when +# building libpng itself. +$(PNGCONF): $(PNGSRC)/scripts/pnglibconf.mak\ + $(PNGSRC)/scripts/pnglibconf.dfa \ + $(PNGSRC)/scripts/options.awk pngusr.h pngusr.dfa + $(RM) pnglibconf.h pnglibconf.dfn + $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\ + srcdir=$(PNGSRC) CPPFLAGS="-DPNG_USER_CONFIG"\ + DFA_XTRA="pngusr.dfa" $@ + +clean: + $(MAKE) $(MAKEFLAGS) -f $(PNGSRC)/scripts/pnglibconf.mak\ + srcdir=$(PNGSRC) clean + $(RM) rpng2-x$(O) + $(RM) rpng2-x$(E) + $(RM) $(OBJS) + +# distclean also removes the copied source and headers +distclean: clean + $(RM) -r scripts # historical reasons + $(RM) $(PNGSRCS) $(PNGH) + $(RM) $(ZSRCS) $(ZH) $(ZCONF) + $(RM) $(PROGSRCS) $(PROGHDRS) $(PROGDOCS) + +# Header file dependencies: +$(PROGOBJS): $(PROGHDRS) $(PNGINC) $(ZINC) +$(PNGOBJS): $(PNGHDRS) $(ZINC) +$(ZOBJS): $(ZHDRS) + +# Gather the source code from the respective directories +$(PNGSRCS) $(PNGH): $(PNGSRC)/$@ + $(RM) $@ + $(COPY) $(PNGSRC)/$@ $@ + +# No dependency on the ZLIBSRC target so that it only needs +# to be specified once. +$(ZSRCS) $(ZH): + $(RM) $@ + $(COPY) $(ZLIBSRC)/$@ $@ + +# The unconfigured zconf.h varies in name according to the +# zlib release +$(ZCONF): + $(RM) $@ + @for f in zconf.h.in zconf.in.h zconf.h; do\ + test -r $(ZLIBSRC)/$$f &&\ + echo $(COPY) $(ZLIBSRC)/$$f $@ &&\ + $(COPY) $(ZLIBSRC)/$$f $@ && exit 0;\ + done; echo copy: $(ZLIBSRC)/zconf.h not found; exit 1 + +$(PROGSRCS) $(PROGHDRS) $(PROGDOCS): $(PROGSRC)/$@ + $(RM) $@ + $(COPY) $(PROGSRC)/$@ $@ + +# End of makefile for rpng2-x diff --git a/contrib/libpng/contrib/pngminim/preader/pngusr.dfa b/contrib/libpng/contrib/pngminim/preader/pngusr.dfa new file mode 100644 index 0000000..5fa9c55 --- /dev/null +++ b/contrib/libpng/contrib/pngminim/preader/pngusr.dfa @@ -0,0 +1,40 @@ +# pngminim/preader/pngusr.dfa +# +# Copyright (c) 2010-2011 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# First all the build options off: + +everything = off + +# Just switch on the progressive read code + +option PROGRESSIVE_READ on + +# You may choose fixed or floating point APIs: +# option FLOATING_POINT on + +option FIXED_POINT on + +# You must chose the internal fixed point implementation or to +# use the system floating point. The latter is considerably +# smaller (by about 1kbyte on an x86 system): + +option FLOATING_ARITHMETIC on +# option FLOATING_ARITHMETIC off + +# Your program will probably need other options. The example +# program here, rpng2-x, requires the following. Take a look +# at pnglibconf.h to find out the full set of what has to be +# enabled to make the following work. + +option SETJMP on +option STDIO on +option READ_bKGD on +option READ_GAMMA on +option READ_EXPAND on +option READ_16_TO_8 on +option READ_GRAY_TO_RGB on diff --git a/contrib/libpng/contrib/pngminim/preader/pngusr.h b/contrib/libpng/contrib/pngminim/preader/pngusr.h new file mode 100644 index 0000000..b40cc46 --- /dev/null +++ b/contrib/libpng/contrib/pngminim/preader/pngusr.h @@ -0,0 +1,23 @@ +/* minrdpngconf.h: headers to make a minimal png-read-only library + * + * Copyright (c) 2009, 2010-2011 Glenn Randers-Pehrson + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Derived from pngcrush.h, Copyright 1998-2007, Glenn Randers-Pehrson + */ + +#ifndef MINPRDPNGCONF_H +#define MINPRDPNGCONF_H + +/* To include pngusr.h set -DPNG_USER_CONFIG in CPPFLAGS */ + +/* List options to turn off features of the build that do not + * affect the API (so are not recorded in pnglibconf.h) + */ + +#define PNG_NO_WARNINGS + +#endif /* MINPRDPNGCONF_H */ diff --git a/contrib/libpng/contrib/pngminus/README b/contrib/libpng/contrib/pngminus/README new file mode 100644 index 0000000..bbe7407 --- /dev/null +++ b/contrib/libpng/contrib/pngminus/README @@ -0,0 +1,153 @@ +PngMinus +-------- +(copyright Willem van Schaik, 1999) + + +License +------- + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and +that both that copyright notice and this permission notice appear in +supporting documentation. This software is provided "as is" without +express or implied warranty. + + +Some history +------------ +Soon after the creation of PNG in 1995, the need was felt for a set of +pnmtopng / pngtopnm utilities. Independantly Alexander Lehmann and I +(Willem van Schaik) started such a project. Luckily we discovered this +and merged the two together into pnmtopng.tar.gz, which is available +from a/o ftp://ftp.simplesystems.org/pub/libpng/png/. + +These two utilities have many, many options and make use of most of the +features of PNG, like gamma, alpha, sbit, text-chunks, etc. This makes +the utilities quite complex and by now not anymore very maintainable. +When we wrote these programs, libpng was still in an early stage. +Therefore, lots of the functionality that we put in our software can now +be done using transform-functions in libpng. + +Finally, to compile these programs, you need to have installed and +compiled three libraries: libpng, zlib and netpbm. Especially the latter +makes the whole setup a bit bulky. But that's unavoidable given the many +features of pnmtopng. + + +What now +-------- +At this moment libpng is in a very stable state and can do much of the +work done in pnmtopng. Also, pnmtopng needs to be upgraded to the new +interface of libpng. Hence, it is time for a rewrite from the ground up +of pnmtopng and pngtopnm. This will happen in the near future (stay +tuned). The new package will get a different name to distinguish it from +the old one: PngPlus. + +To experiment a bit with the new interface of libpng, I started off with +a small prototype that contains only the basic functionality. It doesn't +have any of the options to read or write special chunks and it will do +no gamma correction. But this makes it also a simple program that is +quite easy to understand and can serve well as a template for other +software developments. (By now there are of course a couple of programs, +like Greg Roelofs' rpng/wpng, that can be used just as good.) + + +Can and can not +--------------- +As this is the small brother of the future PngPlus, I called this fellow +PngMinus. Because I started this development in good-old Turbo-C, I +avoided the use the netpbm library, which requires DOS extenders. Again, +another reason to call it PngMinus (minus netpbm :-). So, part of the +program are some elementary routines to read / write pgm- and ppm-files. +It does not read b&w pbm-files. + +The downside of this approach is that you can not use them on images +that require blocks of memory bigger than 64k (the DOS version). For +larger images you will get an out-of-memory error. + +As said before, PngMinus doesn't correct for gamma. When reading +png-files you can do this just as well by piping the output of png2pnm +to pnmgamma, one of the standard PbmPlus tools. This same scenario will +most probably also be followed in the full-blown future PngPlus, with +the addition of course of the possibility to create gamma-chunks when +writing png-files. + +On the other hand it supports alpha-channels. When reading a png-image +you can write the alpha-channel into a pgm-file. And when creating an +RGB+A png-image, you just combine a ppm-file with a corresponding +pgm-file containing the alpha-channel. When reading, transparency chunks +are converted into an alpha-channel and from there on treated the same +way. + +Finally you can opt for writing ascii or binary pgm- and ppm-files. When +the bit-depth is 16, the format will always be ascii. + + +Using it +-------- +To distinguish them from pnmtopng and PngPlus, the utilities are named +png2pnm and pnm2png (2 instead of to). The input- and output-files can +be given as parameters or through redirection. Therefore the programs +can be part of a pipe. + +To list the options type "png2pnm -h" or "pnm2png -h". + + +Just like Scandinavian furniture +-------------------------------- +You have to put it together yourself. I did test the software under +MS-DOS with Turbo-C 3.0 and under RedHat Linux 4.2 with gcc. In both +cases I used libpng-1.0.4 and zlib-1.1.3. Later versions should be OK, +however some older libpng versions have a bug in pngmem.c when using +Turbo-C 3.0 (see below). + +You can build it using one of the two makefiles (make -f makefile.###) +or use the batch/script files pngminus.bat / pngminus.sh. This assumes +that you have built the libraries in ../libpng and ../zlib. Using Linux, +make sure that you have built libpng with makefile.std and not +makefile.linux (also called .lnx in earlier versions of libpng). The +latter creates a .so shared-library, while the PngMinus makefile assumes +a normal .a static library. + +If you create a ../pngsuite directory and then store the basn####.png +files from PngSuite (http://www.schaik.com/pngsuite/) in there, you can +test in one go the proper functioning of PngMinus, see png2pnm.bat and +pnm2png.bat (or the .sh versions). + + +Warranty +------- +Please, remember that this was just a small experiment to learn a few +things. It will have many unforeseen features . Who said bugs? Use +it when you are in need for something simple or when you want to start +developing your own stuff. + + +The Turbo bug +------------- +** pngmem.old + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr += 16L; +** pngmem.c + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr = hptr + 16L; +** + +** pngmem.old + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr += (png_uint_32)65536L; +** pngmem.c + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr = hptr + 65536L; +** + + +The end +------- +Willem van Schaik +mailto:willem@schaik.com +http://www.schaik.com/png/ +------- +Oct 1999 + diff --git a/contrib/libpng/contrib/pngminus/makefile.std b/contrib/libpng/contrib/pngminus/makefile.std new file mode 100644 index 0000000..2fb061b --- /dev/null +++ b/contrib/libpng/contrib/pngminus/makefile.std @@ -0,0 +1,65 @@ +# Makefile for PngMinus (png2pnm and pnm2png) +# Linux / Unix + +#CC=cc +CC=gcc +LD=$(CC) + +RM=rm -f + +#PNGPATH = /usr/local +#PNGINC = -I$(PNGPATH)/include/libpng12 +#PNGLIB = -L$(PNGPATH)/lib -lpng12 +#PNGLIBS = $(PNGPATH)/lib/libpng12.a +PNGINC = -I../.. +PNGLIB = -L../.. -lpng +PNGLIBS = ../../libpng.a + +#ZPATH = /usr/local +#ZINC = -I$(ZPATH)/include +#ZLIB = -L$(ZPATH)/lib -lz +#ZLIBS = $(ZPATH)/lib/libz.a +ZINC = -I../../../zlib +ZLIB = -L../../../zlib -lz +ZLIBS = ../../../zlib/libz.a + +CFLAGS=-O3 $(PNGINC) $(ZINC) +LDFLAGS=$(PNGLIB) $(ZLIB) +LDFLAGSS=$(PNGLIBS) $(ZLIBS) +C=.c +O=.o +L=.a +E= + +# dependencies + +#all: png2pnm$(E) pnm2png$(E) +all: png2pnm$(E) pnm2png$(E) png2pnm-static$(E) pnm2png-static$(E) + +png2pnm$(O): png2pnm$(C) + $(CC) -c $(CFLAGS) png2pnm$(C) + +png2pnm$(E): png2pnm$(O) + $(LD) -o png2pnm$(E) png2pnm$(O) $(LDFLAGS) -lm + +png2pnm-static$(E): png2pnm$(O) + $(LD) -o png2pnm-static$(E) png2pnm$(O) $(LDFLAGSS) -lm + +pnm2png$(O): pnm2png$(C) + $(CC) -c $(CFLAGS) pnm2png$(C) + +pnm2png$(E): pnm2png$(O) + $(LD) -o pnm2png$(E) pnm2png$(O) $(LDFLAGS) -lm + +pnm2png-static$(E): pnm2png$(O) + $(LD) -o pnm2png-static$(E) pnm2png$(O) $(LDFLAGSS) -lm + +clean: + $(RM) png2pnm$(O) + $(RM) pnm2png$(O) + $(RM) png2pnm$(E) + $(RM) pnm2png$(E) + $(RM) png2pnm-static$(E) + $(RM) pnm2png-static$(E) + +# End of makefile for png2pnm / pnm2png diff --git a/contrib/libpng/contrib/pngminus/makefile.tc3 b/contrib/libpng/contrib/pngminus/makefile.tc3 new file mode 100644 index 0000000..404f18d --- /dev/null +++ b/contrib/libpng/contrib/pngminus/makefile.tc3 @@ -0,0 +1,38 @@ +# Makefile for PngMinus (png2pnm and pnm2png) +# TurboC++ 3.0 + +CC=tcc -Ic:\tc3\inc +LD=tcc -Lc:\tc3\lib +LB=tlib +RM=del +CP=copy +MODEL=l +CCFLAGS=-O -m$(MODEL) -I..\libpng -I..\zlib +LDFLAGS=-m$(MODEL) -L..\libpng -L..\zlib +C=.c +O=.obj +L=.lib +E=.exe + +# dependencies + +all: png2pnm$(E) pnm2png$(E) + +png2pnm$(O): png2pnm$(C) + $(CC) -c $(CCFLAGS) png2pnm$(C) + +png2pnm$(E): png2pnm$(O) + $(LD) $(LDFLAGS) png2pnm$(O) libpng$(L) zlib$(L) + +pnm2png$(O): pnm2png$(C) + $(CC) -c $(CCFLAGS) pnm2png$(C) + +pnm2png$(E): pnm2png$(O) + $(LD) $(LDFLAGS) pnm2png$(O) libpng$(L) zlib$(L) + +clean: + $(RM) *$(O) + $(RM) *$(E) + +# End of makefile for png2pnm / pnm2png + diff --git a/contrib/libpng/contrib/pngminus/makevms.com b/contrib/libpng/contrib/pngminus/makevms.com new file mode 100644 index 0000000..00561bc --- /dev/null +++ b/contrib/libpng/contrib/pngminus/makevms.com @@ -0,0 +1,92 @@ +$!------------------------------------------------------------------------------ +$! make Contrib programs of libpng under OpenVMS +$! +$! +$! Look for the compiler used +$! +$ zlibsrc = "[---.zlib]" +$ ccopt="/include=(''zlibsrc',[--])" +$ 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 "[--]libpng.olb/lib" +$ write lopt "''zlibsrc'libz.olb/lib" +$ close lopt +$ open/write xopt x11.opt +$ write xopt "sys$library:decw$xlibshr.exe/share" +$ close xopt +$ write sys$output "Compiling PNG contrib programs ..." +$ write sys$output "Building pnm2png..." +$ CALL MAKE pnm2png.OBJ "cc ''CCOPT' pnm2png" - + pnm2png.c +$ call make pnm2png.exe - + "LINK pnm2png,lib.opt/opt" - + pnm2png.obj +$ write sys$output "Building png2pnm..." +$ CALL MAKE png2pnm.OBJ "cc ''CCOPT' png2pnm" - + png2pnm.c +$ call make png2pnm.exe - + "LINK png2pnm,lib.opt/opt" - + png2pnm.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 diff --git a/contrib/libpng/contrib/pngminus/png2pnm.bat b/contrib/libpng/contrib/pngminus/png2pnm.bat new file mode 100644 index 0000000..449cf36 --- /dev/null +++ b/contrib/libpng/contrib/pngminus/png2pnm.bat @@ -0,0 +1,41 @@ +REM -- grayscale +png2pnm.exe -noraw ..\pngsuite\basn0g01.png basn0g01.pgm +png2pnm.exe -noraw ..\pngsuite\basn0g02.png basn0g02.pgm +png2pnm.exe -noraw ..\pngsuite\basn0g04.png basn0g04.pgm +png2pnm.exe -noraw ..\pngsuite\basn0g08.png basn0g08.pgm +png2pnm.exe -noraw ..\pngsuite\basn0g16.png basn0g16.pgm +REM -- full-color +png2pnm.exe -noraw ..\pngsuite\basn2c08.png basn2c08.ppm +png2pnm.exe -noraw ..\pngsuite\basn2c16.png basn2c16.ppm +REM -- palletted +png2pnm.exe -noraw ..\pngsuite\basn3p01.png basn3p01.ppm +png2pnm.exe -noraw ..\pngsuite\basn3p02.png basn3p02.ppm +png2pnm.exe -noraw ..\pngsuite\basn3p04.png basn3p04.ppm +png2pnm.exe -noraw ..\pngsuite\basn3p08.png basn3p08.ppm +REM -- gray with alpha-channel +png2pnm.exe -noraw ..\pngsuite\basn4a08.png basn4a08.pgm +png2pnm.exe -noraw ..\pngsuite\basn4a16.png basn4a16.pgm +REM -- color with alpha-channel +png2pnm.exe -noraw -alpha basn6a08.pgm ..\pngsuite\basn6a08.png basn6a08.ppm +png2pnm.exe -noraw -alpha basn6a16.pgm ..\pngsuite\basn6a16.png basn6a16.ppm +REM -- grayscale +png2pnm.exe -raw ..\pngsuite\basn0g01.png rawn0g01.pgm +png2pnm.exe -raw ..\pngsuite\basn0g02.png rawn0g02.pgm +png2pnm.exe -raw ..\pngsuite\basn0g04.png rawn0g04.pgm +png2pnm.exe -raw ..\pngsuite\basn0g08.png rawn0g08.pgm +png2pnm.exe -raw ..\pngsuite\basn0g16.png rawn0g16.pgm +REM -- full-color +png2pnm.exe -raw ..\pngsuite\basn2c08.png rawn2c08.ppm +png2pnm.exe -raw ..\pngsuite\basn2c16.png rawn2c16.ppm +REM -- palletted +png2pnm.exe -raw ..\pngsuite\basn3p01.png rawn3p01.ppm +png2pnm.exe -raw ..\pngsuite\basn3p02.png rawn3p02.ppm +png2pnm.exe -raw ..\pngsuite\basn3p04.png rawn3p04.ppm +png2pnm.exe -raw ..\pngsuite\basn3p08.png rawn3p08.ppm +REM -- gray with alpha-channel +png2pnm.exe -raw ..\pngsuite\basn4a08.png rawn4a08.pgm +png2pnm.exe -raw ..\pngsuite\basn4a16.png rawn4a16.pgm +REM -- color with alpha-channel +png2pnm.exe -noraw -alpha rawn6a08.pgm ..\pngsuite\basn6a08.png rawn6a08.ppm +png2pnm.exe -noraw -alpha rawn6a16.pgm ..\pngsuite\basn6a16.png rawn6a16.ppm + diff --git a/contrib/libpng/contrib/pngminus/png2pnm.c b/contrib/libpng/contrib/pngminus/png2pnm.c new file mode 100644 index 0000000..a95acfa --- /dev/null +++ b/contrib/libpng/contrib/pngminus/png2pnm.c @@ -0,0 +1,430 @@ +/* + * png2pnm.c --- conversion from PNG-file to PGM/PPM-file + * copyright (C) 1999 by Willem van Schaik + * + * version 1.0 - 1999.10.15 - First version. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation. This software is provided "as is" without + * express or implied warranty. + */ + +#include +#include +#ifdef __TURBOC__ +#include +#include +#endif + +#ifndef BOOL +#define BOOL unsigned char +#endif +#ifndef TRUE +#define TRUE (BOOL) 1 +#endif +#ifndef FALSE +#define FALSE (BOOL) 0 +#endif + +#ifdef __TURBOC__ +#define STDIN 0 +#define STDOUT 1 +#define STDERR 2 +#endif + +/* to make png2pnm verbose so we can find problems (needs to be before png.h) */ +#ifndef PNG_DEBUG +#define PNG_DEBUG 0 +#endif + +#include "png.h" + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif + +/* function prototypes */ + +int main (int argc, char *argv[]); +void usage (); +BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file, BOOL raw, BOOL alpha); + +/* + * main + */ + +int main(int argc, char *argv[]) +{ + FILE *fp_rd = stdin; + FILE *fp_wr = stdout; + FILE *fp_al = NULL; + BOOL raw = TRUE; + BOOL alpha = FALSE; + int argi; + + for (argi = 1; argi < argc; argi++) + { + if (argv[argi][0] == '-') + { + switch (argv[argi][1]) + { + case 'n': + raw = FALSE; + break; + case 'r': + raw = TRUE; + break; + case 'a': + alpha = TRUE; + argi++; + if ((fp_al = fopen (argv[argi], "wb")) == NULL) + { + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: can not create alpha-channel file %s\n", argv[argi]); + exit (1); + } + break; + case 'h': + case '?': + usage(); + exit(0); + break; + default: + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, "Error: unknown option %s\n", argv[argi]); + usage(); + exit(1); + break; + } /* end switch */ + } + else if (fp_rd == stdin) + { + if ((fp_rd = fopen (argv[argi], "rb")) == NULL) + { + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, "Error: file %s does not exist\n", argv[argi]); + exit (1); + } + } + else if (fp_wr == stdout) + { + if ((fp_wr = fopen (argv[argi], "wb")) == NULL) + { + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, "Error: can not create file %s\n", argv[argi]); + exit (1); + } + } + else + { + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, "Error: too many parameters\n"); + usage(); + exit(1); + } + } /* end for */ + +#ifdef __TURBOC__ + /* set stdin/stdout if required to binary */ + if (fp_rd == stdin) + { + setmode (STDIN, O_BINARY); + } + if ((raw) && (fp_wr == stdout)) + { + setmode (STDOUT, O_BINARY); + } +#endif + + /* call the conversion program itself */ + if (png2pnm (fp_rd, fp_wr, fp_al, raw, alpha) == FALSE) + { + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, "Error: unsuccessful convertion of PNG-image\n"); + exit(1); + } + + /* close input file */ + fclose (fp_rd); + /* close output file */ + fclose (fp_wr); + /* close alpha file */ + if (alpha) + fclose (fp_al); + + return 0; +} + +/* + * usage + */ + +void usage() +{ + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, " by Willem van Schaik, 1999\n"); +#ifdef __TURBOC__ + fprintf (stderr, " for Turbo-C and Borland-C compilers\n"); +#else + fprintf (stderr, " for Linux (and Unix) compilers\n"); +#endif + fprintf (stderr, "Usage: png2pnm [options] .png [.pnm]\n"); + fprintf (stderr, " or: ... | png2pnm [options]\n"); + fprintf (stderr, "Options:\n"); + fprintf (stderr, " -r[aw] write pnm-file in binary format (P4/P5/P6) (default)\n"); + fprintf (stderr, " -n[oraw] write pnm-file in ascii format (P1/P2/P3)\n"); + fprintf (stderr, " -a[lpha] .pgm write PNG alpha channel as pgm-file\n"); + fprintf (stderr, " -h | -? print this help-information\n"); +} + +/* + * png2pnm + */ + +BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file, BOOL raw, BOOL alpha) +{ + png_struct *png_ptr = NULL; + png_info *info_ptr = NULL; + png_byte buf[8]; + png_byte *png_pixels = NULL; + png_byte **row_pointers = NULL; + png_byte *pix_ptr = NULL; + png_uint_32 row_bytes; + + png_uint_32 width; + png_uint_32 height; + int bit_depth; + int channels; + int color_type; + int alpha_present; + int row, col; + int ret; + int i; + long dep_16; + + /* read and check signature in PNG file */ + ret = fread (buf, 1, 8, png_file); + if (ret != 8) + return FALSE; + + ret = png_sig_cmp (buf, 0, 8); + if (ret) + return FALSE; + + /* create png and info structures */ + + png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL); + if (!png_ptr) + return FALSE; /* out of memory */ + + info_ptr = png_create_info_struct (png_ptr); + if (!info_ptr) + { + png_destroy_read_struct (&png_ptr, NULL, NULL); + return FALSE; /* out of memory */ + } + + if (setjmp (png_jmpbuf(png_ptr))) + { + png_destroy_read_struct (&png_ptr, &info_ptr, NULL); + return FALSE; + } + + /* set up the input control for C streams */ + png_init_io (png_ptr, png_file); + png_set_sig_bytes (png_ptr, 8); /* we already read the 8 signature bytes */ + + /* read the file information */ + png_read_info (png_ptr, info_ptr); + + /* get size and bit-depth of the PNG-image */ + png_get_IHDR (png_ptr, info_ptr, + &width, &height, &bit_depth, &color_type, + NULL, NULL, NULL); + + /* set-up the transformations */ + + /* transform paletted images into full-color rgb */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_expand (png_ptr); + /* expand images to bit-depth 8 (only applicable for grayscale images) */ + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand (png_ptr); + /* transform transparency maps into full alpha-channel */ + if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_expand (png_ptr); + +#ifdef NJET + /* downgrade 16-bit images to 8 bit */ + if (bit_depth == 16) + png_set_strip_16 (png_ptr); + /* transform grayscale images into full-color */ + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb (png_ptr); + /* only if file has a file gamma, we do a correction */ + if (png_get_gAMA (png_ptr, info_ptr, &file_gamma)) + png_set_gamma (png_ptr, (double) 2.2, file_gamma); +#endif + + /* 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); + + /* get the new color-type and bit-depth (after expansion/stripping) */ + png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, + NULL, NULL, NULL); + + /* check for 16-bit files */ + if (bit_depth == 16) + { + raw = FALSE; +#ifdef __TURBOC__ + pnm_file->flags &= ~((unsigned) _F_BIN); +#endif + } + + /* calculate new number of channels and store alpha-presence */ + if (color_type == PNG_COLOR_TYPE_GRAY) + channels = 1; + else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + channels = 2; + else if (color_type == PNG_COLOR_TYPE_RGB) + channels = 3; + else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + channels = 4; + else + channels = 0; /* should never happen */ + alpha_present = (channels - 1) % 2; + + /* check if alpha is expected to be present in file */ + if (alpha && !alpha_present) + { + fprintf (stderr, "PNG2PNM\n"); + fprintf (stderr, "Error: PNG-file doesn't contain alpha channel\n"); + exit (1); + } + + /* row_bytes is the width x number of channels x (bit-depth / 8) */ + row_bytes = png_get_rowbytes (png_ptr, info_ptr); + + if ((png_pixels = (png_byte *) malloc (row_bytes * height * sizeof (png_byte))) == NULL) { + png_destroy_read_struct (&png_ptr, &info_ptr, NULL); + return FALSE; + } + + if ((row_pointers = (png_byte **) malloc (height * sizeof (png_bytep))) == NULL) + { + png_destroy_read_struct (&png_ptr, &info_ptr, NULL); + free (png_pixels); + png_pixels = NULL; + return FALSE; + } + + /* set the individual row_pointers to point at the correct offsets */ + for (i = 0; i < (height); i++) + row_pointers[i] = png_pixels + i * row_bytes; + + /* now we can go ahead and just read the whole image */ + png_read_image (png_ptr, row_pointers); + + /* read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end (png_ptr, info_ptr); + + /* clean up after the read, and free any memory allocated - REQUIRED */ + png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL); + + /* write header of PNM file */ + + if ((color_type == PNG_COLOR_TYPE_GRAY) || + (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + { + fprintf (pnm_file, "%s\n", (raw) ? "P5" : "P2"); + fprintf (pnm_file, "%d %d\n", (int) width, (int) height); + fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L)); + } + else if ((color_type == PNG_COLOR_TYPE_RGB) || + (color_type == PNG_COLOR_TYPE_RGB_ALPHA)) + { + fprintf (pnm_file, "%s\n", (raw) ? "P6" : "P3"); + fprintf (pnm_file, "%d %d\n", (int) width, (int) height); + fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L)); + } + + /* write header of PGM file with alpha channel */ + + if ((alpha) && + ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || + (color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + { + fprintf (alpha_file, "%s\n", (raw) ? "P5" : "P2"); + fprintf (alpha_file, "%d %d\n", (int) width, (int) height); + fprintf (alpha_file, "%ld\n", ((1L << (int) bit_depth) - 1L)); + } + + /* write data to PNM file */ + pix_ptr = png_pixels; + + for (row = 0; row < height; row++) + { + for (col = 0; col < width; col++) + { + for (i = 0; i < (channels - alpha_present); i++) + { + if (raw) + fputc ((int) *pix_ptr++ , pnm_file); + else + if (bit_depth == 16){ + dep_16 = (long) *pix_ptr++; + fprintf (pnm_file, "%ld ", (dep_16 << 8) + ((long) *pix_ptr++)); + } + else + fprintf (pnm_file, "%ld ", (long) *pix_ptr++); + } + if (alpha_present) + { + if (!alpha) + { + pix_ptr++; /* alpha */ + if (bit_depth == 16) + pix_ptr++; + } + else /* output alpha-channel as pgm file */ + { + if (raw) + fputc ((int) *pix_ptr++ , alpha_file); + else + if (bit_depth == 16){ + dep_16 = (long) *pix_ptr++; + fprintf (alpha_file, "%ld ", (dep_16 << 8) + (long) *pix_ptr++); + } + else + fprintf (alpha_file, "%ld ", (long) *pix_ptr++); + } + } /* if alpha_present */ + + if (!raw) + if (col % 4 == 3) + fprintf (pnm_file, "\n"); + } /* end for col */ + + if (!raw) + if (col % 4 != 0) + fprintf (pnm_file, "\n"); + } /* end for row */ + + if (row_pointers != (unsigned char**) NULL) + free (row_pointers); + if (png_pixels != (unsigned char*) NULL) + free (png_pixels); + + return TRUE; + +} /* end of source */ + diff --git a/contrib/libpng/contrib/pngminus/png2pnm.sh b/contrib/libpng/contrib/pngminus/png2pnm.sh new file mode 100644 index 0000000..b1c0537 --- /dev/null +++ b/contrib/libpng/contrib/pngminus/png2pnm.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# -- grayscale +./png2pnm -noraw ../pngsuite/basn0g01.png basn0g01.pgm +./png2pnm -noraw ../pngsuite/basn0g02.png basn0g02.pgm +./png2pnm -noraw ../pngsuite/basn0g04.png basn0g04.pgm +./png2pnm -noraw ../pngsuite/basn0g08.png basn0g08.pgm +./png2pnm -noraw ../pngsuite/basn0g16.png basn0g16.pgm +# -- full-color +./png2pnm -noraw ../pngsuite/basn2c08.png basn2c08.ppm +./png2pnm -noraw ../pngsuite/basn2c16.png basn2c16.ppm +# -- palletted +./png2pnm -noraw ../pngsuite/basn3p01.png basn3p01.ppm +./png2pnm -noraw ../pngsuite/basn3p02.png basn3p02.ppm +./png2pnm -noraw ../pngsuite/basn3p04.png basn3p04.ppm +./png2pnm -noraw ../pngsuite/basn3p08.png basn3p08.ppm +# -- gray with alpha-channel +./png2pnm -noraw ../pngsuite/basn4a08.png basn4a08.pgm +./png2pnm -noraw ../pngsuite/basn4a16.png basn4a16.pgm +# -- color with alpha-channel +./png2pnm -noraw -alpha basn6a08.pgm ../pngsuite/basn6a08.png basn6a08.ppm +./png2pnm -noraw -alpha basn6a16.pgm ../pngsuite/basn6a16.png basn6a16.ppm +# -- grayscale +./png2pnm -raw ../pngsuite/basn0g01.png rawn0g01.pgm +./png2pnm -raw ../pngsuite/basn0g02.png rawn0g02.pgm +./png2pnm -raw ../pngsuite/basn0g04.png rawn0g04.pgm +./png2pnm -raw ../pngsuite/basn0g08.png rawn0g08.pgm +./png2pnm -raw ../pngsuite/basn0g16.png rawn0g16.pgm +# -- full-color +./png2pnm -raw ../pngsuite/basn2c08.png rawn2c08.ppm +./png2pnm -raw ../pngsuite/basn2c16.png rawn2c16.ppm +# -- palletted +./png2pnm -raw ../pngsuite/basn3p01.png rawn3p01.ppm +./png2pnm -raw ../pngsuite/basn3p02.png rawn3p02.ppm +./png2pnm -raw ../pngsuite/basn3p04.png rawn3p04.ppm +./png2pnm -raw ../pngsuite/basn3p08.png rawn3p08.ppm +# -- gray with alpha-channel +./png2pnm -raw ../pngsuite/basn4a08.png rawn4a08.pgm +./png2pnm -raw ../pngsuite/basn4a16.png rawn4a16.pgm +# -- color with alpha-channel +./png2pnm -noraw -alpha rawn6a08.pgm ../pngsuite/basn6a08.png rawn6a08.ppm +./png2pnm -noraw -alpha rawn6a16.pgm ../pngsuite/basn6a16.png rawn6a16.ppm + diff --git a/contrib/libpng/contrib/pngminus/pngminus.bat b/contrib/libpng/contrib/pngminus/pngminus.bat new file mode 100644 index 0000000..911bb8d --- /dev/null +++ b/contrib/libpng/contrib/pngminus/pngminus.bat @@ -0,0 +1,4 @@ +make -f makefile.tc3 +call png2pnm.bat +call pnm2png.bat + diff --git a/contrib/libpng/contrib/pngminus/pngminus.sh b/contrib/libpng/contrib/pngminus/pngminus.sh new file mode 100644 index 0000000..2a0a9d8 --- /dev/null +++ b/contrib/libpng/contrib/pngminus/pngminus.sh @@ -0,0 +1,5 @@ +#!/bin/sh +make -f makefile.std +sh png2pnm.sh +sh pnm2png.sh + diff --git a/contrib/libpng/contrib/pngminus/pnm2png.bat b/contrib/libpng/contrib/pngminus/pnm2png.bat new file mode 100644 index 0000000..f756cb8 --- /dev/null +++ b/contrib/libpng/contrib/pngminus/pnm2png.bat @@ -0,0 +1,41 @@ +REM -- grayscale +pnm2png.exe basn0g01.pgm basn0g01.png +pnm2png.exe basn0g02.pgm basn0g02.png +pnm2png.exe basn0g04.pgm basn0g04.png +pnm2png.exe basn0g08.pgm basn0g08.png +pnm2png.exe basn0g16.pgm basn0g16.png +REM -- full-color +pnm2png.exe basn2c08.ppm basn2c08.png +pnm2png.exe basn2c16.ppm basn2c16.png +REM -- palletted +pnm2png.exe basn3p01.ppm basn3p01.png +pnm2png.exe basn3p02.ppm basn3p02.png +pnm2png.exe basn3p04.ppm basn3p04.png +pnm2png.exe basn3p08.ppm basn3p08.png +REM -- gray with alpha-channel +pnm2png.exe -alpha basn6a08.pgm basn4a08.pgm basn4a08.png +pnm2png.exe -alpha basn6a16.pgm basn4a16.pgm basn4a16.png +REM -- color with alpha-channel +pnm2png.exe -alpha basn6a08.pgm basn6a08.ppm basn6a08.png +pnm2png.exe -alpha basn6a16.pgm basn6a16.ppm basn6a16.png +REM -- grayscale +pnm2png.exe rawn0g01.pgm rawn0g01.png +pnm2png.exe rawn0g02.pgm rawn0g02.png +pnm2png.exe rawn0g04.pgm rawn0g04.png +pnm2png.exe rawn0g08.pgm rawn0g08.png +pnm2png.exe rawn0g16.pgm rawn0g16.png +REM -- full-color +pnm2png.exe rawn2c08.ppm rawn2c08.png +pnm2png.exe rawn2c16.ppm rawn2c16.png +REM -- palletted +pnm2png.exe rawn3p01.ppm rawn3p01.png +pnm2png.exe rawn3p02.ppm rawn3p02.png +pnm2png.exe rawn3p04.ppm rawn3p04.png +pnm2png.exe rawn3p08.ppm rawn3p08.png +REM -- gray with alpha-channel +pnm2png.exe -alpha rawn6a08.pgm rawn4a08.pgm rawn4a08.png +pnm2png.exe -alpha rawn6a16.pgm rawn4a16.pgm rawn4a16.png +REM -- color with alpha-channel +pnm2png.exe -alpha rawn6a08.pgm rawn6a08.ppm rawn6a08.png +pnm2png.exe -alpha rawn6a16.pgm rawn6a16.ppm rawn6a16.png + diff --git a/contrib/libpng/contrib/pngminus/pnm2png.c b/contrib/libpng/contrib/pngminus/pnm2png.c new file mode 100644 index 0000000..4cdfad8 --- /dev/null +++ b/contrib/libpng/contrib/pngminus/pnm2png.c @@ -0,0 +1,533 @@ +/* + * pnm2png.c --- conversion from PBM/PGM/PPM-file to PNG-file + * copyright (C) 1999 by Willem van Schaik + * + * version 1.0 - 1999.10.15 - First version. + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation. This software is provided "as is" without + * express or implied warranty. + */ + +#include +#include +#ifdef __TURBOC__ +#include +#include +#endif + +#ifndef BOOL +#define BOOL unsigned char +#endif +#ifndef TRUE +#define TRUE (BOOL) 1 +#endif +#ifndef FALSE +#define FALSE (BOOL) 0 +#endif + +#define STDIN 0 +#define STDOUT 1 +#define STDERR 2 + +/* to make pnm2png verbose so we can find problems (needs to be before png.h) */ +#ifndef PNG_DEBUG +#define PNG_DEBUG 0 +#endif + +#include "png.h" + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif + +/* function prototypes */ + +int main (int argc, char *argv[]); +void usage (); +BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha); +void get_token(FILE *pnm_file, char *token); +png_uint_32 get_data (FILE *pnm_file, int depth); +png_uint_32 get_value (FILE *pnm_file, int depth); + +/* + * main + */ + +int main(int argc, char *argv[]) +{ + FILE *fp_rd = stdin; + FILE *fp_al = NULL; + FILE *fp_wr = stdout; + BOOL interlace = FALSE; + BOOL alpha = FALSE; + int argi; + + for (argi = 1; argi < argc; argi++) + { + if (argv[argi][0] == '-') + { + switch (argv[argi][1]) + { + case 'i': + interlace = TRUE; + break; + case 'a': + alpha = TRUE; + argi++; + if ((fp_al = fopen (argv[argi], "rb")) == NULL) + { + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: alpha-channel file %s does not exist\n", + argv[argi]); + exit (1); + } + break; + case 'h': + case '?': + usage(); + exit(0); + break; + default: + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: unknown option %s\n", argv[argi]); + usage(); + exit(1); + break; + } /* end switch */ + } + else if (fp_rd == stdin) + { + if ((fp_rd = fopen (argv[argi], "rb")) == NULL) + { + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: file %s does not exist\n", argv[argi]); + exit (1); + } + } + else if (fp_wr == stdout) + { + if ((fp_wr = fopen (argv[argi], "wb")) == NULL) + { + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: can not create PNG-file %s\n", argv[argi]); + exit (1); + } + } + else + { + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: too many parameters\n"); + usage(); + exit (1); + } + } /* end for */ + +#ifdef __TURBOC__ + /* set stdin/stdout to binary, we're reading the PNM always! in binary format */ + if (fp_rd == stdin) + { + setmode (STDIN, O_BINARY); + } + if (fp_wr == stdout) + { + setmode (STDOUT, O_BINARY); + } +#endif + + /* call the conversion program itself */ + if (pnm2png (fp_rd, fp_wr, fp_al, interlace, alpha) == FALSE) + { + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, "Error: unsuccessful converting to PNG-image\n"); + exit (1); + } + + /* close input file */ + fclose (fp_rd); + /* close output file */ + fclose (fp_wr); + /* close alpha file */ + if (alpha) + fclose (fp_al); + + return 0; +} + +/* + * usage + */ + +void usage() +{ + fprintf (stderr, "PNM2PNG\n"); + fprintf (stderr, " by Willem van Schaik, 1999\n"); +#ifdef __TURBOC__ + fprintf (stderr, " for Turbo-C and Borland-C compilers\n"); +#else + fprintf (stderr, " for Linux (and Unix) compilers\n"); +#endif + fprintf (stderr, "Usage: pnm2png [options] . [.png]\n"); + fprintf (stderr, " or: ... | pnm2png [options]\n"); + fprintf (stderr, "Options:\n"); + fprintf (stderr, " -i[nterlace] write png-file with interlacing on\n"); + fprintf (stderr, " -a[lpha] .pgm read PNG alpha channel as pgm-file\n"); + fprintf (stderr, " -h | -? print this help-information\n"); +} + +/* + * pnm2png + */ + +BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha) +{ + png_struct *png_ptr = NULL; + png_info *info_ptr = NULL; + png_byte *png_pixels = NULL; + png_byte **row_pointers = NULL; + png_byte *pix_ptr = NULL; + png_uint_32 row_bytes; + + char type_token[16]; + char width_token[16]; + char height_token[16]; + char maxval_token[16]; + int color_type; + png_uint_32 width, alpha_width; + png_uint_32 height, alpha_height; + png_uint_32 maxval; + int bit_depth = 0; + int channels; + int alpha_depth = 0; + int alpha_present; + int row, col; + BOOL raw, alpha_raw = FALSE; + png_uint_32 tmp16; + int i; + + /* read header of PNM file */ + + get_token(pnm_file, type_token); + if (type_token[0] != 'P') + { + return FALSE; + } + else if ((type_token[1] == '1') || (type_token[1] == '4')) + { + raw = (type_token[1] == '4'); + color_type = PNG_COLOR_TYPE_GRAY; + bit_depth = 1; + } + else if ((type_token[1] == '2') || (type_token[1] == '5')) + { + raw = (type_token[1] == '5'); + color_type = PNG_COLOR_TYPE_GRAY; + get_token(pnm_file, width_token); + sscanf (width_token, "%lu", &width); + get_token(pnm_file, height_token); + sscanf (height_token, "%lu", &height); + get_token(pnm_file, maxval_token); + sscanf (maxval_token, "%lu", &maxval); + if (maxval <= 1) + bit_depth = 1; + else if (maxval <= 3) + bit_depth = 2; + else if (maxval <= 15) + bit_depth = 4; + else if (maxval <= 255) + bit_depth = 8; + else /* if (maxval <= 65535) */ + bit_depth = 16; + } + else if ((type_token[1] == '3') || (type_token[1] == '6')) + { + raw = (type_token[1] == '6'); + color_type = PNG_COLOR_TYPE_RGB; + get_token(pnm_file, width_token); + sscanf (width_token, "%lu", &width); + get_token(pnm_file, height_token); + sscanf (height_token, "%lu", &height); + get_token(pnm_file, maxval_token); + sscanf (maxval_token, "%lu", &maxval); + if (maxval <= 1) + bit_depth = 1; + else if (maxval <= 3) + bit_depth = 2; + else if (maxval <= 15) + bit_depth = 4; + else if (maxval <= 255) + bit_depth = 8; + else /* if (maxval <= 65535) */ + bit_depth = 16; + } + else + { + return FALSE; + } + + /* read header of PGM file with alpha channel */ + + if (alpha) + { + if (color_type == PNG_COLOR_TYPE_GRAY) + color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + if (color_type == PNG_COLOR_TYPE_RGB) + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + + get_token(alpha_file, type_token); + if (type_token[0] != 'P') + { + return FALSE; + } + else if ((type_token[1] == '2') || (type_token[1] == '5')) + { + alpha_raw = (type_token[1] == '5'); + get_token(alpha_file, width_token); + sscanf (width_token, "%lu", &alpha_width); + if (alpha_width != width) + return FALSE; + get_token(alpha_file, height_token); + sscanf (height_token, "%lu", &alpha_height); + if (alpha_height != height) + return FALSE; + get_token(alpha_file, maxval_token); + sscanf (maxval_token, "%lu", &maxval); + if (maxval <= 1) + alpha_depth = 1; + else if (maxval <= 3) + alpha_depth = 2; + else if (maxval <= 15) + alpha_depth = 4; + else if (maxval <= 255) + alpha_depth = 8; + else /* if (maxval <= 65535) */ + alpha_depth = 16; + if (alpha_depth != bit_depth) + return FALSE; + } + else + { + return FALSE; + } + } /* end if alpha */ + + /* calculate the number of channels and store alpha-presence */ + if (color_type == PNG_COLOR_TYPE_GRAY) + channels = 1; + else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + channels = 2; + else if (color_type == PNG_COLOR_TYPE_RGB) + channels = 3; + else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + channels = 4; + else + channels = 0; /* should not happen */ + + alpha_present = (channels - 1) % 2; + + /* row_bytes is the width x number of channels x (bit-depth / 8) */ + row_bytes = width * channels * ((bit_depth <= 8) ? 1 : 2); + + if ((png_pixels = (png_byte *) malloc (row_bytes * height * sizeof (png_byte))) == NULL) + return FALSE; + + /* read data from PNM file */ + pix_ptr = png_pixels; + + for (row = 0; row < height; row++) + { + for (col = 0; col < width; col++) + { + for (i = 0; i < (channels - alpha_present); i++) + { + if (raw) + *pix_ptr++ = get_data (pnm_file, bit_depth); + else + if (bit_depth <= 8) + *pix_ptr++ = get_value (pnm_file, bit_depth); + else + { + tmp16 = get_value (pnm_file, bit_depth); + *pix_ptr = (png_byte) ((tmp16 >> 8) & 0xFF); + pix_ptr++; + *pix_ptr = (png_byte) (tmp16 & 0xFF); + pix_ptr++; + } + } + + if (alpha) /* read alpha-channel from pgm file */ + { + if (alpha_raw) + *pix_ptr++ = get_data (alpha_file, alpha_depth); + else + if (alpha_depth <= 8) + *pix_ptr++ = get_value (alpha_file, bit_depth); + else + { + tmp16 = get_value (alpha_file, bit_depth); + *pix_ptr++ = (png_byte) ((tmp16 >> 8) & 0xFF); + *pix_ptr++ = (png_byte) (tmp16 & 0xFF); + } + } /* if alpha */ + + } /* end for col */ + } /* end for row */ + + /* prepare the standard PNG structures */ + png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr) + { + return FALSE; + } + info_ptr = png_create_info_struct (png_ptr); + if (!info_ptr) + { + png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + return FALSE; + } + + /* setjmp() must be called in every function that calls a PNG-reading libpng function */ + if (setjmp (png_jmpbuf(png_ptr))) + { + png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + return FALSE; + } + + /* initialize the png structure */ + png_init_io (png_ptr, png_file); + + /* we're going to write more or less the same PNG as the input file */ + png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth, color_type, + (!interlace) ? PNG_INTERLACE_NONE : PNG_INTERLACE_ADAM7, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + /* write the file header information */ + png_write_info (png_ptr, info_ptr); + + /* if needed we will allocate memory for an new array of row-pointers */ + if (row_pointers == (unsigned char**) NULL) + { + if ((row_pointers = (png_byte **) malloc (height * sizeof (png_bytep))) == NULL) + { + png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + return FALSE; + } + } + + /* set the individual row_pointers to point at the correct offsets */ + for (i = 0; i < (height); i++) + row_pointers[i] = png_pixels + i * row_bytes; + + /* write out the entire image data in one call */ + png_write_image (png_ptr, row_pointers); + + /* write the additional chuncks to the PNG file (not really needed) */ + png_write_end (png_ptr, info_ptr); + + /* clean up after the write, and free any memory allocated */ + png_destroy_write_struct (&png_ptr, (png_infopp) NULL); + + if (row_pointers != (unsigned char**) NULL) + free (row_pointers); + if (png_pixels != (unsigned char*) NULL) + free (png_pixels); + + return TRUE; +} /* end of pnm2png */ + +/* + * get_token() - gets the first string after whitespace + */ + +void get_token(FILE *pnm_file, char *token) +{ + int i = 0; + + /* remove white-space */ + do + { + token[i] = (unsigned char) fgetc (pnm_file); + } + while ((token[i] == '\n') || (token[i] == '\r') || (token[i] == ' ')); + + /* read string */ + do + { + i++; + token[i] = (unsigned char) fgetc (pnm_file); + } + while ((token[i] != '\n') && (token[i] != '\r') && (token[i] != ' ')); + + token[i] = '\0'; + + return; +} + +/* + * get_data() - takes first byte and converts into next pixel value, + * taking as much bits as defined by bit-depth and + * using the bit-depth to fill up a byte (0Ah -> AAh) + */ + +png_uint_32 get_data (FILE *pnm_file, int depth) +{ + static int bits_left = 0; + static int old_value = 0; + static int mask = 0; + int i; + png_uint_32 ret_value; + + if (mask == 0) + for (i = 0; i < depth; i++) + mask = (mask >> 1) | 0x80; + + if (bits_left <= 0) + { + old_value = fgetc (pnm_file); + bits_left = 8; + } + + ret_value = old_value & mask; + for (i = 1; i < (8 / depth); i++) + ret_value = ret_value || (ret_value >> depth); + + old_value = (old_value << depth) & 0xFF; + bits_left -= depth; + + return ret_value; +} + +/* + * get_value() - takes first (numeric) string and converts into number, + * using the bit-depth to fill up a byte (0Ah -> AAh) + */ + +png_uint_32 get_value (FILE *pnm_file, int depth) +{ + static png_uint_32 mask = 0; + png_byte token[16]; + png_uint_32 ret_value; + int i = 0; + + if (mask == 0) + for (i = 0; i < depth; i++) + mask = (mask << 1) | 0x01; + + get_token (pnm_file, (char *) token); + sscanf ((const char *) token, "%lu", &ret_value); + + ret_value &= mask; + + if (depth < 8) + for (i = 0; i < (8 / depth); i++) + ret_value = (ret_value << depth) || ret_value; + + return ret_value; +} + +/* end of source */ + diff --git a/contrib/libpng/contrib/pngminus/pnm2png.sh b/contrib/libpng/contrib/pngminus/pnm2png.sh new file mode 100644 index 0000000..d79df2f --- /dev/null +++ b/contrib/libpng/contrib/pngminus/pnm2png.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# -- grayscale +./pnm2png basn0g01.pgm basn0g01.png +./pnm2png basn0g02.pgm basn0g02.png +./pnm2png basn0g04.pgm basn0g04.png +./pnm2png basn0g08.pgm basn0g08.png +./pnm2png basn0g16.pgm basn0g16.png +# -- full-color +./pnm2png basn2c08.ppm basn2c08.png +./pnm2png basn2c16.ppm basn2c16.png +# -- palletted +./pnm2png basn3p01.ppm basn3p01.png +./pnm2png basn3p02.ppm basn3p02.png +./pnm2png basn3p04.ppm basn3p04.png +./pnm2png basn3p08.ppm basn3p08.png +# -- gray with alpha-channel +./pnm2png -alpha basn6a08.pgm basn4a08.pgm basn4a08.png +./pnm2png -alpha basn6a16.pgm basn4a16.pgm basn4a16.png +# -- color with alpha-channel +./pnm2png -alpha basn6a08.pgm basn6a08.ppm basn6a08.png +./pnm2png -alpha basn6a16.pgm basn6a16.ppm basn6a16.png +# -- grayscale +./pnm2png rawn0g01.pgm rawn0g01.png +./pnm2png rawn0g02.pgm rawn0g02.png +./pnm2png rawn0g04.pgm rawn0g04.png +./pnm2png rawn0g08.pgm rawn0g08.png +./pnm2png rawn0g16.pgm rawn0g16.png +# -- full-color +./pnm2png rawn2c08.ppm rawn2c08.png +./pnm2png rawn2c16.ppm rawn2c16.png +# -- palletted +./pnm2png rawn3p01.ppm rawn3p01.png +./pnm2png rawn3p02.ppm rawn3p02.png +./pnm2png rawn3p04.ppm rawn3p04.png +./pnm2png rawn3p08.ppm rawn3p08.png +# -- gray with alpha-channel +./pnm2png -alpha rawn6a08.pgm rawn4a08.pgm rawn4a08.png +./pnm2png -alpha rawn6a16.pgm rawn4a16.pgm rawn4a16.png +# -- color with alpha-channel +./pnm2png -alpha rawn6a08.pgm rawn6a08.ppm rawn6a08.png +./pnm2png -alpha rawn6a16.pgm rawn6a16.ppm rawn6a16.png + diff --git a/contrib/libpng/contrib/pngsuite/README b/contrib/libpng/contrib/pngsuite/README new file mode 100644 index 0000000..f321e48 --- /dev/null +++ b/contrib/libpng/contrib/pngsuite/README @@ -0,0 +1,102 @@ + +pngsuite +-------- +(c) Willem van Schaik, 1999 + +Permission to use, copy, and distribute these images for any purpose and +without fee is hereby granted. + +The 15 "bas*.png" images are part of the much larger PngSuite test-set of +images, available for developers of PNG supporting software. The +complete set, available at http:/www.schaik.com/pngsuite/, contains +a variety of images to test interlacing, gamma settings, ancillary +chunks, etc. + +The "ft*.png" images are "free/libre" replacements for the transparent +corresponding t*.png images in the PngSuite. + +The images in this directory represent the basic PNG color-types: +grayscale (1-16 bit deep), full color (8 or 16 bit), paletted +(1-8 bit) and grayscale or color images with alpha channel. You +can use them to test the proper functioning of PNG software. + + filename depth type + ------------ ------ -------------- + basn0g01.png 1-bit grayscale + basn0g02.png 2-bit grayscale + basn0g04.png 4-bit grayscale + basn0g08.png 8-bit grayscale + basn0g16.png 16-bit grayscale + basn2c08.png 8-bit truecolor + basn2c16.png 16-bit truecolor + basn3p01.png 1-bit paletted + basn3p02.png 2-bit paletted + basn3p04.png 4-bit paletted + basn3p08.png 8-bit paletted + basn4a08.png 8-bit gray with alpha + basn4a16.png 16-bit gray with alpha + basn6a08.png 8-bit RGBA + basn6a16.png 16-bit RGBA + + ftbbn0g04.png 4-bit grayscale, black bKGD + ftbbn2c16.png 16-bit truecolor, black bKGD + ftbbn3p08.png 8-bit paletted, black bKGD + ftbgn2c16.png 16-bit truecolor, gray bKGD + ftbgn3p08.png 8-bit paletted, gray bKGD + ftbrn2c08.png 8-bit truecolor, red bKGD + ftbwn0g16.png 16-bit gray, white bKGD + ftbwn3p08.png 8-bit paletted, white bKGD + ftbyn3p08.png 8-bit paletted, yellow bKGD + ftp0n0g08.png 8-bit grayscale, opaque + ftp0n2c08.png 8-bit truecolor, opaque + ftp0n3p08.png 8-bit paletted, opaque + ftp1n3p08.png 8-bit paletted, no bKGD + +Here is the correct result of typing "pngtest -m *.png" in +this directory: + +Testing basn0g01.png: PASS (524 zero samples) + Filter 0 was used 32 times +Testing basn0g02.png: PASS (448 zero samples) + Filter 0 was used 32 times +Testing basn0g04.png: PASS (520 zero samples) + Filter 0 was used 32 times +Testing basn0g08.png: PASS (3 zero samples) + Filter 1 was used 9 times + Filter 4 was used 23 times +Testing basn0g16.png: PASS (1 zero samples) + Filter 1 was used 1 times + Filter 2 was used 31 times +Testing basn2c08.png: PASS (6 zero samples) + Filter 1 was used 5 times + Filter 4 was used 27 times +Testing basn2c16.png: PASS (592 zero samples) + Filter 1 was used 1 times + Filter 4 was used 31 times +Testing basn3p01.png: PASS (512 zero samples) + Filter 0 was used 32 times +Testing basn3p02.png: PASS (448 zero samples) + Filter 0 was used 32 times +Testing basn3p04.png: PASS (544 zero samples) + Filter 0 was used 32 times +Testing basn3p08.png: PASS (4 zero samples) + Filter 0 was used 32 times +Testing basn4a08.png: PASS (32 zero samples) + Filter 1 was used 1 times + Filter 4 was used 31 times +Testing basn4a16.png: PASS (64 zero samples) + Filter 0 was used 1 times + Filter 1 was used 2 times + Filter 2 was used 1 times + Filter 4 was used 28 times +Testing basn6a08.png: PASS (160 zero samples) + Filter 1 was used 1 times + Filter 4 was used 31 times +Testing basn6a16.png: PASS (1072 zero samples) + Filter 1 was used 4 times + Filter 4 was used 28 times +libpng passes test + +Willem van Schaik + +October 1999 diff --git a/contrib/libpng/contrib/pngsuite/basn0g01.png b/contrib/libpng/contrib/pngsuite/basn0g01.png new file mode 100644 index 0000000..e31e1c7 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn0g01.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn0g02.png b/contrib/libpng/contrib/pngsuite/basn0g02.png new file mode 100644 index 0000000..68809dd Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn0g02.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn0g04.png b/contrib/libpng/contrib/pngsuite/basn0g04.png new file mode 100644 index 0000000..6fa089c Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn0g04.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn0g08.png b/contrib/libpng/contrib/pngsuite/basn0g08.png new file mode 100644 index 0000000..bf522ee Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn0g08.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn0g16.png b/contrib/libpng/contrib/pngsuite/basn0g16.png new file mode 100644 index 0000000..318ebca Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn0g16.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn2c08.png b/contrib/libpng/contrib/pngsuite/basn2c08.png new file mode 100644 index 0000000..21d2f91 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn2c08.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn2c16.png b/contrib/libpng/contrib/pngsuite/basn2c16.png new file mode 100644 index 0000000..1bd4a4d Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn2c16.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn3p01.png b/contrib/libpng/contrib/pngsuite/basn3p01.png new file mode 100644 index 0000000..a21db59 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn3p01.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn3p02.png b/contrib/libpng/contrib/pngsuite/basn3p02.png new file mode 100644 index 0000000..1d0ab61 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn3p02.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn3p04.png b/contrib/libpng/contrib/pngsuite/basn3p04.png new file mode 100644 index 0000000..6dc6eac Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn3p04.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn3p08.png b/contrib/libpng/contrib/pngsuite/basn3p08.png new file mode 100644 index 0000000..0e07f48 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn3p08.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn4a08.png b/contrib/libpng/contrib/pngsuite/basn4a08.png new file mode 100644 index 0000000..3bb0dd0 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn4a08.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn4a16.png b/contrib/libpng/contrib/pngsuite/basn4a16.png new file mode 100644 index 0000000..6dbee9f Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn4a16.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn6a08.png b/contrib/libpng/contrib/pngsuite/basn6a08.png new file mode 100644 index 0000000..6106230 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn6a08.png differ diff --git a/contrib/libpng/contrib/pngsuite/basn6a16.png b/contrib/libpng/contrib/pngsuite/basn6a16.png new file mode 100644 index 0000000..a9bf3cb Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/basn6a16.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftbbn1g04.png b/contrib/libpng/contrib/pngsuite/ftbbn1g04.png new file mode 100644 index 0000000..39a7050 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftbbn1g04.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftbbn2c16.png b/contrib/libpng/contrib/pngsuite/ftbbn2c16.png new file mode 100644 index 0000000..dd3168e Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftbbn2c16.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftbbn3p08.png b/contrib/libpng/contrib/pngsuite/ftbbn3p08.png new file mode 100644 index 0000000..0ede357 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftbbn3p08.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftbgn2c16.png b/contrib/libpng/contrib/pngsuite/ftbgn2c16.png new file mode 100644 index 0000000..85cec39 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftbgn2c16.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftbgn3p08.png b/contrib/libpng/contrib/pngsuite/ftbgn3p08.png new file mode 100644 index 0000000..8cf2e6f Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftbgn3p08.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftbrn2c08.png b/contrib/libpng/contrib/pngsuite/ftbrn2c08.png new file mode 100644 index 0000000..5cca0d6 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftbrn2c08.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftbwn1g16.png b/contrib/libpng/contrib/pngsuite/ftbwn1g16.png new file mode 100644 index 0000000..99bdeed Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftbwn1g16.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftbwn3p08.png b/contrib/libpng/contrib/pngsuite/ftbwn3p08.png new file mode 100644 index 0000000..eacab7a Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftbwn3p08.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftbyn3p08.png b/contrib/libpng/contrib/pngsuite/ftbyn3p08.png new file mode 100644 index 0000000..656db09 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftbyn3p08.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftp0n1g08.png b/contrib/libpng/contrib/pngsuite/ftp0n1g08.png new file mode 100644 index 0000000..333465f Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftp0n1g08.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftp0n2c08.png b/contrib/libpng/contrib/pngsuite/ftp0n2c08.png new file mode 100644 index 0000000..fc6e42c Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftp0n2c08.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftp0n3p08.png b/contrib/libpng/contrib/pngsuite/ftp0n3p08.png new file mode 100644 index 0000000..69a69e5 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftp0n3p08.png differ diff --git a/contrib/libpng/contrib/pngsuite/ftp1n3p08.png b/contrib/libpng/contrib/pngsuite/ftp1n3p08.png new file mode 100644 index 0000000..a6c9f35 Binary files /dev/null and b/contrib/libpng/contrib/pngsuite/ftp1n3p08.png differ diff --git a/contrib/libpng/contrib/visupng/PngFile.c b/contrib/libpng/contrib/visupng/PngFile.c new file mode 100644 index 0000000..db0219e --- /dev/null +++ b/contrib/libpng/contrib/visupng/PngFile.c @@ -0,0 +1,442 @@ +//------------------------------------- +// PNGFILE.C -- Image File Functions +//------------------------------------- + +// Copyright 2000, Willem van Schaik. +// +// This code is released under the libpng license. +// For conditions of distribution and use, see the disclaimer +// and license in png.h + +#include +#include +#include +#include + +#include "png.h" +#include "pngfile.h" +#include "cexcept.h" + +define_exception_type(const char *); +extern struct exception_context the_exception_context[1]; +struct exception_context the_exception_context[1]; +png_const_charp msg; + +static OPENFILENAME ofn; + +static png_structp png_ptr = NULL; +static png_infop info_ptr = NULL; + + +// cexcept interface + +static void +png_cexcept_error(png_structp png_ptr, png_const_charp msg) +{ + if(png_ptr) + ; +#ifdef PNG_CONSOLE_IO_SUPPORTED + fprintf(stderr, "libpng error: %s\n", msg); +#endif + { + Throw msg; + } +} + +// Windows open-file functions + +void PngFileInitialize (HWND hwnd) +{ + static TCHAR szFilter[] = TEXT ("PNG Files (*.PNG)\0*.png\0") + TEXT ("All Files (*.*)\0*.*\0\0"); + + ofn.lStructSize = sizeof (OPENFILENAME); + ofn.hwndOwner = hwnd; + ofn.hInstance = NULL; + ofn.lpstrFilter = szFilter; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 0; + ofn.lpstrFile = NULL; // Set in Open and Close functions + ofn.nMaxFile = MAX_PATH; + ofn.lpstrFileTitle = NULL; // Set in Open and Close functions + ofn.nMaxFileTitle = MAX_PATH; + ofn.lpstrInitialDir = NULL; + ofn.lpstrTitle = NULL; + ofn.Flags = 0; // Set in Open and Close functions + ofn.nFileOffset = 0; + ofn.nFileExtension = 0; + ofn.lpstrDefExt = TEXT ("png"); + ofn.lCustData = 0; + ofn.lpfnHook = NULL; + ofn.lpTemplateName = NULL; +} + +BOOL PngFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName) +{ + ofn.hwndOwner = hwnd; + ofn.lpstrFile = pstrFileName; + ofn.lpstrFileTitle = pstrTitleName; + ofn.Flags = OFN_HIDEREADONLY; + + return GetOpenFileName (&ofn); +} + +BOOL PngFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName) +{ + ofn.hwndOwner = hwnd; + ofn.lpstrFile = pstrFileName; + ofn.lpstrFileTitle = pstrTitleName; + ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; + + return GetSaveFileName (&ofn); +} + +// PNG image handler functions + +BOOL PngLoadImage (PTSTR pstrFileName, png_byte **ppbImageData, + int *piWidth, int *piHeight, int *piChannels, png_color *pBkgColor) +{ + static FILE *pfFile; + png_byte pbSig[8]; + int iBitDepth; + int iColorType; + double dGamma; + png_color_16 *pBackground; + png_uint_32 ulChannels; + png_uint_32 ulRowBytes; + png_byte *pbImageData = *ppbImageData; + static png_byte **ppbRowPointers = NULL; + int i; + + // open the PNG input file + + if (!pstrFileName) + { + *ppbImageData = pbImageData = NULL; + return FALSE; + } + + if (!(pfFile = fopen(pstrFileName, "rb"))) + { + *ppbImageData = pbImageData = NULL; + return FALSE; + } + + // first check the eight byte PNG signature + + fread(pbSig, 1, 8, pfFile); + if (png_sig_cmp(pbSig, 0, 8)) + { + *ppbImageData = pbImageData = NULL; + return FALSE; + } + + // create the two png(-info) structures + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, + (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL); + if (!png_ptr) + { + *ppbImageData = pbImageData = NULL; + return FALSE; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, NULL, NULL); + *ppbImageData = pbImageData = NULL; + return FALSE; + } + + Try + { + + // initialize the png structure + +#ifdef PNG_STDIO_SUPPORTED + png_init_io(png_ptr, pfFile); +#else + png_set_read_fn(png_ptr, (png_voidp)pfFile, png_read_data); +#endif + + png_set_sig_bytes(png_ptr, 8); + + // read all PNG info up to image data + + png_read_info(png_ptr, info_ptr); + + // get width, height, bit-depth and color-type + + png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth, + &iColorType, NULL, NULL, NULL); + + // expand images of all color-type and bit-depth to 3x8 bit RGB images + // let the library process things like alpha, transparency, background + + if (iBitDepth == 16) + png_set_strip_16(png_ptr); + if (iColorType == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png_ptr); + if (iBitDepth < 8) + png_set_expand(png_ptr); + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_expand(png_ptr); + if (iColorType == PNG_COLOR_TYPE_GRAY || + iColorType == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + + // set the background color to draw transparent and alpha images over. + if (png_get_bKGD(png_ptr, info_ptr, &pBackground)) + { + png_set_background(png_ptr, pBackground, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + pBkgColor->red = (byte) pBackground->red; + pBkgColor->green = (byte) pBackground->green; + pBkgColor->blue = (byte) pBackground->blue; + } + else + { + pBkgColor = NULL; + } + + // if required set gamma conversion + if (png_get_gAMA(png_ptr, info_ptr, &dGamma)) + png_set_gamma(png_ptr, (double) 2.2, dGamma); + + // after the transformations have been registered update info_ptr data + + png_read_update_info(png_ptr, info_ptr); + + // get again width, height and the new bit-depth and color-type + + png_get_IHDR(png_ptr, info_ptr, piWidth, piHeight, &iBitDepth, + &iColorType, NULL, NULL, NULL); + + + // row_bytes is the width x number of channels + + ulRowBytes = png_get_rowbytes(png_ptr, info_ptr); + ulChannels = png_get_channels(png_ptr, info_ptr); + + *piChannels = ulChannels; + + // now we can allocate memory to store the image + + if (pbImageData) + { + free (pbImageData); + pbImageData = NULL; + } + if ((pbImageData = (png_byte *) malloc(ulRowBytes * (*piHeight) + * sizeof(png_byte))) == NULL) + { + png_error(png_ptr, "Visual PNG: out of memory"); + } + *ppbImageData = pbImageData; + + // and allocate memory for an array of row-pointers + + if ((ppbRowPointers = (png_bytepp) malloc((*piHeight) + * sizeof(png_bytep))) == NULL) + { + png_error(png_ptr, "Visual PNG: out of memory"); + } + + // set the individual row-pointers to point at the correct offsets + + for (i = 0; i < (*piHeight); i++) + ppbRowPointers[i] = pbImageData + i * ulRowBytes; + + // now we can go ahead and just read the whole image + + png_read_image(png_ptr, ppbRowPointers); + + // read the additional chunks in the PNG file (not really needed) + + png_read_end(png_ptr, NULL); + + // and we're done + + free (ppbRowPointers); + ppbRowPointers = NULL; + + // yepp, done + } + + Catch (msg) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + *ppbImageData = pbImageData = NULL; + + if(ppbRowPointers) + free (ppbRowPointers); + + fclose(pfFile); + + return FALSE; + } + + fclose (pfFile); + + return TRUE; +} + + +BOOL PngSaveImage (PTSTR pstrFileName, png_byte *pDiData, + int iWidth, int iHeight, png_color bkgColor) +{ + const int ciBitDepth = 8; + const int ciChannels = 3; + + static FILE *pfFile; + png_uint_32 ulRowBytes; + static png_byte **ppbRowPointers = NULL; + int i; + + // open the PNG output file + + if (!pstrFileName) + return FALSE; + + if (!(pfFile = fopen(pstrFileName, "wb"))) + return FALSE; + + // prepare the standard PNG structures + + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, + (png_error_ptr)png_cexcept_error, (png_error_ptr)NULL); + if (!png_ptr) + { + fclose(pfFile); + return FALSE; + } + + info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) { + fclose(pfFile); + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + return FALSE; + } + + Try + { + // initialize the png structure + +#ifdef PNG_STDIO_SUPPORTED + png_init_io(png_ptr, pfFile); +#else + png_set_write_fn(png_ptr, (png_voidp)pfFile, png_write_data, png_flush); +#endif + + // we're going to write a very simple 3x8 bit RGB image + + png_set_IHDR(png_ptr, info_ptr, iWidth, iHeight, ciBitDepth, + PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, + PNG_FILTER_TYPE_BASE); + + // write the file header information + + png_write_info(png_ptr, info_ptr); + + // swap the BGR pixels in the DiData structure to RGB + + png_set_bgr(png_ptr); + + // row_bytes is the width x number of channels + + ulRowBytes = iWidth * ciChannels; + + // we can allocate memory for an array of row-pointers + + if ((ppbRowPointers = (png_bytepp) malloc(iHeight * sizeof(png_bytep))) == NULL) + Throw "Visualpng: Out of memory"; + + // set the individual row-pointers to point at the correct offsets + + for (i = 0; i < iHeight; i++) + ppbRowPointers[i] = pDiData + i * (((ulRowBytes + 3) >> 2) << 2); + + // write out the entire image data in one call + + png_write_image (png_ptr, ppbRowPointers); + + // write the additional chunks to the PNG file (not really needed) + + png_write_end(png_ptr, info_ptr); + + // and we're done + + free (ppbRowPointers); + ppbRowPointers = NULL; + + // clean up after the write, and free any memory allocated + + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + + // yepp, done + } + + Catch (msg) + { + png_destroy_write_struct(&png_ptr, (png_infopp) NULL); + + if(ppbRowPointers) + free (ppbRowPointers); + + fclose(pfFile); + + return FALSE; + } + + fclose (pfFile); + + return TRUE; +} + +#ifndef PNG_STDIO_SUPPORTED + +static void +png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + check = (png_size_t)fread(data, (png_size_t)1, length, + (FILE *)png_ptr->io_ptr); + + if (check != length) + { + png_error(png_ptr, "Read Error"); + } +} + +static void +png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + + check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr)); + if (check != length) + { + png_error(png_ptr, "Write Error"); + } +} + +static void +png_flush(png_structp png_ptr) +{ + FILE *io_ptr; + io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr)); + if (io_ptr != NULL) + fflush(io_ptr); +} + +#endif + +//----------------- +// end of source +//----------------- diff --git a/contrib/libpng/contrib/visupng/PngFile.h b/contrib/libpng/contrib/visupng/PngFile.h new file mode 100644 index 0000000..dc6bbb4 --- /dev/null +++ b/contrib/libpng/contrib/visupng/PngFile.h @@ -0,0 +1,30 @@ +//------------------------------------------ +// PNGFILE.H -- Header File for pngfile.c +//------------------------------------------ + +// Copyright 2000, Willem van Schaik. + +// This code is released under the libpng license. +// For conditions of distribution and use, see the disclaimer +// and license in png.h + +#include +#include +#include +#include + +void PngFileInitialize (HWND hwnd) ; +BOOL PngFileOpenDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName) ; +BOOL PngFileSaveDlg (HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName) ; + +BOOL PngLoadImage (PTSTR pstrFileName, png_byte **ppbImageData, + int *piWidth, int *piHeight, int *piChannels, png_color *pBkgColor); +BOOL PngSaveImage (PTSTR pstrFileName, png_byte *pDiData, + int iWidth, int iHeight, png_color BkgColor); + +#ifndef PNG_STDIO_SUPPORTED +static void png_read_data(png_structp png_ptr, png_bytep data, png_size_t length); +static void png_write_data(png_structp png_ptr, png_bytep data, png_size_t length); +static void png_flush(png_structp png_ptr); +#endif + diff --git a/contrib/libpng/contrib/visupng/README.txt b/contrib/libpng/contrib/visupng/README.txt new file mode 100644 index 0000000..4047119 --- /dev/null +++ b/contrib/libpng/contrib/visupng/README.txt @@ -0,0 +1,61 @@ +Microsoft Developer Studio Build File, Format Version 6.00 for VisualPng +------------------------------------------------------------------------ + +Copyright 2000, Willem van Schaik. + +This code is released under the libpng license. +For conditions of distribution and use, see the disclaimer +and license in png.h + +As a PNG .dll demo VisualPng is finished. More features would only hinder +the program's objective. However, further extensions (like support for other +graphics formats) are in development. To get these, or for pre-compiled +binaries, go to "http://www.schaik.com/png/visualpng.html". + +------------------------------------------------------------------------ + +Assumes that + + libpng DLLs and LIBs are in ..\..\projects\msvc\win32\libpng + zlib DLLs and LIBs are in ..\..\projects\msvc\win32\zlib + libpng header files are in ..\..\..\libpng + zlib header files are in ..\..\..\zlib + the pngsuite images are in ..\pngsuite + +To build: + +1) On the main menu Select "Build|Set Active configuration". + Choose the configuration that corresponds to the library you want to test. + This library must have been built using the libpng MS project located in + the "..\..\mscv" subdirectory. + +2) Select "Build|Clean" + +3) Select "Build|Rebuild All" + +4) After compiling and linking VisualPng will be started to view an image + from the PngSuite directory. Press Ctrl-N (and Ctrl-V) for other images. + + +To install: + +When distributing VisualPng (or a further development) the following options +are available: + +1) Build the program with the configuration "Win32 LIB" and you only need to + include the executable from the ./lib directory in your distribution. + +2) Build the program with the configuration "Win32 DLL" and you need to put + in your distribution the executable from the ./dll directory and the dll's + libpng1.dll, zlib.dll and msvcrt.dll. These need to be in the user's PATH. + + +Willem van Schaik +Calgary, June 6th 2000 + +P.S. VisualPng was written based on preliminary work of: + + - Simon-Pierre Cadieux + - Glenn Randers-Pehrson + - Greg Roelofs + diff --git a/contrib/libpng/contrib/visupng/VisualPng.c b/contrib/libpng/contrib/visupng/VisualPng.c new file mode 100644 index 0000000..2018999 --- /dev/null +++ b/contrib/libpng/contrib/visupng/VisualPng.c @@ -0,0 +1,964 @@ +//------------------------------------ +// VisualPng.C -- Shows a PNG image +//------------------------------------ + +// Copyright 2000, Willem van Schaik. + +// This code is released under the libpng license. +// For conditions of distribution and use, see the disclaimer +// and license in png.h + +// switches + +// defines + +#define PROGNAME "VisualPng" +#define LONGNAME "Win32 Viewer for PNG-files" +#define VERSION "1.0 of 2000 June 07" + +// constants + +#define MARGIN 8 + +// standard includes + +#include +#include +#include +#include + +// application includes + +#include "png.h" +#include "pngfile.h" +#include "resource.h" + +// macros + +// function prototypes + +LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); +BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ; + +BOOL CenterAbout (HWND hwndChild, HWND hwndParent); + +BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount, + int *pFileIndex); + +BOOL SearchPngList (TCHAR *pFileList, int FileCount, int *pFileIndex, + PTSTR pstrPrevName, PTSTR pstrNextName); + +BOOL LoadImageFile(HWND hwnd, PTSTR pstrPathName, + png_byte **ppbImage, int *pxImgSize, int *pyImgSize, int *piChannels, + png_color *pBkgColor); + +BOOL DisplayImage (HWND hwnd, BYTE **ppDib, + BYTE **ppDiData, int cxWinSize, int cyWinSize, + BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels, + BOOL bStretched); + +BOOL InitBitmap ( + BYTE *pDiData, int cxWinSize, int cyWinSize); + +BOOL FillBitmap ( + BYTE *pDiData, int cxWinSize, int cyWinSize, + BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels, + BOOL bStretched); + +// a few global variables + +static char *szProgName = PROGNAME; +static char *szAppName = LONGNAME; +static char *szIconName = PROGNAME; +static char szCmdFileName [MAX_PATH]; + +// MAIN routine + +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, + PSTR szCmdLine, int iCmdShow) +{ + HACCEL hAccel; + HWND hwnd; + MSG msg; + WNDCLASS wndclass; + int ixBorders, iyBorders; + + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInstance; + wndclass.hIcon = LoadIcon (hInstance, szIconName) ; + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); + wndclass.hbrBackground = NULL; // (HBRUSH) GetStockObject (GRAY_BRUSH); + wndclass.lpszMenuName = szProgName; + wndclass.lpszClassName = szProgName; + + if (!RegisterClass (&wndclass)) + { + MessageBox (NULL, TEXT ("Error: this program requires Windows NT!"), + szProgName, MB_ICONERROR); + return 0; + } + + // if filename given on commandline, store it + if ((szCmdLine != NULL) && (*szCmdLine != '\0')) + if (szCmdLine[0] == '"') + strncpy (szCmdFileName, szCmdLine + 1, strlen(szCmdLine) - 2); + else + strcpy (szCmdFileName, szCmdLine); + else + strcpy (szCmdFileName, ""); + + // calculate size of window-borders + ixBorders = 2 * (GetSystemMetrics (SM_CXBORDER) + + GetSystemMetrics (SM_CXDLGFRAME)); + iyBorders = 2 * (GetSystemMetrics (SM_CYBORDER) + + GetSystemMetrics (SM_CYDLGFRAME)) + + GetSystemMetrics (SM_CYCAPTION) + + GetSystemMetrics (SM_CYMENUSIZE) + + 1; /* WvS: don't ask me why? */ + + hwnd = CreateWindow (szProgName, szAppName, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, + 512 + 2 * MARGIN + ixBorders, 384 + 2 * MARGIN + iyBorders, +// CW_USEDEFAULT, CW_USEDEFAULT, + NULL, NULL, hInstance, NULL); + + ShowWindow (hwnd, iCmdShow); + UpdateWindow (hwnd); + + hAccel = LoadAccelerators (hInstance, szProgName); + + while (GetMessage (&msg, NULL, 0, 0)) + { + if (!TranslateAccelerator (hwnd, hAccel, &msg)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + } + return msg.wParam; +} + +LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, + LPARAM lParam) +{ + static HINSTANCE hInstance ; + static HDC hdc; + static PAINTSTRUCT ps; + static HMENU hMenu; + + static BITMAPFILEHEADER *pbmfh; + static BITMAPINFOHEADER *pbmih; + static BYTE *pbImage; + static int cxWinSize, cyWinSize; + static int cxImgSize, cyImgSize; + static int cImgChannels; + static png_color bkgColor = {127, 127, 127}; + + static BOOL bStretched = TRUE; + + static BYTE *pDib = NULL; + static BYTE *pDiData = NULL; + + static TCHAR szImgPathName [MAX_PATH]; + static TCHAR szTitleName [MAX_PATH]; + + static TCHAR *pPngFileList = NULL; + static int iPngFileCount; + static int iPngFileIndex; + + BOOL bOk; + + switch (message) + { + case WM_CREATE: + hInstance = ((LPCREATESTRUCT) lParam)->hInstance ; + PngFileInitialize (hwnd); + + strcpy (szImgPathName, ""); + + // in case we process file given on command-line + + if (szCmdFileName[0] != '\0') + { + strcpy (szImgPathName, szCmdFileName); + + // read the other png-files in the directory for later + // next/previous commands + + BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount, + &iPngFileIndex); + + // load the image from file + + if (!LoadImageFile (hwnd, szImgPathName, + &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor)) + return 0; + + // invalidate the client area for later update + + InvalidateRect (hwnd, NULL, TRUE); + + // display the PNG into the DIBitmap + + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); + } + + return 0; + + case WM_SIZE: + cxWinSize = LOWORD (lParam); + cyWinSize = HIWORD (lParam); + + // invalidate the client area for later update + + InvalidateRect (hwnd, NULL, TRUE); + + // display the PNG into the DIBitmap + + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); + + return 0; + + case WM_INITMENUPOPUP: + hMenu = GetMenu (hwnd); + + if (pbImage) + EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_ENABLED); + else + EnableMenuItem (hMenu, IDM_FILE_SAVE, MF_GRAYED); + + return 0; + + case WM_COMMAND: + hMenu = GetMenu (hwnd); + + switch (LOWORD (wParam)) + { + case IDM_FILE_OPEN: + + // show the File Open dialog box + + if (!PngFileOpenDlg (hwnd, szImgPathName, szTitleName)) + return 0; + + // read the other png-files in the directory for later + // next/previous commands + + BuildPngList (szImgPathName, &pPngFileList, &iPngFileCount, + &iPngFileIndex); + + // load the image from file + + if (!LoadImageFile (hwnd, szImgPathName, + &pbImage, &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor)) + return 0; + + // invalidate the client area for later update + + InvalidateRect (hwnd, NULL, TRUE); + + // display the PNG into the DIBitmap + + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); + + return 0; + + case IDM_FILE_SAVE: + + // show the File Save dialog box + + if (!PngFileSaveDlg (hwnd, szImgPathName, szTitleName)) + return 0; + + // save the PNG to a disk file + + SetCursor (LoadCursor (NULL, IDC_WAIT)); + ShowCursor (TRUE); + + bOk = PngSaveImage (szImgPathName, pDiData, cxWinSize, cyWinSize, + bkgColor); + + ShowCursor (FALSE); + SetCursor (LoadCursor (NULL, IDC_ARROW)); + + if (!bOk) + MessageBox (hwnd, TEXT ("Error in saving the PNG image"), + szProgName, MB_ICONEXCLAMATION | MB_OK); + return 0; + + case IDM_FILE_NEXT: + + // read next entry in the directory + + if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex, + NULL, szImgPathName)) + { + if (strcmp (szImgPathName, "") == 0) + return 0; + + // load the image from file + + if (!LoadImageFile (hwnd, szImgPathName, &pbImage, + &cxImgSize, &cyImgSize, &cImgChannels, &bkgColor)) + return 0; + + // invalidate the client area for later update + + InvalidateRect (hwnd, NULL, TRUE); + + // display the PNG into the DIBitmap + + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); + } + + return 0; + + case IDM_FILE_PREVIOUS: + + // read previous entry in the directory + + if (SearchPngList (pPngFileList, iPngFileCount, &iPngFileIndex, + szImgPathName, NULL)) + { + + if (strcmp (szImgPathName, "") == 0) + return 0; + + // load the image from file + + if (!LoadImageFile (hwnd, szImgPathName, &pbImage, &cxImgSize, + &cyImgSize, &cImgChannels, &bkgColor)) + return 0; + + // invalidate the client area for later update + + InvalidateRect (hwnd, NULL, TRUE); + + // display the PNG into the DIBitmap + + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); + } + + return 0; + + case IDM_FILE_EXIT: + + // more cleanup needed... + + // free image buffer + + if (pDib != NULL) + { + free (pDib); + pDib = NULL; + } + + // free file-list + + if (pPngFileList != NULL) + { + free (pPngFileList); + pPngFileList = NULL; + } + + // let's go ... + + exit (0); + + return 0; + + case IDM_OPTIONS_STRETCH: + bStretched = !bStretched; + if (bStretched) + CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_CHECKED); + else + CheckMenuItem (hMenu, IDM_OPTIONS_STRETCH, MF_UNCHECKED); + + // invalidate the client area for later update + + InvalidateRect (hwnd, NULL, TRUE); + + // display the PNG into the DIBitmap + + DisplayImage (hwnd, &pDib, &pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, bStretched); + + return 0; + + case IDM_HELP_ABOUT: + DialogBox (hInstance, TEXT ("AboutBox"), hwnd, AboutDlgProc) ; + return 0; + + } // end switch + + break; + + case WM_PAINT: + hdc = BeginPaint (hwnd, &ps); + + if (pDib) + SetDIBitsToDevice (hdc, 0, 0, cxWinSize, cyWinSize, 0, 0, + 0, cyWinSize, pDiData, (BITMAPINFO *) pDib, DIB_RGB_COLORS); + + EndPaint (hwnd, &ps); + return 0; + + case WM_DESTROY: + if (pbmfh) + { + free (pbmfh); + pbmfh = NULL; + } + + PostQuitMessage (0); + return 0; + } + + return DefWindowProc (hwnd, message, wParam, lParam); +} + +BOOL CALLBACK AboutDlgProc (HWND hDlg, UINT message, + WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG : + ShowWindow (hDlg, SW_HIDE); + CenterAbout (hDlg, GetWindow (hDlg, GW_OWNER)); + ShowWindow (hDlg, SW_SHOW); + return TRUE ; + + case WM_COMMAND : + switch (LOWORD (wParam)) + { + case IDOK : + case IDCANCEL : + EndDialog (hDlg, 0) ; + return TRUE ; + } + break ; + } + return FALSE ; +} + +//--------------- +// CenterAbout +//--------------- + +BOOL CenterAbout (HWND hwndChild, HWND hwndParent) +{ + RECT rChild, rParent, rWorkArea; + int wChild, hChild, wParent, hParent; + int xNew, yNew; + BOOL bResult; + + // Get the Height and Width of the child window + GetWindowRect (hwndChild, &rChild); + wChild = rChild.right - rChild.left; + hChild = rChild.bottom - rChild.top; + + // Get the Height and Width of the parent window + GetWindowRect (hwndParent, &rParent); + wParent = rParent.right - rParent.left; + hParent = rParent.bottom - rParent.top; + + // Get the limits of the 'workarea' + bResult = SystemParametersInfo( + SPI_GETWORKAREA, // system parameter to query or set + sizeof(RECT), + &rWorkArea, + 0); + if (!bResult) { + rWorkArea.left = rWorkArea.top = 0; + rWorkArea.right = GetSystemMetrics(SM_CXSCREEN); + rWorkArea.bottom = GetSystemMetrics(SM_CYSCREEN); + } + + // Calculate new X position, then adjust for workarea + xNew = rParent.left + ((wParent - wChild) /2); + if (xNew < rWorkArea.left) { + xNew = rWorkArea.left; + } else if ((xNew+wChild) > rWorkArea.right) { + xNew = rWorkArea.right - wChild; + } + + // Calculate new Y position, then adjust for workarea + yNew = rParent.top + ((hParent - hChild) /2); + if (yNew < rWorkArea.top) { + yNew = rWorkArea.top; + } else if ((yNew+hChild) > rWorkArea.bottom) { + yNew = rWorkArea.bottom - hChild; + } + + // Set it, and return + return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | + SWP_NOZORDER); +} + +//---------------- +// BuildPngList +//---------------- + +BOOL BuildPngList (PTSTR pstrPathName, TCHAR **ppFileList, int *pFileCount, + int *pFileIndex) +{ + static TCHAR szImgPathName [MAX_PATH]; + static TCHAR szImgFileName [MAX_PATH]; + static TCHAR szImgFindName [MAX_PATH]; + + WIN32_FIND_DATA finddata; + HANDLE hFind; + + static TCHAR szTmp [MAX_PATH]; + BOOL bOk; + int i, ii; + int j, jj; + + // free previous file-list + + if (*ppFileList != NULL) + { + free (*ppFileList); + *ppFileList = NULL; + } + + // extract foldername, filename and search-name + + strcpy (szImgPathName, pstrPathName); + strcpy (szImgFileName, strrchr (pstrPathName, '\\') + 1); + + strcpy (szImgFindName, szImgPathName); + *(strrchr (szImgFindName, '\\') + 1) = '\0'; + strcat (szImgFindName, "*.png"); + + // first cycle: count number of files in directory for memory allocation + + *pFileCount = 0; + + hFind = FindFirstFile(szImgFindName, &finddata); + bOk = (hFind != (HANDLE) -1); + + while (bOk) + { + *pFileCount += 1; + bOk = FindNextFile(hFind, &finddata); + } + FindClose(hFind); + + // allocation memory for file-list + + *ppFileList = (TCHAR *) malloc (*pFileCount * MAX_PATH); + + // second cycle: read directory and store filenames in file-list + + hFind = FindFirstFile(szImgFindName, &finddata); + bOk = (hFind != (HANDLE) -1); + + i = 0; + ii = 0; + while (bOk) + { + strcpy (*ppFileList + ii, szImgPathName); + strcpy (strrchr(*ppFileList + ii, '\\') + 1, finddata.cFileName); + + if (strcmp(pstrPathName, *ppFileList + ii) == 0) + *pFileIndex = i; + + ii += MAX_PATH; + i++; + + bOk = FindNextFile(hFind, &finddata); + } + FindClose(hFind); + + // finally we must sort the file-list + + for (i = 0; i < *pFileCount - 1; i++) + { + ii = i * MAX_PATH; + for (j = i+1; j < *pFileCount; j++) + { + jj = j * MAX_PATH; + if (strcmp (*ppFileList + ii, *ppFileList + jj) > 0) + { + strcpy (szTmp, *ppFileList + jj); + strcpy (*ppFileList + jj, *ppFileList + ii); + strcpy (*ppFileList + ii, szTmp); + + // check if this was the current image that we moved + + if (*pFileIndex == i) + *pFileIndex = j; + else + if (*pFileIndex == j) + *pFileIndex = i; + } + } + } + + return TRUE; +} + +//---------------- +// SearchPngList +//---------------- + +BOOL SearchPngList ( + TCHAR *pFileList, int FileCount, int *pFileIndex, + PTSTR pstrPrevName, PTSTR pstrNextName) +{ + if (FileCount > 0) + { + // get previous entry + + if (pstrPrevName != NULL) + { + if (*pFileIndex > 0) + *pFileIndex -= 1; + else + *pFileIndex = FileCount - 1; + + strcpy (pstrPrevName, pFileList + (*pFileIndex * MAX_PATH)); + } + + // get next entry + + if (pstrNextName != NULL) + { + if (*pFileIndex < FileCount - 1) + *pFileIndex += 1; + else + *pFileIndex = 0; + + strcpy (pstrNextName, pFileList + (*pFileIndex * MAX_PATH)); + } + + return TRUE; + } + else + { + return FALSE; + } +} + +//----------------- +// LoadImageFile +//----------------- + +BOOL LoadImageFile (HWND hwnd, PTSTR pstrPathName, + png_byte **ppbImage, int *pxImgSize, int *pyImgSize, + int *piChannels, png_color *pBkgColor) +{ + static TCHAR szTmp [MAX_PATH]; + + // if there's an existing PNG, free the memory + + if (*ppbImage) + { + free (*ppbImage); + *ppbImage = NULL; + } + + // Load the entire PNG into memory + + SetCursor (LoadCursor (NULL, IDC_WAIT)); + ShowCursor (TRUE); + + PngLoadImage (pstrPathName, ppbImage, pxImgSize, pyImgSize, piChannels, + pBkgColor); + + ShowCursor (FALSE); + SetCursor (LoadCursor (NULL, IDC_ARROW)); + + if (*ppbImage != NULL) + { + sprintf (szTmp, "VisualPng - %s", strrchr(pstrPathName, '\\') + 1); + SetWindowText (hwnd, szTmp); + } + else + { + MessageBox (hwnd, TEXT ("Error in loading the PNG image"), + szProgName, MB_ICONEXCLAMATION | MB_OK); + return FALSE; + } + + return TRUE; +} + +//---------------- +// DisplayImage +//---------------- + +BOOL DisplayImage (HWND hwnd, BYTE **ppDib, + BYTE **ppDiData, int cxWinSize, int cyWinSize, + BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels, + BOOL bStretched) +{ + BYTE *pDib = *ppDib; + BYTE *pDiData = *ppDiData; + // BITMAPFILEHEADER *pbmfh; + BITMAPINFOHEADER *pbmih; + WORD wDIRowBytes; + png_color bkgBlack = {0, 0, 0}; + png_color bkgGray = {127, 127, 127}; + png_color bkgWhite = {255, 255, 255}; + + // allocate memory for the Device Independant bitmap + + wDIRowBytes = (WORD) ((3 * cxWinSize + 3L) >> 2) << 2; + + if (pDib) + { + free (pDib); + pDib = NULL; + } + + if (!(pDib = (BYTE *) malloc (sizeof(BITMAPINFOHEADER) + + wDIRowBytes * cyWinSize))) + { + MessageBox (hwnd, TEXT ("Error in displaying the PNG image"), + szProgName, MB_ICONEXCLAMATION | MB_OK); + *ppDib = pDib = NULL; + return FALSE; + } + *ppDib = pDib; + memset (pDib, 0, sizeof(BITMAPINFOHEADER)); + + // initialize the dib-structure + + pbmih = (BITMAPINFOHEADER *) pDib; + pbmih->biSize = sizeof(BITMAPINFOHEADER); + pbmih->biWidth = cxWinSize; + pbmih->biHeight = -((long) cyWinSize); + pbmih->biPlanes = 1; + pbmih->biBitCount = 24; + pbmih->biCompression = 0; + pDiData = pDib + sizeof(BITMAPINFOHEADER); + *ppDiData = pDiData; + + // first fill bitmap with gray and image border + + InitBitmap (pDiData, cxWinSize, cyWinSize); + + // then fill bitmap with image + + if (pbImage) + { + FillBitmap ( + pDiData, cxWinSize, cyWinSize, + pbImage, cxImgSize, cyImgSize, cImgChannels, + bStretched); + } + + return TRUE; +} + +//-------------- +// InitBitmap +//-------------- + +BOOL InitBitmap (BYTE *pDiData, int cxWinSize, int cyWinSize) +{ + BYTE *dst; + int x, y, col; + + // initialize the background with gray + + dst = pDiData; + for (y = 0; y < cyWinSize; y++) + { + col = 0; + for (x = 0; x < cxWinSize; x++) + { + // fill with GRAY + *dst++ = 127; + *dst++ = 127; + *dst++ = 127; + col += 3; + } + // rows start on 4 byte boundaries + while ((col % 4) != 0) + { + dst++; + col++; + } + } + + return TRUE; +} + +//-------------- +// FillBitmap +//-------------- + +BOOL FillBitmap ( + BYTE *pDiData, int cxWinSize, int cyWinSize, + BYTE *pbImage, int cxImgSize, int cyImgSize, int cImgChannels, + BOOL bStretched) +{ + BYTE *pStretchedImage; + BYTE *pImg; + BYTE *src, *dst; + BYTE r, g, b, a; + const int cDIChannels = 3; + WORD wImgRowBytes; + WORD wDIRowBytes; + int cxNewSize, cyNewSize; + int cxImgPos, cyImgPos; + int xImg, yImg; + int xWin, yWin; + int xOld, yOld; + int xNew, yNew; + + if (bStretched) + { + cxNewSize = cxWinSize - 2 * MARGIN; + cyNewSize = cyWinSize - 2 * MARGIN; + + // stretch the image to it's window determined size + + // the following two are the same, but the first has side-effects + // because of rounding +// if ((cyNewSize / cxNewSize) > (cyImgSize / cxImgSize)) + if ((cyNewSize * cxImgSize) > (cyImgSize * cxNewSize)) + { + cyNewSize = cxNewSize * cyImgSize / cxImgSize; + cxImgPos = MARGIN; + cyImgPos = (cyWinSize - cyNewSize) / 2; + } + else + { + cxNewSize = cyNewSize * cxImgSize / cyImgSize; + cyImgPos = MARGIN; + cxImgPos = (cxWinSize - cxNewSize) / 2; + } + + pStretchedImage = malloc (cImgChannels * cxNewSize * cyNewSize); + pImg = pStretchedImage; + + for (yNew = 0; yNew < cyNewSize; yNew++) + { + yOld = yNew * cyImgSize / cyNewSize; + for (xNew = 0; xNew < cxNewSize; xNew++) + { + xOld = xNew * cxImgSize / cxNewSize; + + r = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 0); + g = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 1); + b = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + 2); + *pImg++ = r; + *pImg++ = g; + *pImg++ = b; + if (cImgChannels == 4) + { + a = *(pbImage + cImgChannels * ((yOld * cxImgSize) + xOld) + + 3); + *pImg++ = a; + } + } + } + + // calculate row-bytes + + wImgRowBytes = cImgChannels * cxNewSize; + wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2; + + // copy image to screen + + for (yImg = 0, yWin = cyImgPos; yImg < cyNewSize; yImg++, yWin++) + { + if (yWin >= cyWinSize - cyImgPos) + break; + src = pStretchedImage + yImg * wImgRowBytes; + dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels; + + for (xImg = 0, xWin = cxImgPos; xImg < cxNewSize; xImg++, xWin++) + { + if (xWin >= cxWinSize - cxImgPos) + break; + r = *src++; + g = *src++; + b = *src++; + *dst++ = b; /* note the reverse order */ + *dst++ = g; + *dst++ = r; + if (cImgChannels == 4) + { + a = *src++; + } + } + } + + // free memory + + if (pStretchedImage != NULL) + { + free (pStretchedImage); + pStretchedImage = NULL; + } + + } + + // process the image not-stretched + + else + { + // calculate the central position + + cxImgPos = (cxWinSize - cxImgSize) / 2; + cyImgPos = (cyWinSize - cyImgSize) / 2; + + // check for image larger than window + + if (cxImgPos < MARGIN) + cxImgPos = MARGIN; + if (cyImgPos < MARGIN) + cyImgPos = MARGIN; + + // calculate both row-bytes + + wImgRowBytes = cImgChannels * cxImgSize; + wDIRowBytes = (WORD) ((cDIChannels * cxWinSize + 3L) >> 2) << 2; + + // copy image to screen + + for (yImg = 0, yWin = cyImgPos; yImg < cyImgSize; yImg++, yWin++) + { + if (yWin >= cyWinSize - MARGIN) + break; + src = pbImage + yImg * wImgRowBytes; + dst = pDiData + yWin * wDIRowBytes + cxImgPos * cDIChannels; + + for (xImg = 0, xWin = cxImgPos; xImg < cxImgSize; xImg++, xWin++) + { + if (xWin >= cxWinSize - MARGIN) + break; + r = *src++; + g = *src++; + b = *src++; + *dst++ = b; /* note the reverse order */ + *dst++ = g; + *dst++ = r; + if (cImgChannels == 4) + { + a = *src++; + } + } + } + } + + return TRUE; +} + +//----------------- +// end of source +//----------------- diff --git a/contrib/libpng/contrib/visupng/VisualPng.dsp b/contrib/libpng/contrib/visupng/VisualPng.dsp new file mode 100644 index 0000000..741ef6c --- /dev/null +++ b/contrib/libpng/contrib/visupng/VisualPng.dsp @@ -0,0 +1,147 @@ +# Microsoft Developer Studio Project File - Name="VisualPng" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=VisualPng - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "VisualPng.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "VisualPng.mak" CFG="VisualPng - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "VisualPng - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "VisualPng - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "VisualPng - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /O2 /I "..\.." /I "..\..\..\zlib" /D "WIN32" /D "NDEBUG" /D "PNG_NO_STDIO" /FD /c +# SUBTRACT BASE CPP /YX +# ADD CPP /nologo /MD /W3 /O2 /I "..\.." /I "..\..\..\zlib" /D "WIN32" /D "NDEBUG" /D "PNG_NO_STDIO" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 ..\..\projects\visualc6\Win32_LIB_Release\libpng.lib ..\..\..\zlib\projects\visualc6\Win32_LIB_Release\zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# Begin Special Build Tool +OutDir=.\Release +SOURCE="$(InputPath)" +PostBuild_Cmds=$(outdir)\VisualPng.exe ..\..\contrib\pngsuite\basn6a16.png +# End Special Build Tool + +!ELSEIF "$(CFG)" == "VisualPng - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /ZI /Od /I "..\.." /I "..\..\..\zlib" /D "WIN32" /D "_DEBUG" /D "PNG_NO_STDIO" /FD /GZ /c +# SUBTRACT BASE CPP /YX +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "..\.." /I "..\..\..\zlib" /D "WIN32" /D "_DEBUG" /D "PNG_NO_STDIO" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ..\..\projects\visualc6\Win32_LIB_Release\libpng.lib ..\..\..\zlib\projects\visualc6\Win32_LIB_Release\zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /pdbtype:sept +# Begin Special Build Tool +OutDir=.\Debug +SOURCE="$(InputPath)" +PostBuild_Cmds=$(outdir)\VisualPng.exe ..\..\contrib\pngsuite\basn6a16.png +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "VisualPng - Win32 Release" +# Name "VisualPng - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\PngFile.c +# End Source File +# Begin Source File + +SOURCE=.\VisualPng.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\cexcept.h +# End Source File +# Begin Source File + +SOURCE=.\PngFile.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\VisualPng.ico +# End Source File +# Begin Source File + +SOURCE=.\VisualPng.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/contrib/libpng/contrib/visupng/VisualPng.dsw b/contrib/libpng/contrib/visupng/VisualPng.dsw new file mode 100644 index 0000000..a30e1cc --- /dev/null +++ b/contrib/libpng/contrib/visupng/VisualPng.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "VisualPng"=.\VisualPng.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/contrib/libpng/contrib/visupng/VisualPng.ico b/contrib/libpng/contrib/visupng/VisualPng.ico new file mode 100644 index 0000000..68aa371 Binary files /dev/null and b/contrib/libpng/contrib/visupng/VisualPng.ico differ diff --git a/contrib/libpng/contrib/visupng/VisualPng.png b/contrib/libpng/contrib/visupng/VisualPng.png new file mode 100644 index 0000000..c6aa80a Binary files /dev/null and b/contrib/libpng/contrib/visupng/VisualPng.png differ diff --git a/contrib/libpng/contrib/visupng/VisualPng.rc b/contrib/libpng/contrib/visupng/VisualPng.rc new file mode 100644 index 0000000..6e0623a --- /dev/null +++ b/contrib/libpng/contrib/visupng/VisualPng.rc @@ -0,0 +1,152 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +VISUALPNG MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Open Image...\tCtrl+O", IDM_FILE_OPEN + MENUITEM "Save &As...", IDM_FILE_SAVE + MENUITEM SEPARATOR + MENUITEM "&Next Image\tCtrl+N", IDM_FILE_NEXT + MENUITEM "Pre&vious Image\tCtrl+V", IDM_FILE_PREVIOUS + MENUITEM SEPARATOR + MENUITEM "E&xit\tAlt+X", IDM_FILE_EXIT + END + POPUP "&Options" + BEGIN + MENUITEM "&Stretch", IDM_OPTIONS_STRETCH, CHECKED + END + POPUP "&Help" + BEGIN + MENUITEM "&About", IDM_HELP_ABOUT + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +VISUALPNG ACCELERATORS DISCARDABLE +BEGIN + "N", IDM_FILE_NEXT, VIRTKEY, CONTROL, NOINVERT + "O", IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT + "P", IDM_FILE_PREVIOUS, VIRTKEY, CONTROL, NOINVERT + "V", IDM_FILE_PREVIOUS, VIRTKEY, CONTROL, NOINVERT + "X", IDM_FILE_EXIT, VIRTKEY, ALT, NOINVERT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +VISUALPNG ICON DISCARDABLE "VisualPng.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +ABOUTBOX DIALOG DISCARDABLE 0, 0, 186, 94 +STYLE DS_MODALFRAME | WS_POPUP +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,68,67,50,14 + CTEXT "VisualPng 1.0 - June 2000",IDC_STATIC,49,14,88,8 + LTEXT "a PNG image viewer",IDC_STATIC,60,30,66,8 + LTEXT "(c) Willem van Schaik, 2000",IDC_STATIC,48,52,90,8 + LTEXT "to demonstrate the use of libpng in Visual C", + IDC_STATIC,25,38,136,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + "ABOUTBOX", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 87 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/contrib/libpng/contrib/visupng/cexcept.h b/contrib/libpng/contrib/visupng/cexcept.h new file mode 100644 index 0000000..5f45d76 --- /dev/null +++ b/contrib/libpng/contrib/visupng/cexcept.h @@ -0,0 +1,248 @@ +/*=== +cexcept.h 2.0.1 (2008-Jul-19-Sat) +http://www.nicemice.net/cexcept/ +Adam M. Costello +http://www.nicemice.net/amc/ + +An interface for exception-handling in ANSI C (C89 and subsequent ISO +standards), developed jointly with Cosmin Truta. + + Copyright (c) 2000-2008 Adam M. Costello and Cosmin Truta. + This software may be modified only if its author and version + information is updated accurately, and may be redistributed + only if accompanied by this unaltered notice. Subject to those + restrictions, permission is granted to anyone to do anything + with this software. The copyright holders make no guarantees + regarding this software, and are not responsible for any damage + resulting from its use. + +The cexcept interface is not compatible with and cannot interact +with system exceptions (like division by zero or memory segmentation +violation), compiler-generated exceptions (like C++ exceptions), or +other exception-handling interfaces. + +When using this interface across multiple .c files, do not include +this header file directly. Instead, create a wrapper header file that +includes this header file and then invokes the define_exception_type +macro (see below). The .c files should then include that header file. + +The interface consists of one type, one well-known name, and six macros. + + +define_exception_type(type_name); + + This macro is used like an external declaration. It specifies + the type of object that gets copied from the exception thrower to + the exception catcher. The type_name can be any type that can be + assigned to, that is, a non-constant arithmetic type, struct, union, + or pointer. Examples: + + define_exception_type(int); + + enum exception { out_of_memory, bad_arguments, disk_full }; + define_exception_type(enum exception); + + struct exception { int code; const char *msg; }; + define_exception_type(struct exception); + + Because throwing an exception causes the object to be copied (not + just once, but twice), programmers may wish to consider size when + choosing the exception type. + + +struct exception_context; + + This type may be used after the define_exception_type() macro has + been invoked. A struct exception_context must be known to both + the thrower and the catcher. It is expected that there be one + context for each thread that uses exceptions. It would certainly + be dangerous for multiple threads to access the same context. + One thread can use multiple contexts, but that is likely to be + confusing and not typically useful. The application can allocate + this structure in any way it pleases--automatic, static, or dynamic. + The application programmer should pretend not to know the structure + members, which are subject to change. + + +struct exception_context *the_exception_context; + + The Try/Catch and Throw statements (described below) implicitly + refer to a context, using the name the_exception_context. It is + the application's responsibility to make sure that this name yields + the address of a mutable (non-constant) struct exception_context + wherever those statements are used. Subject to that constraint, the + application may declare a variable of this name anywhere it likes + (inside a function, in a parameter list, or externally), and may + use whatever storage class specifiers (static, extern, etc) or type + qualifiers (const, volatile, etc) it likes. Examples: + + static struct exception_context + * const the_exception_context = &foo; + + { struct exception_context *the_exception_context = bar; ... } + + int blah(struct exception_context *the_exception_context, ...); + + extern struct exception_context the_exception_context[1]; + + The last example illustrates a trick that avoids creating a pointer + object separate from the structure object. + + The name could even be a macro, for example: + + struct exception_context ec_array[numthreads]; + #define the_exception_context (ec_array + thread_id) + + Be aware that the_exception_context is used several times by the + Try/Catch/Throw macros, so it shouldn't be expensive or have side + effects. The expansion must be a drop-in replacement for an + identifier, so it's safest to put parentheses around it. + + +void init_exception_context(struct exception_context *ec); + + For context structures allocated statically (by an external + definition or using the "static" keyword), the implicit + initialization to all zeros is sufficient, but contexts allocated + by other means must be initialized using this macro before they + are used by a Try/Catch statement. It does no harm to initialize + a context more than once (by using this macro on a statically + allocated context, or using this macro twice on the same context), + but a context must not be re-initialized after it has been used by a + Try/Catch statement. + + +Try statement +Catch (expression) statement + + The Try/Catch/Throw macros are capitalized in order to avoid + confusion with the C++ keywords, which have subtly different + semantics. + + A Try/Catch statement has a syntax similar to an if/else statement, + except that the parenthesized expression goes after the second + keyword rather than the first. As with if/else, there are two + clauses, each of which may be a simple statement ending with a + semicolon or a brace-enclosed compound statement. But whereas + the else clause is optional, the Catch clause is required. The + expression must be a modifiable lvalue (something capable of being + assigned to) of the same type (disregarding type qualifiers) that + was passed to define_exception_type(). + + If a Throw that uses the same exception context as the Try/Catch is + executed within the Try clause (typically within a function called + by the Try clause), and the exception is not caught by a nested + Try/Catch statement, then a copy of the exception will be assigned + to the expression, and control will jump to the Catch clause. If no + such Throw is executed, then the assignment is not performed, and + the Catch clause is not executed. + + The expression is not evaluated unless and until the exception is + caught, which is significant if it has side effects, for example: + + Try foo(); + Catch (p[++i].e) { ... } + + IMPORTANT: Jumping into or out of a Try clause (for example via + return, break, continue, goto, longjmp) is forbidden--the compiler + will not complain, but bad things will happen at run-time. Jumping + into or out of a Catch clause is okay, and so is jumping around + inside a Try clause. In many cases where one is tempted to return + from a Try clause, it will suffice to use Throw, and then return + from the Catch clause. Another option is to set a flag variable and + use goto to jump to the end of the Try clause, then check the flag + after the Try/Catch statement. + + IMPORTANT: The values of any non-volatile automatic variables + changed within the Try clause are undefined after an exception is + caught. Therefore, variables modified inside the Try block whose + values are needed later outside the Try block must either use static + storage or be declared with the "volatile" type qualifier. + + +Throw expression; + + A Throw statement is very much like a return statement, except that + the expression is required. Whereas return jumps back to the place + where the current function was called, Throw jumps back to the Catch + clause of the innermost enclosing Try clause. The expression must + be compatible with the type passed to define_exception_type(). The + exception must be caught, otherwise the program may crash. + + Slight limitation: If the expression is a comma-expression, it must + be enclosed in parentheses. + + +Try statement +Catch_anonymous statement + + When the value of the exception is not needed, a Try/Catch statement + can use Catch_anonymous instead of Catch (expression). + + +Everything below this point is for the benefit of the compiler. The +application programmer should pretend not to know any of it, because it +is subject to change. + +===*/ + + +#ifndef CEXCEPT_H +#define CEXCEPT_H + + +#include + +#define define_exception_type(etype) \ +struct exception_context { \ + jmp_buf *penv; \ + int caught; \ + volatile struct { etype etmp; } v; \ +} + +/* etmp must be volatile because the application might use automatic */ +/* storage for the_exception_context, and etmp is modified between */ +/* the calls to setjmp() and longjmp(). A wrapper struct is used to */ +/* avoid warnings about a duplicate volatile qualifier in case etype */ +/* already includes it. */ + +#define init_exception_context(ec) ((void)((ec)->penv = 0)) + +#define Try \ + { \ + jmp_buf *exception__prev, exception__env; \ + exception__prev = the_exception_context->penv; \ + the_exception_context->penv = &exception__env; \ + if (setjmp(exception__env) == 0) { \ + do + +#define exception__catch(action) \ + while (the_exception_context->caught = 0, \ + the_exception_context->caught); \ + } \ + else { \ + the_exception_context->caught = 1; \ + } \ + the_exception_context->penv = exception__prev; \ + } \ + if (!the_exception_context->caught || action) { } \ + else + +#define Catch(e) exception__catch(((e) = the_exception_context->v.etmp, 0)) +#define Catch_anonymous exception__catch(0) + +/* Try ends with do, and Catch begins with while(0) and ends with */ +/* else, to ensure that Try/Catch syntax is similar to if/else */ +/* syntax. */ +/* */ +/* The 0 in while(0) is expressed as x=0,x in order to appease */ +/* compilers that warn about constant expressions inside while(). */ +/* Most compilers should still recognize that the condition is always */ +/* false and avoid generating code for it. */ + +#define Throw \ + for (;; longjmp(*the_exception_context->penv, 1)) \ + the_exception_context->v.etmp = + + +#endif /* CEXCEPT_H */ diff --git a/contrib/libpng/contrib/visupng/resource.h b/contrib/libpng/contrib/visupng/resource.h new file mode 100644 index 0000000..611dd03 --- /dev/null +++ b/contrib/libpng/contrib/visupng/resource.h @@ -0,0 +1,23 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by VisualPng.rc +// +#define IDM_FILE_OPEN 40001 +#define IDM_FILE_SAVE 40002 +#define IDM_FILE_NEXT 40003 +#define IDM_FILE_PREVIOUS 40004 +#define IDM_FILE_EXIT 40005 +#define IDM_OPTIONS_BACKGROUND 40006 +#define IDM_OPTIONS_STRETCH 40007 +#define IDM_HELP_ABOUT 40008 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 113 +#define _APS_NEXT_COMMAND_VALUE 40009 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/contrib/libpng/depcomp b/contrib/libpng/depcomp new file mode 100755 index 0000000..df8eea7 --- /dev/null +++ b/contrib/libpng/depcomp @@ -0,0 +1,630 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free +# Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +cygpath_u="cygpath -u -f -" +if test "$depmode" = msvcmsys; then + # This is just like msvisualcpp but w/o cygpath translation. + # Just convert the backslash-escaped backslashes to single forward + # slashes to satisfy depend.m4 + cygpath_u="sed s,\\\\\\\\,/,g" + depmode=msvisualcpp +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> "$depfile" + echo >> "$depfile" + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add `dependent.h:' lines. + sed -ne '2,${ + s/^ *// + s/ \\*$// + s/$/:/ + p + }' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no eat=no + for arg + do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + if test $eat = yes; then + eat=no + continue + fi + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -arch) + eat=yes ;; + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix=`echo "$object" | sed 's/^.*\././'` + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test "X$1" != 'X--mode=compile'; do + shift + done + shift + fi + + IFS=" " + for arg + do + case "$arg" in + -o) + shift + ;; + $object) + shift + ;; + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E 2>/dev/null | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvcmsys) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/contrib/libpng/example.c b/contrib/libpng/example.c new file mode 100644 index 0000000..cd3682f --- /dev/null +++ b/contrib/libpng/example.c @@ -0,0 +1,843 @@ + +#if 0 /* in case someone actually tries to compile this */ + +/* example.c - an example of using libpng + * Last changed in libpng 1.5.0 [January 6, 2011] + * This file has been placed in the public domain by the authors. + * Maintained 1998-2011 Glenn Randers-Pehrson + * Maintained 1996, 1997 Andreas Dilger) + * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + */ + +/* This is an example of how to use libpng to read and write PNG files. + * The file libpng-manual.txt is much more verbose then this. If you have not + * read it, do so first. This was designed to be a starting point of an + * implementation. This is not officially part of libpng, is hereby placed + * in the public domain, and therefore does not require a copyright notice. + * + * This file does not currently compile, because it is missing certain + * parts, like allocating memory to hold an image. You will have to + * supply these parts to get it to compile. For an example of a minimal + * working PNG reader/writer, see pngtest.c, included in this distribution; + * see also the programs in the contrib directory. + */ + +#include "png.h" + + /* The png_jmpbuf() macro, used in error handling, became available in + * libpng version 1.0.6. If you want to be able to run your code with older + * versions of libpng, you must define the macro yourself (but only if it + * is not already defined by libpng!). + */ + +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->png_jmpbuf) +#endif + +/* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp() + * returns zero if the image is a PNG and nonzero if it isn't a PNG. + * + * The function check_if_png() shown here, but not used, returns nonzero (true) + * if the file can be opened and is a PNG, 0 (false) otherwise. + * + * If this call is successful, and you are going to keep the file open, + * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once + * you have created the png_ptr, so that libpng knows your application + * has read that many bytes from the start of the file. Make sure you + * don't call png_set_sig_bytes() with more than 8 bytes read or give it + * an incorrect number of bytes read, or you will either have read too + * many bytes (your fault), or you are telling libpng to read the wrong + * number of magic bytes (also your fault). + * + * Many applications already read the first 2 or 4 bytes from the start + * of the image to determine the file type, so it would be easiest just + * to pass the bytes to png_sig_cmp() or even skip that if you know + * you have a PNG file, and call png_set_sig_bytes(). + */ +#define PNG_BYTES_TO_CHECK 4 +int check_if_png(char *file_name, FILE **fp) +{ + char buf[PNG_BYTES_TO_CHECK]; + + /* Open the prospective PNG file. */ + if ((*fp = fopen(file_name, "rb")) == NULL) + return 0; + + /* Read in some of the signature bytes */ + if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) + return 0; + + /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. + Return nonzero (true) if they match */ + + return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK)); +} + +/* Read a PNG file. You may want to return an error code if the read + * fails (depending upon the failure). There are two "prototypes" given + * here - one where we are given the filename, and we need to open the + * file, and the other where we are given an open file (possibly with + * some or all of the magic bytes read - see comments above). + */ +#ifdef open_file /* prototype 1 */ +void read_png(char *file_name) /* We need to open the file */ +{ + png_structp png_ptr; + png_infop info_ptr; + unsigned int sig_read = 0; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + FILE *fp; + + if ((fp = fopen(file_name, "rb")) == NULL) + return (ERROR); + +#else no_open_file /* prototype 2 */ +void read_png(FILE *fp, unsigned int sig_read) /* File is already open */ +{ + png_structp png_ptr; + png_infop info_ptr; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; +#endif no_open_file /* Only use one prototype! */ + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also supply the + * the compiler header file version, so that we know if the application + * was compiled with a compatible version of the library. REQUIRED + */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + png_voidp user_error_ptr, user_error_fn, user_warning_fn); + + if (png_ptr == NULL) + { + fclose(fp); + return (ERROR); + } + + /* Allocate/initialize the memory for image information. REQUIRED. */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(fp); + png_destroy_read_struct(&png_ptr, NULL, NULL); + return (ERROR); + } + + /* Set error handling if you are using the setjmp/longjmp method (this is + * the normal method of doing things with libpng). REQUIRED unless you + * set up your own error handlers in the png_create_read_struct() earlier. + */ + + if (setjmp(png_jmpbuf(png_ptr))) + { + /* Free all of the memory associated with the png_ptr and info_ptr */ + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(fp); + /* If we get here, we had a problem reading the file */ + return (ERROR); + } + + /* One of the following I/O initialization methods is REQUIRED */ +#ifdef streams /* PNG file I/O method 1 */ + /* Set up the input control if you are using standard C streams */ + png_init_io(png_ptr, fp); + +#else no_streams /* PNG file I/O method 2 */ + /* If you are using replacement read functions, instead of calling + * png_init_io() here you would call: + */ + png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); + /* where user_io_ptr is a structure you want available to the callbacks */ +#endif no_streams /* Use only one I/O method! */ + + /* If we have already read some of the signature */ + png_set_sig_bytes(png_ptr, sig_read); + +#ifdef hilevel + /* + * If you have enough memory to read in the entire image at once, + * and you need to specify only transforms that can be controlled + * with one of the PNG_TRANSFORM_* bits (this presently excludes + * quantizing, filling, setting background, and doing gamma + * adjustment), then you can read the entire image (including + * pixels) into the info structure with this call: + */ + png_read_png(png_ptr, info_ptr, png_transforms, NULL); + +#else + /* OK, you're doing it the hard way, with the lower-level functions */ + + /* The call to png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). REQUIRED + */ + png_read_info(png_ptr, info_ptr); + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, + &interlace_type, NULL, NULL); + + /* Set up the data transformations you want. Note that these are all + * optional. Only call them if you want/need them. Many of the + * transformations only work on specific types of images, and many + * are mutually exclusive. + */ + + /* Tell libpng to strip 16 bit/color files down to 8 bits/color */ + png_set_strip_16(png_ptr); + + /* Strip alpha bytes from the input data without combining with the + * background (not recommended). + */ + png_set_strip_alpha(png_ptr); + + /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + png_set_packing(png_ptr); + + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). */ + png_set_packswap(png_ptr); + + /* Expand paletted colors into true RGB triplets */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */ + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand_gray_1_2_4_to_8(png_ptr); + + /* Expand paletted or RGB images with transparency to full alpha channels + * so the data will be available as RGBA quartets. + */ + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + + /* Set the background color to draw transparent and alpha images over. + * It is possible to set the red, green, and blue components directly + * for paletted images instead of supplying a palette index. Note that + * even if the PNG file supplies a background, you are not required to + * use it - you should use the (solid) application background if it has one. + */ + + png_color_16 my_background, *image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + + /* Some suggestions as to how to get a screen gamma value + * + * Note that screen gamma is the display_exponent, which includes + * the CRT_exponent and any correction for viewing conditions + */ + if (/* We have a user-defined screen gamma value */) + { + screen_gamma = user-defined screen_gamma; + } + /* This is one way that applications share the same screen gamma value */ + else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL) + { + screen_gamma = atof(gamma_str); + } + /* If we don't have another value */ + else + { + screen_gamma = 2.2; /* A good guess for a PC monitor in a dimly + lit room */ + screen_gamma = 1.7 or 1.0; /* A good guess for Mac systems */ + } + + /* Tell libpng to handle the gamma conversion for you. The final call + * is a good guess for PC generated images, but it should be configurable + * by the user at run time by the user. It is strongly suggested that + * your application support gamma correction. + */ + + int intent; + + if (png_get_sRGB(png_ptr, info_ptr, &intent)) + png_set_gamma(png_ptr, screen_gamma, 0.45455); + else + { + double image_gamma; + if (png_get_gAMA(png_ptr, info_ptr, &image_gamma)) + png_set_gamma(png_ptr, screen_gamma, image_gamma); + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + } + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + /* Quantize RGB files down to 8 bit palette or reduce palettes + * to the number of colors available on your screen. + */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + int num_palette; + png_colorp palette; + + /* This reduces the image to the application supplied palette */ + if (/* We have our own palette */) + { + /* An array of colors to which the image should be quantized */ + png_color std_color_cube[MAX_SCREEN_COLORS]; + + png_set_quantize(png_ptr, std_color_cube, MAX_SCREEN_COLORS, + MAX_SCREEN_COLORS, NULL, 0); + } + /* This reduces the image to the palette supplied in the file */ + else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, &histogram); + + png_set_quantize(png_ptr, palette, num_palette, + max_screen_colors, histogram, 0); + } + } +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + + /* Invert monochrome files to have 0 as white and 1 as black */ + png_set_invert_mono(png_ptr); + + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit_p; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit_p); + png_set_shift(png_ptr, sig_bit_p); + } + + /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ + if (color_type & PNG_COLOR_MASK_COLOR) + png_set_bgr(png_ptr); + + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ + png_set_swap_alpha(png_ptr); + + /* Swap bytes of 16 bit files to least significant byte first */ + png_set_swap(png_ptr); + + /* Add filler (or alpha) byte (before/after each RGB triplet) */ + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + + /* Turn on interlace handling. REQUIRED if you are not using + * png_read_image(). To see how to handle interlacing passes, + * see the png_read_row() method below: + */ + number_passes = png_set_interlace_handling(png_ptr); + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (ie you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* Allocate the memory to hold the image using the fields of info_ptr. */ + + /* The easiest way to read the image: */ + png_bytep row_pointers[height]; + + /* Clear the pointer array */ + for (row = 0; row < height; row++) + row_pointers[row] = NULL; + + for (row = 0; row < height; row++) + row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, + info_ptr)); + + /* Now it's time to read the image. One of these methods is REQUIRED */ +#ifdef entire /* Read the entire image in one go */ + png_read_image(png_ptr, row_pointers); + +#else no_entire /* Read the image one or more scanlines at a time */ + /* The other way to read images - deal with interlacing: */ + + for (pass = 0; pass < number_passes; pass++) + { +#ifdef single /* Read the image a single row at a time */ + for (y = 0; y < height; y++) + { + png_read_rows(png_ptr, &row_pointers[y], NULL, 1); + } + +#else no_single /* Read the image several rows at a time */ + for (y = 0; y < height; y += number_of_rows) + { +#ifdef sparkle /* Read the image using the "sparkle" effect. */ + png_read_rows(png_ptr, &row_pointers[y], NULL, + number_of_rows); +#else no_sparkle /* Read the image using the "rectangle" effect */ + png_read_rows(png_ptr, NULL, &row_pointers[y], + number_of_rows); +#endif no_sparkle /* Use only one of these two methods */ + } + + /* If you want to display the image after every pass, do so here */ +#endif no_single /* Use only one of these two methods */ + } +#endif no_entire /* Use only one of these two methods */ + + /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); +#endif hilevel + + /* At this point you have read the entire image */ + + /* Clean up after the read, and free any memory allocated - REQUIRED */ + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + /* Close the file */ + fclose(fp); + + /* That's it */ + return (OK); +} + +/* Progressively read a file */ + +int +initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr) +{ + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible in case we are using dynamically + * linked libraries. + */ + *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + png_voidp user_error_ptr, user_error_fn, user_warning_fn); + + if (*png_ptr == NULL) + { + *info_ptr = NULL; + return (ERROR); + } + + *info_ptr = png_create_info_struct(png_ptr); + + if (*info_ptr == NULL) + { + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return (ERROR); + } + + if (setjmp(png_jmpbuf((*png_ptr)))) + { + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return (ERROR); + } + + /* This one's new. You will need to provide all three + * function callbacks, even if you aren't using them all. + * If you aren't using all functions, you can specify NULL + * parameters. Even when all three functions are NULL, + * you need to call png_set_progressive_read_fn(). + * These functions shouldn't be dependent on global or + * static variables if you are decoding several images + * simultaneously. You should store stream specific data + * in a separate struct, given as the second parameter, + * and retrieve the pointer from inside the callbacks using + * the function png_get_progressive_ptr(png_ptr). + */ + png_set_progressive_read_fn(*png_ptr, (void *)stream_data, + info_callback, row_callback, end_callback); + + return (OK); +} + +int +process_data(png_structp *png_ptr, png_infop *info_ptr, + png_bytep buffer, png_uint_32 length) +{ + if (setjmp(png_jmpbuf((*png_ptr)))) + { + /* Free the png_ptr and info_ptr memory on error */ + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return (ERROR); + } + + /* This one's new also. Simply give it chunks of data as + * they arrive from the data stream (in order, of course). + * On segmented machines, don't give it any more than 64K. + * The library seems to run fine with sizes of 4K, although + * you can give it much less if necessary (I assume you can + * give it chunks of 1 byte, but I haven't tried with less + * than 256 bytes yet). When this function returns, you may + * want to display any rows that were generated in the row + * callback, if you aren't already displaying them there. + */ + png_process_data(*png_ptr, *info_ptr, buffer, length); + return (OK); +} + +info_callback(png_structp png_ptr, png_infop info) +{ + /* Do any setup here, including setting any of the transformations + * mentioned in the Reading PNG files section. For now, you _must_ + * call either png_start_read_image() or png_read_update_info() + * after all the transformations are set (even if you don't set + * any). You may start getting rows before png_process_data() + * returns, so this is your last chance to prepare for that. + */ +} + +row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) +{ + /* + * This function is called for every row in the image. If the + * image is interlaced, and you turned on the interlace handler, + * this function will be called for every row in every pass. + * + * In this function you will receive a pointer to new row data from + * libpng called new_row that is to replace a corresponding row (of + * the same data format) in a buffer allocated by your application. + * + * The new row data pointer "new_row" may be NULL, indicating there is + * no new data to be replaced (in cases of interlace loading). + * + * If new_row is not NULL then you need to call + * png_progressive_combine_row() to replace the corresponding row as + * shown below: + */ + + /* Get pointer to corresponding row in our + * PNG read buffer. + */ + png_bytep old_row = ((png_bytep *)our_data)[row_num]; + + /* If both rows are allocated then copy the new row + * data to the corresponding row data. + */ + if ((old_row != NULL) && (new_row != NULL)) + png_progressive_combine_row(png_ptr, old_row, new_row); + + /* + * The rows and passes are called in order, so you don't really + * need the row_num and pass, but I'm supplying them because it + * may make your life easier. + * + * For the non-NULL rows of interlaced images, you must call + * png_progressive_combine_row() passing in the new row and the + * old row, as demonstrated above. You can call this function for + * NULL rows (it will just return) and for non-interlaced images + * (it just does the png_memcpy for you) if it will make the code + * easier. Thus, you can just do this for all cases: + */ + + png_progressive_combine_row(png_ptr, old_row, new_row); + + /* where old_row is what was displayed for previous rows. Note + * that the first pass (pass == 0 really) will completely cover + * the old row, so the rows do not have to be initialized. After + * the first pass (and only for interlaced images), you will have + * to pass the current row as new_row, and the function will combine + * the old row and the new row. + */ +} + +end_callback(png_structp png_ptr, png_infop info) +{ + /* This function is called when the whole image has been read, + * including any chunks after the image (up to and including + * the IEND). You will usually have the same info chunk as you + * had in the header, although some data may have been added + * to the comments and time fields. + * + * Most people won't do much here, perhaps setting a flag that + * marks the image as finished. + */ +} + +/* Write a png file */ +void write_png(char *file_name /* , ... other image information ... */) +{ + FILE *fp; + png_structp png_ptr; + png_infop info_ptr; + png_colorp palette; + + /* Open the file */ + fp = fopen(file_name, "wb"); + if (fp == NULL) + return (ERROR); + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible with the one used at compile time, + * in case we are using dynamically linked libraries. REQUIRED. + */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, + png_voidp user_error_ptr, user_error_fn, user_warning_fn); + + if (png_ptr == NULL) + { + fclose(fp); + return (ERROR); + } + + /* Allocate/initialize the image information data. REQUIRED */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(fp); + png_destroy_write_struct(&png_ptr, NULL); + return (ERROR); + } + + /* Set error handling. REQUIRED if you aren't supplying your own + * error handling functions in the png_create_write_struct() call. + */ + if (setjmp(png_jmpbuf(png_ptr))) + { + /* If we get here, we had a problem writing the file */ + fclose(fp); + png_destroy_write_struct(&png_ptr, &info_ptr); + return (ERROR); + } + + /* One of the following I/O initialization functions is REQUIRED */ + +#ifdef streams /* I/O initialization method 1 */ + /* Set up the output control if you are using standard C streams */ + png_init_io(png_ptr, fp); + +#else no_streams /* I/O initialization method 2 */ + /* If you are using replacement write functions, instead of calling + * png_init_io() here you would call + */ + png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn, + user_IO_flush_function); + /* where user_io_ptr is a structure you want available to the callbacks */ +#endif no_streams /* Only use one initialization method */ + +#ifdef hilevel + /* This is the easy way. Use it if you already have all the + * image info living in the structure. You could "|" many + * PNG_TRANSFORM flags into the png_transforms integer here. + */ + png_write_png(png_ptr, info_ptr, png_transforms, NULL); + +#else + /* This is the hard way */ + + /* Set the image information here. Width and height are up to 2^31, + * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on + * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, + * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, + * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or + * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST + * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED + */ + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???, + PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + /* Set the palette if there is one. REQUIRED for indexed-color images */ + palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH + * png_sizeof(png_color)); + /* ... Set palette colors ... */ + png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); + /* You must not free palette here, because png_set_PLTE only makes a link to + * the palette that you malloced. Wait until you are about to destroy + * the png structure. + */ + + /* Optional significant bit (sBIT) chunk */ + png_color_8 sig_bit; + + /* If we are dealing with a grayscale image then */ + sig_bit.gray = true_bit_depth; + + /* Otherwise, if we are dealing with a color image then */ + sig_bit.red = true_red_bit_depth; + sig_bit.green = true_green_bit_depth; + sig_bit.blue = true_blue_bit_depth; + + /* If the image has an alpha channel then */ + sig_bit.alpha = true_alpha_bit_depth; + + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + + + /* Optional gamma chunk is strongly suggested if you have any guess + * as to the correct gamma of the image. + */ + png_set_gAMA(png_ptr, info_ptr, gamma); + + /* Optionally write comments into the image */ + text_ptr[0].key = "Title"; + text_ptr[0].text = "Mona Lisa"; + text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[0].itxt_length = 0; + text_ptr[0].lang = NULL; + text_ptr[0].lang_key = NULL; + text_ptr[1].key = "Author"; + text_ptr[1].text = "Leonardo DaVinci"; + text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[1].itxt_length = 0; + text_ptr[1].lang = NULL; + text_ptr[1].lang_key = NULL; + text_ptr[2].key = "Description"; + text_ptr[2].text = ""; + text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr[2].itxt_length = 0; + text_ptr[2].lang = NULL; + text_ptr[2].lang_key = NULL; + png_set_text(png_ptr, info_ptr, text_ptr, 3); + + /* Other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs */ + + /* Note that if sRGB is present the gAMA and cHRM chunks must be ignored + * on read and, if your application chooses to write them, they must + * be written in accordance with the sRGB profile + */ + + /* Write the file header information. REQUIRED */ + png_write_info(png_ptr, info_ptr); + + /* If you want, you can write the info in two steps, in case you need to + * write your private chunk ahead of PLTE: + * + * png_write_info_before_PLTE(write_ptr, write_info_ptr); + * write_my_chunk(); + * png_write_info(png_ptr, info_ptr); + * + * However, given the level of known- and unknown-chunk support in 1.2.0 + * and up, this should no longer be necessary. + */ + + /* Once we write out the header, the compression type on the text + * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or + * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again + * at the end. + */ + + /* Set up the transformations you want. Note that these are + * all optional. Only call them if you want them. + */ + + /* Invert monochrome pixels */ + png_set_invert_mono(png_ptr); + + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + png_set_shift(png_ptr, &sig_bit); + + /* Pack pixels into bytes */ + png_set_packing(png_ptr); + + /* Swap location of alpha bytes from ARGB to RGBA */ + png_set_swap_alpha(png_ptr); + + /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into + * RGB (4 channels -> 3 channels). The second parameter is not used. + */ + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + + /* Flip BGR pixels to RGB */ + png_set_bgr(png_ptr); + + /* Swap bytes of 16-bit files to most significant byte first */ + png_set_swap(png_ptr); + + /* Swap bits of 1, 2, 4 bit packed pixel formats */ + png_set_packswap(png_ptr); + + /* Turn on interlace handling if you are not using png_write_image() */ + if (interlacing) + number_passes = png_set_interlace_handling(png_ptr); + + else + number_passes = 1; + + /* The easiest way to write the image (you may have a different memory + * layout, however, so choose what fits your needs best). You need to + * use the first method if you aren't handling interlacing yourself. + */ + png_uint_32 k, height, width; + png_byte image[height][width*bytes_per_pixel]; + png_bytep row_pointers[height]; + + if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) + png_error (png_ptr, "Image is too tall to process in memory"); + + for (k = 0; k < height; k++) + row_pointers[k] = image + k*width*bytes_per_pixel; + + /* One of the following output methods is REQUIRED */ + +#ifdef entire /* Write out the entire image data in one call */ + png_write_image(png_ptr, row_pointers); + + /* The other way to write the image - deal with interlacing */ + +#else no_entire /* Write out the image data by one or more scanlines */ + + /* The number of passes is either 1 for non-interlaced images, + * or 7 for interlaced images. + */ + for (pass = 0; pass < number_passes; pass++) + { + /* Write a few rows at a time. */ + png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows); + + /* If you are only writing one row at a time, this works */ + for (y = 0; y < height; y++) + png_write_rows(png_ptr, &row_pointers[y], 1); + } +#endif no_entire /* Use only one output method */ + + /* You can write optional chunks like tEXt, zTXt, and tIME at the end + * as well. Shouldn't be necessary in 1.2.0 and up as all the public + * chunks are supported and you can use png_set_unknown_chunks() to + * register unknown chunks into the info structure to be written out. + */ + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); +#endif hilevel + + /* If you png_malloced a palette, free it here (don't free info_ptr->palette, + * as recommended in versions 1.0.5m and earlier of this example; if + * libpng mallocs info_ptr->palette, libpng will free it). If you + * allocated it with malloc() instead of png_malloc(), use free() instead + * of png_free(). + */ + png_free(png_ptr, palette); + palette = NULL; + + /* Similarly, if you png_malloced any data that you passed in with + * png_set_something(), such as a hist or trans array, free it here, + * when you can be sure that libpng is through with it. + */ + png_free(png_ptr, trans); + trans = NULL; + /* Whenever you use png_free() it is a good idea to set the pointer to + * NULL in case your application inadvertently tries to png_free() it + * again. When png_free() sees a NULL it returns without action, thus + * avoiding the double-free security problem. + */ + + /* Clean up after the write, and free any memory allocated */ + png_destroy_write_struct(&png_ptr, &info_ptr); + + /* Close the file */ + fclose(fp); + + /* That's it */ + return (OK); +} + +#endif /* if 0 */ diff --git a/contrib/libpng/install-sh b/contrib/libpng/install-sh new file mode 100755 index 0000000..6781b98 --- /dev/null +++ b/contrib/libpng/install-sh @@ -0,0 +1,520 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2009-04-28.21; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/contrib/libpng/libpng-config.in b/contrib/libpng/libpng-config.in new file mode 100755 index 0000000..69bf8e3 --- /dev/null +++ b/contrib/libpng/libpng-config.in @@ -0,0 +1,127 @@ +#! /bin/sh + +# libpng-config +# provides configuration info for libpng. + +# Copyright (C) 2002, 2004, 2006, 2007 Glenn Randers-Pehrson + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Modeled after libxml-config. + +version="@PNGLIB_VERSION@" +prefix="@prefix@" +exec_prefix="@exec_prefix@" +libdir="@libdir@" +includedir="@includedir@/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@" +libs="-lpng@PNGLIB_MAJOR@@PNGLIB_MINOR@" +all_libs="-lpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ @LIBS@" +I_opts="-I${includedir}" +L_opts="-L${libdir}" +R_opts="" +cppflags="" +ccopts="" +ldopts="" + +usage() +{ + cat < + Copyright (c) 1998-2011 Glenn Randers-Pehrson + + This document is released under the libpng license. + For conditions of distribution and use, see the disclaimer + and license in png.h + + Based on: + + libpng versions 0.97, January 1998, through 1.5.1 - February 3, 2011 + Updated and distributed by Glenn Randers-Pehrson + Copyright (c) 1998-2011 Glenn Randers-Pehrson + + libpng 1.0 beta 6 version 0.96 May 28, 1997 + Updated and distributed by Andreas Dilger + Copyright (c) 1996, 1997 Andreas Dilger + + libpng 1.0 beta 2 - version 0.88 January 26, 1996 + For conditions of distribution and use, see copyright + notice in png.h. Copyright (c) 1995, 1996 Guy Eric + Schalnat, Group 42, Inc. + + Updated/rewritten per request in the libpng FAQ + Copyright (c) 1995, 1996 Frank J. T. Wojcik + December 18, 1995 & January 20, 1996 + +I. Introduction + +This file describes how to use and modify the PNG reference library +(known as libpng) for your own use. There are five sections to this +file: introduction, structures, reading, writing, and modification and +configuration notes for various special platforms. In addition to this +file, example.c is a good starting point for using the library, as +it is heavily commented and should include everything most people +will need. We assume that libpng is already installed; see the +INSTALL file for instructions on how to install libpng. + +For examples of libpng usage, see the files "example.c", "pngtest.c", +and the files in the "contrib" directory, all of which are included in +the libpng distribution. + +Libpng was written as a companion to the PNG specification, as a way +of reducing the amount of time and effort it takes to support the PNG +file format in application programs. + +The PNG specification (second edition), November 2003, is available as +a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at +. It is technically equivalent +to the PNG specification (second edition) but has some additional material. + +The PNG-1.0 specification is available +as RFC 2083 and as a +W3C Recommendation . + +Some additional chunks are described in the special-purpose public chunks +documents at . + +Other information +about PNG, and the latest version of libpng, can be found at the PNG home +page, . + +Most users will not have to modify the library significantly; advanced +users may want to modify it more. All attempts were made to make it as +complete as possible, while keeping the code easy to understand. +Currently, this library only supports C. Support for other languages +is being considered. + +Libpng has been designed to handle multiple sessions at one time, +to be easily modifiable, to be portable to the vast majority of +machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy +to use. The ultimate goal of libpng is to promote the acceptance of +the PNG file format in whatever way possible. While there is still +work to be done (see the TODO file), libpng should cover the +majority of the needs of its users. + +Libpng uses zlib for its compression and decompression of PNG files. +Further information about zlib, and the latest version of zlib, can +be found at the zlib home page, . +The zlib compression utility is a general purpose utility that is +useful for more than PNG files, and can be used without libpng. +See the documentation delivered with zlib for more details. +You can usually find the source files for the zlib utility wherever you +find the libpng source files. + +Libpng is thread safe, provided the threads are using different +instances of the structures. Each thread should have its own +png_struct and png_info instances, and thus its own image. +Libpng does not protect itself against two threads using the +same instance of a structure. + +II. Structures + +There are two main structures that are important to libpng, png_struct +and png_info. Both are internal structures that are no longer exposed +in the libpng interface (as of libpng 1.5.0). + +The png_info structure is designed to provide information about the +PNG file. At one time, the fields of png_info were intended to be +directly accessible to the user. However, this tended to cause problems +with applications using dynamically loaded libraries, and as a result +a set of interface functions for png_info (the png_get_*() and png_set_*() +functions) was developed. + +The png_struct structure is the object used by the library to decode a +single image. As of 1.5.0 this structure is also not exposed. + +Almost all libpng APIs require a pointer to a png_struct as the first argument. +Many (in particular the png_set and png_get APIs) also require a pointer +to png_info as the second argument. Some application visible macros +defined in png.h designed for basic data access (reading and writing +integers in the PNG format) break this rule, but it's almost always safe +to assume that a (png_struct*) has to be passed to call an API function. + +The png.h header file is an invaluable reference for programming with libpng. +And while I'm on the topic, make sure you include the libpng header file: + +#include + +Types + +The png.h header file defines a number of integral types used by the +APIs. Most of these are fairly obvious; for example types corresponding +to integers of particular sizes and types for passing color values. + +One exception is how non-integral numbers are handled. For application +convenience most APIs that take such numbers have C (double) arguments, +however internally PNG, and libpng, use 32 bit signed integers and encode +the value by multiplying by 100,000. As of libpng 1.5.0 a convenience +macro PNG_FP_1 is defined in png.h along with a type (png_fixed_point) +which is simply (png_int_32). + +All APIs that take (double) arguments also have an matching API that +takes the corresponding fixed point integer arguments. The fixed point +API has the same name as the floating point one with _fixed appended. +The actual range of values permitted in the APIs is frequently less than +the full range of (png_fixed_point) (-21474 to +21474). When APIs require +a non-negative argument the type is recorded as png_uint_32 above. Consult +the header file and the text below for more information. + +Special care must be take with sCAL chunk handling because the chunk itself +uses non-integral values encoded as strings containing decimal floating point +numbers. See the comments in the header file. + +Configuration + +The main header file function declarations are frequently protected by C +preprocessing directives of the form: + + #ifdef PNG_feature_SUPPORTED + declare-function + #endif + +The library can be built without support for these APIs, although a +standard build will have all implemented APIs. Application programs +should check the feature macros before using an API for maximum +portability. From libpng 1.5.0 the feature macros set during the build +of libpng are recorded in the header file "pnglibconf.h" and this file +is always included by png.h. + +If you don't need to change the library configuration from the default skip to +the next section ("Reading"). + +Notice that some of the makefiles in the 'scripts' directory and (in 1.5.0) all +of the build project files in the 'projects' directory simply copy +scripts/pnglibconf.h.prebuilt to pnglibconf.h. This means that these build +systems do not permit easy auto-configuration of the library - they only +support the default configuration. + +The easiest way to make minor changes to the libpng configuration when +auto-configuration is supported is to add definitions to the command line +using (typically) CPPFLAGS. For example: + +CPPFLAGS=-DPNG_NO_FLOATING_ARITHMETIC + +will change the internal libpng math implementation for gamma correction and +other arithmetic calculations to fixed point, avoiding the need for fast +floating point support. The result can be seen in the generated pnglibconf.h - +make sure it contains the changed feature macro setting. + +If you need to make more extensive configuration changes - more than one or two +feature macro settings - you can either add -DPNG_USER_CONFIG to the build +command line and put a list of feature macro settings in pngusr.h or you can set +DFA_XTRA (a makefile variable) to a file containing the same information in the +form of 'option' settings. + +A. Changing pnglibconf.h + +A variety of methods exist to build libpng. Not all of these support +reconfiguration of pnglibconf.h. To reconfigure pnglibconf.h it must either be +rebuilt from scripts/pnglibconf.dfa using awk or it must be edited by hand. + +Hand editing is achieved by copying scripts/pnglibconf.h.prebuilt and changing +the lines defining the supported features, paying very close attention to the +'option' information in scripts/pnglibconf.dfa that describes those features and +their requirements. This is easy to get wrong. + +B. Configuration using DFA_XTRA + +Rebuilding from pnglibconf.dfa is easy if a functioning 'awk', or a later +variant such as 'nawk' or 'gawk', is available. The configure build will +automatically find an appropriate awk and build pnglibconf.h. +scripts/pnglibconf.mak contains a set of make rules for doing the same thing if +configure is not used, and many of the makefiles in the scripts directory use +this approach. + +When rebuilding simply write new file containing changed options and set +DFA_XTRA to the name of this file. This causes the build to append the new file +to the end of scripts/pnglibconf.dfa. pngusr.dfa should contain lines of the +following forms: + +everything = off + +This turns all optional features off. Include it at the start of pngusr.dfa to +make it easier to build a minimal configuration. You will need to turn at least +some features on afterward to enable either reading or writing code, or both. + +option feature on +option feature off + +Enable or disable a single feature. This will automatically enable other +features required by a feature that is turned on or disable other features that +require a feature which is turned off. Conflicting settings will cause an error +message to be emitted by awk. + +setting feature default value + +Changes the default value of setting 'feature' to 'value'. There are a small +number of settings listed at the top of pnglibconf.h, they are documented in the +source code. Most of these values have performance implications for the library +but most of them have no visible effect on the API. Some can also be overridden +from the API. + +C. Configuration using PNG_USR_CONFIG + +If -DPNG_USR_CONFIG is added to the CFLAGS when pnglibconf.h is built the file +pngusr.h will automatically be included before the options in +scripts/pnglibconf.dfa are processed. pngusr.h should contain only macro +definitions turning features on or off or setting settings. + +Apart from the global setting "everything = off" all the options listed above +can be set using macros in pngusr.h: + +#define PNG_feature_SUPPORTED + +is equivalent to: + +option feature on + +#define PNG_NO_feature + +is equivalent to: + +option feature off + +#define PNG_feature value + +is equivalent to: + +setting feature default value + +Notice that in both cases, pngusr.dfa and pngusr.h, the contents of the +pngusr file you supply override the contents of scripts/pnglibconf.dfa + +If confusing or incomprehensible behavior results it is possible to +examine the intermediate file pnglibconf.dfn to find the full set of +dependency information for each setting and option. Simply locate the +feature in the file and read the C comments that precede it. + +III. Reading + +We'll now walk you through the possible functions to call when reading +in a PNG file sequentially, briefly explaining the syntax and purpose +of each one. See example.c and png.h for more detail. While +progressive reading is covered in the next section, you will still +need some of the functions discussed in this section to read a PNG +file. + +Setup + +You will want to do the I/O initialization(*) before you get into libpng, +so if it doesn't work, you don't have much to undo. Of course, you +will also want to insure that you are, in fact, dealing with a PNG +file. Libpng provides a simple check to see if a file is a PNG file. +To use it, pass in the first 1 to 8 bytes of the file to the function +png_sig_cmp(), and it will return 0 (false) if the bytes match the +corresponding bytes of the PNG signature, or nonzero (true) otherwise. +Of course, the more bytes you pass in, the greater the accuracy of the +prediction. + +If you are intending to keep the file pointer open for use in libpng, +you must ensure you don't read more than 8 bytes from the beginning +of the file, and you also have to make a call to png_set_sig_bytes_read() +with the number of bytes you read from the beginning. Libpng will +then only check the bytes (if any) that your program didn't read. + +(*): If you are not using the standard I/O functions, you will need +to replace them with custom functions. See the discussion under +Customizing libpng. + + + FILE *fp = fopen(file_name, "rb"); + if (!fp) + { + return (ERROR); + } + + fread(header, 1, number, fp); + is_png = !png_sig_cmp(header, 0, number); + + if (!is_png) + { + return (NOT_PNG); + } + + +Next, png_struct and png_info need to be allocated and initialized. In +order to ensure that the size of these structures is correct even with a +dynamically linked libpng, there are functions to initialize and +allocate the structures. We also pass the library version, optional +pointers to error handling functions, and a pointer to a data struct for +use by the error functions, if necessary (the pointer and functions can +be NULL if the default error handlers are to be used). See the section +on Changes to Libpng below regarding the old initialization functions. +The structure allocation functions quietly return NULL if they fail to +create the structure, so your application should check for that. + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return (ERROR); + } + + png_infop end_info = png_create_info_struct(png_ptr); + + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +use a libpng that was built with PNG_USER_MEM_SUPPORTED defined, and use +png_create_read_struct_2() instead of png_create_read_struct(): + + png_structp png_ptr = png_create_read_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +The error handling routines passed to png_create_read_struct() +and the memory alloc/free routines passed to png_create_struct_2() +are only necessary if you are not using the libpng supplied error +handling and memory alloc/free functions. + +When libpng encounters an error, it expects to longjmp back +to your routine. Therefore, you will need to call setjmp and pass +your png_jmpbuf(png_ptr). If you read the file from different +routines, you will need to update the jmpbuf field every time you enter +a new routine that will call a png_*() function. + +See your documentation of setjmp/longjmp for your compiler for more +information on setjmp/longjmp. See the discussion on libpng error +handling in the Customizing Libpng section below for more information +on the libpng error handling. If an error occurs, and libpng longjmp's +back to your setjmp, you will want to call png_destroy_read_struct() to +free any memory. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + fclose(fp); + return (ERROR); + } + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_NO_SETJMP, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +Now you need to set up the input code. The default for libpng is to +use the C function fread(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. If you wish to handle reading data in another +way, you need not call the png_init_io() function, but you must then +implement the libpng I/O methods discussed in the Customizing Libpng +section below. + + png_init_io(png_ptr, fp); + +If you had previously opened the file and read any of the signature from +the beginning in order to see if this was a PNG file, you need to let +libpng know that there are some bytes missing from the start of the file. + + png_set_sig_bytes(png_ptr, number); + +You can change the zlib compression buffer size to be used while +reading compressed data with + + png_set_compression_buffer_size(png_ptr, buffer_size); + +where the default size is 8192 bytes. Note that the buffer size +is changed immediately and the buffer is reallocated immediately, +instead of setting a flag to be acted upon later. + +If you want CRC errors to be handled in a different manner than +the default, use + + png_set_crc_action(png_ptr, crit_action, ancil_action); + +The values for png_set_crc_action() say how libpng is to handle CRC errors in +ancillary and critical chunks, and whether to use the data contained +therein. Note that it is impossible to "discard" data in a critical +chunk. + +Choices for (int) crit_action are + PNG_CRC_DEFAULT 0 error/quit + PNG_CRC_ERROR_QUIT 1 error/quit + PNG_CRC_WARN_USE 3 warn/use data + PNG_CRC_QUIET_USE 4 quiet/use data + PNG_CRC_NO_CHANGE 5 use the current value + +Choices for (int) ancil_action are + PNG_CRC_DEFAULT 0 error/quit + PNG_CRC_ERROR_QUIT 1 error/quit + PNG_CRC_WARN_DISCARD 2 warn/discard data + PNG_CRC_WARN_USE 3 warn/use data + PNG_CRC_QUIET_USE 4 quiet/use data + PNG_CRC_NO_CHANGE 5 use the current value + +Setting up callback code + +You can set up a callback function to handle any unknown chunks in the +input stream. You must supply the function + + read_chunk_callback(png_structp png_ptr, + png_unknown_chunkp chunk); + { + /* The unknown chunk structure contains your + chunk data, along with similar data for any other + unknown chunks: */ + + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* Note that libpng has already taken care of + the CRC handling */ + + /* put your code here. Search for your chunk in the + unknown chunk structure, process it, and return one + of the following: */ + + return (-n); /* chunk had an error */ + return (0); /* did not recognize */ + return (n); /* success */ + } + +(You can give your function another name that you like instead of +"read_chunk_callback") + +To inform libpng about your function, use + + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, + read_chunk_callback); + +This names not only the callback function, but also a user pointer that +you can retrieve with + + png_get_user_chunk_ptr(png_ptr); + +If you call the png_set_read_user_chunk_fn() function, then all unknown +chunks will be saved when read, in case your callback function will need +one or more of them. This behavior can be changed with the +png_set_keep_unknown_chunks() function, described below. + +At this point, you can set up a callback function that will be +called after each row has been read, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void read_row_callback(png_structp png_ptr, + png_uint_32 row, int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "read_row_callback") + +To inform libpng about your function, use + + png_set_read_status_fn(png_ptr, read_row_callback); + +Unknown-chunk handling + +Now you get to set the way the library processes unknown chunks in the +input PNG stream. Both known and unknown chunks will be read. Normal +behavior is that known chunks will be parsed into information in +various info_ptr members while unknown chunks will be discarded. This +behavior can be wasteful if your application will never use some known +chunk types. To change this, you can call: + + png_set_keep_unknown_chunks(png_ptr, keep, + chunk_list, num_chunks); + keep - 0: default unknown chunk handling + 1: ignore; do not keep + 2: keep only if safe-to-copy + 3: keep even if unsafe-to-copy + + You can use these definitions: + PNG_HANDLE_CHUNK_AS_DEFAULT 0 + PNG_HANDLE_CHUNK_NEVER 1 + PNG_HANDLE_CHUNK_IF_SAFE 2 + PNG_HANDLE_CHUNK_ALWAYS 3 + + chunk_list - list of chunks affected (a byte string, + five bytes per chunk, NULL or '\0' if + num_chunks is 0) + + num_chunks - number of chunks affected; if 0, all + unknown chunks are affected. If nonzero, + only the chunks in the list are affected + +Unknown chunks declared in this way will be saved as raw data onto a +list of png_unknown_chunk structures. If a chunk that is normally +known to libpng is named in the list, it will be handled as unknown, +according to the "keep" directive. If a chunk is named in successive +instances of png_set_keep_unknown_chunks(), the final instance will +take precedence. The IHDR and IEND chunks should not be named in +chunk_list; if they are, libpng will process them normally anyway. + +Here is an example of the usage of png_set_keep_unknown_chunks(), +where the private "vpAg" chunk will later be processed by a user chunk +callback function: + + png_byte vpAg[5]={118, 112, 65, 103, (png_byte) '\0'}; + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + png_byte unused_chunks[]= + { + 104, 73, 83, 84, (png_byte) '\0', /* hIST */ + 105, 84, 88, 116, (png_byte) '\0', /* iTXt */ + 112, 67, 65, 76, (png_byte) '\0', /* pCAL */ + 115, 67, 65, 76, (png_byte) '\0', /* sCAL */ + 115, 80, 76, 84, (png_byte) '\0', /* sPLT */ + 116, 73, 77, 69, (png_byte) '\0', /* tIME */ + }; + #endif + + ... + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + /* ignore all unknown chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0); + + /* except for vpAg: */ + png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1); + + /* also ignore unused known chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks, + (int)sizeof(unused_chunks)/5); + #endif + +User limits + +The PNG specification allows the width and height of an image to be as +large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns. +Since very few applications really need to process such large images, +we have imposed an arbitrary 1-million limit on rows and columns. +Larger images will be rejected immediately with a png_error() call. If +you wish to override this limit, you can use + + png_set_user_limits(png_ptr, width_max, height_max); + +to set your own limits, or use width_max = height_max = 0x7fffffffL +to allow all valid dimensions (libpng may reject some very large images +anyway because of potential buffer overflow conditions). + +You should put this statement after you create the PNG structure and +before calling png_read_info(), png_read_png(), or png_process_data(). +If you need to retrieve the limits that are being applied, use + + width_max = png_get_user_width_max(png_ptr); + height_max = png_get_user_height_max(png_ptr); + +The PNG specification sets no limit on the number of ancillary chunks +allowed in a PNG datastream. You can impose a limit on the total number +of sPLT, tEXt, iTXt, zTXt, and unknown chunks that will be stored, with + + png_set_chunk_cache_max(png_ptr, user_chunk_cache_max); + +where 0x7fffffffL means unlimited. You can retrieve this limit with + + chunk_cache_max = png_get_chunk_cache_max(png_ptr); + +This limit also applies to the number of buffers that can be allocated +by png_decompress_chunk() while decompressing iTXt, zTXt, and iCCP chunks. + +You can also set a limit on the amount of memory that a compressed chunk +other than IDAT can occupy, with + + png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); + +and you can retrieve the limit with + + chunk_malloc_max = png_get_chunk_malloc_max(png_ptr); + +Any chunks that would cause either of these limits to be exceeded will +be ignored. + +The high-level read interface + +At this point there are two ways to proceed; through the high-level +read interface, or through a sequence of low-level read operations. +You can use the high-level interface if (a) you are willing to read +the entire image into memory, and (b) the input transformations +you want to do are limited to the following set: + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to + 8 bits + PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel + PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit + samples to bytes + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_EXPAND Perform set_expand() + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_GRAY_TO_RGB Expand grayscale samples + to RGB (or GA to RGBA) + +(This excludes setting a background color, doing gamma transformation, +quantizing, and setting filler.) If this is the case, simply do this: + + png_read_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some +set of transformation flags. This call is equivalent to png_read_info(), +followed the set of transformations indicated by the transform mask, +then png_read_image(), and finally png_read_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future input transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_read_png(). + +After you have called png_read_png(), you can retrieve the image data +with + + row_pointers = png_get_rows(png_ptr, info_ptr); + +where row_pointers is an array of pointers to the pixel data for each row: + + png_bytep row_pointers[height]; + +If you know your image size and pixel size ahead of time, you can allocate +row_pointers prior to calling png_read_png() with + + if (height > PNG_UINT_32_MAX/png_sizeof(png_byte)) + png_error (png_ptr, + "Image is too tall to process in memory"); + + if (width > PNG_UINT_32_MAX/pixel_size) + png_error (png_ptr, + "Image is too wide to process in memory"); + + row_pointers = png_malloc(png_ptr, + height*png_sizeof(png_bytep)); + + for (int i=0; i) and +png_get_(png_ptr, info_ptr, ...) functions return non-zero if the +data has been read, or zero if it is missing. The parameters to the +png_get_ are set directly if they are simple data types, or a +pointer into the info_ptr is returned for any complex types. + + png_get_PLTE(png_ptr, info_ptr, &palette, + &num_palette); + + palette - the palette for the file + (array of png_color) + + num_palette - number of entries in the palette + + png_get_gAMA(png_ptr, info_ptr, &file_gamma); + png_get_gAMA_fixed(png_ptr, info_ptr, &int_file_gamma); + + file_gamma - the gamma at which the file is + written (PNG_INFO_gAMA) + + int_file_gamma - 100,000 times the gamma at which the + file is written + + png_get_sRGB(png_ptr, info_ptr, &srgb_intent); + + file_srgb_intent - the rendering intent (PNG_INFO_sRGB) + The presence of the sRGB chunk + means that the pixel data is in the + sRGB color space. This chunk also + implies specific values of gAMA and + cHRM. + + png_get_iCCP(png_ptr, info_ptr, &name, + &compression_type, &profile, &proflen); + + name - The profile name. + + compression_type - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + + profile - International Color Consortium color + profile data. May contain NULs. + + proflen - length of profile data in bytes. + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, + red, green, and blue channels, + whichever are appropriate for the + given color type (png_color_16) + + png_get_tRNS(png_ptr, info_ptr, &trans_alpha, + &num_trans, &trans_color); + + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + trans_color - graylevel or color sample values of + the single transparent color for + non-paletted images (PNG_INFO_tRNS) + + png_get_hIST(png_ptr, info_ptr, &hist); + (PNG_INFO_hIST) + + hist - histogram of palette (array of + png_uint_16) + + png_get_tIME(png_ptr, info_ptr, &mod_time); + + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_get_bKGD(png_ptr, info_ptr, &background); + + background - background color (PNG_VALID_bKGD) + valid 16-bit red, green and blue + values, regardless of color_type + + num_comments = png_get_text(png_ptr, info_ptr, + &text_ptr, &num_text); + + num_comments - number of comments + + text_ptr - array of png_text holding image + comments + + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + + text_ptr[i].text - text comments for current + keyword. Can be empty. + + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + + text_ptr[i].lang - language of comment (empty + string for unknown). + + text_ptr[i].lang_key - keyword in UTF-8 + (empty string for unknown). + + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist + when the library is built with iTXt chunk support. + + num_text - number of comments (same as + num_comments; you can put NULL here + to avoid the duplication) + + Note while png_set_text() will accept text, language, + and translated keywords that can be NULL pointers, the + structure returned by png_get_text will always contain + regular zero-terminated C strings. They might be + empty strings but they will never be NULL pointers. + + num_spalettes = png_get_sPLT(png_ptr, info_ptr, + &palette_ptr); + + num_spalettes - number of sPLT chunks read. + + palette_ptr - array of palette structures holding + contents of one or more sPLT chunks + read. + + png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, + &unit_type); + + offset_x - positive offset from the left edge + of the screen + + offset_y - positive offset from the top edge + of the screen + + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, + &unit_type); + + res_x - pixels/unit physical resolution in + x direction + + res_y - pixels/unit physical resolution in + x direction + + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_get_sCAL(png_ptr, info_ptr, &unit, &width, + &height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are doubles) + + png_get_sCAL_s(png_ptr, info_ptr, &unit, &width, + &height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + num_unknown_chunks = png_get_unknown_chunks(png_ptr, + info_ptr, &unknowns) + + unknowns - array of png_unknown_chunk + structures holding unknown chunks + + unknowns[i].name - name of unknown chunk + + unknowns[i].data - data of unknown chunk + + unknowns[i].size - size of unknown chunk's data + + unknowns[i].location - position of chunk in file + + The value of "i" corresponds to the order in which the + chunks were read from the PNG file or inserted with the + png_set_unknown_chunks() function. + +The data from the pHYs chunk can be retrieved in several convenient +forms: + + res_x = png_get_x_pixels_per_meter(png_ptr, + info_ptr) + + res_y = png_get_y_pixels_per_meter(png_ptr, + info_ptr) + + res_x_and_y = png_get_pixels_per_meter(png_ptr, + info_ptr) + + res_x = png_get_x_pixels_per_inch(png_ptr, + info_ptr) + + res_y = png_get_y_pixels_per_inch(png_ptr, + info_ptr) + + res_x_and_y = png_get_pixels_per_inch(png_ptr, + info_ptr) + + aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, + info_ptr) + + Each of these returns 0 [signifying "unknown"] if + the data is not present or if res_x is 0; + res_x_and_y is 0 if res_x != res_y + + Note that because of the way the resolutions are + stored internally, the inch conversions won't + come out to exactly even number. For example, + 72 dpi is stored as 0.28346 pixels/meter, and + when this is retrieved it is 71.9988 dpi, so + be sure to round the returned value appropriately + if you want to display a reasonable-looking result. + +The data from the oFFs chunk can be retrieved in several convenient +forms: + + x_offset = png_get_x_offset_microns(png_ptr, info_ptr); + + y_offset = png_get_y_offset_microns(png_ptr, info_ptr); + + x_offset = png_get_x_offset_inches(png_ptr, info_ptr); + + y_offset = png_get_y_offset_inches(png_ptr, info_ptr); + + Each of these returns 0 [signifying "unknown" if both + x and y are 0] if the data is not present or if the + chunk is present but the unit is the pixel. The + remark about inexact inch conversions applies here + as well, because a value in inches can't always be + converted to microns and back without some loss + of precision. + +For more information, see the png_info definition in png.h and the +PNG specification for chunk contents. Be careful with trusting +rowbytes, as some of the transformations could increase the space +needed to hold a row (expand, filler, gray_to_rgb, etc.). +See png_read_update_info(), below. + +A quick word about text_ptr and num_text. PNG stores comments in +keyword/text pairs, one pair per chunk, with no limit on the number +of text chunks, and a 2^31 byte limit on their size. While there are +suggested keywords, there is no requirement to restrict the use to these +strings. It is strongly suggested that keywords and text be sensible +to humans (that's the point), so don't use abbreviations. Non-printing +symbols are not allowed. See the PNG specification for more details. +There is also no requirement to have text after the keyword. + +Keywords should be limited to 79 Latin-1 characters without leading or +trailing spaces, but non-consecutive spaces are allowed within the +keyword. It is possible to have the same keyword any number of times. +The text_ptr is an array of png_text structures, each holding a +pointer to a language string, a pointer to a keyword and a pointer to +a text string. The text string, language code, and translated +keyword may be empty or NULL pointers. The keyword/text +pairs are put into the array in the order that they are received. +However, some or all of the text chunks may be after the image, so, to +make sure you have read all the text chunks, don't mess with these +until after you read the stuff after the image. This will be +mentioned again below in the discussion that goes with png_read_end(). + +Input transformations + +After you've read the header information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +The colors used for the background and transparency values should be +supplied in the same format/depth as the current image data. They +are stored in the same format/depth as the image data in a bKGD or tRNS +chunk, so this is what libpng expects for this data. The colors are +transformed to keep in sync with the image data when an application +calls the png_read_update_info() routine (see below). + +Data will be decoded into the supplied row buffers packed into bytes +unless the library has been told to transform it into another format. +For example, 4 bit/pixel paletted or grayscale data will be returned +2 pixels/byte with the leftmost pixel in the high-order bits of the +byte, unless png_set_packing() is called. 8-bit RGB data will be stored +in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() +is called to insert filler bytes, either before or after each RGB triplet. +16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant +byte of the color value first, unless png_set_strip_16() is called to +transform it to regular RGB RGB triplets, or png_set_filler() or +png_set_add alpha() is called to insert filler bytes, either before or +after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can +be modified with +png_set_filler(), png_set_add_alpha(), or png_set_strip_16(). + +The following code transforms grayscale images of less than 8 to 8 bits, +changes paletted images to RGB, and adds a full alpha channel if there is +transparency information in a tRNS chunk. This is most useful on +grayscale images with bit depths of 2 or 4 or if there is a multiple-image +viewing application that wishes to treat all images in the same way. + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY && + bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); + + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + +These three functions are actually aliases for png_set_expand(), added +in libpng version 1.0.4, with the function names expanded to improve code +readability. In some future version they may actually do different +things. + +As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was +added. It expands the sample depth without changing tRNS to alpha. + +As of libpng version 1.5.1, not all possible expansions are supported. + +In the following table, the 01 means grayscale with depth<8, 31 means +indexed with depth<8, other numerals represent the color type, "T" means +the tRNS chunk is present, A means an alpha channel is present, and O +means tRNS or alpha is present but all pixels in the image are opaque. + + FROM 01 31 0 0T 0O 2 2T 2O 3 3T 3O 4A 4O 6A 6O + TO + 01 - + 31 - + 0 1 - + 0T - + 0O - + 2 GX - + 2T - + 2O - + 3 1 - + 3T - + 3O - + 4A T - + 4O - + 6A GX TX TX - + 6O GX TX - + +Within the matrix, + "-" means the transformation is not supported. + "X" means the transformation is obtained by png_set_expand(). + "1" means the transformation is obtained by + png_set_expand_gray_1_2_4_to_8 + "G" means the transformation is obtained by + png_set_gray_to_rgb(). + "P" means the transformation is obtained by + png_set_expand_palette_to_rgb(). + "T" means the transformation is obtained by + png_set_tRNS_to_alpha(). + +PNG can have files with 16 bits per channel. If you only can handle +8 bits per channel, this will strip the pixels down to 8 bit. + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + +If, for some reason, you don't need the alpha channel on an image, +and you want to remove it rather than combining it with the background +(but the image author certainly had in mind that you *would* combine +it with the background, so that's what you should probably do): + + if (color_type & PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_ptr); + +In PNG files, the alpha channel in an image +is the level of opacity. If you need the alpha channel in an image to +be the level of transparency instead of opacity, you can invert the +alpha channel (or the tRNS chunk data) after it's read, so that 0 is +fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit +images) is fully transparent, with + + png_set_invert_alpha(png_ptr); + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit +files. This code expands to 1 pixel per byte without changing the +values of the pixels: + + if (bit_depth < 8) + png_set_packing(png_ptr); + +PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels +stored in a PNG image have been "scaled" or "shifted" up to the next +higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] +to 8 bits/sample in the range [0, 255]). However, it is also possible +to convert the PNG pixel data back to the original bit depth of the +image. This call reduces the pixels back down to the original bit depth: + + png_color_8p sig_bit; + + if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + png_set_shift(png_ptr, sig_bit); + +PNG files store 3-color pixels in red, green, blue order. This code +changes the storage of the pixels to blue, green, red: + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_bgr(png_ptr); + +PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them +into 4 or 8 bytes for windowing systems that need them in this format: + + if (color_type == PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); + +where "filler" is the 8 or 16-bit number to fill with, and the location is +either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether +you want the filler before the RGB or after. This transformation +does not affect images that already have full alpha channels. To add an +opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which +will generate RGBA pixels. + +Note that png_set_filler() does not change the color type. If you want +to do that, you can add a true alpha channel with + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY) + png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); + +where "filler" contains the alpha value to assign to each pixel. +This function was added in libpng-1.2.7. + +If you are reading an image with an alpha channel, and you need the +data as ARGB instead of the normal PNG format RGBA: + + if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_swap_alpha(png_ptr); + +For some uses, you may want a grayscale image to be represented as +RGB. This code will do that conversion: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + +Conversely, you can convert an RGB or RGBA image to grayscale or grayscale +with alpha. + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_rgb_to_gray_fixed(png_ptr, error_action, + int red_weight, int green_weight); + + error_action = 1: silently do the conversion + + error_action = 2: issue a warning if the original + image has any pixel where + red != green or red != blue + + error_action = 3: issue an error and abort the + conversion if the original + image has any pixel where + red != green or red != blue + + red_weight: weight of red component times 100000 + + green_weight: weight of green component times 100000 + If either weight is negative, default + weights (21268, 71514) are used. + +If you have set error_action = 1 or 2, you can +later check whether the image really was gray, after processing +the image rows, with the png_get_rgb_to_gray_status(png_ptr) function. +It will return a png_byte that is zero if the image was gray or +1 if there were any non-gray pixels. bKGD and sBIT data +will be silently converted to grayscale, using the green channel +data, regardless of the error_action setting. + +With red_weight+green_weight<=100000, +the normalized graylevel is computed: + + int rw = red_weight * 65536; + int gw = green_weight * 65536; + int bw = 65536 - (rw + gw); + gray = (rw*red + gw*green + bw*blue)/65536; + +The default values approximate those recommended in the Charles +Poynton's Color FAQ, +Copyright (c) 1998-01-04 Charles Poynton + + Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + +Libpng approximates this with integers scaled by 32768: + + Y = (6968 * R + 23434 * G + 2366 * B)/32768 + +The calculation is done in a linear colorspace, if the image gamma +can be determined. + +If you have a grayscale and you are using png_set_expand_depth(), +png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to +a higher bit-depth, you must either supply the background color as a gray +value at the original file bit-depth (need_expand = 1) or else supply the +background color as an RGB triplet at the final, expanded bit depth +(need_expand = 0). Similarly, if you are reading a paletted image, you +must either supply the background color as a palette index (need_expand = 1) +or as an RGB triplet that may or may not be in the palette (need_expand = 0). + + png_color_16 my_background; + png_color_16p image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + +The png_set_background() function tells libpng to composite images +with alpha or simple transparency against the supplied background +color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), +you may use this color, or supply another color more suitable for +the current display (e.g., the background color from a web page). You +need to tell libpng whether the color is in the gamma space of the +display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file +(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one +that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't +know why anyone would use this, but it's here). + +To properly display PNG images on any kind of system, the application needs +to know what the display gamma is. Ideally, the user will know this, and +the application will allow them to set it. One method of allowing the user +to set the display gamma separately for each system is to check for a +SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be +correctly set. + +Note that display_gamma is the overall gamma correction required to produce +pleasing results, which depends on the lighting conditions in the surrounding +environment. In a dim or brightly lit room, no compensation other than +the physical gamma exponent of the monitor is needed, while in a dark room +a slightly smaller exponent is better. + + double gamma, screen_gamma; + + if (/* We have a user-defined screen + gamma value */) + { + screen_gamma = user_defined_screen_gamma; + } + + /* One way that applications can share the same + screen gamma value */ + else if ((gamma_str = getenv("SCREEN_GAMMA")) + != NULL) + { + screen_gamma = (double)atof(gamma_str); + } + + /* If we don't have another value */ + else + { + screen_gamma = 2.2; /* A good guess for a + PC monitor in a bright office or a dim room */ + + screen_gamma = 2.0; /* A good guess for a + PC monitor in a dark room */ + + screen_gamma = 1.7 or 1.0; /* A good + guess for Mac systems */ + } + +The functions png_set_gamma() and its fixed point equivalent +png_set_gamma_fixed() handle gamma transformations of the data. +Pass both the file gamma and the current screen_gamma. If the file does +not have a gamma value, you can pass one anyway if you have an idea what +it is (usually 0.45455 is a good guess for GIF images on PCs). Note +that file gammas are inverted from screen gammas. See the discussions +on gamma in the PNG specification for an excellent description of what +gamma is, and why all applications should support it. It is strongly +recommended that PNG viewers support gamma correction. + + if (png_get_gAMA(png_ptr, info_ptr, &file_gamma)) + png_set_gamma(png_ptr, screen_gamma, file_gamma); + + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + +If you need to reduce an RGB file to a paletted file, or if a paletted +file has more entries then will fit on your screen, png_set_quantize() +will do that. Note that this is a simple match quantization that merely +finds the closest color available. This should work fairly well with +optimized palettes, but fairly badly with linear color cubes. If you +pass a palette that is larger then maximum_colors, the file will +reduce the number of colors in the palette so it will fit into +maximum_colors. If there is a histogram, it will use it to make +more intelligent choices when reducing the palette. If there is no +histogram, it may not do as good a job. + + if (color_type & PNG_COLOR_MASK_COLOR) + { + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_PLTE)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, + &histogram); + png_set_quantize(png_ptr, palette, num_palette, + max_screen_colors, histogram, 1); + } + + else + { + png_color std_color_cube[MAX_SCREEN_COLORS] = + { ... colors ... }; + + png_set_quantize(png_ptr, std_color_cube, + MAX_SCREEN_COLORS, MAX_SCREEN_COLORS, + NULL,0); + } + } + +PNG files describe monochrome as black being zero and white being one. +The following code will reverse this (make black be one and white be +zero): + + if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) + png_set_invert_mono(png_ptr); + +This function can also be used to invert grayscale and gray-alpha images: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_invert_mono(png_ptr); + +PNG files store 16 bit pixels in network byte order (big-endian, +ie. most significant bits first). This code changes the storage to the +other way (little-endian, i.e. least significant bits first, the +way PCs store them): + + if (bit_depth == 16) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_read_user_transform_fn(png_ptr, + read_transform_fn); + +You must supply the function + + void read_transform_fn(png_structp png_ptr, row_info_ptr + row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +after all of the other transformations have been processed. Take care with +interlaced images if you do the interlace yourself - the width of the row is the +width in 'row_info', not the overall image width. + +If supported libpng provides two information routines that you can use to find +where you are in processing the image: + + png_get_current_pass_number(png_structp png_ptr); + png_get_current_row_number(png_structp png_ptr); + +Don't try using these outside a transform callback - firstly they are only +supported if user transforms are supported, secondly they may well return +unexpected results unless the row is actually being processed at the moment they +are called. + +You can also set up a pointer to a user structure for use by your +callback function, and you can inform libpng that your transform +function will change the number of channels or bit depth with the +function + + png_set_user_transform_info(png_ptr, user_ptr, + user_depth, user_channels); + +The user's application, not libpng, is responsible for allocating and +freeing any memory required for the user structure. + +You can retrieve the pointer via the function +png_get_user_transform_ptr(). For example: + + voidp read_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +The last thing to handle is interlacing; this is covered in detail below, +but you must call the function here if you want libpng to handle expansion +of the interlaced image. + + number_of_passes = png_set_interlace_handling(png_ptr); + +After setting the transformations, libpng can update your png_info +structure to reflect any transformations you've requested with this +call. This is most useful to update the info structure's rowbytes +field so you can use it to allocate your image memory. This function +will also update your palette with the correct screen_gamma and +background if these have been given with the calls above. + + png_read_update_info(png_ptr, info_ptr); + +After you call png_read_update_info(), you can allocate any +memory you need to hold the image. The row data is simply +raw byte data for all forms of images. As the actual allocation +varies among applications, no example will be given. If you +are allocating one large chunk, you will need to build an +array of pointers to each row, as it will be needed for some +of the functions below. + +Remember: Before you call png_read_update_info(), the png_get_ +functions return the values corresponding to the original PNG image. +After you call png_read_update_info the values refer to the image +that libpng will output. Consequently you must call all the png_set_ +functions before you call png_read_update_info(). This is particularly +important for png_set_interlace_handling() - if you are going to call +png_read_update_info() you must call png_set_interlace_handling() before +it unless you want to receive interlaced output. + +Reading image data + +After you've allocated memory, you can read the image data. +The simplest way to do this is in one function call. If you are +allocating enough memory to hold the whole image, you can just +call png_read_image() and libpng will read in all the image data +and put it in the memory area supplied. You will need to pass in +an array of pointers to each row. + +This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() (unless you call +png_read_update_info()) or call this function multiple times, or any +of that other stuff necessary with png_read_rows(). + + png_read_image(png_ptr, row_pointers); + +where row_pointers is: + + png_bytep row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to read in the whole image at once, you can +use png_read_rows() instead. If there is no interlacing (check +interlace_type == PNG_INTERLACE_NONE), this is simple: + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +where row_pointers is the same as in the png_read_image() call. + +If you are doing this just one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + png_read_row(png_ptr, row_pointer, NULL); + +If the file is interlaced (interlace_type != 0 in the IHDR chunk), things +get somewhat harder. The only current (PNG Specification version 1.2) +interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7); +a somewhat complicated 2D interlace scheme, known as Adam7, that +breaks down an image into seven smaller images of varying size, based +on an 8x8 grid. This number is defined (from libpng 1.5) as +PNG_INTERLACE_ADAM7_PASSES in png.h + +libpng can fill out those images or it can give them to you "as is". +It is almost always better to have libpng handle the interlacing for you. +If you want the images filled out, there are two ways to do that. The one +mentioned in the PNG specification is to expand each pixel to cover +those pixels that have not been read yet (the "rectangle" method). +This results in a blocky image for the first pass, which gradually +smooths out as more pixels are read. The other method is the "sparkle" +method, where pixels are drawn only in their final locations, with the +rest of the image remaining whatever colors they were initialized to +before the start of the read. The first method usually looks better, +but tends to be slower, as there are more pixels to put in the rows. + +If, as is likely, you want libpng to expand the images, call this before +calling png_start_read_image() or png_read_update_info(): + + if (interlace_type == PNG_INTERLACE_ADAM7) + number_of_passes + = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this is seven, +but may change if another interlace type is added. This function can be +called even if the file is not interlaced, where it will return one pass. +You then need to read the whole image 'number_of_passes' times. Each time +will distribute the pixels from the current pass to the correct place in +the output image, so you need to supply the same rows to png_read_rows in +each pass. + +If you are not going to display the image after each pass, but are +going to wait until the entire image is read in, use the sparkle +effect. This effect is faster and the end result of either method +is exactly the same. If you are planning on displaying the image +after each pass, the "rectangle" effect is generally considered the +better looking one. + +If you only want the "sparkle" effect, just call png_read_rows() as +normal, with the third parameter NULL. Make sure you make pass over +the image number_of_passes times, and you don't change the data in the +rows between calls. You can change the locations of the data, just +not the data. Each pass only writes the pixels appropriate for that +pass, and assumes the data from previous passes is still valid. + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +If you only want the first effect (the rectangles), do the same as +before except pass the row buffer in the third parameter, and leave +the second parameter NULL. + + png_read_rows(png_ptr, NULL, row_pointers, + number_of_rows); + +If you don't want libpng to handle the interlacing details, just call +png_read_rows() PNG_INTERLACE_ADAM7_PASSES times to read in all the images. +Each of the images is a valid image by itself, however you will almost +certainly need to distribute the pixels from each sub-image to the +correct place. This is where everything gets very tricky. + +If you want to retrieve the separate images you must pass the correct +number of rows to each successive call of png_read_rows(). The calculation +gets pretty complicated for small images, where some sub-images may +not even exist because either their width or height ends up zero. +libpng provides two macros to help you in 1.5 and later versions: + + png_uint_32 width = PNG_PASS_COLS(image_width, pass_number); + png_uint_32 height = PNG_PASS_ROWS(image_height, pass_number); + +Respectively these tell you the width and height of the sub-image +corresponding to the numbered pass. 'pass' is in in the range 0 to 6 - +this can be confusing because the specification refers to the same passes +as 1 to 7! Be careful, you must check both the width and height before +calling png_read_rows() and not call it for that pass if either is zero. + +You can, of course, read each sub-image row by row. If you want to +produce optimal code to make a pixel-by-pixel transformation of an +interlaced image this is the best approach; read each row of each pass, +transform it, and write it out to a new interlaced image. + +If you want to de-interlace the image yourself libpng provides further +macros to help that tell you where to place the pixels in the output image. +Because the interlacing scheme is rectangular - sub-image pixels are always +arranged on a rectangular grid - all you need to know for each pass is the +starting column and row in the output image of the first pixel plus the +spacing between each pixel. As of libpng 1.5 there are four macros to +retrieve this information: + + png_uint_32 x = PNG_PASS_START_COL(pass); + png_uint_32 y = PNG_PASS_START_ROW(pass); + png_uint_32 xStep = 1U << PNG_PASS_COL_SHIFT(pass); + png_uint_32 yStep = 1U << PNG_PASS_ROW_SHIFT(pass); + +These allow you to write the obvious loop: + + png_uint_32 input_y = 0; + png_uint_32 output_y = PNG_PASS_START_ROW(pass); + + while (output_y < output_image_height) + { + png_uint_32 input_x = 0; + png_uint_32 output_x = PNG_PASS_START_COL(pass); + + while (output_x < output_image_width) + { + image[output_y][output_x] = + subimage[pass][input_y][input_x++]; + + output_x += xStep; + } + + ++input_y; + output_y += yStep; + } + +Notice that the steps between successive output rows and columns are +returned as shifts. This is possible because the pixels in the subimages +are always a power of 2 apart - 1, 2, 4 or 8 pixels - in the original +image. In practice you may need to directly calculate the output coordinate +given an input coordinate. libpng provides two further macros for this +purpose: + + png_uint_32 output_x = PNG_COL_FROM_PASS_COL(input_x, pass); + png_uint_32 output_y = PNG_ROW_FROM_PASS_ROW(input_y, pass); + +Finally a pair of macros are provided to tell you if a particular image +row or column appears in a given pass: + + int col_in_pass = PNG_COL_IN_INTERLACE_PASS(output_x, pass); + int row_in_pass = PNG_ROW_IN_INTERLACE_PASS(output_y, pass); + +Bear in mind that you will probably also need to check the width and height +of the pass in addition to the above to be sure the pass even exists! + +With any luck you are convinced by now that you don't want to do your own +interlace handling. In reality normally the only good reason for doing this +is if you are processing PNG files on a pixel-by-pixel basis and don't want +to load the whole file into memory when it is interlaced. + +libpng includes a test program, pngvalid, that illustrates reading and +writing of interlaced images. If you can't get interlacing to work in your +code and don't want to leave it to libpng (the recommended approach) see +how pngvalid.c does it. + +Finishing a sequential read + +After you are finished reading the image through the +low-level interface, you can finish reading the file. If you are +interested in comments or time, which may be stored either before or +after the image data, you should pass the separate png_info struct if +you want to keep the comments from before and after the image +separate. If you are not interested, you can pass NULL. + + png_read_end(png_ptr, end_info); + +When you are done, you can free all memory allocated by libpng like this: + + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not -1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + + mask - which data elements are affected + same choices as in png_free_data() + +This function only affects data that has already been allocated. +You can call this function after reading the PNG data but before calling +any png_set_*() functions, to control whether the user or the png_set_*() +function is responsible for freeing any existing data that might be present, +and again after the png_set_*() functions to control whether the user +or png_destroy_*() is supposed to free the data. When the user assumes +responsibility for libpng-allocated data, the application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated your row_pointers in a single block, as suggested above in +the description of the high level read interface, you must not transfer +responsibility for freeing it to the png_set_rows or png_read_destroy function, +because they would also try to free the individual row_pointers[i]. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. + +The png_free_data() function will turn off the "valid" flag for anything +it frees. If you need to turn the flag off for a chunk that was freed by +your application instead of by libpng, you can use + + png_set_invalid(png_ptr, info_ptr, mask); + + mask - identifies the chunks to be made invalid, + containing the bitwise OR of one or + more of + PNG_INFO_gAMA, PNG_INFO_sBIT, + PNG_INFO_cHRM, PNG_INFO_PLTE, + PNG_INFO_tRNS, PNG_INFO_bKGD, + PNG_INFO_hIST, PNG_INFO_pHYs, + PNG_INFO_oFFs, PNG_INFO_tIME, + PNG_INFO_pCAL, PNG_INFO_sRGB, + PNG_INFO_iCCP, PNG_INFO_sPLT, + PNG_INFO_sCAL, PNG_INFO_IDAT + +For a more compact example of reading a PNG image, see the file example.c. + +Reading PNG files progressively + +The progressive reader is slightly different then the non-progressive +reader. Instead of calling png_read_info(), png_read_rows(), and +png_read_end(), you make one call to png_process_data(), which calls +callbacks when it has the info, a row, or the end of the image. You +set up these callbacks with png_set_progressive_read_fn(). You don't +have to worry about the input/output functions of libpng, as you are +giving the library the data directly in png_process_data(). I will +assume that you have read the section on reading PNG files above, +so I will only highlight the differences (although I will show +all of the code). + +png_structp png_ptr; +png_infop info_ptr; + + /* An example code fragment of how you would + initialize the progressive reader in your + application. */ + int + initialize_png_reader() + { + png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return (ERROR); + + info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return (ERROR); + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new. You can provide functions + to be called when the header info is valid, + when each row is completed, and when the image + is finished. If you aren't using all functions, + you can specify NULL parameters. Even when all + three functions are NULL, you need to call + png_set_progressive_read_fn(). You can use + any struct as the user_ptr (cast to a void pointer + for the function call), and retrieve the pointer + from inside the callbacks using the function + + png_get_progressive_ptr(png_ptr); + + which will return a void pointer, which you have + to cast appropriately. + */ + png_set_progressive_read_fn(png_ptr, (void *)user_ptr, + info_callback, row_callback, end_callback); + + return 0; + } + + /* A code fragment that you call as you receive blocks + of data */ + int + process_data(png_bytep buffer, png_uint_32 length) + { + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new also. Simply give it a chunk + of data from the file stream (in order, of + course). On machines with segmented memory + models machines, don't give it any more than + 64K. The library seems to run fine with sizes + of 4K. Although you can give it much less if + necessary (I assume you can give it chunks of + 1 byte, I haven't tried less then 256 bytes + yet). When this function returns, you may + want to display any rows that were generated + in the row callback if you don't already do + so there. + */ + png_process_data(png_ptr, info_ptr, buffer, length); + + /* At this point you can call png_process_data_skip if + you want to handle data the library will skip yourself; + it simply returns the number of bytes to skip (and stops + libpng skipping that number of bytes on the next + png_process_data call). + return 0; + } + + /* This function is called (as set by + png_set_progressive_read_fn() above) when enough data + has been supplied so all of the header has been + read. + */ + void + info_callback(png_structp png_ptr, png_infop info) + { + /* Do any setup here, including setting any of + the transformations mentioned in the Reading + PNG files section. For now, you _must_ call + either png_start_read_image() or + png_read_update_info() after all the + transformations are set (even if you don't set + any). You may start getting rows before + png_process_data() returns, so this is your + last chance to prepare for that. + + This is where you turn on interlace handling, + assuming you don't want to do it yourself. + + If you need to you can stop the processing of + your original input data at this point by calling + png_process_data_pause. This returns the number + of unprocessed bytes from the last png_process_data + call - it is up to you to ensure that the next call + sees these bytes again. If you don't want to bother + with this you can get libpng to cache the unread + bytes by setting the 'save' parameter (see png.h) but + then libpng will have to copy the data internally. + */ + } + + /* This function is called when each row of image + data is complete */ + void + row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) + { + /* If the image is interlaced, and you turned + on the interlace handler, this function will + be called for every row in every pass. Some + of these rows will not be changed from the + previous pass. When the row is not changed, + the new_row variable will be NULL. The rows + and passes are called in order, so you don't + really need the row_num and pass, but I'm + supplying them because it may make your life + easier. + + If you did not turn on interlace handling then + the callback is called for each row of each + sub-image when the image is interlaced. In this + case 'row_num' is the row in the sub-image, not + the row in the output image as it is in all other + cases. + + For the non-NULL rows of interlaced images when + you have switched on libpng interlace handling, + you must call png_progressive_combine_row() + passing in the row and the old row. You can + call this function for NULL rows (it will just + return) and for non-interlaced images (it just + does the memcpy for you) if it will make the + code easier. Thus, you can just do this for + all cases if you switch on interlace handling; + */ + + png_progressive_combine_row(png_ptr, old_row, + new_row); + + /* where old_row is what was displayed for + previously for the row. Note that the first + pass (pass == 0, really) will completely cover + the old row, so the rows do not have to be + initialized. After the first pass (and only + for interlaced images), you will have to pass + the current row, and the function will combine + the old row and the new row. + + You can also call png_process_data_pause in this + callback - see above. + */ + } + + void + end_callback(png_structp png_ptr, png_infop info) + { + /* This function is called after the whole image + has been read, including any chunks after the + image (up to and including the IEND). You + will usually have the same info chunk as you + had in the header, although some data may have + been added to the comments and time fields. + + Most people won't do much here, perhaps setting + a flag that marks the image as finished. + */ + } + + + +IV. Writing + +Much of this is very similar to reading. However, everything of +importance is repeated here, so you won't have to constantly look +back up in the reading section to understand writing. + +Setup + +You will want to do the I/O initialization before you get into libpng, +so if it doesn't work, you don't have anything to undo. If you are not +using the standard I/O functions, you will need to replace them with +custom writing functions. See the discussion under Customizing libpng. + + FILE *fp = fopen(file_name, "wb"); + + if (!fp) + return (ERROR); + +Next, png_struct and png_info need to be allocated and initialized. +As these can be both relatively large, you may not want to store these +on the stack, unless you have stack space to spare. Of course, you +will want to check if they return NULL. If you are also reading, +you won't want to name your read structure and your write structure +both "png_ptr"; you can call them anything you like, such as +"read_ptr" and "write_ptr". Look at pngtest.c, for example. + + png_structp png_ptr = png_create_write_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_write_struct_2() instead of png_create_write_struct(): + + png_structp png_ptr = png_create_write_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +After you have these structures, you will need to set up the +error handling. When libpng encounters an error, it expects to +longjmp() back to your routine. Therefore, you will need to call +setjmp() and pass the png_jmpbuf(png_ptr). If you +write the file from different routines, you will need to update +the png_jmpbuf(png_ptr) every time you enter a new routine that will +call a png_*() function. See your documentation of setjmp/longjmp +for your compiler for more information on setjmp/longjmp. See +the discussion on libpng error handling in the Customizing Libpng +section below for more information on the libpng error handling. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + return (ERROR); + } + ... + return; + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_NO_SETJMP, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +Now you need to set up the output code. The default for libpng is to +use the C function fwrite(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. Again, if you wish to handle writing data in +another way, see the discussion on libpng I/O handling in the Customizing +Libpng section below. + + png_init_io(png_ptr, fp); + +If you are embedding your PNG into a datastream such as MNG, and don't +want libpng to write the 8-byte signature, or if you have already +written the signature in your application, use + + png_set_sig_bytes(png_ptr, 8); + +to inform libpng that it should not write a signature. + +Write callbacks + +At this point, you can set up a callback function that will be +called after each row has been written, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void write_row_callback(png_structp png_ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "write_row_callback") + +To inform libpng about your function, use + + png_set_write_status_fn(png_ptr, write_row_callback); + +You now have the option of modifying how the compression library will +run. The following functions are mainly for testing, but may be useful +in some cases, like if you need to write PNG files extremely fast and +are willing to give up some compression, or if you want to get the +maximum possible compression at the expense of slower writing. If you +have no special needs in this area, let the library do what it wants by +not calling this function at all, as it has been tuned to deliver a good +speed/compression ratio. The second parameter to png_set_filter() is +the filter method, for which the only valid values are 0 (as of the +July 1999 PNG specification, version 1.2) or 64 (if you are writing +a PNG datastream that is to be embedded in a MNG datastream). The third +parameter is a flag that indicates which filter type(s) are to be tested +for each scanline. See the PNG specification for details on the specific +filter types. + + + /* turn on or off filtering, and/or choose + specific filters. You can use either a single + PNG_FILTER_VALUE_NAME or the bitwise OR of one + or more PNG_FILTER_NAME masks. + */ + png_set_filter(png_ptr, 0, + PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | + PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | + PNG_FILTER_UP | PNG_FILTER_VALUE_UP | + PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | + PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| + PNG_ALL_FILTERS); + +If an application wants to start and stop using particular filters during +compression, it should start out with all of the filters (to ensure that +the previous row of pixels will be stored in case it's needed later), +and then add and remove them after the start of compression. + +If you are writing a PNG datastream that is to be embedded in a MNG +datastream, the second parameter can be either 0 or 64. + +The png_set_compression_*() functions interface to the zlib compression +library, and should mostly be ignored unless you really know what you are +doing. The only generally useful call is png_set_compression_level() +which changes how much time zlib spends on trying to compress the image +data. See the Compression Library (zlib.h and algorithm.txt, distributed +with zlib) for details on the compression levels. + + /* set the zlib compression level */ + png_set_compression_level(png_ptr, + Z_BEST_COMPRESSION); + + /* set other zlib parameters */ + png_set_compression_mem_level(png_ptr, 8); + png_set_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_compression_window_bits(png_ptr, 15); + png_set_compression_method(png_ptr, 8); + png_set_compression_buffer_size(png_ptr, 8192) + +extern PNG_EXPORT(void,png_set_zbuf_size) + +Setting the contents of info for output + +You now need to fill in the png_info structure with all the data you +wish to write before the actual image. Note that the only thing you +are allowed to write after the image is the text chunks and the time +chunk (as of PNG Specification 1.2, anyway). See png_write_end() and +the latest PNG specification for more information on that. If you +wish to write them before the image, fill them in now, and flag that +data as being valid. If you want to wait until after the data, don't +fill them until png_write_end(). For all the fields in png_info and +their data types, see png.h. For explanations of what the fields +contain, see the PNG specification. + +Some of the more important parts of the png_info are: + + png_set_IHDR(png_ptr, info_ptr, width, height, + bit_depth, color_type, interlace_type, + compression_type, filter_method) + + width - holds the width of the image + in pixels (up to 2^31). + + height - holds the height of the image + in pixels (up to 2^31). + + bit_depth - holds the bit depth of one of the + image channels. + (valid values are 1, 2, 4, 8, 16 + and depend also on the + color_type. See also significant + bits (sBIT) below). + + color_type - describes which color/alpha + channels are present. + PNG_COLOR_TYPE_GRAY + (bit depths 1, 2, 4, 8, 16) + PNG_COLOR_TYPE_GRAY_ALPHA + (bit depths 8, 16) + PNG_COLOR_TYPE_PALETTE + (bit depths 1, 2, 4, 8) + PNG_COLOR_TYPE_RGB + (bit_depths 8, 16) + PNG_COLOR_TYPE_RGB_ALPHA + (bit_depths 8, 16) + + PNG_COLOR_MASK_PALETTE + PNG_COLOR_MASK_COLOR + PNG_COLOR_MASK_ALPHA + + interlace_type - PNG_INTERLACE_NONE or + PNG_INTERLACE_ADAM7 + + compression_type - (must be + PNG_COMPRESSION_TYPE_DEFAULT) + + filter_method - (must be PNG_FILTER_TYPE_DEFAULT + or, if you are writing a PNG to + be embedded in a MNG datastream, + can also be + PNG_INTRAPIXEL_DIFFERENCING) + +If you call png_set_IHDR(), the call must appear before any of the +other png_set_*() functions, because they might require access to some of +the IHDR settings. The remaining png_set_*() functions can be called +in any order. + +If you wish, you can reset the compression_type, interlace_type, or +filter_method later by calling png_set_IHDR() again; if you do this, the +width, height, bit_depth, and color_type must be the same in each call. + + png_set_PLTE(png_ptr, info_ptr, palette, + num_palette); + + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + png_set_gAMA(png_ptr, info_ptr, file_gamma); + png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); + + file_gamma - the gamma at which the image was + created (PNG_INFO_gAMA) + + int_file_gamma - 100,000 times the gamma at which + the image was created + + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of + the sRGB chunk means that the pixel + data is in the sRGB color space. + This chunk also implies specific + values of gAMA and cHRM. Rendering + intent is the CSS-1 property that + has been defined by the International + Color Consortium + (http://www.color.org). + It can be one of + PNG_sRGB_INTENT_SATURATION, + PNG_sRGB_INTENT_PERCEPTUAL, + PNG_sRGB_INTENT_ABSOLUTE, or + PNG_sRGB_INTENT_RELATIVE. + + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, + srgb_intent); + + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of the + sRGB chunk means that the pixel + data is in the sRGB color space. + This function also causes gAMA and + cHRM chunks with the specific values + that are consistent with sRGB to be + written. + + png_set_iCCP(png_ptr, info_ptr, name, compression_type, + profile, proflen); + + name - The profile name. + + compression_type - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + + profile - International Color Consortium color + profile data. May contain NULs. + + proflen - length of profile data in bytes. + + png_set_sBIT(png_ptr, info_ptr, sig_bit); + + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, red, + green, and blue channels, whichever are + appropriate for the given color type + (png_color_16) + + png_set_tRNS(png_ptr, info_ptr, trans_alpha, + num_trans, trans_color); + + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + + trans_color - graylevel or color sample values + (in order red, green, blue) of the + single transparent color for + non-paletted images (PNG_INFO_tRNS) + + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + png_set_hIST(png_ptr, info_ptr, hist); + + hist - histogram of palette (array of + png_uint_16) (PNG_INFO_hIST) + + png_set_tIME(png_ptr, info_ptr, mod_time); + + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_set_bKGD(png_ptr, info_ptr, background); + + background - background color (PNG_VALID_bKGD) + + png_set_text(png_ptr, info_ptr, text_ptr, num_text); + + text_ptr - array of png_text holding image + comments + + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be NULL or empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (NULL or + empty for unknown). + text_ptr[i].translated_keyword - keyword in UTF-8 (NULL + or empty for unknown). + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist + when the library is built with iTXt chunk support. + + num_text - number of comments + + png_set_sPLT(png_ptr, info_ptr, &palette_ptr, + num_spalettes); + + palette_ptr - array of png_sPLT_struct structures + to be added to the list of palettes + in the info structure. + num_spalettes - number of palette structures to be + added. + + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, + unit_type); + + offset_x - positive offset from the left + edge of the screen + + offset_y - positive offset from the top + edge of the screen + + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, + unit_type); + + res_x - pixels/unit physical resolution + in x direction + + res_y - pixels/unit physical resolution + in y direction + + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_set_sCAL(png_ptr, info_ptr, unit, width, height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are doubles) + + png_set_sCAL_s(png_ptr, info_ptr, unit, width, height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + png_set_unknown_chunks(png_ptr, info_ptr, &unknowns, + num_unknowns) + + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position to write chunk in file + 0: do not write chunk + PNG_HAVE_IHDR: before PLTE + PNG_HAVE_PLTE: before IDAT + PNG_AFTER_IDAT: after IDAT + +The "location" member is set automatically according to +what part of the output file has already been written. +You can change its value after calling png_set_unknown_chunks() +as demonstrated in pngtest.c. Within each of the "locations", +the chunks are sequenced according to their position in the +structure (that is, the value of "i", which is the order in which +the chunk was either read from the input file or defined with +png_set_unknown_chunks). + +A quick word about text and num_text. text is an array of png_text +structures. num_text is the number of valid structures in the array. +Each png_text structure holds a language code, a keyword, a text value, +and a compression type. + +The compression types have the same valid numbers as the compression +types of the image data. Currently, the only valid number is zero. +However, you can store text either compressed or uncompressed, unlike +images, which always have to be compressed. So if you don't want the +text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE. +Because tEXt and zTXt chunks don't have a language field, if you +specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt +any language code or translated keyword will not be written out. + +Until text gets around 1000 bytes, it is not worth compressing it. +After the text has been written out to the file, the compression type +is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR, +so that it isn't written out again at the end (in case you are calling +png_write_end() with the same struct). + +The keywords that are given in the PNG Specification are: + + Title Short (one line) title or + caption for image + + Author Name of image's creator + + Description Description of image (possibly long) + + Copyright Copyright notice + + Creation Time Time of original image creation + (usually RFC 1123 format, see below) + + Software Software used to create the image + + Disclaimer Legal disclaimer + + Warning Warning of nature of content + + Source Device used to create the image + + Comment Miscellaneous comment; conversion + from other image format + +The keyword-text pairs work like this. Keywords should be short +simple descriptions of what the comment is about. Some typical +keywords are found in the PNG specification, as is some recommendations +on keywords. You can repeat keywords in a file. You can even write +some text before the image and some after. For example, you may want +to put a description of the image before the image, but leave the +disclaimer until after, so viewers working over modem connections +don't have to wait for the disclaimer to go over the modem before +they start seeing the image. Finally, keywords should be full +words, not abbreviations. Keywords and text are in the ISO 8859-1 +(Latin-1) character set (a superset of regular ASCII) and can not +contain NUL characters, and should not contain control or other +unprintable characters. To make the comments widely readable, stick +with basic ASCII, and avoid machine specific character set extensions +like the IBM-PC character set. The keyword must be present, but +you can leave off the text string on non-compressed pairs. +Compressed pairs must have a text string, as only the text string +is compressed anyway, so the compression would be meaningless. + +PNG supports modification time via the png_time structure. Two +conversion routines are provided, png_convert_from_time_t() for +time_t and png_convert_from_struct_tm() for struct tm. The +time_t routine uses gmtime(). You don't have to use either of +these, but if you wish to fill in the png_time structure directly, +you should provide the time in universal time (GMT) if possible +instead of your local time. Note that the year number is the full +year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and +that months start with 1. + +If you want to store the time of the original image creation, you should +use a plain tEXt chunk with the "Creation Time" keyword. This is +necessary because the "creation time" of a PNG image is somewhat vague, +depending on whether you mean the PNG file, the time the image was +created in a non-PNG format, a still photo from which the image was +scanned, or possibly the subject matter itself. In order to facilitate +machine-readable dates, it is recommended that the "Creation Time" +tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"), +although this isn't a requirement. Unlike the tIME chunk, the +"Creation Time" tEXt chunk is not expected to be automatically changed +by the software. To facilitate the use of RFC 1123 dates, a function +png_convert_to_rfc1123(png_timep) is provided to convert from PNG +time to an RFC 1123 format string. + +Writing unknown chunks + +You can use the png_set_unknown_chunks function to queue up chunks +for writing. You give it a chunk name, raw data, and a size; that's +all there is to it. The chunks will be written by the next following +png_write_info_before_PLTE, png_write_info, or png_write_end function. +Any chunks previously read into the info structure's unknown-chunk +list will also be written out in a sequence that satisfies the PNG +specification's ordering rules. + +The high-level write interface + +At this point there are two ways to proceed; through the high-level +write interface, or through a sequence of low-level write operations. +You can use the high-level interface if your image data is present +in the info structure. All defined output +transformations are permitted, enabled by the following masks. + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_STRIP_FILLER Strip out filler + bytes (deprecated). + PNG_TRANSFORM_STRIP_FILLER_BEFORE Strip out leading + filler bytes + PNG_TRANSFORM_STRIP_FILLER_AFTER Strip out trailing + filler bytes + +If you have valid image data in the info structure (you can use +png_set_rows() to put image data in the info structure), simply do this: + + png_write_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some set of +transformation flags. This call is equivalent to png_write_info(), +followed the set of transformations indicated by the transform mask, +then png_write_image(), and finally png_write_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future output transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_write_png(). + +The low-level write interface + +If you are going the low-level route instead, you are now ready to +write all the file information up to the actual image data. You do +this with a call to png_write_info(). + + png_write_info(png_ptr, info_ptr); + +Note that there is one transformation you may need to do before +png_write_info(). In PNG files, the alpha channel in an image is the +level of opacity. If your data is supplied as a level of transparency, +you can invert the alpha channel before you write it, so that 0 is +fully transparent and 255 (in 8-bit or paletted images) or 65535 +(in 16-bit images) is fully opaque, with + + png_set_invert_alpha(png_ptr); + +This must appear before png_write_info() instead of later with the +other transformations because in the case of paletted images the tRNS +chunk data has to be inverted before the tRNS chunk is written. If +your image is not a paletted image, the tRNS data (which in such cases +represents a single color to be rendered as transparent) won't need to +be changed, and you can safely do this transformation after your +png_write_info() call. + +If you need to write a private chunk that you want to appear before +the PLTE chunk when PLTE is present, you can write the PNG info in +two steps, and insert code to write your own chunk between them: + + png_write_info_before_PLTE(png_ptr, info_ptr); + png_set_unknown_chunks(png_ptr, info_ptr, ...); + png_write_info(png_ptr, info_ptr); + +After you've written the file information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +PNG files store RGB pixels packed into 3 or 6 bytes. This code tells +the library to strip input data that has 4 or 8 bytes per pixel down +to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2 +bytes per pixel). + + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + +where the 0 is unused, and the location is either PNG_FILLER_BEFORE or +PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel +is stored XRGB or RGBX. + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit files. +If the data is supplied at 1 pixel per byte, use this code, which will +correctly pack the pixels into a single byte: + + png_set_packing(png_ptr); + +PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your +data is of another bit depth, you can write an sBIT chunk into the +file so that decoders can recover the original data if desired. + + /* Set the true bit depth of the image data */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit.red = true_bit_depth; + sig_bit.green = true_bit_depth; + sig_bit.blue = true_bit_depth; + } + + else + { + sig_bit.gray = true_bit_depth; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + sig_bit.alpha = true_bit_depth; + } + + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + +If the data is stored in the row buffer in a bit depth other than +one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG), +this will scale the values to appear to be the correct bit depth as +is required by PNG. + + png_set_shift(png_ptr, &sig_bit); + +PNG files store 16 bit pixels in network byte order (big-endian, +ie. most significant bits first). This code would be used if they are +supplied the other way (little-endian, i.e. least significant bits +first, the way PCs store them): + + if (bit_depth > 8) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +PNG files store 3 color pixels in red, green, blue order. This code +would be used if they are supplied as blue, green, red: + + png_set_bgr(png_ptr); + +PNG files describe monochrome as black being zero and white being +one. This code would be used if the pixels are supplied with this reversed +(black being one and white being zero): + + png_set_invert_mono(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_write_user_transform_fn(png_ptr, + write_transform_fn); + +You must supply the function + + void write_transform_fn(png_structp png_ptr ptr, + row_info_ptr row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +before any of the other transformations are processed. If supported +libpng also supplies an information routine that may be called from +your callback: + + png_get_current_row_number(png_ptr); + +This returns the current row passed to the transform. Even with interlaced +images the value returned is the row in the final output image. + +You can also set up a pointer to a user structure for use by your +callback function. + + png_set_user_transform_info(png_ptr, user_ptr, 0, 0); + +The user_channels and user_depth parameters of this function are ignored +when writing; you can set them to zero as shown. + +You can retrieve the pointer via the function png_get_user_transform_ptr(). +For example: + + voidp write_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +It is possible to have libpng flush any pending output, either manually, +or automatically after a certain number of lines have been written. To +flush the output stream a single time call: + + png_write_flush(png_ptr); + +and to have libpng flush the output stream periodically after a certain +number of scanlines have been written, call: + + png_set_flush(png_ptr, nrows); + +Note that the distance between rows is from the last time png_write_flush() +was called, or the first row of the image if it has never been called. +So if you write 50 lines, and then png_set_flush 25, it will flush the +output on the next scanline, and every 25 lines thereafter, unless +png_write_flush() is called before 25 more lines have been written. +If nrows is too small (less than about 10 lines for a 640 pixel wide +RGB image) the image compression may decrease noticeably (although this +may be acceptable for real-time applications). Infrequent flushing will +only degrade the compression performance by a few percent over images +that do not use flushing. + +Writing the image data + +That's it for the transformations. Now you can write the image data. +The simplest way to do this is in one function call. If you have the +whole image in memory, you can just call png_write_image() and libpng +will write the image. You will need to pass in an array of pointers to +each row. This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_write_rows(). + + png_write_image(png_ptr, row_pointers); + +where row_pointers is: + + png_byte *row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to write the whole image at once, you can +use png_write_rows() instead. If the file is not interlaced, +this is simple: + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +row_pointers is the same as in the png_write_image() call. + +If you are just writing one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + + png_write_row(png_ptr, row_pointer); + +When the file is interlaced, things can get a good deal more complicated. +The only currently (as of the PNG Specification version 1.2, dated July +1999) defined interlacing scheme for PNG files is the "Adam7" interlace +scheme, that breaks down an image into seven smaller images of varying +size. libpng will build these images for you, or you can do them +yourself. If you want to build them yourself, see the PNG specification +for details of which pixels to write when. + +If you don't want libpng to handle the interlacing details, just +use png_set_interlace_handling() and call png_write_rows() the +correct number of times to write all the sub-images +(png_set_interlace_handling() returns the number of sub-images.) + +If you want libpng to build the sub-images, call this before you start +writing any rows: + + number_of_passes = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this is seven, +but may change if another interlace type is added. + +Then write the complete image number_of_passes times. + + png_write_rows(png_ptr, row_pointers, number_of_rows); + +Think carefully before you write an interlaced image. Typically code that +reads such images reads all the image data into memory, uncompressed, before +doing any processing. Only code that can display an image on the fly can +take advantage of the interlacing and even then the image has to be exactly +the correct size for the output device, because scaling an image requires +adjacent pixels and these are not available until all the passes have been +read. + +If you do write an interlaced image you will hardly ever need to handle +the interlacing yourself. Call png_set_interlace_handling() and use the +approach described above. + +The only time it is conceivable that you will really need to write an +interlaced image pass-by-pass is when you have read one pass by pass and +made some pixel-by-pixel transformation to it, as described in the read +code above. In this case use the PNG_PASS_ROWS and PNG_PASS_COLS macros +to determine the size of each sub-image in turn and simply write the rows +you obtained from the read code. + +Finishing a sequential write + +After you are finished writing the image, you should finish writing +the file. If you are interested in writing comments or time, you should +pass an appropriately filled png_info pointer. If you are not interested, +you can pass NULL. + + png_write_end(png_ptr, info_ptr); + +When you are done, you can free all memory used by libpng like this: + + png_destroy_write_struct(&png_ptr, &info_ptr); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not -1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +If you allocated data such as a palette that you passed in to libpng +with png_set_*, you must not free it until just before the call to +png_destroy_write_struct(). + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + + mask - which data elements are affected + same choices as in png_free_data() + +For example, to transfer responsibility for some data from a read structure +to a write structure, you could use + + png_data_freer(read_ptr, read_info_ptr, + PNG_USER_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + + png_data_freer(write_ptr, write_info_ptr, + PNG_DESTROY_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + +thereby briefly reassigning responsibility for freeing to the user but +immediately afterwards reassigning it once more to the write_destroy +function. Having done this, it would then be safe to destroy the read +structure and continue to use the PLTE, tRNS, and hIST data in the write +structure. + +This function only affects data that has already been allocated. +You can call this function before calling after the png_set_*() functions +to control whether the user or png_destroy_*() is supposed to free the data. +When the user assumes responsibility for libpng-allocated data, the +application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. +For a more compact example of writing a PNG image, see the file example.c. + +V. Modifying/Customizing libpng: + +There are two issues here. The first is changing how libpng does +standard things like memory allocation, input/output, and error handling. +The second deals with more complicated things like adding new chunks, +adding new transformations, and generally changing how libpng works. +Both of those are compile-time issues; that is, they are generally +determined at the time the code is written, and there is rarely a need +to provide the user with a means of changing them. + +Memory allocation, input/output, and error handling + +All of the memory allocation, input/output, and error handling in libpng +goes through callbacks that are user-settable. The default routines are +in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change +these functions, call the appropriate png_set_*_fn() function. + +Memory allocation is done through the functions png_malloc(), png_calloc(), +and png_free(). These currently just call the standard C functions. +png_calloc() calls png_malloc() and then clears the newly +allocated memory to zero. There is limited support for certain systems +with segmented memory architectures and the types of pointers declared by +png.h match this; you will have to use appropriate pointers in your +application. Since it is +unlikely that the method of handling memory allocation on a platform +will change between applications, these functions must be modified in +the library at compile time. If you prefer to use a different method +of allocating and freeing data, you can use png_create_read_struct_2() or +png_create_write_struct_2() to register your own functions as described +above. These functions also provide a void pointer that can be retrieved +via + + mem_ptr=png_get_mem_ptr(png_ptr); + +Your replacement memory functions must have prototypes as follows: + + png_voidp malloc_fn(png_structp png_ptr, + png_alloc_size_t size); + + void free_fn(png_structp png_ptr, png_voidp ptr); + +Your malloc_fn() must return NULL in case of failure. The png_malloc() +function will normally call png_error() if it receives a NULL from the +system memory allocator or from your replacement malloc_fn(). + +Your free_fn() will never be called with a NULL ptr, since libpng's +png_free() checks for NULL before calling free_fn(). + +Input/Output in libpng is done through png_read() and png_write(), +which currently just call fread() and fwrite(). The FILE * is stored in +png_struct and is initialized via png_init_io(). If you wish to change +the method of I/O, the library supplies callbacks that you can set +through the function png_set_read_fn() and png_set_write_fn() at run +time, instead of calling the png_init_io() function. These functions +also provide a void pointer that can be retrieved via the function +png_get_io_ptr(). For example: + + png_set_read_fn(png_structp read_ptr, + voidp read_io_ptr, png_rw_ptr read_data_fn) + + png_set_write_fn(png_structp write_ptr, + voidp write_io_ptr, png_rw_ptr write_data_fn, + png_flush_ptr output_flush_fn); + + voidp read_io_ptr = png_get_io_ptr(read_ptr); + voidp write_io_ptr = png_get_io_ptr(write_ptr); + +The replacement I/O functions must have prototypes as follows: + + void user_read_data(png_structp png_ptr, + png_bytep data, png_size_t length); + + void user_write_data(png_structp png_ptr, + png_bytep data, png_size_t length); + + void user_flush_data(png_structp png_ptr); + +The user_read_data() function is responsible for detecting and +handling end-of-data errors. + +Supplying NULL for the read, write, or flush functions sets them back +to using the default C stream functions, which expect the io_ptr to +point to a standard *FILE structure. It is probably a mistake +to use NULL for one of write_data_fn and output_flush_fn but not both +of them, unless you have built libpng with PNG_NO_WRITE_FLUSH defined. +It is an error to read from a write stream, and vice versa. + +Error handling in libpng is done through png_error() and png_warning(). +Errors handled through png_error() are fatal, meaning that png_error() +should never return to its caller. Currently, this is handled via +setjmp() and longjmp() (unless you have compiled libpng with +PNG_NO_SETJMP, in which case it is handled via PNG_ABORT()), +but you could change this to do things like exit() if you should wish, +as long as your function does not return. + +On non-fatal errors, png_warning() is called +to print a warning message, and then control returns to the calling code. +By default png_error() and png_warning() print a message on stderr via +fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined +(because you don't want the messages) or PNG_NO_STDIO defined (because +fprintf() isn't available). If you wish to change the behavior of the error +functions, you will need to set up your own message callbacks. These +functions are normally supplied at the time that the png_struct is created. +It is also possible to redirect errors and warnings to your own replacement +functions after png_create_*_struct() has been called by calling: + + png_set_error_fn(png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warning_fn); + + png_voidp error_ptr = png_get_error_ptr(png_ptr); + +If NULL is supplied for either error_fn or warning_fn, then the libpng +default function will be used, calling fprintf() and/or longjmp() if a +problem is encountered. The replacement error functions should have +parameters as follows: + + void user_error_fn(png_structp png_ptr, + png_const_charp error_msg); + + void user_warning_fn(png_structp png_ptr, + png_const_charp warning_msg); + +The motivation behind using setjmp() and longjmp() is the C++ throw and +catch exception handling methods. This makes the code much easier to write, +as there is no need to check every return code of every function call. +However, there are some uncertainties about the status of local variables +after a longjmp, so the user may want to be careful about doing anything +after setjmp returns non-zero besides returning itself. Consult your +compiler documentation for more details. For an alternative approach, you +may wish to use the "cexcept" facility (see http://cexcept.sourceforge.net). + +Custom chunks + +If you need to read or write custom chunks, you may need to get deeper +into the libpng code. The library now has mechanisms for storing +and writing chunks of unknown type; you can even declare callbacks +for custom chunks. However, this may not be good enough if the +library code itself needs to know about interactions between your +chunk and existing `intrinsic' chunks. + +If you need to write a new intrinsic chunk, first read the PNG +specification. Acquire a first level of understanding of how it works. +Pay particular attention to the sections that describe chunk names, +and look at how other chunks were designed, so you can do things +similarly. Second, check out the sections of libpng that read and +write chunks. Try to find a chunk that is similar to yours and use +it as a template. More details can be found in the comments inside +the code. It is best to handle unknown chunks in a generic method, +via callback functions, instead of by modifying libpng functions. + +If you wish to write your own transformation for the data, look through +the part of the code that does the transformations, and check out some of +the simpler ones to get an idea of how they work. Try to find a similar +transformation to the one you want to add and copy off of it. More details +can be found in the comments inside the code itself. + +Configuring for 16 bit platforms + +You will want to look into zconf.h to tell zlib (and thus libpng) that +it cannot allocate more then 64K at a time. Even if you can, the memory +won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. + +Configuring for DOS + +For DOS users who only have access to the lower 640K, you will +have to limit zlib's memory usage via a png_set_compression_mem_level() +call. See zlib.h or zconf.h in the zlib library for more information. + +Configuring for Medium Model + +Libpng's support for medium model has been tested on most of the popular +compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets +defined, and FAR gets defined to far in pngconf.h, and you should be +all set. Everything in the library (except for zlib's structure) is +expecting far data. You must use the typedefs with the p or pp on +the end for pointers (or at least look at them and be careful). Make +note that the rows of data are defined as png_bytepp, which is an +unsigned char far * far *. + +Configuring for gui/windowing platforms: + +You will need to write new error and warning functions that use the GUI +interface, as described previously, and set them to be the error and +warning functions at the time that png_create_*_struct() is called, +in order to have them available during the structure initialization. +They can be changed later via png_set_error_fn(). On some compilers, +you may also have to change the memory allocators (png_malloc, etc.). + +Configuring for compiler xxx: + +All includes for libpng are in pngconf.h. If you need to add, change +or delete an include, this is the place to do it. +The includes that are not needed outside libpng are placed in pngpriv.h, +which is only used by the routines inside libpng itself. +The files in libpng proper only include pngpriv.h and png.h, which +in turn includes pngconf.h. + +Configuring zlib: + +There are special functions to configure the compression. Perhaps the +most useful one changes the compression level, which currently uses +input compression values in the range 0 - 9. The library normally +uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests +have shown that for a large majority of images, compression values in +the range 3-6 compress nearly as well as higher levels, and do so much +faster. For online applications it may be desirable to have maximum speed +(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also +specify no compression (Z_NO_COMPRESSION = 0), but this would create +files larger than just storing the raw bitmap. You can specify the +compression level by calling: + + png_set_compression_level(png_ptr, level); + +Another useful one is to reduce the memory level used by the library. +The memory level defaults to 8, but it can be lowered if you are +short on memory (running DOS, for example, where you only have 640K). +Note that the memory level does have an effect on compression; among +other things, lower levels will result in sections of incompressible +data being emitted in smaller stored blocks, with a correspondingly +larger relative overhead of up to 15% in the worst case. + + png_set_compression_mem_level(png_ptr, level); + +The other functions are for configuring zlib. They are not recommended +for normal use and may result in writing an invalid PNG file. See +zlib.h for more information on what these mean. + + png_set_compression_strategy(png_ptr, + strategy); + + png_set_compression_window_bits(png_ptr, + window_bits); + + png_set_compression_method(png_ptr, method); + png_set_compression_buffer_size(png_ptr, size); + +Controlling row filtering + +If you want to control whether libpng uses filtering or not, which +filters are used, and how it goes about picking row filters, you +can call one of these functions. The selection and configuration +of row filters can have a significant impact on the size and +encoding speed and a somewhat lesser impact on the decoding speed +of an image. Filtering is enabled by default for RGB and grayscale +images (with and without alpha), but not for paletted images nor +for any images with bit depths less than 8 bits/pixel. + +The 'method' parameter sets the main filtering method, which is +currently only '0' in the PNG 1.2 specification. The 'filters' +parameter sets which filter(s), if any, should be used for each +scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS +to turn filtering on and off, respectively. + +Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB, +PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise +ORed together with '|' to specify one or more filters to use. +These filters are described in more detail in the PNG specification. +If you intend to change the filter type during the course of writing +the image, you should start with flags set for all of the filters +you intend to use so that libpng can initialize its internal +structures appropriately for all of the filter types. (Note that this +means the first row must always be adaptively filtered, because libpng +currently does not allocate the filter buffers until png_write_row() +is called for the first time.) + + filters = PNG_FILTER_NONE | PNG_FILTER_SUB + PNG_FILTER_UP | PNG_FILTER_AVG | + PNG_FILTER_PAETH | PNG_ALL_FILTERS; + + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, + filters); + The second parameter can also be + PNG_INTRAPIXEL_DIFFERENCING if you are + writing a PNG to be embedded in a MNG + datastream. This parameter must be the + same as the value of filter_method used + in png_set_IHDR(). + +It is also possible to influence how libpng chooses from among the +available filters. This is done in one or both of two ways - by +telling it how important it is to keep the same filter for successive +rows, and by telling it the relative computational costs of the filters. + + double weights[3] = {1.5, 1.3, 1.1}, + costs[PNG_FILTER_VALUE_LAST] = + {1.0, 1.3, 1.3, 1.5, 1.7}; + + png_set_filter_heuristics(png_ptr, + PNG_FILTER_HEURISTIC_WEIGHTED, 3, + weights, costs); + +The weights are multiplying factors that indicate to libpng that the +row filter should be the same for successive rows unless another row filter +is that many times better than the previous filter. In the above example, +if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a +"sum of absolute differences" 1.5 x 1.3 times higher than other filters +and still be chosen, while the NONE filter could have a sum 1.1 times +higher than other filters and still be chosen. Unspecified weights are +taken to be 1.0, and the specified weights should probably be declining +like those above in order to emphasize recent filters over older filters. + +The filter costs specify for each filter type a relative decoding cost +to be considered when selecting row filters. This means that filters +with higher costs are less likely to be chosen over filters with lower +costs, unless their "sum of absolute differences" is that much smaller. +The costs do not necessarily reflect the exact computational speeds of +the various filters, since this would unduly influence the final image +size. + +Note that the numbers above were invented purely for this example and +are given only to help explain the function usage. Little testing has +been done to find optimum values for either the costs or the weights. + +Removing unwanted object code + +There are a bunch of #define's in pngconf.h that control what parts of +libpng are compiled. All the defines end in _SUPPORTED. If you are +never going to use a capability, you can change the #define to #undef +before recompiling libpng and save yourself code and data space, or +you can turn off individual capabilities with defines that begin with +PNG_NO_. + +In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead. + +You can also turn all of the transforms and ancillary chunk capabilities +off en masse with compiler directives that define +PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, +or all four, +along with directives to turn on any of the capabilities that you do +want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the extra +transformations but still leave the library fully capable of reading +and writing PNG files with all known public chunks. Use of the +PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library +that is incapable of reading or writing ancillary chunks. If you are +not using the progressive reading capability, you can turn that off +with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING +capability, which you'll still have). + +All the reading and writing specific code are in separate files, so the +linker should only grab the files it needs. However, if you want to +make sure, or if you are building a stand alone library, all the +reading files start with pngr and all the writing files start with +pngw. The files that don't match either (like png.c, pngtrans.c, etc.) +are used for both reading and writing, and always need to be included. +The progressive reader is in pngpread.c + +If you are creating or distributing a dynamically linked library (a .so +or DLL file), you should not remove or disable any parts of the library, +as this will cause applications linked with different versions of the +library to fail if they call functions not available in your library. +The size of the library itself should not be an issue, because only +those sections that are actually used will be loaded into memory. + +Requesting debug printout + +The macro definition PNG_DEBUG can be used to request debugging +printout. Set it to an integer value in the range 0 to 3. Higher +numbers result in increasing amounts of debugging information. The +information is printed to the "stderr" file, unless another file +name is specified in the PNG_DEBUG_FILE macro definition. + +When PNG_DEBUG > 0, the following functions (macros) become available: + + png_debug(level, message) + png_debug1(level, message, p1) + png_debug2(level, message, p1, p2) + +in which "level" is compared to PNG_DEBUG to decide whether to print +the message, "message" is the formatted string to be printed, +and p1 and p2 are parameters that are to be embedded in the string +according to printf-style formatting directives. For example, + + png_debug1(2, "foo=%d\n", foo); + +is expanded to + + if (PNG_DEBUG > 2) + fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo); + +When PNG_DEBUG is defined but is zero, the macros aren't defined, but you +can still use PNG_DEBUG to control your own debugging: + + #ifdef PNG_DEBUG + fprintf(stderr, ... + #endif + +When PNG_DEBUG = 1, the macros are defined, but only png_debug statements +having level = 0 will be printed. There aren't any such statements in +this version of libpng, but if you insert some they will be printed. + +VI. MNG support + +The MNG specification (available at http://www.libpng.org/pub/mng) allows +certain extensions to PNG for PNG images that are embedded in MNG datastreams. +Libpng can support some of these extensions. To enable them, use the +png_permit_mng_features() function: + + feature_set = png_permit_mng_features(png_ptr, mask) + + mask is a png_uint_32 containing the bitwise OR of the + features you want to enable. These include + PNG_FLAG_MNG_EMPTY_PLTE + PNG_FLAG_MNG_FILTER_64 + PNG_ALL_MNG_FEATURES + + feature_set is a png_uint_32 that is the bitwise AND of + your mask with the set of MNG features that is + supported by the version of libpng that you are using. + +It is an error to use this function when reading or writing a standalone +PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped +in a MNG datastream. As a minimum, it must have the MNG 8-byte signature +and the MHDR and MEND chunks. Libpng does not provide support for these +or any other MNG chunks; your application must provide its own support for +them. You may wish to consider using libmng (available at +http://www.libmng.com) instead. + +VII. Changes to Libpng from version 0.88 + +It should be noted that versions of libpng later than 0.96 are not +distributed by the original libpng author, Guy Schalnat, nor by +Andreas Dilger, who had taken over from Guy during 1996 and 1997, and +distributed versions 0.89 through 0.96, but rather by another member +of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are +still alive and well, but they have moved on to other things. + +The old libpng functions png_read_init(), png_write_init(), +png_info_init(), png_read_destroy(), and png_write_destroy() have been +moved to PNG_INTERNAL in version 0.95 to discourage their use. These +functions will be removed from libpng version 1.4.0. + +The preferred method of creating and initializing the libpng structures is +via the png_create_read_struct(), png_create_write_struct(), and +png_create_info_struct() because they isolate the size of the structures +from the application, allow version error checking, and also allow the +use of custom error handling routines during the initialization, which +the old functions do not. The functions png_read_destroy() and +png_write_destroy() do not actually free the memory that libpng +allocated for these structs, but just reset the data structures, so they +can be used instead of png_destroy_read_struct() and +png_destroy_write_struct() if you feel there is too much system overhead +allocating and freeing the png_struct for each image read. + +Setting the error callbacks via png_set_message_fn() before +png_read_init() as was suggested in libpng-0.88 is no longer supported +because this caused applications that do not use custom error functions +to fail if the png_ptr was not initialized to zero. It is still possible +to set the error callbacks AFTER png_read_init(), or to change them with +png_set_error_fn(), which is essentially the same function, but with a new +name to force compilation errors with applications that try to use the old +method. + +Starting with version 1.0.7, you can find out which version of the library +you are using at run-time: + + png_uint_32 libpng_vn = png_access_version_number(); + +The number libpng_vn is constructed from the major version, minor +version with leading zero, and release number with leading zero, +(e.g., libpng_vn for version 1.0.7 is 10007). + +You can also check which version of png.h you used when compiling your +application: + + png_uint_32 application_vn = PNG_LIBPNG_VER; + +VIII. Changes to Libpng from version 1.0.x to 1.2.x + +Support for user memory management was enabled by default. To +accomplish this, the functions png_create_read_struct_2(), +png_create_write_struct_2(), png_set_mem_fn(), png_get_mem_ptr(), +png_malloc_default(), and png_free_default() were added. + +Support for the iTXt chunk has been enabled by default as of +version 1.2.41. + +Support for certain MNG features was enabled. + +Support for numbered error messages was added. However, we never got +around to actually numbering the error messages. The function +png_set_strip_error_numbers() was added (Note: the prototype for this +function was inadvertently removed from png.h in PNG_NO_ASSEMBLER_CODE +builds of libpng-1.2.15. It was restored in libpng-1.2.36). + +The png_malloc_warn() function was added at libpng-1.2.3. This issues +a png_warning and returns NULL instead of aborting when it fails to +acquire the requested memory allocation. + +Support for setting user limits on image width and height was enabled +by default. The functions png_set_user_limits(), png_get_user_width_max(), +and png_get_user_height_max() were added at libpng-1.2.6. + +The png_set_add_alpha() function was added at libpng-1.2.7. + +The function png_set_expand_gray_1_2_4_to_8() was added at libpng-1.2.9. +Unlike png_set_gray_1_2_4_to_8(), the new function does not expand the +tRNS chunk to alpha. The png_set_gray_1_2_4_to_8() function is +deprecated. + +A number of macro definitions in support of runtime selection of +assembler code features (especially Intel MMX code support) were +added at libpng-1.2.0: + + PNG_ASM_FLAG_MMX_SUPPORT_COMPILED + PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU + 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 + PNG_ASM_FLAGS_INITIALIZED + PNG_MMX_READ_FLAGS + PNG_MMX_FLAGS + PNG_MMX_WRITE_FLAGS + PNG_MMX_FLAGS + +We added the following functions in support of runtime +selection of assembler code features: + + png_get_mmx_flagmask() + png_set_mmx_thresholds() + png_get_asm_flags() + png_get_mmx_bitdepth_threshold() + png_get_mmx_rowbytes_threshold() + png_set_asm_flags() + +We replaced all of these functions with simple stubs in libpng-1.2.20, +when the Intel assembler code was removed due to a licensing issue. + +These macros are deprecated: + + PNG_READ_TRANSFORMS_NOT_SUPPORTED + PNG_PROGRESSIVE_READ_NOT_SUPPORTED + PNG_NO_SEQUENTIAL_READ_SUPPORTED + PNG_WRITE_TRANSFORMS_NOT_SUPPORTED + PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED + PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED + +They have been replaced, respectively, by: + + PNG_NO_READ_TRANSFORMS + PNG_NO_PROGRESSIVE_READ + PNG_NO_SEQUENTIAL_READ + PNG_NO_WRITE_TRANSFORMS + PNG_NO_READ_ANCILLARY_CHUNKS + PNG_NO_WRITE_ANCILLARY_CHUNKS + +PNG_MAX_UINT was replaced with PNG_UINT_31_MAX. It has been +deprecated since libpng-1.0.16 and libpng-1.2.6. + +The function + png_check_sig(sig, num) +was replaced with + !png_sig_cmp(sig, 0, num) +It has been deprecated since libpng-0.90. + +The function + png_set_gray_1_2_4_to_8() +which also expands tRNS to alpha was replaced with + png_set_expand_gray_1_2_4_to_8() +which does not. It has been deprecated since libpng-1.0.18 and 1.2.9. + +IX. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x + +Private libpng prototypes and macro definitions were moved from +png.h and pngconf.h into a new pngpriv.h header file. + +Functions png_set_benign_errors(), png_benign_error(), and +png_chunk_benign_error() were added. + +Support for setting the maximum amount of memory that the application +will allocate for reading chunks was added, as a security measure. +The functions png_set_chunk_cache_max() and png_get_chunk_cache_max() +were added to the library. + +We implemented support for I/O states by adding png_ptr member io_state +and functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + +We added PNG_TRANSFORM_GRAY_TO_RGB to the available high-level +input transforms. + +Checking for and reporting of errors in the IHDR chunk is more thorough. + +Support for global arrays was removed, to improve thread safety. + +Some obsolete/deprecated macros and functions have been removed. + +Typecasted NULL definitions such as + #define png_voidp_NULL (png_voidp)NULL +were eliminated. If you used these in your application, just use +NULL instead. + +The png_struct and info_struct members "trans" and "trans_values" were +changed to "trans_alpha" and "trans_color", respectively. + +The obsolete, unused pnggccrd.c and pngvcrd.c files and related makefiles +were removed. + +The PNG_1_0_X and PNG_1_2_X macros were eliminated. + +The PNG_LEGACY_SUPPORTED macro was eliminated. + +Many WIN32_WCE #ifdefs were removed. + +The functions png_read_init(info_ptr), png_write_init(info_ptr), +png_info_init(info_ptr), png_read_destroy(), and png_write_destroy() +have been removed. They have been deprecated since libpng-0.95. + +The png_permit_empty_plte() was removed. It has been deprecated +since libpng-1.0.9. Use png_permit_mng_features() instead. + +We removed the obsolete stub functions png_get_mmx_flagmask(), +png_set_mmx_thresholds(), png_get_asm_flags(), +png_get_mmx_bitdepth_threshold(), png_get_mmx_rowbytes_threshold(), +png_set_asm_flags(), and png_mmx_supported() + +We removed the obsolete png_check_sig(), png_memcpy_check(), and +png_memset_check() functions. Instead use !png_sig_cmp(), memcpy(), +and memset(), respectively. + +The function png_set_gray_1_2_4_to_8() was removed. It has been +deprecated since libpng-1.0.18 and 1.2.9, when it was replaced with +png_set_expand_gray_1_2_4_to_8() because the former function also +expanded palette images. + +Macros for png_get_uint_16, png_get_uint_32, and png_get_int_32 +were added and are used by default instead of the corresponding +functions. Unfortunately, +from libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +function) incorrectly returned a value of type png_uint_32. + +We changed the prototype for png_malloc() from + png_malloc(png_structp png_ptr, png_uint_32 size) +to + png_malloc(png_structp png_ptr, png_alloc_size_t size) + +This also applies to the prototype for the user replacement malloc_fn(). + +The png_calloc() function was added and is used in place of +of "png_malloc(); memset();" except in the case in png_read_png() +where the array consists of pointers; in this case a "for" loop is used +after the png_malloc() to set the pointers to NULL, to give robust. +behavior in case the application runs out of memory part-way through +the process. + +We changed the prototypes of png_get_compression_buffer_size() and +png_set_compression_buffer_size() to work with png_size_t instead of +png_uint_32. + +Support for numbered error messages was removed by default, since we +never got around to actually numbering the error messages. The function +png_set_strip_error_numbers() was removed from the library by default. + +The png_zalloc() and png_zfree() functions are no longer exported. +The png_zalloc() function no longer zeroes out the memory that it +allocates. + +Support for dithering was disabled by default in libpng-1.4.0, because +been well tested and doesn't actually "dither". The code was not +removed, however, and could be enabled by building libpng with +PNG_READ_DITHER_SUPPORTED defined. In libpng-1.4.2, this support +was reenabled, but the function was renamed png_set_quantize() to +reflect more accurately what it actually does. At the same time, +the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros were also renamed to +PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS, and PNG_READ_DITHER_SUPPORTED +was renamed to PNG_READ_QUANTIZE_SUPPORTED. + +We removed the trailing '.' from the warning and error messages. + +X. Changes to Libpng from version 1.4.x to 1.5.x + +From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +function) incorrectly returned a value of type png_uint_32. + +A. Changes that affect users of libpng + +There are no substantial API changes between the non-deprecated parts of +the 1.4.5 API and the 1.5.0 API, however the ability to directly access +the main libpng control structures, png_struct and png_info, deprecated +in earlier versions of libpng, has been completely removed from +libpng 1.5. + +We no longer include zlib.h in png.h. Applications that need access +to information in zlib.h will need to add the '#include "zlib.h"' +directive. It does not matter whether it is placed prior to or after +the '"#include png.h"' directive. + +We moved the png_strcpy(), png_strncpy(), png_strlen(), png_memcpy(), +png_memcmp(), png_sprintf, and png_memcpy() macros into a private +header file (pngpriv.h) that is not accessible to applications. + +In png_get_iCCP, the type of "profile" was changed from png_charpp +to png_bytepp, and in png_set_iCCP, from png_charp to png_const_bytep. + +There are changes of form in png.h, including new and changed macros to +declare +parts of the API. Some API functions with arguments that are pointers to +data not modified within the function have been corrected to declare +these arguments with PNG_CONST. + +Much of the internal use of C macros to control the library build has also +changed and some of this is visible in the exported header files, in +particular the use of macros to control data and API elements visible +during application compilation may require significant revision to +application code. (It is extremely rare for an application to do this.) + +Any program that compiled against libpng 1.4 and did not use deprecated +features or access internal library structures should compile and work +against libpng 1.5. + +libpng 1.5.0 adds PNG_ PASS macros to help in the reading and writing of +interlaced images. The macros return the number of rows and columns in +each pass and information that can be used to de-interlace and (if +absolutely necessary) interlace an image. + +libpng 1.5.0 adds an API png_longjmp(png_ptr, value). This API calls +the application provided png_longjmp_ptr on the internal, but application +initialized, jmpbuf. It is provided as a convenience to avoid the need +to use the png_jmpbuf macro, which had the unnecessary side effect of +resetting the internal png_longjmp_ptr value. + +libpng 1.5.0 includes a complete fixed point API. By default this is +present along with the corresponding floating point API. In general the +fixed point API is faster and smaller than the floating point one because +the PNG file format used fixed point, not floating point. This applies +even if the library uses floating point in internal calculations. A new +macro, PNG_FLOATING_ARITHMETIC_SUPPORTED, reveals whether the library +uses floating point arithmetic (the default) or fixed point arithmetic +internally for performance critical calculations such as gamma correction. +In some cases, the gamma calculations may produce slightly different +results. This has changed the results in png_rgb_to_gray and in alpha +composition (png_set_background for example). This applies even if the +original image was already linear (gamma == 1.0) and, therefore, it is +not necessary to linearize the image. This is because libpng has *not* +been changed to optimize that case correctly, yet. + +Fixed point support for the sCAL chunk comes with an important caveat; +the sCAL specification uses a decimal encoding of floating point values +and the accuracy of PNG fixed point values is insufficient for +representation of these values. Consequently a "string" API +(png_get_sCAL_s and png_set_sCAL_s) is the only reliable way of reading +arbitrary sCAL chunks in the absence of either the floating point API or +internal floating point calculations. + +Applications no longer need to include the optional distribution header +file pngusr.h or define the corresponding macros during application +build in order to see the correct variant of the libpng API. From 1.5.0 +application code can check for the corresponding _SUPPORTED macro: + +#ifdef PNG_INCH_CONVERSIONS_SUPPORTED + /* code that uses the inch conversion APIs. */ +#endif + +This macro will only be defined if the inch conversion functions have been +compiled into libpng. The full set of macros, and whether or not support +has been compiled in, are available in the header file pnglibconf.h. +This header file is specific to the libpng build. Notice that prior to +1.5.0 the _SUPPORTED macros would always have the default definition unless +reset by pngusr.h or by explicit settings on the compiler command line. +These settings may produce compiler warnings or errors in 1.5.0 because +of macro redefinition. + +From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +function) incorrectly returned a value of type png_uint_32. libpng 1.5.0 +is consistent with the implementation in 1.4.5 and 1.2.x (where the macro +did not exist.) + +Applications can now choose whether to use these macros or to call the +corresponding function by defining PNG_USE_READ_MACROS or +PNG_NO_USE_READ_MACROS before including png.h. Notice that this is +only supported from 1.5.0 -defining PNG_NO_USE_READ_MACROS prior to 1.5.0 + will lead to a link failure. + +B. Changes to the build and configuration of libpng + +Details of internal changes to the library code can be found in the CHANGES +file. These will be of no concern to the vast majority of library users or +builders, however the few who configure libpng to a non-default feature +set may need to change how this is done. + +There should be no need for library builders to alter build scripts if +these use the distributed build support - configure or the makefiles - +however users of the makefiles may care to update their build scripts +to build pnglibconf.h where the corresponding makefile does not do so. + +Building libpng with a non-default configuration has changed completely. +The old method using pngusr.h should still work correctly even though the +way pngusr.h is used in the build has been changed, however library +builders will probably want to examine the changes to take advantage of +new capabilities and to simplify their build system. + +B.1 Specific changes to library configuration capabilities + +The library now supports a complete fixed point implementation and can +thus be used on systems which have no floating point support or very +limited or slow support. Previously gamma correction, an essential part +of complete PNG support, required reasonably fast floating point. + +As part of this the choice of internal implementation has been made +independent of the choice of fixed versus floating point APIs and all the +missing fixed point APIs have been implemented. + +The exact mechanism used to control attributes of API functions has +changed. A single set of operating system independent macro definitions +is used and operating system specific directives are defined in +pnglibconf.h + +As part of this the mechanism used to choose procedure call standards on +those systems that allow a choice has been changed. At present this only +affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems +running on Intel processors. As before PNGAPI is defined where required +to control the exported API functions; however, two new macros, PNGCBAPI +and PNGCAPI, are used instead for callback functions (PNGCBAPI) and +(PNGCAPI) for functions that must match a C library prototype (currently +only png_longjmp_ptr, which must match the C longjmp function.) The new +approach is documented in pngconf.h + +Despite these changes libpng 1.5.0 only supports the native C function +calling standard on those platforms tested so far (__cdecl on Microsoft +Windows). This is because the support requirements for alternative +calling conventions seem to no longer exist. Developers who find it +necessary to set PNG_API_RULE to 1 should advise the mailing list +(png-mng-implement) of this and library builders who use Openwatcom and +therefore set PNG_API_RULE to 2 should also contact the mailing list. + +A new test program, pngvalid, is provided in addition to pngtest. +pngvalid validates the arithmetic accuracy of the gamma correction +calculations and includes a number of validations of the file format. +A subset of the full range of tests is run when "make check" is done +(in the 'configure' build.) pngvalid also allows total allocated memory +usage to be evaluated and performs additional memory overwrite validation. + +Many changes to individual feature macros have been made. The following +are the changes most likely to be noticed by library builders who +configure libpng: + +1) All feature macros now have consistent naming: + +#define PNG_NO_feature turns the feature off +#define PNG_feature_SUPPORTED turns the feature on + +pnglibconf.h contains one line for each feature macro which is either: + +#define PNG_feature_SUPPORTED + +if the feature is supported or: + +/*#undef PNG_feature_SUPPORTED*/ + +if it is not. Library code consistently checks for the 'SUPPORTED' macro. +It does not, and should not, check for the 'NO' macro which will not +normally be defined even if the feature is not supported. + +Compatibility with the old names is provided as follows: + +PNG_INCH_CONVERSIONS turns on PNG_INCH_CONVERSIONS_SUPPORTED + +And the following definitions disable the corresponding feature: + +PNG_SETJMP_NOT_SUPPORTED disables SETJMP +PNG_READ_TRANSFORMS_NOT_SUPPORTED disables READ_TRANSFORMS +PNG_NO_READ_COMPOSITED_NODIV disables READ_COMPOSITE_NODIV +PNG_WRITE_TRANSFORMS_NOT_SUPPORTED disables WRITE_TRANSFORMS +PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED disables READ_ANCILLARY_CHUNKS +PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED disables WRITE_ANCILLARY_CHUNKS + +Library builders should remove use of the above, inconsistent, names. + +2) Warning and error message formatting was previously conditional on +the STDIO feature. The library has been changed to use the +CONSOLE_IO feature instead. This means that if CONSOLE_IO is disabled +the library no longer uses the printf(3) functions, even though the +default read/write implementations use (FILE) style stdio.h functions. + +3) Three feature macros now control the fixed/floating point decisions: + +PNG_FLOATING_POINT_SUPPORTED enables the floating point APIs + +PNG_FIXED_POINT_SUPPORTED enables the fixed point APIs; however, in +practice these are normally required internally anyway (because the PNG +file format is fixed point), therefore in most cases PNG_NO_FIXED_POINT +merely stops the function from being exported. + +PNG_FLOATING_ARITHMETIC_SUPPORTED chooses between the internal floating +point implementation or the fixed point one. Typically the fixed point +implementation is larger and slower than the floating point implementation +on a system that supports floating point, however it may be faster on a +system which lacks floating point hardware and therefore uses a software +emulation. + +4) Added PNG_{READ,WRITE}_INT_FUNCTIONS_SUPPORTED. This allows the +functions to read and write ints to be disabled independently of +PNG_USE_READ_MACROS, which allows libpng to be built with the functions +even though the default is to use the macros - this allows applications +to choose at app buildtime whether or not to use macros (previously +impossible because the functions weren't in the default build.) + +B.2 Changes to the configuration mechanism + +Prior to libpng-1.5.0 library builders who needed to configure libpng +had either to modify the exported pngconf.h header file to add system +specific configuration or had to write feature selection macros into +pngusr.h and cause this to be included into pngconf.h by defining +PNG_USER_CONFIG. The latter mechanism had the disadvantage that an +application built without PNG_USER_CONFIG defined would see the +unmodified, default, libpng API and thus would probably fail to link. + +These mechanisms still work in the configure build and in any makefile +build that builds pnglibconf.h although the feature selection macros +have changed somewhat as described above. In 1.5.0, however, pngusr.h is +processed only once, when the exported header file pnglibconf.h is built. +pngconf.h no longer includes pngusr.h, therefore it is ignored after the +build of pnglibconf.h and it is never included in an application build. + +The rarely used alternative of adding a list of feature macros to the +CFLAGS setting in the build also still works, however the macros will be +copied to pnglibconf.h and this may produce macro redefinition warnings +when the individual C files are compiled. + +All configuration now only works if pnglibconf.h is built from +scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan +(the original author of awk) maintains C source code of that awk and this +and all known later implementations (often called by subtly different +names - nawk and gawk for example) are adequate to build pnglibconf.h. +The Sun Microsystems (now Oracle) program 'awk' is an earlier version +and does not work, this may also apply to other systems that have a +functioning awk called 'nawk'. + +Configuration options are now documented in scripts/pnglibconf.dfa. This +file also includes dependency information that ensures a configuration is +consistent; that is, if a feature is switched off dependent features are +also removed. As a recommended alternative to using feature macros in +pngusr.h a system builder may also define equivalent options in pngusr.dfa +(or, indeed, any file) and add that to the configuration by setting +DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate +how to do this, and a case where pngusr.h is still required. + +XI. Detecting libpng + +The png_get_io_ptr() function has been present since libpng-0.88, has never +changed, and is unaffected by conditional compilation macros. It is the +best choice for use in configure scripts for detecting the presence of any +libpng version since 0.88. In an autoconf "configure.in" you could use + + AC_CHECK_LIB(png, png_get_io_ptr, ... + +XII. Source code repository + +Since about February 2009, version 1.2.34, libpng has been under "git" source +control. The git repository was built from old libpng-x.y.z.tar.gz files +going back to version 0.70. You can access the git repository (read only) +at + + git://libpng.git.sourceforge.net/gitroot/libpng + +or you can browse it via "gitweb" at + + http://libpng.git.sourceforge.net/git/gitweb.cgi?p=libpng + +Patches can be sent to glennrp at users.sourceforge.net or to +png-mng-implement at lists.sourceforge.net or you can upload them to +the libpng bug tracker at + + http://libpng.sourceforge.net + +We also accept patches built from the tar or zip distributions, and +simple verbal discriptions of bug fixes, reported either to the +SourceForge bug tracker or to the png-mng-implement at lists.sf.net +mailing list. + +XIII. Coding style + +Our coding style is similar to the "Allman" style, with curly +braces on separate lines: + + if (condition) + { + action; + } + + else if (another condition) + { + another action; + } + +The braces can be omitted from simple one-line actions: + + if (condition) + return (0); + +We use 3-space indentation, except for continued statements which +are usually indented the same as the first line of the statement +plus four more spaces. + +For macro definitions we use 2-space indentation, always leaving the "#" +in the first column. + + #ifndef PNG_NO_FEATURE + # ifndef PNG_FEATURE_SUPPORTED + # define PNG_FEATURE_SUPPORTED + # endif + #endif + +Comments appear with the leading "/*" at the same indentation as +the statement that follows the comment: + + /* Single-line comment */ + statement; + + /* This is a multiple-line + * comment. + */ + statement; + +Very short comments can be placed after the end of the statement +to which they pertain: + + statement; /* comment */ + +We don't use C++ style ("//") comments. We have, however, +used them in the past in some now-abandoned MMX assembler +code. + +Functions and their curly braces are not indented, and +exported functions are marked with PNGAPI: + + /* This is a public function that is visible to + * application programmers. It does thus-and-so. + */ + void PNGAPI + png_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for all exported functions appear in png.h, +above the comment that says + + /* Maintainer: Put new public prototypes here ... */ + +We mark all non-exported functions with "/* PRIVATE */"": + + void /* PRIVATE */ + png_non_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for non-exported functions (except for those in +pngtest) appear in +pngpriv.h +above the comment that says + + /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +To avoid polluting the global namespace, the names of all exported +functions and variables begin with "png_", and all publicly visible C +preprocessor macros begin with "PNG_". We request that applications that +use libpng *not* begin any of their own symbols with either of these strings. + +We put a space after each comma and after each semicolon +in "for" statements, and we put spaces before and after each +C binary operator and after "for" or "while", and before +"?". We don't put a space between a typecast and the expression +being cast, nor do we put one between a function name and the +left parenthesis that follows it: + + for (i = 2; i > 0; --i) + y[i] = a(x) + (int)b; + +We prefer #ifdef and #ifndef to #if defined() and if !defined() +when there is only one macro being tested. + +We do not use the TAB character for indentation in the C sources. + +Lines do not exceed 80 characters. + +Other rules can be inferred by inspecting the libpng source. + +XIV. Y2K Compliance in libpng + +February 3, 2011 + +Since the PNG Development group is an ad-hoc body, we can't make +an official declaration. + +This is your unofficial assurance that libpng from version 0.71 and +upward through 1.5.1 are Y2K compliant. It is my belief that earlier +versions were also Y2K compliant. + +Libpng only has three year fields. One is a 2-byte unsigned integer that +will hold years up to 65535. The other two hold the date in text +format, and will hold years up to 9999. + +The integer is + "png_uint_16 year" in png_time_struct. + +The strings are + "png_charp time_buffer" in png_struct and + "near_time_buffer", which is a local character string in png.c. + +There are seven time-related functions: + + png_convert_to_rfc_1123() in png.c + (formerly png_convert_to_rfc_1152() in error) + png_convert_from_struct_tm() in pngwrite.c, called + in pngwrite.c + png_convert_from_time_t() in pngwrite.c + png_get_tIME() in pngget.c + png_handle_tIME() in pngrutil.c, called in pngread.c + png_set_tIME() in pngset.c + png_write_tIME() in pngwutil.c, called in pngwrite.c + +All appear to handle dates properly in a Y2K environment. The +png_convert_from_time_t() function calls gmtime() to convert from system +clock time, which returns (year - 1900), which we properly convert to +the full 4-digit year. There is a possibility that applications using +libpng are not passing 4-digit years into the png_convert_to_rfc_1123() +function, or that they are incorrectly passing only a 2-digit year +instead of "year - 1900" into the png_convert_from_struct_tm() function, +but this is not under our control. The libpng documentation has always +stated that it works with 4-digit years, and the APIs have been +documented as such. + +The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned +integer to hold the year, and can hold years as large as 65535. + +zlib, upon which libpng depends, is also Y2K compliant. It contains +no date-related code. + + + Glenn Randers-Pehrson + libpng maintainer + PNG Development Group diff --git a/contrib/libpng/libpng.3 b/contrib/libpng/libpng.3 new file mode 100644 index 0000000..ecc4277 --- /dev/null +++ b/contrib/libpng/libpng.3 @@ -0,0 +1,5376 @@ +.TH LIBPNG 3 "February 3, 2011" +.SH NAME +libpng \- Portable Network Graphics (PNG) Reference Library 1.5.1 +.SH SYNOPSIS +\fI\fB + +\fB#include \fP + +\fI\fB + +\fBpng_uint_32 png_access_version_number \fI(void\fP\fB);\fP + +\fI\fB + +\fBvoid png_benign_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_build_grayscale_palette (int \fP\fIbit_depth\fP\fB, png_colorp \fIpalette\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_calloc (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoid png_chunk_benign_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_chunk_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_chunk_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP + +\fI\fB + +\fBvoid png_convert_from_struct_tm (png_timep \fP\fIptime\fP\fB, struct tm FAR * \fIttime\fP\fB);\fP + +\fI\fB + +\fBvoid png_convert_from_time_t (png_timep \fP\fIptime\fP\fB, time_t \fIttime\fP\fB);\fP + +\fI\fB + +\fBpng_charp png_convert_to_rfc1123 (png_structp \fP\fIpng_ptr\fP\fB, png_timep \fIptime\fP\fB);\fP + +\fI\fB + +\fBpng_infop png_create_info_struct (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_read_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_read_struct_2 (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_write_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP + +\fI\fB + +\fBpng_structp png_create_write_struct_2 (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_data_freer (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIfreer\fP\fB, png_uint_32 \fImask)\fP\fB);\fP + +\fI\fB + +\fBvoid png_destroy_info_struct (png_structp \fP\fIpng_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_destroy_read_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fP\fIinfo_ptr_ptr\fP\fB, png_infopp \fIend_info_ptr_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_destroy_write_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_err (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP + +\fI\fB + +\fBvoid png_free (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_free_chunk_list (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_free_default (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_free_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fInum\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_bit_depth (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_bKGD (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fI*background\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_channels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_cHRM (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, double \fP\fI*white_x\fP\fB, double \fP\fI*white_y\fP\fB, double \fP\fI*red_x\fP\fB, double \fP\fI*red_y\fP\fB, double \fP\fI*green_x\fP\fB, double \fP\fI*green_y\fP\fB, double \fP\fI*blue_x\fP\fB, double \fI*blue_y\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_cHRM_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*white_x\fP\fB, png_uint_32 \fP\fI*white_y\fP\fB, png_uint_32 \fP\fI*red_x\fP\fB, png_uint_32 \fP\fI*red_y\fP\fB, png_uint_32 \fP\fI*green_x\fP\fB, png_uint_32 \fP\fI*green_y\fP\fB, png_uint_32 \fP\fI*blue_x\fP\fB, png_uint_32 \fI*blue_y\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_chunk_cache_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fI\fB + +\fBpng_alloc_size_t png_get_chunk_malloc_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_color_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_compression_buffer_size (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_compression_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_copyright (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_current_row_number \fI(png_const_structp\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_current_pass_number \fI(png_const_structp\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_error_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_filter_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_gAMA (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, double \fI*file_gamma\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_gAMA_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fI*int_file_gamma\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_header_ver (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_header_version (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_hIST (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fI*hist\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_iCCP (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_bytepp \fP\fIprofile\fP\fB, png_uint_32 \fI*proflen\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*width\fP\fB, png_uint_32 \fP\fI*height\fP\fB, int \fP\fI*bit_depth\fP\fB, int \fP\fI*color_type\fP\fB, int \fP\fI*interlace_type\fP\fB, int \fP\fI*compression_type\fP\fB, int \fI*filter_type\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_image_height (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_image_width (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_int_32 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_interlace_type (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_const_bytep png_get_io_chunk_name (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_io_chunk_type (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_io_ptr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_io_state (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_libpng_ver (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_mem_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_oFFs (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*offset_x\fP\fB, png_uint_32 \fP\fI*offset_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pCAL (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fI*purpose\fP\fB, png_int_32 \fP\fI*X0\fP\fB, png_int_32 \fP\fI*X1\fP\fB, int \fP\fI*type\fP\fB, int \fP\fI*nparams\fP\fB, png_charp \fP\fI*units\fP\fB, png_charpp \fI*params\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pHYs (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*res_x\fP\fB, png_uint_32 \fP\fI*res_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fI\fB + +\fBfloat png_get_pixel_aspect_ratio (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pHYs_dpi (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*res_x\fP\fB, png_uint_32 \fP\fI*res_y\fP\fB, int \fI*unit_type\fP\fB);\fP + +\fI\fB + +\fBpng_fixed_point png_get_pixel_aspect_ratio_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_progressive_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_PLTE (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fI*palette\fP\fB, int \fI*num_palette\fP\fB);\fP + +\fI\fB + +\fBpng_byte png_get_rgb_to_gray_status (png_const_structp \fIpng_ptr) + +\fBpng_uint_32 png_get_rowbytes (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_bytepp png_get_rows (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sBIT (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fI*sig_bit\fP\fB);\fP + +\fI\fB + +\fBvoid png_get_sCAL (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, double* \fP\fIwidth\fP\fB, double* \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_get_sCAL_fixed (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, png_fixed_pointp \fP\fIwidth\fP\fB, png_fixed_pointp \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_get_sCAL_s (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int* \fP\fIunit\fP\fB, png_charpp \fP\fIwidth\fP\fB, png_charpp \fIheight\fP\fB);\fP + +\fI\fB + +\fBpng_bytep png_get_signature (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sPLT (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fI*splt_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_sRGB (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, int \fI*file_srgb_intent\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_text (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fI*text_ptr\fP\fB, int \fI*num_text\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_tIME (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fI*mod_time\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_tRNS (png_const_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fI*trans_alpha\fP\fB, int \fP\fI*num_trans\fP\fB, png_color_16p \fI*trans_color\fP\fB);\fP + +\fI\fB + +\fB/* This function is really an inline macro. \fI*/ + +\fBpng_uint_16 png_get_uint_16 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_uint_31 (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fB/* This function is really an inline macro. \fI*/ + +\fBpng_uint_32 png_get_uint_32 (png_bytep \fIbuf\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_unknown_chunks (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkpp \fIunknowns\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_user_chunk_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_user_height_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_get_user_transform_ptr (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_user_width_max (png_const_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_valid (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIflag\fP\fB);\fP + +\fI\fB + +\fBfloat png_get_x_offset_inches (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_fixed_point png_get_x_offset_inches_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_x_offset_microns (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_x_offset_pixels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_x_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_x_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBfloat png_get_y_offset_inches (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_fixed_point png_get_y_offset_inches_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_y_offset_microns (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_int_32 png_get_y_offset_pixels (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_y_pixels_per_inch (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_get_y_pixels_per_meter (png_const_structp \fP\fIpng_ptr\fP\fB, png_const_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBint png_handle_as_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP + +\fI\fB + +\fBvoid png_info_init_3 (png_infopp \fP\fIinfo_ptr\fP\fB, png_size_t \fIpng_info_struct_size\fP\fB);\fP + +\fI\fB + +\fBvoid png_init_io (png_structp \fP\fIpng_ptr\fP\fB, FILE \fI*fp\fP\fB);\fP + +\fI\fB + +\fBvoid png_longjmp (png_structp \fP\fIpng_ptr\fP\fB, int \fIval\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc_default (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_voidp png_malloc_warn (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIsize\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_permit_mng_features (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fImng_features_permitted\fP\fB);\fP + +\fI\fB + +\fBvoid png_process_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_size\fP\fB);\fP + +\fI\fB + +\fBpng_size_t png_process_data_pause \fP\fI(png_structp\fP\fB, int \fIsave\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_process_data_skip \fI(png_structp\fP\fB);\fP + +\fI\fB + +\fBvoid png_progressive_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIold_row\fP\fB, png_bytep \fInew_row\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fIdisplay_row\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_bytepp \fP\fIdisplay_row\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP + +\fI\fB + +\fBvoid png_read_update_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBint png_reset_zstream (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_save_int_32 (png_bytep \fP\fIbuf\fP\fB, png_int_32 \fIi\fP\fB);\fP + +\fI\fB + +\fBvoid png_save_uint_16 (png_bytep \fP\fIbuf\fP\fB, unsigned int \fIi\fP\fB);\fP + +\fI\fB + +\fBvoid png_save_uint_32 (png_bytep \fP\fIbuf\fP\fB, png_uint_32 \fIi\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_add_alpha (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_background (png_structp \fP\fIpng_ptr\fP\fB, png_color_16p \fP\fIbackground_color\fP\fB, int \fP\fIbackground_gamma_code\fP\fB, int \fP\fIneed_expand\fP\fB, double \fIbackground_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_background_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_color_16p \fP\fIbackground_color\fP\fB, int \fP\fIbackground_gamma_code\fP\fB, int \fP\fIneed_expand\fP\fB, png_uint_32 \fIbackground_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_benign_errors (png_structp \fP\fIpng_ptr\fP\fB, int \fIallowed\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_bgr (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fIbackground\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwhite_x\fP\fB, png_uint_32 \fP\fIwhite_y\fP\fB, png_uint_32 \fP\fIred_x\fP\fB, png_uint_32 \fP\fIred_y\fP\fB, png_uint_32 \fP\fIgreen_x\fP\fB, png_uint_32 \fP\fIgreen_y\fP\fB, png_uint_32 \fP\fIblue_x\fP\fB, png_uint_32 \fIblue_y\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_chunk_cache_max (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIuser_chunk_cache_max\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_level (png_structp \fP\fIpng_ptr\fP\fB, int \fIlevel\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_mem_level (png_structp \fP\fIpng_ptr\fP\fB, int \fImem_level\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_method (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_strategy (png_structp \fP\fIpng_ptr\fP\fB, int \fIstrategy\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_crc_action (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcrit_action\fP\fB, int \fIancil_action\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_error_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarning_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_expand (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_expand_gray_1_2_4_to_8 (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filler (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filter (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImethod\fP\fB, int \fIfilters\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filter_heuristics (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_doublep \fP\fIfilter_weights\fP\fB, png_doublep \fIfilter_costs\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_filter_heuristics_fixed (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_fixed_point_p \fP\fIfilter_weights\fP\fB, png_fixed_point_p \fIfilter_costs\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_flush (png_structp \fP\fIpng_ptr\fP\fB, int \fInrows\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gamma (png_structp \fP\fIpng_ptr\fP\fB, double \fP\fIscreen_gamma\fP\fB, double \fIdefault_file_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gamma_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIscreen_gamma\fP\fB, png_uint_32 \fIdefault_file_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fIfile_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIfile_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gray_1_2_4_to_8 (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_gray_to_rgb (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fIhist\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_const_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_const_bytep \fP\fIprofile\fP\fB, png_uint_32 \fIproflen\fP\fB);\fP + +\fI\fB + +\fBint png_set_interlace_handling (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_invalid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fImask\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_invert_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_invert_mono (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIinterlace_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fIfilter_type\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_keep_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIkeep\fP\fB, png_bytep \fP\fIchunk_list\fP\fB, int \fInum_chunks\fP\fB);\fP + +\fI\fB + +\fBjmp_buf* png_set_longjmp_fn (png_structp \fP\fIpng_ptr\fP\fB, png_longjmp_ptr \fP\fIlongjmp_fn\fP\fB, size_t \fIjmp_buf_size\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_chunk_malloc_max (png_structp \fP\fIpng_ptr\fP\fB, png_alloc_size_t \fIuser_chunk_cache_max\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_compression_buffer_size (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_mem_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIoffset_x\fP\fB, png_uint_32 \fP\fIoffset_y\fP\fB, int \fIunit_type\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_packing (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_packswap (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_palette_to_rgb (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIpurpose\fP\fB, png_int_32 \fP\fIX0\fP\fB, png_int_32 \fP\fIX1\fP\fB, int \fP\fItype\fP\fB, int \fP\fInparams\fP\fB, png_charp \fP\fIunits\fP\fB, png_charpp \fIparams\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIres_x\fP\fB, png_uint_32 \fP\fIres_y\fP\fB, int \fIunit_type\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_progressive_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIprogressive_ptr\fP\fB, png_progressive_info_ptr \fP\fIinfo_fn\fP\fB, png_progressive_row_ptr \fP\fIrow_fn\fP\fB, png_progressive_end_ptr \fIend_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fInum_palette\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_quantize (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fP\fInum_palette\fP\fB, int \fP\fImaximum_colors\fP\fB, png_uint_16p \fP\fIhistogram\fP\fB, int \fIfull_quantize\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fIread_data_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_read_status_ptr \fIread_row_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_user_chunk_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_chunk_ptr\fP\fB, png_user_chunk_ptr \fIread_user_chunk_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_read_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIread_user_transform_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_rgb_to_gray (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIerror_action\fP\fB, double \fP\fIred\fP\fB, double \fIgreen\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_rgb_to_gray_fixed (png_structp \fP\fIpng_ptr\fP\fB, int error_action png_uint_32 \fP\fIred\fP\fB, png_uint_32 \fIgreen\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytepp \fIrow_pointers\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fIsig_bit\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sCAL_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, png_fixed_point \fP\fIwidth\fP\fB, png_fixed_point \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sCAL_s (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIunit\fP\fB, png_charp \fP\fIwidth\fP\fB, png_charp \fIheight\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_shift (png_structp \fP\fIpng_ptr\fP\fB, png_color_8p \fItrue_bits\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sig_bytes (png_structp \fP\fIpng_ptr\fP\fB, int \fInum_bytes\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fP\fIsplt_ptr\fP\fB, int \fInum_spalettes\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIsrgb_intent\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_sRGB_gAMA_and_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIsrgb_intent\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_strip_16 (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_strip_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_strip_error_numbers (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIstrip_mode\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_swap (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_swap_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fItext_ptr\fP\fB, int \fInum_text\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fItrans_alpha\fP\fB, int \fP\fInum_trans\fP\fB, png_color_16p \fItrans_color\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_tRNS_to_alpha (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBpng_uint_32 png_set_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkp \fP\fIunknowns\fP\fB, int \fP\fInum\fP\fB, int \fIlocation\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_unknown_chunk_location (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIchunk\fP\fB, int \fIlocation\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_user_limits (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIuser_width_max\fP\fB, png_uint_32 \fIuser_height_max\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_user_transform_info (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_transform_ptr\fP\fB, int \fP\fIuser_transform_depth\fP\fB, int \fIuser_transform_channels\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_write_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fP\fIwrite_data_fn\fP\fB, png_flush_ptr \fIoutput_flush_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_write_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_write_status_ptr \fIwrite_row_fn\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_write_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIwrite_user_transform_fn\fP\fB);\fP + +\fI\fB + +\fBint png_sig_cmp (png_bytep \fP\fIsig\fP\fB, png_size_t \fP\fIstart\fP\fB, png_size_t \fInum_to_check\fP\fB);\fP + +\fI\fB + +\fBvoid png_start_read_image (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk_end (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_chunk_start (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_uint_32 \fIlength\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_flush (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_info_before_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP + +\fI\fB + +\fBvoid png_write_sig (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + +\fBvoidpf png_zalloc (voidpf \fP\fIpng_ptr\fP\fB, uInt \fP\fIitems\fP\fB, uInt \fIsize\fP\fB);\fP + +\fI\fB + +\fBvoid png_zfree (voidpf \fP\fIpng_ptr\fP\fB, voidpf \fIptr\fP\fB);\fP + +\fI\fB + +.SH DESCRIPTION +The +.I libpng +library supports encoding, decoding, and various manipulations of +the Portable Network Graphics (PNG) format image files. It uses the +.IR zlib(3) +compression library. +Following is a copy of the libpng-manual.txt file that accompanies libpng. +.SH LIBPNG.TXT +libpng-manual.txt - A description on how to use and modify libpng + + libpng version 1.5.1 - February 3, 2011 + Updated and distributed by Glenn Randers-Pehrson + + Copyright (c) 1998-2011 Glenn Randers-Pehrson + + This document is released under the libpng license. + For conditions of distribution and use, see the disclaimer + and license in png.h + + Based on: + + libpng versions 0.97, January 1998, through 1.5.1 - February 3, 2011 + Updated and distributed by Glenn Randers-Pehrson + Copyright (c) 1998-2011 Glenn Randers-Pehrson + + libpng 1.0 beta 6 version 0.96 May 28, 1997 + Updated and distributed by Andreas Dilger + Copyright (c) 1996, 1997 Andreas Dilger + + libpng 1.0 beta 2 - version 0.88 January 26, 1996 + For conditions of distribution and use, see copyright + notice in png.h. Copyright (c) 1995, 1996 Guy Eric + Schalnat, Group 42, Inc. + + Updated/rewritten per request in the libpng FAQ + Copyright (c) 1995, 1996 Frank J. T. Wojcik + December 18, 1995 & January 20, 1996 + +.SH I. Introduction + +This file describes how to use and modify the PNG reference library +(known as libpng) for your own use. There are five sections to this +file: introduction, structures, reading, writing, and modification and +configuration notes for various special platforms. In addition to this +file, example.c is a good starting point for using the library, as +it is heavily commented and should include everything most people +will need. We assume that libpng is already installed; see the +INSTALL file for instructions on how to install libpng. + +For examples of libpng usage, see the files "example.c", "pngtest.c", +and the files in the "contrib" directory, all of which are included in +the libpng distribution. + +Libpng was written as a companion to the PNG specification, as a way +of reducing the amount of time and effort it takes to support the PNG +file format in application programs. + +The PNG specification (second edition), November 2003, is available as +a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at +. It is technically equivalent +to the PNG specification (second edition) but has some additional material. + +The PNG-1.0 specification is available +as RFC 2083 and as a +W3C Recommendation . + +Some additional chunks are described in the special-purpose public chunks +documents at . + +Other information +about PNG, and the latest version of libpng, can be found at the PNG home +page, . + +Most users will not have to modify the library significantly; advanced +users may want to modify it more. All attempts were made to make it as +complete as possible, while keeping the code easy to understand. +Currently, this library only supports C. Support for other languages +is being considered. + +Libpng has been designed to handle multiple sessions at one time, +to be easily modifiable, to be portable to the vast majority of +machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy +to use. The ultimate goal of libpng is to promote the acceptance of +the PNG file format in whatever way possible. While there is still +work to be done (see the TODO file), libpng should cover the +majority of the needs of its users. + +Libpng uses zlib for its compression and decompression of PNG files. +Further information about zlib, and the latest version of zlib, can +be found at the zlib home page, . +The zlib compression utility is a general purpose utility that is +useful for more than PNG files, and can be used without libpng. +See the documentation delivered with zlib for more details. +You can usually find the source files for the zlib utility wherever you +find the libpng source files. + +Libpng is thread safe, provided the threads are using different +instances of the structures. Each thread should have its own +png_struct and png_info instances, and thus its own image. +Libpng does not protect itself against two threads using the +same instance of a structure. + +.SH II. Structures + +There are two main structures that are important to libpng, png_struct +and png_info. Both are internal structures that are no longer exposed +in the libpng interface (as of libpng 1.5.0). + +The png_info structure is designed to provide information about the +PNG file. At one time, the fields of png_info were intended to be +directly accessible to the user. However, this tended to cause problems +with applications using dynamically loaded libraries, and as a result +a set of interface functions for png_info (the png_get_*() and png_set_*() +functions) was developed. + +The png_struct structure is the object used by the library to decode a +single image. As of 1.5.0 this structure is also not exposed. + +Almost all libpng APIs require a pointer to a png_struct as the first argument. +Many (in particular the png_set and png_get APIs) also require a pointer +to png_info as the second argument. Some application visible macros +defined in png.h designed for basic data access (reading and writing +integers in the PNG format) break this rule, but it's almost always safe +to assume that a (png_struct*) has to be passed to call an API function. + +The png.h header file is an invaluable reference for programming with libpng. +And while I'm on the topic, make sure you include the libpng header file: + +#include + +.SS Types + +The png.h header file defines a number of integral types used by the +APIs. Most of these are fairly obvious; for example types corresponding +to integers of particular sizes and types for passing color values. + +One exception is how non-integral numbers are handled. For application +convenience most APIs that take such numbers have C (double) arguments, +however internally PNG, and libpng, use 32 bit signed integers and encode +the value by multiplying by 100,000. As of libpng 1.5.0 a convenience +macro PNG_FP_1 is defined in png.h along with a type (png_fixed_point) +which is simply (png_int_32). + +All APIs that take (double) arguments also have an matching API that +takes the corresponding fixed point integer arguments. The fixed point +API has the same name as the floating point one with _fixed appended. +The actual range of values permitted in the APIs is frequently less than +the full range of (png_fixed_point) (-21474 to +21474). When APIs require +a non-negative argument the type is recorded as png_uint_32 above. Consult +the header file and the text below for more information. + +Special care must be take with sCAL chunk handling because the chunk itself +uses non-integral values encoded as strings containing decimal floating point +numbers. See the comments in the header file. + +.SS Configuration + +The main header file function declarations are frequently protected by C +preprocessing directives of the form: + + #ifdef PNG_feature_SUPPORTED + declare-function + #endif + +The library can be built without support for these APIs, although a +standard build will have all implemented APIs. Application programs +should check the feature macros before using an API for maximum +portability. From libpng 1.5.0 the feature macros set during the build +of libpng are recorded in the header file "pnglibconf.h" and this file +is always included by png.h. + +If you don't need to change the library configuration from the default skip to +the next section ("Reading"). + +Notice that some of the makefiles in the 'scripts' directory and (in 1.5.0) all +of the build project files in the 'projects' directory simply copy +scripts/pnglibconf.h.prebuilt to pnglibconf.h. This means that these build +systems do not permit easy auto-configuration of the library - they only +support the default configuration. + +The easiest way to make minor changes to the libpng configuration when +auto-configuration is supported is to add definitions to the command line +using (typically) CPPFLAGS. For example: + +CPPFLAGS=-DPNG_NO_FLOATING_ARITHMETIC + +will change the internal libpng math implementation for gamma correction and +other arithmetic calculations to fixed point, avoiding the need for fast +floating point support. The result can be seen in the generated pnglibconf.h - +make sure it contains the changed feature macro setting. + +If you need to make more extensive configuration changes - more than one or two +feature macro settings - you can either add -DPNG_USER_CONFIG to the build +command line and put a list of feature macro settings in pngusr.h or you can set +DFA_XTRA (a makefile variable) to a file containing the same information in the +form of 'option' settings. + +A. Changing pnglibconf.h + +A variety of methods exist to build libpng. Not all of these support +reconfiguration of pnglibconf.h. To reconfigure pnglibconf.h it must either be +rebuilt from scripts/pnglibconf.dfa using awk or it must be edited by hand. + +Hand editing is achieved by copying scripts/pnglibconf.h.prebuilt and changing +the lines defining the supported features, paying very close attention to the +'option' information in scripts/pnglibconf.dfa that describes those features and +their requirements. This is easy to get wrong. + +B. Configuration using DFA_XTRA + +Rebuilding from pnglibconf.dfa is easy if a functioning 'awk', or a later +variant such as 'nawk' or 'gawk', is available. The configure build will +automatically find an appropriate awk and build pnglibconf.h. +scripts/pnglibconf.mak contains a set of make rules for doing the same thing if +configure is not used, and many of the makefiles in the scripts directory use +this approach. + +When rebuilding simply write new file containing changed options and set +DFA_XTRA to the name of this file. This causes the build to append the new file +to the end of scripts/pnglibconf.dfa. pngusr.dfa should contain lines of the +following forms: + +everything = off + +This turns all optional features off. Include it at the start of pngusr.dfa to +make it easier to build a minimal configuration. You will need to turn at least +some features on afterward to enable either reading or writing code, or both. + +option feature on +option feature off + +Enable or disable a single feature. This will automatically enable other +features required by a feature that is turned on or disable other features that +require a feature which is turned off. Conflicting settings will cause an error +message to be emitted by awk. + +setting feature default value + +Changes the default value of setting 'feature' to 'value'. There are a small +number of settings listed at the top of pnglibconf.h, they are documented in the +source code. Most of these values have performance implications for the library +but most of them have no visible effect on the API. Some can also be overridden +from the API. + +C. Configuration using PNG_USR_CONFIG + +If -DPNG_USR_CONFIG is added to the CFLAGS when pnglibconf.h is built the file +pngusr.h will automatically be included before the options in +scripts/pnglibconf.dfa are processed. pngusr.h should contain only macro +definitions turning features on or off or setting settings. + +Apart from the global setting "everything = off" all the options listed above +can be set using macros in pngusr.h: + +#define PNG_feature_SUPPORTED + +is equivalent to: + +option feature on + +#define PNG_NO_feature + +is equivalent to: + +option feature off + +#define PNG_feature value + +is equivalent to: + +setting feature default value + +Notice that in both cases, pngusr.dfa and pngusr.h, the contents of the +pngusr file you supply override the contents of scripts/pnglibconf.dfa + +If confusing or incomprehensible behavior results it is possible to +examine the intermediate file pnglibconf.dfn to find the full set of +dependency information for each setting and option. Simply locate the +feature in the file and read the C comments that precede it. + +.SH III. Reading + +We'll now walk you through the possible functions to call when reading +in a PNG file sequentially, briefly explaining the syntax and purpose +of each one. See example.c and png.h for more detail. While +progressive reading is covered in the next section, you will still +need some of the functions discussed in this section to read a PNG +file. + +.SS Setup + +You will want to do the I/O initialization(*) before you get into libpng, +so if it doesn't work, you don't have much to undo. Of course, you +will also want to insure that you are, in fact, dealing with a PNG +file. Libpng provides a simple check to see if a file is a PNG file. +To use it, pass in the first 1 to 8 bytes of the file to the function +png_sig_cmp(), and it will return 0 (false) if the bytes match the +corresponding bytes of the PNG signature, or nonzero (true) otherwise. +Of course, the more bytes you pass in, the greater the accuracy of the +prediction. + +If you are intending to keep the file pointer open for use in libpng, +you must ensure you don't read more than 8 bytes from the beginning +of the file, and you also have to make a call to png_set_sig_bytes_read() +with the number of bytes you read from the beginning. Libpng will +then only check the bytes (if any) that your program didn't read. + +(*): If you are not using the standard I/O functions, you will need +to replace them with custom functions. See the discussion under +Customizing libpng. + + + FILE *fp = fopen(file_name, "rb"); + if (!fp) + { + return (ERROR); + } + + fread(header, 1, number, fp); + is_png = !png_sig_cmp(header, 0, number); + + if (!is_png) + { + return (NOT_PNG); + } + + +Next, png_struct and png_info need to be allocated and initialized. In +order to ensure that the size of these structures is correct even with a +dynamically linked libpng, there are functions to initialize and +allocate the structures. We also pass the library version, optional +pointers to error handling functions, and a pointer to a data struct for +use by the error functions, if necessary (the pointer and functions can +be NULL if the default error handlers are to be used). See the section +on Changes to Libpng below regarding the old initialization functions. +The structure allocation functions quietly return NULL if they fail to +create the structure, so your application should check for that. + + png_structp png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return (ERROR); + } + + png_infop end_info = png_create_info_struct(png_ptr); + + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +use a libpng that was built with PNG_USER_MEM_SUPPORTED defined, and use +png_create_read_struct_2() instead of png_create_read_struct(): + + png_structp png_ptr = png_create_read_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +The error handling routines passed to png_create_read_struct() +and the memory alloc/free routines passed to png_create_struct_2() +are only necessary if you are not using the libpng supplied error +handling and memory alloc/free functions. + +When libpng encounters an error, it expects to longjmp back +to your routine. Therefore, you will need to call setjmp and pass +your png_jmpbuf(png_ptr). If you read the file from different +routines, you will need to update the jmpbuf field every time you enter +a new routine that will call a png_*() function. + +See your documentation of setjmp/longjmp for your compiler for more +information on setjmp/longjmp. See the discussion on libpng error +handling in the Customizing Libpng section below for more information +on the libpng error handling. If an error occurs, and libpng longjmp's +back to your setjmp, you will want to call png_destroy_read_struct() to +free any memory. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + fclose(fp); + return (ERROR); + } + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_NO_SETJMP, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +Now you need to set up the input code. The default for libpng is to +use the C function fread(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. If you wish to handle reading data in another +way, you need not call the png_init_io() function, but you must then +implement the libpng I/O methods discussed in the Customizing Libpng +section below. + + png_init_io(png_ptr, fp); + +If you had previously opened the file and read any of the signature from +the beginning in order to see if this was a PNG file, you need to let +libpng know that there are some bytes missing from the start of the file. + + png_set_sig_bytes(png_ptr, number); + +You can change the zlib compression buffer size to be used while +reading compressed data with + + png_set_compression_buffer_size(png_ptr, buffer_size); + +where the default size is 8192 bytes. Note that the buffer size +is changed immediately and the buffer is reallocated immediately, +instead of setting a flag to be acted upon later. + +If you want CRC errors to be handled in a different manner than +the default, use + + png_set_crc_action(png_ptr, crit_action, ancil_action); + +The values for png_set_crc_action() say how libpng is to handle CRC errors in +ancillary and critical chunks, and whether to use the data contained +therein. Note that it is impossible to "discard" data in a critical +chunk. + +Choices for (int) crit_action are + PNG_CRC_DEFAULT 0 error/quit + PNG_CRC_ERROR_QUIT 1 error/quit + PNG_CRC_WARN_USE 3 warn/use data + PNG_CRC_QUIET_USE 4 quiet/use data + PNG_CRC_NO_CHANGE 5 use the current value + +Choices for (int) ancil_action are + PNG_CRC_DEFAULT 0 error/quit + PNG_CRC_ERROR_QUIT 1 error/quit + PNG_CRC_WARN_DISCARD 2 warn/discard data + PNG_CRC_WARN_USE 3 warn/use data + PNG_CRC_QUIET_USE 4 quiet/use data + PNG_CRC_NO_CHANGE 5 use the current value + +.SS Setting up callback code + +You can set up a callback function to handle any unknown chunks in the +input stream. You must supply the function + + read_chunk_callback(png_structp png_ptr, + png_unknown_chunkp chunk); + { + /* The unknown chunk structure contains your + chunk data, along with similar data for any other + unknown chunks: */ + + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* Note that libpng has already taken care of + the CRC handling */ + + /* put your code here. Search for your chunk in the + unknown chunk structure, process it, and return one + of the following: */ + + return (-n); /* chunk had an error */ + return (0); /* did not recognize */ + return (n); /* success */ + } + +(You can give your function another name that you like instead of +"read_chunk_callback") + +To inform libpng about your function, use + + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, + read_chunk_callback); + +This names not only the callback function, but also a user pointer that +you can retrieve with + + png_get_user_chunk_ptr(png_ptr); + +If you call the png_set_read_user_chunk_fn() function, then all unknown +chunks will be saved when read, in case your callback function will need +one or more of them. This behavior can be changed with the +png_set_keep_unknown_chunks() function, described below. + +At this point, you can set up a callback function that will be +called after each row has been read, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void read_row_callback(png_structp png_ptr, + png_uint_32 row, int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "read_row_callback") + +To inform libpng about your function, use + + png_set_read_status_fn(png_ptr, read_row_callback); + +.SS Unknown-chunk handling + +Now you get to set the way the library processes unknown chunks in the +input PNG stream. Both known and unknown chunks will be read. Normal +behavior is that known chunks will be parsed into information in +various info_ptr members while unknown chunks will be discarded. This +behavior can be wasteful if your application will never use some known +chunk types. To change this, you can call: + + png_set_keep_unknown_chunks(png_ptr, keep, + chunk_list, num_chunks); + keep - 0: default unknown chunk handling + 1: ignore; do not keep + 2: keep only if safe-to-copy + 3: keep even if unsafe-to-copy + + You can use these definitions: + PNG_HANDLE_CHUNK_AS_DEFAULT 0 + PNG_HANDLE_CHUNK_NEVER 1 + PNG_HANDLE_CHUNK_IF_SAFE 2 + PNG_HANDLE_CHUNK_ALWAYS 3 + + chunk_list - list of chunks affected (a byte string, + five bytes per chunk, NULL or '\0' if + num_chunks is 0) + + num_chunks - number of chunks affected; if 0, all + unknown chunks are affected. If nonzero, + only the chunks in the list are affected + +Unknown chunks declared in this way will be saved as raw data onto a +list of png_unknown_chunk structures. If a chunk that is normally +known to libpng is named in the list, it will be handled as unknown, +according to the "keep" directive. If a chunk is named in successive +instances of png_set_keep_unknown_chunks(), the final instance will +take precedence. The IHDR and IEND chunks should not be named in +chunk_list; if they are, libpng will process them normally anyway. + +Here is an example of the usage of png_set_keep_unknown_chunks(), +where the private "vpAg" chunk will later be processed by a user chunk +callback function: + + png_byte vpAg[5]={118, 112, 65, 103, (png_byte) '\0'}; + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + png_byte unused_chunks[]= + { + 104, 73, 83, 84, (png_byte) '\0', /* hIST */ + 105, 84, 88, 116, (png_byte) '\0', /* iTXt */ + 112, 67, 65, 76, (png_byte) '\0', /* pCAL */ + 115, 67, 65, 76, (png_byte) '\0', /* sCAL */ + 115, 80, 76, 84, (png_byte) '\0', /* sPLT */ + 116, 73, 77, 69, (png_byte) '\0', /* tIME */ + }; + #endif + + ... + + #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) + /* ignore all unknown chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0); + + /* except for vpAg: */ + png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1); + + /* also ignore unused known chunks: */ + png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks, + (int)sizeof(unused_chunks)/5); + #endif + +.SS User limits + +The PNG specification allows the width and height of an image to be as +large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns. +Since very few applications really need to process such large images, +we have imposed an arbitrary 1-million limit on rows and columns. +Larger images will be rejected immediately with a png_error() call. If +you wish to override this limit, you can use + + png_set_user_limits(png_ptr, width_max, height_max); + +to set your own limits, or use width_max = height_max = 0x7fffffffL +to allow all valid dimensions (libpng may reject some very large images +anyway because of potential buffer overflow conditions). + +You should put this statement after you create the PNG structure and +before calling png_read_info(), png_read_png(), or png_process_data(). +If you need to retrieve the limits that are being applied, use + + width_max = png_get_user_width_max(png_ptr); + height_max = png_get_user_height_max(png_ptr); + +The PNG specification sets no limit on the number of ancillary chunks +allowed in a PNG datastream. You can impose a limit on the total number +of sPLT, tEXt, iTXt, zTXt, and unknown chunks that will be stored, with + + png_set_chunk_cache_max(png_ptr, user_chunk_cache_max); + +where 0x7fffffffL means unlimited. You can retrieve this limit with + + chunk_cache_max = png_get_chunk_cache_max(png_ptr); + +This limit also applies to the number of buffers that can be allocated +by png_decompress_chunk() while decompressing iTXt, zTXt, and iCCP chunks. + +You can also set a limit on the amount of memory that a compressed chunk +other than IDAT can occupy, with + + png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); + +and you can retrieve the limit with + + chunk_malloc_max = png_get_chunk_malloc_max(png_ptr); + +Any chunks that would cause either of these limits to be exceeded will +be ignored. + +.SS The high-level read interface + +At this point there are two ways to proceed; through the high-level +read interface, or through a sequence of low-level read operations. +You can use the high-level interface if (a) you are willing to read +the entire image into memory, and (b) the input transformations +you want to do are limited to the following set: + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to + 8 bits + PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel + PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit + samples to bytes + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_EXPAND Perform set_expand() + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_GRAY_TO_RGB Expand grayscale samples + to RGB (or GA to RGBA) + +(This excludes setting a background color, doing gamma transformation, +quantizing, and setting filler.) If this is the case, simply do this: + + png_read_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some +set of transformation flags. This call is equivalent to png_read_info(), +followed the set of transformations indicated by the transform mask, +then png_read_image(), and finally png_read_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future input transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_read_png(). + +After you have called png_read_png(), you can retrieve the image data +with + + row_pointers = png_get_rows(png_ptr, info_ptr); + +where row_pointers is an array of pointers to the pixel data for each row: + + png_bytep row_pointers[height]; + +If you know your image size and pixel size ahead of time, you can allocate +row_pointers prior to calling png_read_png() with + + if (height > PNG_UINT_32_MAX/png_sizeof(png_byte)) + png_error (png_ptr, + "Image is too tall to process in memory"); + + if (width > PNG_UINT_32_MAX/pixel_size) + png_error (png_ptr, + "Image is too wide to process in memory"); + + row_pointers = png_malloc(png_ptr, + height*png_sizeof(png_bytep)); + + for (int i=0; i) and +png_get_(png_ptr, info_ptr, ...) functions return non-zero if the +data has been read, or zero if it is missing. The parameters to the +png_get_ are set directly if they are simple data types, or a +pointer into the info_ptr is returned for any complex types. + + png_get_PLTE(png_ptr, info_ptr, &palette, + &num_palette); + + palette - the palette for the file + (array of png_color) + + num_palette - number of entries in the palette + + png_get_gAMA(png_ptr, info_ptr, &file_gamma); + png_get_gAMA_fixed(png_ptr, info_ptr, &int_file_gamma); + + file_gamma - the gamma at which the file is + written (PNG_INFO_gAMA) + + int_file_gamma - 100,000 times the gamma at which the + file is written + + png_get_sRGB(png_ptr, info_ptr, &srgb_intent); + + file_srgb_intent - the rendering intent (PNG_INFO_sRGB) + The presence of the sRGB chunk + means that the pixel data is in the + sRGB color space. This chunk also + implies specific values of gAMA and + cHRM. + + png_get_iCCP(png_ptr, info_ptr, &name, + &compression_type, &profile, &proflen); + + name - The profile name. + + compression_type - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + + profile - International Color Consortium color + profile data. May contain NULs. + + proflen - length of profile data in bytes. + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, + red, green, and blue channels, + whichever are appropriate for the + given color type (png_color_16) + + png_get_tRNS(png_ptr, info_ptr, &trans_alpha, + &num_trans, &trans_color); + + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + trans_color - graylevel or color sample values of + the single transparent color for + non-paletted images (PNG_INFO_tRNS) + + png_get_hIST(png_ptr, info_ptr, &hist); + (PNG_INFO_hIST) + + hist - histogram of palette (array of + png_uint_16) + + png_get_tIME(png_ptr, info_ptr, &mod_time); + + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_get_bKGD(png_ptr, info_ptr, &background); + + background - background color (PNG_VALID_bKGD) + valid 16-bit red, green and blue + values, regardless of color_type + + num_comments = png_get_text(png_ptr, info_ptr, + &text_ptr, &num_text); + + num_comments - number of comments + + text_ptr - array of png_text holding image + comments + + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + + text_ptr[i].text - text comments for current + keyword. Can be empty. + + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + + text_ptr[i].lang - language of comment (empty + string for unknown). + + text_ptr[i].lang_key - keyword in UTF-8 + (empty string for unknown). + + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist + when the library is built with iTXt chunk support. + + num_text - number of comments (same as + num_comments; you can put NULL here + to avoid the duplication) + + Note while png_set_text() will accept text, language, + and translated keywords that can be NULL pointers, the + structure returned by png_get_text will always contain + regular zero-terminated C strings. They might be + empty strings but they will never be NULL pointers. + + num_spalettes = png_get_sPLT(png_ptr, info_ptr, + &palette_ptr); + + num_spalettes - number of sPLT chunks read. + + palette_ptr - array of palette structures holding + contents of one or more sPLT chunks + read. + + png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, + &unit_type); + + offset_x - positive offset from the left edge + of the screen + + offset_y - positive offset from the top edge + of the screen + + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, + &unit_type); + + res_x - pixels/unit physical resolution in + x direction + + res_y - pixels/unit physical resolution in + x direction + + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_get_sCAL(png_ptr, info_ptr, &unit, &width, + &height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are doubles) + + png_get_sCAL_s(png_ptr, info_ptr, &unit, &width, + &height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + num_unknown_chunks = png_get_unknown_chunks(png_ptr, + info_ptr, &unknowns) + + unknowns - array of png_unknown_chunk + structures holding unknown chunks + + unknowns[i].name - name of unknown chunk + + unknowns[i].data - data of unknown chunk + + unknowns[i].size - size of unknown chunk's data + + unknowns[i].location - position of chunk in file + + The value of "i" corresponds to the order in which the + chunks were read from the PNG file or inserted with the + png_set_unknown_chunks() function. + +The data from the pHYs chunk can be retrieved in several convenient +forms: + + res_x = png_get_x_pixels_per_meter(png_ptr, + info_ptr) + + res_y = png_get_y_pixels_per_meter(png_ptr, + info_ptr) + + res_x_and_y = png_get_pixels_per_meter(png_ptr, + info_ptr) + + res_x = png_get_x_pixels_per_inch(png_ptr, + info_ptr) + + res_y = png_get_y_pixels_per_inch(png_ptr, + info_ptr) + + res_x_and_y = png_get_pixels_per_inch(png_ptr, + info_ptr) + + aspect_ratio = png_get_pixel_aspect_ratio(png_ptr, + info_ptr) + + Each of these returns 0 [signifying "unknown"] if + the data is not present or if res_x is 0; + res_x_and_y is 0 if res_x != res_y + + Note that because of the way the resolutions are + stored internally, the inch conversions won't + come out to exactly even number. For example, + 72 dpi is stored as 0.28346 pixels/meter, and + when this is retrieved it is 71.9988 dpi, so + be sure to round the returned value appropriately + if you want to display a reasonable-looking result. + +The data from the oFFs chunk can be retrieved in several convenient +forms: + + x_offset = png_get_x_offset_microns(png_ptr, info_ptr); + + y_offset = png_get_y_offset_microns(png_ptr, info_ptr); + + x_offset = png_get_x_offset_inches(png_ptr, info_ptr); + + y_offset = png_get_y_offset_inches(png_ptr, info_ptr); + + Each of these returns 0 [signifying "unknown" if both + x and y are 0] if the data is not present or if the + chunk is present but the unit is the pixel. The + remark about inexact inch conversions applies here + as well, because a value in inches can't always be + converted to microns and back without some loss + of precision. + +For more information, see the png_info definition in png.h and the +PNG specification for chunk contents. Be careful with trusting +rowbytes, as some of the transformations could increase the space +needed to hold a row (expand, filler, gray_to_rgb, etc.). +See png_read_update_info(), below. + +A quick word about text_ptr and num_text. PNG stores comments in +keyword/text pairs, one pair per chunk, with no limit on the number +of text chunks, and a 2^31 byte limit on their size. While there are +suggested keywords, there is no requirement to restrict the use to these +strings. It is strongly suggested that keywords and text be sensible +to humans (that's the point), so don't use abbreviations. Non-printing +symbols are not allowed. See the PNG specification for more details. +There is also no requirement to have text after the keyword. + +Keywords should be limited to 79 Latin-1 characters without leading or +trailing spaces, but non-consecutive spaces are allowed within the +keyword. It is possible to have the same keyword any number of times. +The text_ptr is an array of png_text structures, each holding a +pointer to a language string, a pointer to a keyword and a pointer to +a text string. The text string, language code, and translated +keyword may be empty or NULL pointers. The keyword/text +pairs are put into the array in the order that they are received. +However, some or all of the text chunks may be after the image, so, to +make sure you have read all the text chunks, don't mess with these +until after you read the stuff after the image. This will be +mentioned again below in the discussion that goes with png_read_end(). + +.SS Input transformations + +After you've read the header information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +The colors used for the background and transparency values should be +supplied in the same format/depth as the current image data. They +are stored in the same format/depth as the image data in a bKGD or tRNS +chunk, so this is what libpng expects for this data. The colors are +transformed to keep in sync with the image data when an application +calls the png_read_update_info() routine (see below). + +Data will be decoded into the supplied row buffers packed into bytes +unless the library has been told to transform it into another format. +For example, 4 bit/pixel paletted or grayscale data will be returned +2 pixels/byte with the leftmost pixel in the high-order bits of the +byte, unless png_set_packing() is called. 8-bit RGB data will be stored +in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() +is called to insert filler bytes, either before or after each RGB triplet. +16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant +byte of the color value first, unless png_set_strip_16() is called to +transform it to regular RGB RGB triplets, or png_set_filler() or +png_set_add alpha() is called to insert filler bytes, either before or +after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can +be modified with +png_set_filler(), png_set_add_alpha(), or png_set_strip_16(). + +The following code transforms grayscale images of less than 8 to 8 bits, +changes paletted images to RGB, and adds a full alpha channel if there is +transparency information in a tRNS chunk. This is most useful on +grayscale images with bit depths of 2 or 4 or if there is a multiple-image +viewing application that wishes to treat all images in the same way. + + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + if (color_type == PNG_COLOR_TYPE_GRAY && + bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); + + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); + +These three functions are actually aliases for png_set_expand(), added +in libpng version 1.0.4, with the function names expanded to improve code +readability. In some future version they may actually do different +things. + +As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was +added. It expands the sample depth without changing tRNS to alpha. + +As of libpng version 1.5.1, not all possible expansions are supported. + +In the following table, the 01 means grayscale with depth<8, 31 means +indexed with depth<8, other numerals represent the color type, "T" means +the tRNS chunk is present, A means an alpha channel is present, and O +means tRNS or alpha is present but all pixels in the image are opaque. + + FROM 01 31 0 0T 0O 2 2T 2O 3 3T 3O 4A 4O 6A 6O + TO + 01 - + 31 - + 0 1 - + 0T - + 0O - + 2 GX - + 2T - + 2O - + 3 1 - + 3T - + 3O - + 4A T - + 4O - + 6A GX TX TX - + 6O GX TX - + +Within the matrix, + "-" means the transformation is not supported. + "X" means the transformation is obtained by png_set_expand(). + "1" means the transformation is obtained by + png_set_expand_gray_1_2_4_to_8 + "G" means the transformation is obtained by + png_set_gray_to_rgb(). + "P" means the transformation is obtained by + png_set_expand_palette_to_rgb(). + "T" means the transformation is obtained by + png_set_tRNS_to_alpha(). + +PNG can have files with 16 bits per channel. If you only can handle +8 bits per channel, this will strip the pixels down to 8 bit. + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + +If, for some reason, you don't need the alpha channel on an image, +and you want to remove it rather than combining it with the background +(but the image author certainly had in mind that you *would* combine +it with the background, so that's what you should probably do): + + if (color_type & PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_ptr); + +In PNG files, the alpha channel in an image +is the level of opacity. If you need the alpha channel in an image to +be the level of transparency instead of opacity, you can invert the +alpha channel (or the tRNS chunk data) after it's read, so that 0 is +fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit +images) is fully transparent, with + + png_set_invert_alpha(png_ptr); + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit +files. This code expands to 1 pixel per byte without changing the +values of the pixels: + + if (bit_depth < 8) + png_set_packing(png_ptr); + +PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels +stored in a PNG image have been "scaled" or "shifted" up to the next +higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] +to 8 bits/sample in the range [0, 255]). However, it is also possible +to convert the PNG pixel data back to the original bit depth of the +image. This call reduces the pixels back down to the original bit depth: + + png_color_8p sig_bit; + + if (png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + png_set_shift(png_ptr, sig_bit); + +PNG files store 3-color pixels in red, green, blue order. This code +changes the storage of the pixels to blue, green, red: + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_bgr(png_ptr); + +PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them +into 4 or 8 bytes for windowing systems that need them in this format: + + if (color_type == PNG_COLOR_TYPE_RGB) + png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); + +where "filler" is the 8 or 16-bit number to fill with, and the location is +either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether +you want the filler before the RGB or after. This transformation +does not affect images that already have full alpha channels. To add an +opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which +will generate RGBA pixels. + +Note that png_set_filler() does not change the color type. If you want +to do that, you can add a true alpha channel with + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY) + png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); + +where "filler" contains the alpha value to assign to each pixel. +This function was added in libpng-1.2.7. + +If you are reading an image with an alpha channel, and you need the +data as ARGB instead of the normal PNG format RGBA: + + if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_swap_alpha(png_ptr); + +For some uses, you may want a grayscale image to be represented as +RGB. This code will do that conversion: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + +Conversely, you can convert an RGB or RGBA image to grayscale or grayscale +with alpha. + + if (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) + png_set_rgb_to_gray_fixed(png_ptr, error_action, + int red_weight, int green_weight); + + error_action = 1: silently do the conversion + + error_action = 2: issue a warning if the original + image has any pixel where + red != green or red != blue + + error_action = 3: issue an error and abort the + conversion if the original + image has any pixel where + red != green or red != blue + + red_weight: weight of red component times 100000 + + green_weight: weight of green component times 100000 + If either weight is negative, default + weights (21268, 71514) are used. + +If you have set error_action = 1 or 2, you can +later check whether the image really was gray, after processing +the image rows, with the png_get_rgb_to_gray_status(png_ptr) function. +It will return a png_byte that is zero if the image was gray or +1 if there were any non-gray pixels. bKGD and sBIT data +will be silently converted to grayscale, using the green channel +data, regardless of the error_action setting. + +With red_weight+green_weight<=100000, +the normalized graylevel is computed: + + int rw = red_weight * 65536; + int gw = green_weight * 65536; + int bw = 65536 - (rw + gw); + gray = (rw*red + gw*green + bw*blue)/65536; + +The default values approximate those recommended in the Charles +Poynton's Color FAQ, +Copyright (c) 1998-01-04 Charles Poynton + + Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + +Libpng approximates this with integers scaled by 32768: + + Y = (6968 * R + 23434 * G + 2366 * B)/32768 + +The calculation is done in a linear colorspace, if the image gamma +can be determined. + +If you have a grayscale and you are using png_set_expand_depth(), +png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to +a higher bit-depth, you must either supply the background color as a gray +value at the original file bit-depth (need_expand = 1) or else supply the +background color as an RGB triplet at the final, expanded bit depth +(need_expand = 0). Similarly, if you are reading a paletted image, you +must either supply the background color as a palette index (need_expand = 1) +or as an RGB triplet that may or may not be in the palette (need_expand = 0). + + png_color_16 my_background; + png_color_16p image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background)) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + +The png_set_background() function tells libpng to composite images +with alpha or simple transparency against the supplied background +color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), +you may use this color, or supply another color more suitable for +the current display (e.g., the background color from a web page). You +need to tell libpng whether the color is in the gamma space of the +display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file +(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one +that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't +know why anyone would use this, but it's here). + +To properly display PNG images on any kind of system, the application needs +to know what the display gamma is. Ideally, the user will know this, and +the application will allow them to set it. One method of allowing the user +to set the display gamma separately for each system is to check for a +SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be +correctly set. + +Note that display_gamma is the overall gamma correction required to produce +pleasing results, which depends on the lighting conditions in the surrounding +environment. In a dim or brightly lit room, no compensation other than +the physical gamma exponent of the monitor is needed, while in a dark room +a slightly smaller exponent is better. + + double gamma, screen_gamma; + + if (/* We have a user-defined screen + gamma value */) + { + screen_gamma = user_defined_screen_gamma; + } + + /* One way that applications can share the same + screen gamma value */ + else if ((gamma_str = getenv("SCREEN_GAMMA")) + != NULL) + { + screen_gamma = (double)atof(gamma_str); + } + + /* If we don't have another value */ + else + { + screen_gamma = 2.2; /* A good guess for a + PC monitor in a bright office or a dim room */ + + screen_gamma = 2.0; /* A good guess for a + PC monitor in a dark room */ + + screen_gamma = 1.7 or 1.0; /* A good + guess for Mac systems */ + } + +The functions png_set_gamma() and its fixed point equivalent +png_set_gamma_fixed() handle gamma transformations of the data. +Pass both the file gamma and the current screen_gamma. If the file does +not have a gamma value, you can pass one anyway if you have an idea what +it is (usually 0.45455 is a good guess for GIF images on PCs). Note +that file gammas are inverted from screen gammas. See the discussions +on gamma in the PNG specification for an excellent description of what +gamma is, and why all applications should support it. It is strongly +recommended that PNG viewers support gamma correction. + + if (png_get_gAMA(png_ptr, info_ptr, &file_gamma)) + png_set_gamma(png_ptr, screen_gamma, file_gamma); + + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + +If you need to reduce an RGB file to a paletted file, or if a paletted +file has more entries then will fit on your screen, png_set_quantize() +will do that. Note that this is a simple match quantization that merely +finds the closest color available. This should work fairly well with +optimized palettes, but fairly badly with linear color cubes. If you +pass a palette that is larger then maximum_colors, the file will +reduce the number of colors in the palette so it will fit into +maximum_colors. If there is a histogram, it will use it to make +more intelligent choices when reducing the palette. If there is no +histogram, it may not do as good a job. + + if (color_type & PNG_COLOR_MASK_COLOR) + { + if (png_get_valid(png_ptr, info_ptr, + PNG_INFO_PLTE)) + { + png_uint_16p histogram = NULL; + + png_get_hIST(png_ptr, info_ptr, + &histogram); + png_set_quantize(png_ptr, palette, num_palette, + max_screen_colors, histogram, 1); + } + + else + { + png_color std_color_cube[MAX_SCREEN_COLORS] = + { ... colors ... }; + + png_set_quantize(png_ptr, std_color_cube, + MAX_SCREEN_COLORS, MAX_SCREEN_COLORS, + NULL,0); + } + } + +PNG files describe monochrome as black being zero and white being one. +The following code will reverse this (make black be one and white be +zero): + + if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY) + png_set_invert_mono(png_ptr); + +This function can also be used to invert grayscale and gray-alpha images: + + if (color_type == PNG_COLOR_TYPE_GRAY || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_invert_mono(png_ptr); + +PNG files store 16 bit pixels in network byte order (big-endian, +ie. most significant bits first). This code changes the storage to the +other way (little-endian, i.e. least significant bits first, the +way PCs store them): + + if (bit_depth == 16) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_read_user_transform_fn(png_ptr, + read_transform_fn); + +You must supply the function + + void read_transform_fn(png_structp png_ptr, row_info_ptr + row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +after all of the other transformations have been processed. Take care with +interlaced images if you do the interlace yourself - the width of the row is the +width in 'row_info', not the overall image width. + +If supported libpng provides two information routines that you can use to find +where you are in processing the image: + + png_get_current_pass_number(png_structp png_ptr); + png_get_current_row_number(png_structp png_ptr); + +Don't try using these outside a transform callback - firstly they are only +supported if user transforms are supported, secondly they may well return +unexpected results unless the row is actually being processed at the moment they +are called. + +You can also set up a pointer to a user structure for use by your +callback function, and you can inform libpng that your transform +function will change the number of channels or bit depth with the +function + + png_set_user_transform_info(png_ptr, user_ptr, + user_depth, user_channels); + +The user's application, not libpng, is responsible for allocating and +freeing any memory required for the user structure. + +You can retrieve the pointer via the function +png_get_user_transform_ptr(). For example: + + voidp read_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +The last thing to handle is interlacing; this is covered in detail below, +but you must call the function here if you want libpng to handle expansion +of the interlaced image. + + number_of_passes = png_set_interlace_handling(png_ptr); + +After setting the transformations, libpng can update your png_info +structure to reflect any transformations you've requested with this +call. This is most useful to update the info structure's rowbytes +field so you can use it to allocate your image memory. This function +will also update your palette with the correct screen_gamma and +background if these have been given with the calls above. + + png_read_update_info(png_ptr, info_ptr); + +After you call png_read_update_info(), you can allocate any +memory you need to hold the image. The row data is simply +raw byte data for all forms of images. As the actual allocation +varies among applications, no example will be given. If you +are allocating one large chunk, you will need to build an +array of pointers to each row, as it will be needed for some +of the functions below. + +Remember: Before you call png_read_update_info(), the png_get_ +functions return the values corresponding to the original PNG image. +After you call png_read_update_info the values refer to the image +that libpng will output. Consequently you must call all the png_set_ +functions before you call png_read_update_info(). This is particularly +important for png_set_interlace_handling() - if you are going to call +png_read_update_info() you must call png_set_interlace_handling() before +it unless you want to receive interlaced output. + +.SS Reading image data + +After you've allocated memory, you can read the image data. +The simplest way to do this is in one function call. If you are +allocating enough memory to hold the whole image, you can just +call png_read_image() and libpng will read in all the image data +and put it in the memory area supplied. You will need to pass in +an array of pointers to each row. + +This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() (unless you call +png_read_update_info()) or call this function multiple times, or any +of that other stuff necessary with png_read_rows(). + + png_read_image(png_ptr, row_pointers); + +where row_pointers is: + + png_bytep row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to read in the whole image at once, you can +use png_read_rows() instead. If there is no interlacing (check +interlace_type == PNG_INTERLACE_NONE), this is simple: + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +where row_pointers is the same as in the png_read_image() call. + +If you are doing this just one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + png_read_row(png_ptr, row_pointer, NULL); + +If the file is interlaced (interlace_type != 0 in the IHDR chunk), things +get somewhat harder. The only current (PNG Specification version 1.2) +interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7); +a somewhat complicated 2D interlace scheme, known as Adam7, that +breaks down an image into seven smaller images of varying size, based +on an 8x8 grid. This number is defined (from libpng 1.5) as +PNG_INTERLACE_ADAM7_PASSES in png.h + +libpng can fill out those images or it can give them to you "as is". +It is almost always better to have libpng handle the interlacing for you. +If you want the images filled out, there are two ways to do that. The one +mentioned in the PNG specification is to expand each pixel to cover +those pixels that have not been read yet (the "rectangle" method). +This results in a blocky image for the first pass, which gradually +smooths out as more pixels are read. The other method is the "sparkle" +method, where pixels are drawn only in their final locations, with the +rest of the image remaining whatever colors they were initialized to +before the start of the read. The first method usually looks better, +but tends to be slower, as there are more pixels to put in the rows. + +If, as is likely, you want libpng to expand the images, call this before +calling png_start_read_image() or png_read_update_info(): + + if (interlace_type == PNG_INTERLACE_ADAM7) + number_of_passes + = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this is seven, +but may change if another interlace type is added. This function can be +called even if the file is not interlaced, where it will return one pass. +You then need to read the whole image 'number_of_passes' times. Each time +will distribute the pixels from the current pass to the correct place in +the output image, so you need to supply the same rows to png_read_rows in +each pass. + +If you are not going to display the image after each pass, but are +going to wait until the entire image is read in, use the sparkle +effect. This effect is faster and the end result of either method +is exactly the same. If you are planning on displaying the image +after each pass, the "rectangle" effect is generally considered the +better looking one. + +If you only want the "sparkle" effect, just call png_read_rows() as +normal, with the third parameter NULL. Make sure you make pass over +the image number_of_passes times, and you don't change the data in the +rows between calls. You can change the locations of the data, just +not the data. Each pass only writes the pixels appropriate for that +pass, and assumes the data from previous passes is still valid. + + png_read_rows(png_ptr, row_pointers, NULL, + number_of_rows); + +If you only want the first effect (the rectangles), do the same as +before except pass the row buffer in the third parameter, and leave +the second parameter NULL. + + png_read_rows(png_ptr, NULL, row_pointers, + number_of_rows); + +If you don't want libpng to handle the interlacing details, just call +png_read_rows() PNG_INTERLACE_ADAM7_PASSES times to read in all the images. +Each of the images is a valid image by itself, however you will almost +certainly need to distribute the pixels from each sub-image to the +correct place. This is where everything gets very tricky. + +If you want to retrieve the separate images you must pass the correct +number of rows to each successive call of png_read_rows(). The calculation +gets pretty complicated for small images, where some sub-images may +not even exist because either their width or height ends up zero. +libpng provides two macros to help you in 1.5 and later versions: + + png_uint_32 width = PNG_PASS_COLS(image_width, pass_number); + png_uint_32 height = PNG_PASS_ROWS(image_height, pass_number); + +Respectively these tell you the width and height of the sub-image +corresponding to the numbered pass. 'pass' is in in the range 0 to 6 - +this can be confusing because the specification refers to the same passes +as 1 to 7! Be careful, you must check both the width and height before +calling png_read_rows() and not call it for that pass if either is zero. + +You can, of course, read each sub-image row by row. If you want to +produce optimal code to make a pixel-by-pixel transformation of an +interlaced image this is the best approach; read each row of each pass, +transform it, and write it out to a new interlaced image. + +If you want to de-interlace the image yourself libpng provides further +macros to help that tell you where to place the pixels in the output image. +Because the interlacing scheme is rectangular - sub-image pixels are always +arranged on a rectangular grid - all you need to know for each pass is the +starting column and row in the output image of the first pixel plus the +spacing between each pixel. As of libpng 1.5 there are four macros to +retrieve this information: + + png_uint_32 x = PNG_PASS_START_COL(pass); + png_uint_32 y = PNG_PASS_START_ROW(pass); + png_uint_32 xStep = 1U << PNG_PASS_COL_SHIFT(pass); + png_uint_32 yStep = 1U << PNG_PASS_ROW_SHIFT(pass); + +These allow you to write the obvious loop: + + png_uint_32 input_y = 0; + png_uint_32 output_y = PNG_PASS_START_ROW(pass); + + while (output_y < output_image_height) + { + png_uint_32 input_x = 0; + png_uint_32 output_x = PNG_PASS_START_COL(pass); + + while (output_x < output_image_width) + { + image[output_y][output_x] = + subimage[pass][input_y][input_x++]; + + output_x += xStep; + } + + ++input_y; + output_y += yStep; + } + +Notice that the steps between successive output rows and columns are +returned as shifts. This is possible because the pixels in the subimages +are always a power of 2 apart - 1, 2, 4 or 8 pixels - in the original +image. In practice you may need to directly calculate the output coordinate +given an input coordinate. libpng provides two further macros for this +purpose: + + png_uint_32 output_x = PNG_COL_FROM_PASS_COL(input_x, pass); + png_uint_32 output_y = PNG_ROW_FROM_PASS_ROW(input_y, pass); + +Finally a pair of macros are provided to tell you if a particular image +row or column appears in a given pass: + + int col_in_pass = PNG_COL_IN_INTERLACE_PASS(output_x, pass); + int row_in_pass = PNG_ROW_IN_INTERLACE_PASS(output_y, pass); + +Bear in mind that you will probably also need to check the width and height +of the pass in addition to the above to be sure the pass even exists! + +With any luck you are convinced by now that you don't want to do your own +interlace handling. In reality normally the only good reason for doing this +is if you are processing PNG files on a pixel-by-pixel basis and don't want +to load the whole file into memory when it is interlaced. + +libpng includes a test program, pngvalid, that illustrates reading and +writing of interlaced images. If you can't get interlacing to work in your +code and don't want to leave it to libpng (the recommended approach) see +how pngvalid.c does it. + +.SS Finishing a sequential read + +After you are finished reading the image through the +low-level interface, you can finish reading the file. If you are +interested in comments or time, which may be stored either before or +after the image data, you should pass the separate png_info struct if +you want to keep the comments from before and after the image +separate. If you are not interested, you can pass NULL. + + png_read_end(png_ptr, end_info); + +When you are done, you can free all memory allocated by libpng like this: + + png_destroy_read_struct(&png_ptr, &info_ptr, + &end_info); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not -1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + + mask - which data elements are affected + same choices as in png_free_data() + +This function only affects data that has already been allocated. +You can call this function after reading the PNG data but before calling +any png_set_*() functions, to control whether the user or the png_set_*() +function is responsible for freeing any existing data that might be present, +and again after the png_set_*() functions to control whether the user +or png_destroy_*() is supposed to free the data. When the user assumes +responsibility for libpng-allocated data, the application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated your row_pointers in a single block, as suggested above in +the description of the high level read interface, you must not transfer +responsibility for freeing it to the png_set_rows or png_read_destroy function, +because they would also try to free the individual row_pointers[i]. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. + +The png_free_data() function will turn off the "valid" flag for anything +it frees. If you need to turn the flag off for a chunk that was freed by +your application instead of by libpng, you can use + + png_set_invalid(png_ptr, info_ptr, mask); + + mask - identifies the chunks to be made invalid, + containing the bitwise OR of one or + more of + PNG_INFO_gAMA, PNG_INFO_sBIT, + PNG_INFO_cHRM, PNG_INFO_PLTE, + PNG_INFO_tRNS, PNG_INFO_bKGD, + PNG_INFO_hIST, PNG_INFO_pHYs, + PNG_INFO_oFFs, PNG_INFO_tIME, + PNG_INFO_pCAL, PNG_INFO_sRGB, + PNG_INFO_iCCP, PNG_INFO_sPLT, + PNG_INFO_sCAL, PNG_INFO_IDAT + +For a more compact example of reading a PNG image, see the file example.c. + +.SS Reading PNG files progressively + +The progressive reader is slightly different then the non-progressive +reader. Instead of calling png_read_info(), png_read_rows(), and +png_read_end(), you make one call to png_process_data(), which calls +callbacks when it has the info, a row, or the end of the image. You +set up these callbacks with png_set_progressive_read_fn(). You don't +have to worry about the input/output functions of libpng, as you are +giving the library the data directly in png_process_data(). I will +assume that you have read the section on reading PNG files above, +so I will only highlight the differences (although I will show +all of the code). + +png_structp png_ptr; +png_infop info_ptr; + + /* An example code fragment of how you would + initialize the progressive reader in your + application. */ + int + initialize_png_reader() + { + png_ptr = png_create_read_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return (ERROR); + + info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + { + png_destroy_read_struct(&png_ptr, + (png_infopp)NULL, (png_infopp)NULL); + return (ERROR); + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new. You can provide functions + to be called when the header info is valid, + when each row is completed, and when the image + is finished. If you aren't using all functions, + you can specify NULL parameters. Even when all + three functions are NULL, you need to call + png_set_progressive_read_fn(). You can use + any struct as the user_ptr (cast to a void pointer + for the function call), and retrieve the pointer + from inside the callbacks using the function + + png_get_progressive_ptr(png_ptr); + + which will return a void pointer, which you have + to cast appropriately. + */ + png_set_progressive_read_fn(png_ptr, (void *)user_ptr, + info_callback, row_callback, end_callback); + + return 0; + } + + /* A code fragment that you call as you receive blocks + of data */ + int + process_data(png_bytep buffer, png_uint_32 length) + { + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } + + /* This one's new also. Simply give it a chunk + of data from the file stream (in order, of + course). On machines with segmented memory + models machines, don't give it any more than + 64K. The library seems to run fine with sizes + of 4K. Although you can give it much less if + necessary (I assume you can give it chunks of + 1 byte, I haven't tried less then 256 bytes + yet). When this function returns, you may + want to display any rows that were generated + in the row callback if you don't already do + so there. + */ + png_process_data(png_ptr, info_ptr, buffer, length); + + /* At this point you can call png_process_data_skip if + you want to handle data the library will skip yourself; + it simply returns the number of bytes to skip (and stops + libpng skipping that number of bytes on the next + png_process_data call). + return 0; + } + + /* This function is called (as set by + png_set_progressive_read_fn() above) when enough data + has been supplied so all of the header has been + read. + */ + void + info_callback(png_structp png_ptr, png_infop info) + { + /* Do any setup here, including setting any of + the transformations mentioned in the Reading + PNG files section. For now, you _must_ call + either png_start_read_image() or + png_read_update_info() after all the + transformations are set (even if you don't set + any). You may start getting rows before + png_process_data() returns, so this is your + last chance to prepare for that. + + This is where you turn on interlace handling, + assuming you don't want to do it yourself. + + If you need to you can stop the processing of + your original input data at this point by calling + png_process_data_pause. This returns the number + of unprocessed bytes from the last png_process_data + call - it is up to you to ensure that the next call + sees these bytes again. If you don't want to bother + with this you can get libpng to cache the unread + bytes by setting the 'save' parameter (see png.h) but + then libpng will have to copy the data internally. + */ + } + + /* This function is called when each row of image + data is complete */ + void + row_callback(png_structp png_ptr, png_bytep new_row, + png_uint_32 row_num, int pass) + { + /* If the image is interlaced, and you turned + on the interlace handler, this function will + be called for every row in every pass. Some + of these rows will not be changed from the + previous pass. When the row is not changed, + the new_row variable will be NULL. The rows + and passes are called in order, so you don't + really need the row_num and pass, but I'm + supplying them because it may make your life + easier. + + If you did not turn on interlace handling then + the callback is called for each row of each + sub-image when the image is interlaced. In this + case 'row_num' is the row in the sub-image, not + the row in the output image as it is in all other + cases. + + For the non-NULL rows of interlaced images when + you have switched on libpng interlace handling, + you must call png_progressive_combine_row() + passing in the row and the old row. You can + call this function for NULL rows (it will just + return) and for non-interlaced images (it just + does the memcpy for you) if it will make the + code easier. Thus, you can just do this for + all cases if you switch on interlace handling; + */ + + png_progressive_combine_row(png_ptr, old_row, + new_row); + + /* where old_row is what was displayed for + previously for the row. Note that the first + pass (pass == 0, really) will completely cover + the old row, so the rows do not have to be + initialized. After the first pass (and only + for interlaced images), you will have to pass + the current row, and the function will combine + the old row and the new row. + + You can also call png_process_data_pause in this + callback - see above. + */ + } + + void + end_callback(png_structp png_ptr, png_infop info) + { + /* This function is called after the whole image + has been read, including any chunks after the + image (up to and including the IEND). You + will usually have the same info chunk as you + had in the header, although some data may have + been added to the comments and time fields. + + Most people won't do much here, perhaps setting + a flag that marks the image as finished. + */ + } + + + +.SH IV. Writing + +Much of this is very similar to reading. However, everything of +importance is repeated here, so you won't have to constantly look +back up in the reading section to understand writing. + +.SS Setup + +You will want to do the I/O initialization before you get into libpng, +so if it doesn't work, you don't have anything to undo. If you are not +using the standard I/O functions, you will need to replace them with +custom writing functions. See the discussion under Customizing libpng. + + FILE *fp = fopen(file_name, "wb"); + + if (!fp) + return (ERROR); + +Next, png_struct and png_info need to be allocated and initialized. +As these can be both relatively large, you may not want to store these +on the stack, unless you have stack space to spare. Of course, you +will want to check if they return NULL. If you are also reading, +you won't want to name your read structure and your write structure +both "png_ptr"; you can call them anything you like, such as +"read_ptr" and "write_ptr". Look at pngtest.c, for example. + + png_structp png_ptr = png_create_write_struct + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn); + + if (!png_ptr) + return (ERROR); + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, + (png_infopp)NULL); + return (ERROR); + } + +If you want to use your own memory allocation routines, +define PNG_USER_MEM_SUPPORTED and use +png_create_write_struct_2() instead of png_create_write_struct(): + + png_structp png_ptr = png_create_write_struct_2 + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + user_error_fn, user_warning_fn, (png_voidp) + user_mem_ptr, user_malloc_fn, user_free_fn); + +After you have these structures, you will need to set up the +error handling. When libpng encounters an error, it expects to +longjmp() back to your routine. Therefore, you will need to call +setjmp() and pass the png_jmpbuf(png_ptr). If you +write the file from different routines, you will need to update +the png_jmpbuf(png_ptr) every time you enter a new routine that will +call a png_*() function. See your documentation of setjmp/longjmp +for your compiler for more information on setjmp/longjmp. See +the discussion on libpng error handling in the Customizing Libpng +section below for more information on the libpng error handling. + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fp); + return (ERROR); + } + ... + return; + +If you would rather avoid the complexity of setjmp/longjmp issues, +you can compile libpng with PNG_NO_SETJMP, in which case +errors will result in a call to PNG_ABORT() which defaults to abort(). + +You can #define PNG_ABORT() to a function that does something +more useful than abort(), as long as your function does not +return. + +Now you need to set up the output code. The default for libpng is to +use the C function fwrite(). If you use this, you will need to pass a +valid FILE * in the function png_init_io(). Be sure that the file is +opened in binary mode. Again, if you wish to handle writing data in +another way, see the discussion on libpng I/O handling in the Customizing +Libpng section below. + + png_init_io(png_ptr, fp); + +If you are embedding your PNG into a datastream such as MNG, and don't +want libpng to write the 8-byte signature, or if you have already +written the signature in your application, use + + png_set_sig_bytes(png_ptr, 8); + +to inform libpng that it should not write a signature. + +.SS Write callbacks + +At this point, you can set up a callback function that will be +called after each row has been written, which you can use to control +a progress meter or the like. It's demonstrated in pngtest.c. +You must supply a function + + void write_row_callback(png_structp png_ptr, png_uint_32 row, + int pass); + { + /* put your code here */ + } + +(You can give it another name that you like instead of "write_row_callback") + +To inform libpng about your function, use + + png_set_write_status_fn(png_ptr, write_row_callback); + +You now have the option of modifying how the compression library will +run. The following functions are mainly for testing, but may be useful +in some cases, like if you need to write PNG files extremely fast and +are willing to give up some compression, or if you want to get the +maximum possible compression at the expense of slower writing. If you +have no special needs in this area, let the library do what it wants by +not calling this function at all, as it has been tuned to deliver a good +speed/compression ratio. The second parameter to png_set_filter() is +the filter method, for which the only valid values are 0 (as of the +July 1999 PNG specification, version 1.2) or 64 (if you are writing +a PNG datastream that is to be embedded in a MNG datastream). The third +parameter is a flag that indicates which filter type(s) are to be tested +for each scanline. See the PNG specification for details on the specific +filter types. + + + /* turn on or off filtering, and/or choose + specific filters. You can use either a single + PNG_FILTER_VALUE_NAME or the bitwise OR of one + or more PNG_FILTER_NAME masks. + */ + png_set_filter(png_ptr, 0, + PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE | + PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB | + PNG_FILTER_UP | PNG_FILTER_VALUE_UP | + PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG | + PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH| + PNG_ALL_FILTERS); + +If an application wants to start and stop using particular filters during +compression, it should start out with all of the filters (to ensure that +the previous row of pixels will be stored in case it's needed later), +and then add and remove them after the start of compression. + +If you are writing a PNG datastream that is to be embedded in a MNG +datastream, the second parameter can be either 0 or 64. + +The png_set_compression_*() functions interface to the zlib compression +library, and should mostly be ignored unless you really know what you are +doing. The only generally useful call is png_set_compression_level() +which changes how much time zlib spends on trying to compress the image +data. See the Compression Library (zlib.h and algorithm.txt, distributed +with zlib) for details on the compression levels. + + /* set the zlib compression level */ + png_set_compression_level(png_ptr, + Z_BEST_COMPRESSION); + + /* set other zlib parameters */ + png_set_compression_mem_level(png_ptr, 8); + png_set_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_compression_window_bits(png_ptr, 15); + png_set_compression_method(png_ptr, 8); + png_set_compression_buffer_size(png_ptr, 8192) + +extern PNG_EXPORT(void,png_set_zbuf_size) + +.SS Setting the contents of info for output + +You now need to fill in the png_info structure with all the data you +wish to write before the actual image. Note that the only thing you +are allowed to write after the image is the text chunks and the time +chunk (as of PNG Specification 1.2, anyway). See png_write_end() and +the latest PNG specification for more information on that. If you +wish to write them before the image, fill them in now, and flag that +data as being valid. If you want to wait until after the data, don't +fill them until png_write_end(). For all the fields in png_info and +their data types, see png.h. For explanations of what the fields +contain, see the PNG specification. + +Some of the more important parts of the png_info are: + + png_set_IHDR(png_ptr, info_ptr, width, height, + bit_depth, color_type, interlace_type, + compression_type, filter_method) + + width - holds the width of the image + in pixels (up to 2^31). + + height - holds the height of the image + in pixels (up to 2^31). + + bit_depth - holds the bit depth of one of the + image channels. + (valid values are 1, 2, 4, 8, 16 + and depend also on the + color_type. See also significant + bits (sBIT) below). + + color_type - describes which color/alpha + channels are present. + PNG_COLOR_TYPE_GRAY + (bit depths 1, 2, 4, 8, 16) + PNG_COLOR_TYPE_GRAY_ALPHA + (bit depths 8, 16) + PNG_COLOR_TYPE_PALETTE + (bit depths 1, 2, 4, 8) + PNG_COLOR_TYPE_RGB + (bit_depths 8, 16) + PNG_COLOR_TYPE_RGB_ALPHA + (bit_depths 8, 16) + + PNG_COLOR_MASK_PALETTE + PNG_COLOR_MASK_COLOR + PNG_COLOR_MASK_ALPHA + + interlace_type - PNG_INTERLACE_NONE or + PNG_INTERLACE_ADAM7 + + compression_type - (must be + PNG_COMPRESSION_TYPE_DEFAULT) + + filter_method - (must be PNG_FILTER_TYPE_DEFAULT + or, if you are writing a PNG to + be embedded in a MNG datastream, + can also be + PNG_INTRAPIXEL_DIFFERENCING) + +If you call png_set_IHDR(), the call must appear before any of the +other png_set_*() functions, because they might require access to some of +the IHDR settings. The remaining png_set_*() functions can be called +in any order. + +If you wish, you can reset the compression_type, interlace_type, or +filter_method later by calling png_set_IHDR() again; if you do this, the +width, height, bit_depth, and color_type must be the same in each call. + + png_set_PLTE(png_ptr, info_ptr, palette, + num_palette); + + palette - the palette for the file + (array of png_color) + num_palette - number of entries in the palette + + png_set_gAMA(png_ptr, info_ptr, file_gamma); + png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); + + file_gamma - the gamma at which the image was + created (PNG_INFO_gAMA) + + int_file_gamma - 100,000 times the gamma at which + the image was created + + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of + the sRGB chunk means that the pixel + data is in the sRGB color space. + This chunk also implies specific + values of gAMA and cHRM. Rendering + intent is the CSS-1 property that + has been defined by the International + Color Consortium + (http://www.color.org). + It can be one of + PNG_sRGB_INTENT_SATURATION, + PNG_sRGB_INTENT_PERCEPTUAL, + PNG_sRGB_INTENT_ABSOLUTE, or + PNG_sRGB_INTENT_RELATIVE. + + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, + srgb_intent); + + srgb_intent - the rendering intent + (PNG_INFO_sRGB) The presence of the + sRGB chunk means that the pixel + data is in the sRGB color space. + This function also causes gAMA and + cHRM chunks with the specific values + that are consistent with sRGB to be + written. + + png_set_iCCP(png_ptr, info_ptr, name, compression_type, + profile, proflen); + + name - The profile name. + + compression_type - The compression type; always + PNG_COMPRESSION_TYPE_BASE for PNG 1.0. + You may give NULL to this argument to + ignore it. + + profile - International Color Consortium color + profile data. May contain NULs. + + proflen - length of profile data in bytes. + + png_set_sBIT(png_ptr, info_ptr, sig_bit); + + sig_bit - the number of significant bits for + (PNG_INFO_sBIT) each of the gray, red, + green, and blue channels, whichever are + appropriate for the given color type + (png_color_16) + + png_set_tRNS(png_ptr, info_ptr, trans_alpha, + num_trans, trans_color); + + trans_alpha - array of alpha (transparency) + entries for palette (PNG_INFO_tRNS) + + trans_color - graylevel or color sample values + (in order red, green, blue) of the + single transparent color for + non-paletted images (PNG_INFO_tRNS) + + num_trans - number of transparent entries + (PNG_INFO_tRNS) + + png_set_hIST(png_ptr, info_ptr, hist); + + hist - histogram of palette (array of + png_uint_16) (PNG_INFO_hIST) + + png_set_tIME(png_ptr, info_ptr, mod_time); + + mod_time - time image was last modified + (PNG_VALID_tIME) + + png_set_bKGD(png_ptr, info_ptr, background); + + background - background color (PNG_VALID_bKGD) + + png_set_text(png_ptr, info_ptr, text_ptr, num_text); + + text_ptr - array of png_text holding image + comments + + text_ptr[i].compression - type of compression used + on "text" PNG_TEXT_COMPRESSION_NONE + PNG_TEXT_COMPRESSION_zTXt + PNG_ITXT_COMPRESSION_NONE + PNG_ITXT_COMPRESSION_zTXt + text_ptr[i].key - keyword for comment. Must contain + 1-79 characters. + text_ptr[i].text - text comments for current + keyword. Can be NULL or empty. + text_ptr[i].text_length - length of text string, + after decompression, 0 for iTXt + text_ptr[i].itxt_length - length of itxt string, + after decompression, 0 for tEXt/zTXt + text_ptr[i].lang - language of comment (NULL or + empty for unknown). + text_ptr[i].translated_keyword - keyword in UTF-8 (NULL + or empty for unknown). + Note that the itxt_length, lang, and lang_key + members of the text_ptr structure only exist + when the library is built with iTXt chunk support. + + num_text - number of comments + + png_set_sPLT(png_ptr, info_ptr, &palette_ptr, + num_spalettes); + + palette_ptr - array of png_sPLT_struct structures + to be added to the list of palettes + in the info structure. + num_spalettes - number of palette structures to be + added. + + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, + unit_type); + + offset_x - positive offset from the left + edge of the screen + + offset_y - positive offset from the top + edge of the screen + + unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER + + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, + unit_type); + + res_x - pixels/unit physical resolution + in x direction + + res_y - pixels/unit physical resolution + in y direction + + unit_type - PNG_RESOLUTION_UNKNOWN, + PNG_RESOLUTION_METER + + png_set_sCAL(png_ptr, info_ptr, unit, width, height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are doubles) + + png_set_sCAL_s(png_ptr, info_ptr, unit, width, height) + + unit - physical scale units (an integer) + + width - width of a pixel in physical scale units + + height - height of a pixel in physical scale units + (width and height are strings like "2.54") + + png_set_unknown_chunks(png_ptr, info_ptr, &unknowns, + num_unknowns) + + unknowns - array of png_unknown_chunk + structures holding unknown chunks + unknowns[i].name - name of unknown chunk + unknowns[i].data - data of unknown chunk + unknowns[i].size - size of unknown chunk's data + unknowns[i].location - position to write chunk in file + 0: do not write chunk + PNG_HAVE_IHDR: before PLTE + PNG_HAVE_PLTE: before IDAT + PNG_AFTER_IDAT: after IDAT + +The "location" member is set automatically according to +what part of the output file has already been written. +You can change its value after calling png_set_unknown_chunks() +as demonstrated in pngtest.c. Within each of the "locations", +the chunks are sequenced according to their position in the +structure (that is, the value of "i", which is the order in which +the chunk was either read from the input file or defined with +png_set_unknown_chunks). + +A quick word about text and num_text. text is an array of png_text +structures. num_text is the number of valid structures in the array. +Each png_text structure holds a language code, a keyword, a text value, +and a compression type. + +The compression types have the same valid numbers as the compression +types of the image data. Currently, the only valid number is zero. +However, you can store text either compressed or uncompressed, unlike +images, which always have to be compressed. So if you don't want the +text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE. +Because tEXt and zTXt chunks don't have a language field, if you +specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt +any language code or translated keyword will not be written out. + +Until text gets around 1000 bytes, it is not worth compressing it. +After the text has been written out to the file, the compression type +is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR, +so that it isn't written out again at the end (in case you are calling +png_write_end() with the same struct). + +The keywords that are given in the PNG Specification are: + + Title Short (one line) title or + caption for image + + Author Name of image's creator + + Description Description of image (possibly long) + + Copyright Copyright notice + + Creation Time Time of original image creation + (usually RFC 1123 format, see below) + + Software Software used to create the image + + Disclaimer Legal disclaimer + + Warning Warning of nature of content + + Source Device used to create the image + + Comment Miscellaneous comment; conversion + from other image format + +The keyword-text pairs work like this. Keywords should be short +simple descriptions of what the comment is about. Some typical +keywords are found in the PNG specification, as is some recommendations +on keywords. You can repeat keywords in a file. You can even write +some text before the image and some after. For example, you may want +to put a description of the image before the image, but leave the +disclaimer until after, so viewers working over modem connections +don't have to wait for the disclaimer to go over the modem before +they start seeing the image. Finally, keywords should be full +words, not abbreviations. Keywords and text are in the ISO 8859-1 +(Latin-1) character set (a superset of regular ASCII) and can not +contain NUL characters, and should not contain control or other +unprintable characters. To make the comments widely readable, stick +with basic ASCII, and avoid machine specific character set extensions +like the IBM-PC character set. The keyword must be present, but +you can leave off the text string on non-compressed pairs. +Compressed pairs must have a text string, as only the text string +is compressed anyway, so the compression would be meaningless. + +PNG supports modification time via the png_time structure. Two +conversion routines are provided, png_convert_from_time_t() for +time_t and png_convert_from_struct_tm() for struct tm. The +time_t routine uses gmtime(). You don't have to use either of +these, but if you wish to fill in the png_time structure directly, +you should provide the time in universal time (GMT) if possible +instead of your local time. Note that the year number is the full +year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and +that months start with 1. + +If you want to store the time of the original image creation, you should +use a plain tEXt chunk with the "Creation Time" keyword. This is +necessary because the "creation time" of a PNG image is somewhat vague, +depending on whether you mean the PNG file, the time the image was +created in a non-PNG format, a still photo from which the image was +scanned, or possibly the subject matter itself. In order to facilitate +machine-readable dates, it is recommended that the "Creation Time" +tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"), +although this isn't a requirement. Unlike the tIME chunk, the +"Creation Time" tEXt chunk is not expected to be automatically changed +by the software. To facilitate the use of RFC 1123 dates, a function +png_convert_to_rfc1123(png_timep) is provided to convert from PNG +time to an RFC 1123 format string. + +.SS Writing unknown chunks + +You can use the png_set_unknown_chunks function to queue up chunks +for writing. You give it a chunk name, raw data, and a size; that's +all there is to it. The chunks will be written by the next following +png_write_info_before_PLTE, png_write_info, or png_write_end function. +Any chunks previously read into the info structure's unknown-chunk +list will also be written out in a sequence that satisfies the PNG +specification's ordering rules. + +.SS The high-level write interface + +At this point there are two ways to proceed; through the high-level +write interface, or through a sequence of low-level write operations. +You can use the high-level interface if your image data is present +in the info structure. All defined output +transformations are permitted, enabled by the following masks. + + PNG_TRANSFORM_IDENTITY No transformation + PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples + PNG_TRANSFORM_PACKSWAP Change order of packed + pixels to LSB first + PNG_TRANSFORM_INVERT_MONO Invert monochrome images + PNG_TRANSFORM_SHIFT Normalize pixels to the + sBIT depth + PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA + to BGRA + PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA + to AG + PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity + to transparency + PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples + PNG_TRANSFORM_STRIP_FILLER Strip out filler + bytes (deprecated). + PNG_TRANSFORM_STRIP_FILLER_BEFORE Strip out leading + filler bytes + PNG_TRANSFORM_STRIP_FILLER_AFTER Strip out trailing + filler bytes + +If you have valid image data in the info structure (you can use +png_set_rows() to put image data in the info structure), simply do this: + + png_write_png(png_ptr, info_ptr, png_transforms, NULL) + +where png_transforms is an integer containing the bitwise OR of some set of +transformation flags. This call is equivalent to png_write_info(), +followed the set of transformations indicated by the transform mask, +then png_write_image(), and finally png_write_end(). + +(The final parameter of this call is not yet used. Someday it might point +to transformation parameters required by some future output transform.) + +You must use png_transforms and not call any png_set_transform() functions +when you use png_write_png(). + +.SS The low-level write interface + +If you are going the low-level route instead, you are now ready to +write all the file information up to the actual image data. You do +this with a call to png_write_info(). + + png_write_info(png_ptr, info_ptr); + +Note that there is one transformation you may need to do before +png_write_info(). In PNG files, the alpha channel in an image is the +level of opacity. If your data is supplied as a level of transparency, +you can invert the alpha channel before you write it, so that 0 is +fully transparent and 255 (in 8-bit or paletted images) or 65535 +(in 16-bit images) is fully opaque, with + + png_set_invert_alpha(png_ptr); + +This must appear before png_write_info() instead of later with the +other transformations because in the case of paletted images the tRNS +chunk data has to be inverted before the tRNS chunk is written. If +your image is not a paletted image, the tRNS data (which in such cases +represents a single color to be rendered as transparent) won't need to +be changed, and you can safely do this transformation after your +png_write_info() call. + +If you need to write a private chunk that you want to appear before +the PLTE chunk when PLTE is present, you can write the PNG info in +two steps, and insert code to write your own chunk between them: + + png_write_info_before_PLTE(png_ptr, info_ptr); + png_set_unknown_chunks(png_ptr, info_ptr, ...); + png_write_info(png_ptr, info_ptr); + +After you've written the file information, you can set up the library +to handle any special transformations of the image data. The various +ways to transform the data will be described in the order that they +should occur. This is important, as some of these change the color +type and/or bit depth of the data, and some others only work on +certain color types and bit depths. Even though each transformation +checks to see if it has data that it can do something with, you should +make sure to only enable a transformation if it will be valid for the +data. For example, don't swap red and blue on grayscale data. + +PNG files store RGB pixels packed into 3 or 6 bytes. This code tells +the library to strip input data that has 4 or 8 bytes per pixel down +to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2 +bytes per pixel). + + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + +where the 0 is unused, and the location is either PNG_FILLER_BEFORE or +PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel +is stored XRGB or RGBX. + +PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as +they can, resulting in, for example, 8 pixels per byte for 1 bit files. +If the data is supplied at 1 pixel per byte, use this code, which will +correctly pack the pixels into a single byte: + + png_set_packing(png_ptr); + +PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your +data is of another bit depth, you can write an sBIT chunk into the +file so that decoders can recover the original data if desired. + + /* Set the true bit depth of the image data */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit.red = true_bit_depth; + sig_bit.green = true_bit_depth; + sig_bit.blue = true_bit_depth; + } + + else + { + sig_bit.gray = true_bit_depth; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + sig_bit.alpha = true_bit_depth; + } + + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + +If the data is stored in the row buffer in a bit depth other than +one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG), +this will scale the values to appear to be the correct bit depth as +is required by PNG. + + png_set_shift(png_ptr, &sig_bit); + +PNG files store 16 bit pixels in network byte order (big-endian, +ie. most significant bits first). This code would be used if they are +supplied the other way (little-endian, i.e. least significant bits +first, the way PCs store them): + + if (bit_depth > 8) + png_set_swap(png_ptr); + +If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you +need to change the order the pixels are packed into bytes, you can use: + + if (bit_depth < 8) + png_set_packswap(png_ptr); + +PNG files store 3 color pixels in red, green, blue order. This code +would be used if they are supplied as blue, green, red: + + png_set_bgr(png_ptr); + +PNG files describe monochrome as black being zero and white being +one. This code would be used if the pixels are supplied with this reversed +(black being one and white being zero): + + png_set_invert_mono(png_ptr); + +Finally, you can write your own transformation function if none of +the existing ones meets your needs. This is done by setting a callback +with + + png_set_write_user_transform_fn(png_ptr, + write_transform_fn); + +You must supply the function + + void write_transform_fn(png_structp png_ptr ptr, + row_info_ptr row_info, png_bytep data) + +See pngtest.c for a working example. Your function will be called +before any of the other transformations are processed. If supported +libpng also supplies an information routine that may be called from +your callback: + + png_get_current_row_number(png_ptr); + +This returns the current row passed to the transform. Even with interlaced +images the value returned is the row in the final output image. + +You can also set up a pointer to a user structure for use by your +callback function. + + png_set_user_transform_info(png_ptr, user_ptr, 0, 0); + +The user_channels and user_depth parameters of this function are ignored +when writing; you can set them to zero as shown. + +You can retrieve the pointer via the function png_get_user_transform_ptr(). +For example: + + voidp write_user_transform_ptr = + png_get_user_transform_ptr(png_ptr); + +It is possible to have libpng flush any pending output, either manually, +or automatically after a certain number of lines have been written. To +flush the output stream a single time call: + + png_write_flush(png_ptr); + +and to have libpng flush the output stream periodically after a certain +number of scanlines have been written, call: + + png_set_flush(png_ptr, nrows); + +Note that the distance between rows is from the last time png_write_flush() +was called, or the first row of the image if it has never been called. +So if you write 50 lines, and then png_set_flush 25, it will flush the +output on the next scanline, and every 25 lines thereafter, unless +png_write_flush() is called before 25 more lines have been written. +If nrows is too small (less than about 10 lines for a 640 pixel wide +RGB image) the image compression may decrease noticeably (although this +may be acceptable for real-time applications). Infrequent flushing will +only degrade the compression performance by a few percent over images +that do not use flushing. + +.SS Writing the image data + +That's it for the transformations. Now you can write the image data. +The simplest way to do this is in one function call. If you have the +whole image in memory, you can just call png_write_image() and libpng +will write the image. You will need to pass in an array of pointers to +each row. This function automatically handles interlacing, so you don't +need to call png_set_interlace_handling() or call this function multiple +times, or any of that other stuff necessary with png_write_rows(). + + png_write_image(png_ptr, row_pointers); + +where row_pointers is: + + png_byte *row_pointers[height]; + +You can point to void or char or whatever you use for pixels. + +If you don't want to write the whole image at once, you can +use png_write_rows() instead. If the file is not interlaced, +this is simple: + + png_write_rows(png_ptr, row_pointers, + number_of_rows); + +row_pointers is the same as in the png_write_image() call. + +If you are just writing one row at a time, you can do this with +a single row_pointer instead of an array of row_pointers: + + png_bytep row_pointer = row; + + png_write_row(png_ptr, row_pointer); + +When the file is interlaced, things can get a good deal more complicated. +The only currently (as of the PNG Specification version 1.2, dated July +1999) defined interlacing scheme for PNG files is the "Adam7" interlace +scheme, that breaks down an image into seven smaller images of varying +size. libpng will build these images for you, or you can do them +yourself. If you want to build them yourself, see the PNG specification +for details of which pixels to write when. + +If you don't want libpng to handle the interlacing details, just +use png_set_interlace_handling() and call png_write_rows() the +correct number of times to write all the sub-images +(png_set_interlace_handling() returns the number of sub-images.) + +If you want libpng to build the sub-images, call this before you start +writing any rows: + + number_of_passes = png_set_interlace_handling(png_ptr); + +This will return the number of passes needed. Currently, this is seven, +but may change if another interlace type is added. + +Then write the complete image number_of_passes times. + + png_write_rows(png_ptr, row_pointers, number_of_rows); + +Think carefully before you write an interlaced image. Typically code that +reads such images reads all the image data into memory, uncompressed, before +doing any processing. Only code that can display an image on the fly can +take advantage of the interlacing and even then the image has to be exactly +the correct size for the output device, because scaling an image requires +adjacent pixels and these are not available until all the passes have been +read. + +If you do write an interlaced image you will hardly ever need to handle +the interlacing yourself. Call png_set_interlace_handling() and use the +approach described above. + +The only time it is conceivable that you will really need to write an +interlaced image pass-by-pass is when you have read one pass by pass and +made some pixel-by-pixel transformation to it, as described in the read +code above. In this case use the PNG_PASS_ROWS and PNG_PASS_COLS macros +to determine the size of each sub-image in turn and simply write the rows +you obtained from the read code. + +.SS Finishing a sequential write + +After you are finished writing the image, you should finish writing +the file. If you are interested in writing comments or time, you should +pass an appropriately filled png_info pointer. If you are not interested, +you can pass NULL. + + png_write_end(png_ptr, info_ptr); + +When you are done, you can free all memory used by libpng like this: + + png_destroy_write_struct(&png_ptr, &info_ptr); + +It is also possible to individually free the info_ptr members that +point to libpng-allocated storage with the following function: + + png_free_data(png_ptr, info_ptr, mask, seq) + + mask - identifies data to be freed, a mask + containing the bitwise OR of one or + more of + PNG_FREE_PLTE, PNG_FREE_TRNS, + PNG_FREE_HIST, PNG_FREE_ICCP, + PNG_FREE_PCAL, PNG_FREE_ROWS, + PNG_FREE_SCAL, PNG_FREE_SPLT, + PNG_FREE_TEXT, PNG_FREE_UNKN, + or simply PNG_FREE_ALL + + seq - sequence number of item to be freed + (-1 for all items) + +This function may be safely called when the relevant storage has +already been freed, or has not yet been allocated, or was allocated +by the user and not by libpng, and will in those cases do nothing. +The "seq" parameter is ignored if only one item of the selected data +type, such as PLTE, is allowed. If "seq" is not -1, and multiple items +are allowed for the data type identified in the mask, such as text or +sPLT, only the n'th item in the structure is freed, where n is "seq". + +If you allocated data such as a palette that you passed in to libpng +with png_set_*, you must not free it until just before the call to +png_destroy_write_struct(). + +The default behavior is only to free data that was allocated internally +by libpng. This can be changed, so that libpng will not free the data, +or so that it will free data that was allocated by the user with png_malloc() +or png_zalloc() and passed in via a png_set_*() function, with + + png_data_freer(png_ptr, info_ptr, freer, mask) + + freer - one of + PNG_DESTROY_WILL_FREE_DATA + PNG_SET_WILL_FREE_DATA + PNG_USER_WILL_FREE_DATA + + mask - which data elements are affected + same choices as in png_free_data() + +For example, to transfer responsibility for some data from a read structure +to a write structure, you could use + + png_data_freer(read_ptr, read_info_ptr, + PNG_USER_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + + png_data_freer(write_ptr, write_info_ptr, + PNG_DESTROY_WILL_FREE_DATA, + PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST) + +thereby briefly reassigning responsibility for freeing to the user but +immediately afterwards reassigning it once more to the write_destroy +function. Having done this, it would then be safe to destroy the read +structure and continue to use the PLTE, tRNS, and hIST data in the write +structure. + +This function only affects data that has already been allocated. +You can call this function before calling after the png_set_*() functions +to control whether the user or png_destroy_*() is supposed to free the data. +When the user assumes responsibility for libpng-allocated data, the +application must use +png_free() to free it, and when the user transfers responsibility to libpng +for data that the user has allocated, the user must have used png_malloc() +or png_zalloc() to allocate it. + +If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword +separately, do not transfer responsibility for freeing text_ptr to libpng, +because when libpng fills a png_text structure it combines these members with +the key member, and png_free_data() will free only text_ptr.key. Similarly, +if you transfer responsibility for free'ing text_ptr from libpng to your +application, your application must not separately free those members. +For a more compact example of writing a PNG image, see the file example.c. + +.SH V. Modifying/Customizing libpng: + +There are two issues here. The first is changing how libpng does +standard things like memory allocation, input/output, and error handling. +The second deals with more complicated things like adding new chunks, +adding new transformations, and generally changing how libpng works. +Both of those are compile-time issues; that is, they are generally +determined at the time the code is written, and there is rarely a need +to provide the user with a means of changing them. + +Memory allocation, input/output, and error handling + +All of the memory allocation, input/output, and error handling in libpng +goes through callbacks that are user-settable. The default routines are +in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change +these functions, call the appropriate png_set_*_fn() function. + +Memory allocation is done through the functions png_malloc(), png_calloc(), +and png_free(). These currently just call the standard C functions. +png_calloc() calls png_malloc() and then clears the newly +allocated memory to zero. There is limited support for certain systems +with segmented memory architectures and the types of pointers declared by +png.h match this; you will have to use appropriate pointers in your +application. Since it is +unlikely that the method of handling memory allocation on a platform +will change between applications, these functions must be modified in +the library at compile time. If you prefer to use a different method +of allocating and freeing data, you can use png_create_read_struct_2() or +png_create_write_struct_2() to register your own functions as described +above. These functions also provide a void pointer that can be retrieved +via + + mem_ptr=png_get_mem_ptr(png_ptr); + +Your replacement memory functions must have prototypes as follows: + + png_voidp malloc_fn(png_structp png_ptr, + png_alloc_size_t size); + + void free_fn(png_structp png_ptr, png_voidp ptr); + +Your malloc_fn() must return NULL in case of failure. The png_malloc() +function will normally call png_error() if it receives a NULL from the +system memory allocator or from your replacement malloc_fn(). + +Your free_fn() will never be called with a NULL ptr, since libpng's +png_free() checks for NULL before calling free_fn(). + +Input/Output in libpng is done through png_read() and png_write(), +which currently just call fread() and fwrite(). The FILE * is stored in +png_struct and is initialized via png_init_io(). If you wish to change +the method of I/O, the library supplies callbacks that you can set +through the function png_set_read_fn() and png_set_write_fn() at run +time, instead of calling the png_init_io() function. These functions +also provide a void pointer that can be retrieved via the function +png_get_io_ptr(). For example: + + png_set_read_fn(png_structp read_ptr, + voidp read_io_ptr, png_rw_ptr read_data_fn) + + png_set_write_fn(png_structp write_ptr, + voidp write_io_ptr, png_rw_ptr write_data_fn, + png_flush_ptr output_flush_fn); + + voidp read_io_ptr = png_get_io_ptr(read_ptr); + voidp write_io_ptr = png_get_io_ptr(write_ptr); + +The replacement I/O functions must have prototypes as follows: + + void user_read_data(png_structp png_ptr, + png_bytep data, png_size_t length); + + void user_write_data(png_structp png_ptr, + png_bytep data, png_size_t length); + + void user_flush_data(png_structp png_ptr); + +The user_read_data() function is responsible for detecting and +handling end-of-data errors. + +Supplying NULL for the read, write, or flush functions sets them back +to using the default C stream functions, which expect the io_ptr to +point to a standard *FILE structure. It is probably a mistake +to use NULL for one of write_data_fn and output_flush_fn but not both +of them, unless you have built libpng with PNG_NO_WRITE_FLUSH defined. +It is an error to read from a write stream, and vice versa. + +Error handling in libpng is done through png_error() and png_warning(). +Errors handled through png_error() are fatal, meaning that png_error() +should never return to its caller. Currently, this is handled via +setjmp() and longjmp() (unless you have compiled libpng with +PNG_NO_SETJMP, in which case it is handled via PNG_ABORT()), +but you could change this to do things like exit() if you should wish, +as long as your function does not return. + +On non-fatal errors, png_warning() is called +to print a warning message, and then control returns to the calling code. +By default png_error() and png_warning() print a message on stderr via +fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined +(because you don't want the messages) or PNG_NO_STDIO defined (because +fprintf() isn't available). If you wish to change the behavior of the error +functions, you will need to set up your own message callbacks. These +functions are normally supplied at the time that the png_struct is created. +It is also possible to redirect errors and warnings to your own replacement +functions after png_create_*_struct() has been called by calling: + + png_set_error_fn(png_structp png_ptr, + png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warning_fn); + + png_voidp error_ptr = png_get_error_ptr(png_ptr); + +If NULL is supplied for either error_fn or warning_fn, then the libpng +default function will be used, calling fprintf() and/or longjmp() if a +problem is encountered. The replacement error functions should have +parameters as follows: + + void user_error_fn(png_structp png_ptr, + png_const_charp error_msg); + + void user_warning_fn(png_structp png_ptr, + png_const_charp warning_msg); + +The motivation behind using setjmp() and longjmp() is the C++ throw and +catch exception handling methods. This makes the code much easier to write, +as there is no need to check every return code of every function call. +However, there are some uncertainties about the status of local variables +after a longjmp, so the user may want to be careful about doing anything +after setjmp returns non-zero besides returning itself. Consult your +compiler documentation for more details. For an alternative approach, you +may wish to use the "cexcept" facility (see http://cexcept.sourceforge.net). + +.SS Custom chunks + +If you need to read or write custom chunks, you may need to get deeper +into the libpng code. The library now has mechanisms for storing +and writing chunks of unknown type; you can even declare callbacks +for custom chunks. However, this may not be good enough if the +library code itself needs to know about interactions between your +chunk and existing `intrinsic' chunks. + +If you need to write a new intrinsic chunk, first read the PNG +specification. Acquire a first level of understanding of how it works. +Pay particular attention to the sections that describe chunk names, +and look at how other chunks were designed, so you can do things +similarly. Second, check out the sections of libpng that read and +write chunks. Try to find a chunk that is similar to yours and use +it as a template. More details can be found in the comments inside +the code. It is best to handle unknown chunks in a generic method, +via callback functions, instead of by modifying libpng functions. + +If you wish to write your own transformation for the data, look through +the part of the code that does the transformations, and check out some of +the simpler ones to get an idea of how they work. Try to find a similar +transformation to the one you want to add and copy off of it. More details +can be found in the comments inside the code itself. + +.SS Configuring for 16 bit platforms + +You will want to look into zconf.h to tell zlib (and thus libpng) that +it cannot allocate more then 64K at a time. Even if you can, the memory +won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. + +.SS Configuring for DOS + +For DOS users who only have access to the lower 640K, you will +have to limit zlib's memory usage via a png_set_compression_mem_level() +call. See zlib.h or zconf.h in the zlib library for more information. + +.SS Configuring for Medium Model + +Libpng's support for medium model has been tested on most of the popular +compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets +defined, and FAR gets defined to far in pngconf.h, and you should be +all set. Everything in the library (except for zlib's structure) is +expecting far data. You must use the typedefs with the p or pp on +the end for pointers (or at least look at them and be careful). Make +note that the rows of data are defined as png_bytepp, which is an +unsigned char far * far *. + +.SS Configuring for gui/windowing platforms: + +You will need to write new error and warning functions that use the GUI +interface, as described previously, and set them to be the error and +warning functions at the time that png_create_*_struct() is called, +in order to have them available during the structure initialization. +They can be changed later via png_set_error_fn(). On some compilers, +you may also have to change the memory allocators (png_malloc, etc.). + +.SS Configuring for compiler xxx: + +All includes for libpng are in pngconf.h. If you need to add, change +or delete an include, this is the place to do it. +The includes that are not needed outside libpng are placed in pngpriv.h, +which is only used by the routines inside libpng itself. +The files in libpng proper only include pngpriv.h and png.h, which +in turn includes pngconf.h. + +.SS Configuring zlib: + +There are special functions to configure the compression. Perhaps the +most useful one changes the compression level, which currently uses +input compression values in the range 0 - 9. The library normally +uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests +have shown that for a large majority of images, compression values in +the range 3-6 compress nearly as well as higher levels, and do so much +faster. For online applications it may be desirable to have maximum speed +(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also +specify no compression (Z_NO_COMPRESSION = 0), but this would create +files larger than just storing the raw bitmap. You can specify the +compression level by calling: + + png_set_compression_level(png_ptr, level); + +Another useful one is to reduce the memory level used by the library. +The memory level defaults to 8, but it can be lowered if you are +short on memory (running DOS, for example, where you only have 640K). +Note that the memory level does have an effect on compression; among +other things, lower levels will result in sections of incompressible +data being emitted in smaller stored blocks, with a correspondingly +larger relative overhead of up to 15% in the worst case. + + png_set_compression_mem_level(png_ptr, level); + +The other functions are for configuring zlib. They are not recommended +for normal use and may result in writing an invalid PNG file. See +zlib.h for more information on what these mean. + + png_set_compression_strategy(png_ptr, + strategy); + + png_set_compression_window_bits(png_ptr, + window_bits); + + png_set_compression_method(png_ptr, method); + png_set_compression_buffer_size(png_ptr, size); + +.SS Controlling row filtering + +If you want to control whether libpng uses filtering or not, which +filters are used, and how it goes about picking row filters, you +can call one of these functions. The selection and configuration +of row filters can have a significant impact on the size and +encoding speed and a somewhat lesser impact on the decoding speed +of an image. Filtering is enabled by default for RGB and grayscale +images (with and without alpha), but not for paletted images nor +for any images with bit depths less than 8 bits/pixel. + +The 'method' parameter sets the main filtering method, which is +currently only '0' in the PNG 1.2 specification. The 'filters' +parameter sets which filter(s), if any, should be used for each +scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS +to turn filtering on and off, respectively. + +Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB, +PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise +ORed together with '|' to specify one or more filters to use. +These filters are described in more detail in the PNG specification. +If you intend to change the filter type during the course of writing +the image, you should start with flags set for all of the filters +you intend to use so that libpng can initialize its internal +structures appropriately for all of the filter types. (Note that this +means the first row must always be adaptively filtered, because libpng +currently does not allocate the filter buffers until png_write_row() +is called for the first time.) + + filters = PNG_FILTER_NONE | PNG_FILTER_SUB + PNG_FILTER_UP | PNG_FILTER_AVG | + PNG_FILTER_PAETH | PNG_ALL_FILTERS; + + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, + filters); + The second parameter can also be + PNG_INTRAPIXEL_DIFFERENCING if you are + writing a PNG to be embedded in a MNG + datastream. This parameter must be the + same as the value of filter_method used + in png_set_IHDR(). + +It is also possible to influence how libpng chooses from among the +available filters. This is done in one or both of two ways - by +telling it how important it is to keep the same filter for successive +rows, and by telling it the relative computational costs of the filters. + + double weights[3] = {1.5, 1.3, 1.1}, + costs[PNG_FILTER_VALUE_LAST] = + {1.0, 1.3, 1.3, 1.5, 1.7}; + + png_set_filter_heuristics(png_ptr, + PNG_FILTER_HEURISTIC_WEIGHTED, 3, + weights, costs); + +The weights are multiplying factors that indicate to libpng that the +row filter should be the same for successive rows unless another row filter +is that many times better than the previous filter. In the above example, +if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a +"sum of absolute differences" 1.5 x 1.3 times higher than other filters +and still be chosen, while the NONE filter could have a sum 1.1 times +higher than other filters and still be chosen. Unspecified weights are +taken to be 1.0, and the specified weights should probably be declining +like those above in order to emphasize recent filters over older filters. + +The filter costs specify for each filter type a relative decoding cost +to be considered when selecting row filters. This means that filters +with higher costs are less likely to be chosen over filters with lower +costs, unless their "sum of absolute differences" is that much smaller. +The costs do not necessarily reflect the exact computational speeds of +the various filters, since this would unduly influence the final image +size. + +Note that the numbers above were invented purely for this example and +are given only to help explain the function usage. Little testing has +been done to find optimum values for either the costs or the weights. + +.SS Removing unwanted object code + +There are a bunch of #define's in pngconf.h that control what parts of +libpng are compiled. All the defines end in _SUPPORTED. If you are +never going to use a capability, you can change the #define to #undef +before recompiling libpng and save yourself code and data space, or +you can turn off individual capabilities with defines that begin with +PNG_NO_. + +In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead. + +You can also turn all of the transforms and ancillary chunk capabilities +off en masse with compiler directives that define +PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, +or all four, +along with directives to turn on any of the capabilities that you do +want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the extra +transformations but still leave the library fully capable of reading +and writing PNG files with all known public chunks. Use of the +PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library +that is incapable of reading or writing ancillary chunks. If you are +not using the progressive reading capability, you can turn that off +with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING +capability, which you'll still have). + +All the reading and writing specific code are in separate files, so the +linker should only grab the files it needs. However, if you want to +make sure, or if you are building a stand alone library, all the +reading files start with pngr and all the writing files start with +pngw. The files that don't match either (like png.c, pngtrans.c, etc.) +are used for both reading and writing, and always need to be included. +The progressive reader is in pngpread.c + +If you are creating or distributing a dynamically linked library (a .so +or DLL file), you should not remove or disable any parts of the library, +as this will cause applications linked with different versions of the +library to fail if they call functions not available in your library. +The size of the library itself should not be an issue, because only +those sections that are actually used will be loaded into memory. + +.SS Requesting debug printout + +The macro definition PNG_DEBUG can be used to request debugging +printout. Set it to an integer value in the range 0 to 3. Higher +numbers result in increasing amounts of debugging information. The +information is printed to the "stderr" file, unless another file +name is specified in the PNG_DEBUG_FILE macro definition. + +When PNG_DEBUG > 0, the following functions (macros) become available: + + png_debug(level, message) + png_debug1(level, message, p1) + png_debug2(level, message, p1, p2) + +in which "level" is compared to PNG_DEBUG to decide whether to print +the message, "message" is the formatted string to be printed, +and p1 and p2 are parameters that are to be embedded in the string +according to printf-style formatting directives. For example, + + png_debug1(2, "foo=%d\n", foo); + +is expanded to + + if (PNG_DEBUG > 2) + fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo); + +When PNG_DEBUG is defined but is zero, the macros aren't defined, but you +can still use PNG_DEBUG to control your own debugging: + + #ifdef PNG_DEBUG + fprintf(stderr, ... + #endif + +When PNG_DEBUG = 1, the macros are defined, but only png_debug statements +having level = 0 will be printed. There aren't any such statements in +this version of libpng, but if you insert some they will be printed. + +.SH VI. MNG support + +The MNG specification (available at http://www.libpng.org/pub/mng) allows +certain extensions to PNG for PNG images that are embedded in MNG datastreams. +Libpng can support some of these extensions. To enable them, use the +png_permit_mng_features() function: + + feature_set = png_permit_mng_features(png_ptr, mask) + + mask is a png_uint_32 containing the bitwise OR of the + features you want to enable. These include + PNG_FLAG_MNG_EMPTY_PLTE + PNG_FLAG_MNG_FILTER_64 + PNG_ALL_MNG_FEATURES + + feature_set is a png_uint_32 that is the bitwise AND of + your mask with the set of MNG features that is + supported by the version of libpng that you are using. + +It is an error to use this function when reading or writing a standalone +PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped +in a MNG datastream. As a minimum, it must have the MNG 8-byte signature +and the MHDR and MEND chunks. Libpng does not provide support for these +or any other MNG chunks; your application must provide its own support for +them. You may wish to consider using libmng (available at +http://www.libmng.com) instead. + +.SH VII. Changes to Libpng from version 0.88 + +It should be noted that versions of libpng later than 0.96 are not +distributed by the original libpng author, Guy Schalnat, nor by +Andreas Dilger, who had taken over from Guy during 1996 and 1997, and +distributed versions 0.89 through 0.96, but rather by another member +of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are +still alive and well, but they have moved on to other things. + +The old libpng functions png_read_init(), png_write_init(), +png_info_init(), png_read_destroy(), and png_write_destroy() have been +moved to PNG_INTERNAL in version 0.95 to discourage their use. These +functions will be removed from libpng version 1.4.0. + +The preferred method of creating and initializing the libpng structures is +via the png_create_read_struct(), png_create_write_struct(), and +png_create_info_struct() because they isolate the size of the structures +from the application, allow version error checking, and also allow the +use of custom error handling routines during the initialization, which +the old functions do not. The functions png_read_destroy() and +png_write_destroy() do not actually free the memory that libpng +allocated for these structs, but just reset the data structures, so they +can be used instead of png_destroy_read_struct() and +png_destroy_write_struct() if you feel there is too much system overhead +allocating and freeing the png_struct for each image read. + +Setting the error callbacks via png_set_message_fn() before +png_read_init() as was suggested in libpng-0.88 is no longer supported +because this caused applications that do not use custom error functions +to fail if the png_ptr was not initialized to zero. It is still possible +to set the error callbacks AFTER png_read_init(), or to change them with +png_set_error_fn(), which is essentially the same function, but with a new +name to force compilation errors with applications that try to use the old +method. + +Starting with version 1.0.7, you can find out which version of the library +you are using at run-time: + + png_uint_32 libpng_vn = png_access_version_number(); + +The number libpng_vn is constructed from the major version, minor +version with leading zero, and release number with leading zero, +(e.g., libpng_vn for version 1.0.7 is 10007). + +You can also check which version of png.h you used when compiling your +application: + + png_uint_32 application_vn = PNG_LIBPNG_VER; + +.SH VIII. Changes to Libpng from version 1.0.x to 1.2.x + +Support for user memory management was enabled by default. To +accomplish this, the functions png_create_read_struct_2(), +png_create_write_struct_2(), png_set_mem_fn(), png_get_mem_ptr(), +png_malloc_default(), and png_free_default() were added. + +Support for the iTXt chunk has been enabled by default as of +version 1.2.41. + +Support for certain MNG features was enabled. + +Support for numbered error messages was added. However, we never got +around to actually numbering the error messages. The function +png_set_strip_error_numbers() was added (Note: the prototype for this +function was inadvertently removed from png.h in PNG_NO_ASSEMBLER_CODE +builds of libpng-1.2.15. It was restored in libpng-1.2.36). + +The png_malloc_warn() function was added at libpng-1.2.3. This issues +a png_warning and returns NULL instead of aborting when it fails to +acquire the requested memory allocation. + +Support for setting user limits on image width and height was enabled +by default. The functions png_set_user_limits(), png_get_user_width_max(), +and png_get_user_height_max() were added at libpng-1.2.6. + +The png_set_add_alpha() function was added at libpng-1.2.7. + +The function png_set_expand_gray_1_2_4_to_8() was added at libpng-1.2.9. +Unlike png_set_gray_1_2_4_to_8(), the new function does not expand the +tRNS chunk to alpha. The png_set_gray_1_2_4_to_8() function is +deprecated. + +A number of macro definitions in support of runtime selection of +assembler code features (especially Intel MMX code support) were +added at libpng-1.2.0: + + PNG_ASM_FLAG_MMX_SUPPORT_COMPILED + PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU + 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 + PNG_ASM_FLAGS_INITIALIZED + PNG_MMX_READ_FLAGS + PNG_MMX_FLAGS + PNG_MMX_WRITE_FLAGS + PNG_MMX_FLAGS + +We added the following functions in support of runtime +selection of assembler code features: + + png_get_mmx_flagmask() + png_set_mmx_thresholds() + png_get_asm_flags() + png_get_mmx_bitdepth_threshold() + png_get_mmx_rowbytes_threshold() + png_set_asm_flags() + +We replaced all of these functions with simple stubs in libpng-1.2.20, +when the Intel assembler code was removed due to a licensing issue. + +These macros are deprecated: + + PNG_READ_TRANSFORMS_NOT_SUPPORTED + PNG_PROGRESSIVE_READ_NOT_SUPPORTED + PNG_NO_SEQUENTIAL_READ_SUPPORTED + PNG_WRITE_TRANSFORMS_NOT_SUPPORTED + PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED + PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED + +They have been replaced, respectively, by: + + PNG_NO_READ_TRANSFORMS + PNG_NO_PROGRESSIVE_READ + PNG_NO_SEQUENTIAL_READ + PNG_NO_WRITE_TRANSFORMS + PNG_NO_READ_ANCILLARY_CHUNKS + PNG_NO_WRITE_ANCILLARY_CHUNKS + +PNG_MAX_UINT was replaced with PNG_UINT_31_MAX. It has been +deprecated since libpng-1.0.16 and libpng-1.2.6. + +The function + png_check_sig(sig, num) +was replaced with + !png_sig_cmp(sig, 0, num) +It has been deprecated since libpng-0.90. + +The function + png_set_gray_1_2_4_to_8() +which also expands tRNS to alpha was replaced with + png_set_expand_gray_1_2_4_to_8() +which does not. It has been deprecated since libpng-1.0.18 and 1.2.9. + +.SH IX. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x + +Private libpng prototypes and macro definitions were moved from +png.h and pngconf.h into a new pngpriv.h header file. + +Functions png_set_benign_errors(), png_benign_error(), and +png_chunk_benign_error() were added. + +Support for setting the maximum amount of memory that the application +will allocate for reading chunks was added, as a security measure. +The functions png_set_chunk_cache_max() and png_get_chunk_cache_max() +were added to the library. + +We implemented support for I/O states by adding png_ptr member io_state +and functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + +We added PNG_TRANSFORM_GRAY_TO_RGB to the available high-level +input transforms. + +Checking for and reporting of errors in the IHDR chunk is more thorough. + +Support for global arrays was removed, to improve thread safety. + +Some obsolete/deprecated macros and functions have been removed. + +Typecasted NULL definitions such as + #define png_voidp_NULL (png_voidp)NULL +were eliminated. If you used these in your application, just use +NULL instead. + +The png_struct and info_struct members "trans" and "trans_values" were +changed to "trans_alpha" and "trans_color", respectively. + +The obsolete, unused pnggccrd.c and pngvcrd.c files and related makefiles +were removed. + +The PNG_1_0_X and PNG_1_2_X macros were eliminated. + +The PNG_LEGACY_SUPPORTED macro was eliminated. + +Many WIN32_WCE #ifdefs were removed. + +The functions png_read_init(info_ptr), png_write_init(info_ptr), +png_info_init(info_ptr), png_read_destroy(), and png_write_destroy() +have been removed. They have been deprecated since libpng-0.95. + +The png_permit_empty_plte() was removed. It has been deprecated +since libpng-1.0.9. Use png_permit_mng_features() instead. + +We removed the obsolete stub functions png_get_mmx_flagmask(), +png_set_mmx_thresholds(), png_get_asm_flags(), +png_get_mmx_bitdepth_threshold(), png_get_mmx_rowbytes_threshold(), +png_set_asm_flags(), and png_mmx_supported() + +We removed the obsolete png_check_sig(), png_memcpy_check(), and +png_memset_check() functions. Instead use !png_sig_cmp(), memcpy(), +and memset(), respectively. + +The function png_set_gray_1_2_4_to_8() was removed. It has been +deprecated since libpng-1.0.18 and 1.2.9, when it was replaced with +png_set_expand_gray_1_2_4_to_8() because the former function also +expanded palette images. + +Macros for png_get_uint_16, png_get_uint_32, and png_get_int_32 +were added and are used by default instead of the corresponding +functions. Unfortunately, +from libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +function) incorrectly returned a value of type png_uint_32. + +We changed the prototype for png_malloc() from + png_malloc(png_structp png_ptr, png_uint_32 size) +to + png_malloc(png_structp png_ptr, png_alloc_size_t size) + +This also applies to the prototype for the user replacement malloc_fn(). + +The png_calloc() function was added and is used in place of +of "png_malloc(); memset();" except in the case in png_read_png() +where the array consists of pointers; in this case a "for" loop is used +after the png_malloc() to set the pointers to NULL, to give robust. +behavior in case the application runs out of memory part-way through +the process. + +We changed the prototypes of png_get_compression_buffer_size() and +png_set_compression_buffer_size() to work with png_size_t instead of +png_uint_32. + +Support for numbered error messages was removed by default, since we +never got around to actually numbering the error messages. The function +png_set_strip_error_numbers() was removed from the library by default. + +The png_zalloc() and png_zfree() functions are no longer exported. +The png_zalloc() function no longer zeroes out the memory that it +allocates. + +Support for dithering was disabled by default in libpng-1.4.0, because +been well tested and doesn't actually "dither". The code was not +removed, however, and could be enabled by building libpng with +PNG_READ_DITHER_SUPPORTED defined. In libpng-1.4.2, this support +was reenabled, but the function was renamed png_set_quantize() to +reflect more accurately what it actually does. At the same time, +the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros were also renamed to +PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS, and PNG_READ_DITHER_SUPPORTED +was renamed to PNG_READ_QUANTIZE_SUPPORTED. + +We removed the trailing '.' from the warning and error messages. + +.SH X. Changes to Libpng from version 1.4.x to 1.5.x + +From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +function) incorrectly returned a value of type png_uint_32. + +A. Changes that affect users of libpng + +There are no substantial API changes between the non-deprecated parts of +the 1.4.5 API and the 1.5.0 API, however the ability to directly access +the main libpng control structures, png_struct and png_info, deprecated +in earlier versions of libpng, has been completely removed from +libpng 1.5. + +We no longer include zlib.h in png.h. Applications that need access +to information in zlib.h will need to add the '#include "zlib.h"' +directive. It does not matter whether it is placed prior to or after +the '"#include png.h"' directive. + +We moved the png_strcpy(), png_strncpy(), png_strlen(), png_memcpy(), +png_memcmp(), png_sprintf, and png_memcpy() macros into a private +header file (pngpriv.h) that is not accessible to applications. + +In png_get_iCCP, the type of "profile" was changed from png_charpp +to png_bytepp, and in png_set_iCCP, from png_charp to png_const_bytep. + +There are changes of form in png.h, including new and changed macros to +declare +parts of the API. Some API functions with arguments that are pointers to +data not modified within the function have been corrected to declare +these arguments with PNG_CONST. + +Much of the internal use of C macros to control the library build has also +changed and some of this is visible in the exported header files, in +particular the use of macros to control data and API elements visible +during application compilation may require significant revision to +application code. (It is extremely rare for an application to do this.) + +Any program that compiled against libpng 1.4 and did not use deprecated +features or access internal library structures should compile and work +against libpng 1.5. + +libpng 1.5.0 adds PNG_ PASS macros to help in the reading and writing of +interlaced images. The macros return the number of rows and columns in +each pass and information that can be used to de-interlace and (if +absolutely necessary) interlace an image. + +libpng 1.5.0 adds an API png_longjmp(png_ptr, value). This API calls +the application provided png_longjmp_ptr on the internal, but application +initialized, jmpbuf. It is provided as a convenience to avoid the need +to use the png_jmpbuf macro, which had the unnecessary side effect of +resetting the internal png_longjmp_ptr value. + +libpng 1.5.0 includes a complete fixed point API. By default this is +present along with the corresponding floating point API. In general the +fixed point API is faster and smaller than the floating point one because +the PNG file format used fixed point, not floating point. This applies +even if the library uses floating point in internal calculations. A new +macro, PNG_FLOATING_ARITHMETIC_SUPPORTED, reveals whether the library +uses floating point arithmetic (the default) or fixed point arithmetic +internally for performance critical calculations such as gamma correction. +In some cases, the gamma calculations may produce slightly different +results. This has changed the results in png_rgb_to_gray and in alpha +composition (png_set_background for example). This applies even if the +original image was already linear (gamma == 1.0) and, therefore, it is +not necessary to linearize the image. This is because libpng has *not* +been changed to optimize that case correctly, yet. + +Fixed point support for the sCAL chunk comes with an important caveat; +the sCAL specification uses a decimal encoding of floating point values +and the accuracy of PNG fixed point values is insufficient for +representation of these values. Consequently a "string" API +(png_get_sCAL_s and png_set_sCAL_s) is the only reliable way of reading +arbitrary sCAL chunks in the absence of either the floating point API or +internal floating point calculations. + +Applications no longer need to include the optional distribution header +file pngusr.h or define the corresponding macros during application +build in order to see the correct variant of the libpng API. From 1.5.0 +application code can check for the corresponding _SUPPORTED macro: + +#ifdef PNG_INCH_CONVERSIONS_SUPPORTED + /* code that uses the inch conversion APIs. */ +#endif + +This macro will only be defined if the inch conversion functions have been +compiled into libpng. The full set of macros, and whether or not support +has been compiled in, are available in the header file pnglibconf.h. +This header file is specific to the libpng build. Notice that prior to +1.5.0 the _SUPPORTED macros would always have the default definition unless +reset by pngusr.h or by explicit settings on the compiler command line. +These settings may produce compiler warnings or errors in 1.5.0 because +of macro redefinition. + +From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +function) incorrectly returned a value of type png_uint_32. libpng 1.5.0 +is consistent with the implementation in 1.4.5 and 1.2.x (where the macro +did not exist.) + +Applications can now choose whether to use these macros or to call the +corresponding function by defining PNG_USE_READ_MACROS or +PNG_NO_USE_READ_MACROS before including png.h. Notice that this is +only supported from 1.5.0 -defining PNG_NO_USE_READ_MACROS prior to 1.5.0 + will lead to a link failure. + +B. Changes to the build and configuration of libpng + +Details of internal changes to the library code can be found in the CHANGES +file. These will be of no concern to the vast majority of library users or +builders, however the few who configure libpng to a non-default feature +set may need to change how this is done. + +There should be no need for library builders to alter build scripts if +these use the distributed build support - configure or the makefiles - +however users of the makefiles may care to update their build scripts +to build pnglibconf.h where the corresponding makefile does not do so. + +Building libpng with a non-default configuration has changed completely. +The old method using pngusr.h should still work correctly even though the +way pngusr.h is used in the build has been changed, however library +builders will probably want to examine the changes to take advantage of +new capabilities and to simplify their build system. + +B.1 Specific changes to library configuration capabilities + +The library now supports a complete fixed point implementation and can +thus be used on systems which have no floating point support or very +limited or slow support. Previously gamma correction, an essential part +of complete PNG support, required reasonably fast floating point. + +As part of this the choice of internal implementation has been made +independent of the choice of fixed versus floating point APIs and all the +missing fixed point APIs have been implemented. + +The exact mechanism used to control attributes of API functions has +changed. A single set of operating system independent macro definitions +is used and operating system specific directives are defined in +pnglibconf.h + +As part of this the mechanism used to choose procedure call standards on +those systems that allow a choice has been changed. At present this only +affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems +running on Intel processors. As before PNGAPI is defined where required +to control the exported API functions; however, two new macros, PNGCBAPI +and PNGCAPI, are used instead for callback functions (PNGCBAPI) and +(PNGCAPI) for functions that must match a C library prototype (currently +only png_longjmp_ptr, which must match the C longjmp function.) The new +approach is documented in pngconf.h + +Despite these changes libpng 1.5.0 only supports the native C function +calling standard on those platforms tested so far (__cdecl on Microsoft +Windows). This is because the support requirements for alternative +calling conventions seem to no longer exist. Developers who find it +necessary to set PNG_API_RULE to 1 should advise the mailing list +(png-mng-implement) of this and library builders who use Openwatcom and +therefore set PNG_API_RULE to 2 should also contact the mailing list. + +A new test program, pngvalid, is provided in addition to pngtest. +pngvalid validates the arithmetic accuracy of the gamma correction +calculations and includes a number of validations of the file format. +A subset of the full range of tests is run when "make check" is done +(in the 'configure' build.) pngvalid also allows total allocated memory +usage to be evaluated and performs additional memory overwrite validation. + +Many changes to individual feature macros have been made. The following +are the changes most likely to be noticed by library builders who +configure libpng: + +1) All feature macros now have consistent naming: + +#define PNG_NO_feature turns the feature off +#define PNG_feature_SUPPORTED turns the feature on + +pnglibconf.h contains one line for each feature macro which is either: + +#define PNG_feature_SUPPORTED + +if the feature is supported or: + +/*#undef PNG_feature_SUPPORTED*/ + +if it is not. Library code consistently checks for the 'SUPPORTED' macro. +It does not, and should not, check for the 'NO' macro which will not +normally be defined even if the feature is not supported. + +Compatibility with the old names is provided as follows: + +PNG_INCH_CONVERSIONS turns on PNG_INCH_CONVERSIONS_SUPPORTED + +And the following definitions disable the corresponding feature: + +PNG_SETJMP_NOT_SUPPORTED disables SETJMP +PNG_READ_TRANSFORMS_NOT_SUPPORTED disables READ_TRANSFORMS +PNG_NO_READ_COMPOSITED_NODIV disables READ_COMPOSITE_NODIV +PNG_WRITE_TRANSFORMS_NOT_SUPPORTED disables WRITE_TRANSFORMS +PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED disables READ_ANCILLARY_CHUNKS +PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED disables WRITE_ANCILLARY_CHUNKS + +Library builders should remove use of the above, inconsistent, names. + +2) Warning and error message formatting was previously conditional on +the STDIO feature. The library has been changed to use the +CONSOLE_IO feature instead. This means that if CONSOLE_IO is disabled +the library no longer uses the printf(3) functions, even though the +default read/write implementations use (FILE) style stdio.h functions. + +3) Three feature macros now control the fixed/floating point decisions: + +PNG_FLOATING_POINT_SUPPORTED enables the floating point APIs + +PNG_FIXED_POINT_SUPPORTED enables the fixed point APIs; however, in +practice these are normally required internally anyway (because the PNG +file format is fixed point), therefore in most cases PNG_NO_FIXED_POINT +merely stops the function from being exported. + +PNG_FLOATING_ARITHMETIC_SUPPORTED chooses between the internal floating +point implementation or the fixed point one. Typically the fixed point +implementation is larger and slower than the floating point implementation +on a system that supports floating point, however it may be faster on a +system which lacks floating point hardware and therefore uses a software +emulation. + +4) Added PNG_{READ,WRITE}_INT_FUNCTIONS_SUPPORTED. This allows the +functions to read and write ints to be disabled independently of +PNG_USE_READ_MACROS, which allows libpng to be built with the functions +even though the default is to use the macros - this allows applications +to choose at app buildtime whether or not to use macros (previously +impossible because the functions weren't in the default build.) + +B.2 Changes to the configuration mechanism + +Prior to libpng-1.5.0 library builders who needed to configure libpng +had either to modify the exported pngconf.h header file to add system +specific configuration or had to write feature selection macros into +pngusr.h and cause this to be included into pngconf.h by defining +PNG_USER_CONFIG. The latter mechanism had the disadvantage that an +application built without PNG_USER_CONFIG defined would see the +unmodified, default, libpng API and thus would probably fail to link. + +These mechanisms still work in the configure build and in any makefile +build that builds pnglibconf.h although the feature selection macros +have changed somewhat as described above. In 1.5.0, however, pngusr.h is +processed only once, when the exported header file pnglibconf.h is built. +pngconf.h no longer includes pngusr.h, therefore it is ignored after the +build of pnglibconf.h and it is never included in an application build. + +The rarely used alternative of adding a list of feature macros to the +CFLAGS setting in the build also still works, however the macros will be +copied to pnglibconf.h and this may produce macro redefinition warnings +when the individual C files are compiled. + +All configuration now only works if pnglibconf.h is built from +scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan +(the original author of awk) maintains C source code of that awk and this +and all known later implementations (often called by subtly different +names - nawk and gawk for example) are adequate to build pnglibconf.h. +The Sun Microsystems (now Oracle) program 'awk' is an earlier version +and does not work, this may also apply to other systems that have a +functioning awk called 'nawk'. + +Configuration options are now documented in scripts/pnglibconf.dfa. This +file also includes dependency information that ensures a configuration is +consistent; that is, if a feature is switched off dependent features are +also removed. As a recommended alternative to using feature macros in +pngusr.h a system builder may also define equivalent options in pngusr.dfa +(or, indeed, any file) and add that to the configuration by setting +DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate +how to do this, and a case where pngusr.h is still required. + +.SH XI. Detecting libpng + +The png_get_io_ptr() function has been present since libpng-0.88, has never +changed, and is unaffected by conditional compilation macros. It is the +best choice for use in configure scripts for detecting the presence of any +libpng version since 0.88. In an autoconf "configure.in" you could use + + AC_CHECK_LIB(png, png_get_io_ptr, ... + +.SH XII. Source code repository + +Since about February 2009, version 1.2.34, libpng has been under "git" source +control. The git repository was built from old libpng-x.y.z.tar.gz files +going back to version 0.70. You can access the git repository (read only) +at + + git://libpng.git.sourceforge.net/gitroot/libpng + +or you can browse it via "gitweb" at + + http://libpng.git.sourceforge.net/git/gitweb.cgi?p=libpng + +Patches can be sent to glennrp at users.sourceforge.net or to +png-mng-implement at lists.sourceforge.net or you can upload them to +the libpng bug tracker at + + http://libpng.sourceforge.net + +We also accept patches built from the tar or zip distributions, and +simple verbal discriptions of bug fixes, reported either to the +SourceForge bug tracker or to the png-mng-implement at lists.sf.net +mailing list. + +.SH XIII. Coding style + +Our coding style is similar to the "Allman" style, with curly +braces on separate lines: + + if (condition) + { + action; + } + + else if (another condition) + { + another action; + } + +The braces can be omitted from simple one-line actions: + + if (condition) + return (0); + +We use 3-space indentation, except for continued statements which +are usually indented the same as the first line of the statement +plus four more spaces. + +For macro definitions we use 2-space indentation, always leaving the "#" +in the first column. + + #ifndef PNG_NO_FEATURE + # ifndef PNG_FEATURE_SUPPORTED + # define PNG_FEATURE_SUPPORTED + # endif + #endif + +Comments appear with the leading "/*" at the same indentation as +the statement that follows the comment: + + /* Single-line comment */ + statement; + + /* This is a multiple-line + * comment. + */ + statement; + +Very short comments can be placed after the end of the statement +to which they pertain: + + statement; /* comment */ + +We don't use C++ style ("//") comments. We have, however, +used them in the past in some now-abandoned MMX assembler +code. + +Functions and their curly braces are not indented, and +exported functions are marked with PNGAPI: + + /* This is a public function that is visible to + * application programmers. It does thus-and-so. + */ + void PNGAPI + png_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for all exported functions appear in png.h, +above the comment that says + + /* Maintainer: Put new public prototypes here ... */ + +We mark all non-exported functions with "/* PRIVATE */"": + + void /* PRIVATE */ + png_non_exported_function(png_ptr, png_info, foo) + { + body; + } + +The prototypes for non-exported functions (except for those in +pngtest) appear in +pngpriv.h +above the comment that says + + /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + +To avoid polluting the global namespace, the names of all exported +functions and variables begin with "png_", and all publicly visible C +preprocessor macros begin with "PNG_". We request that applications that +use libpng *not* begin any of their own symbols with either of these strings. + +We put a space after each comma and after each semicolon +in "for" statements, and we put spaces before and after each +C binary operator and after "for" or "while", and before +"?". We don't put a space between a typecast and the expression +being cast, nor do we put one between a function name and the +left parenthesis that follows it: + + for (i = 2; i > 0; --i) + y[i] = a(x) + (int)b; + +We prefer #ifdef and #ifndef to #if defined() and if !defined() +when there is only one macro being tested. + +We do not use the TAB character for indentation in the C sources. + +Lines do not exceed 80 characters. + +Other rules can be inferred by inspecting the libpng source. + +.SH XIV. Y2K Compliance in libpng + +February 3, 2011 + +Since the PNG Development group is an ad-hoc body, we can't make +an official declaration. + +This is your unofficial assurance that libpng from version 0.71 and +upward through 1.5.1 are Y2K compliant. It is my belief that earlier +versions were also Y2K compliant. + +Libpng only has three year fields. One is a 2-byte unsigned integer that +will hold years up to 65535. The other two hold the date in text +format, and will hold years up to 9999. + +The integer is + "png_uint_16 year" in png_time_struct. + +The strings are + "png_charp time_buffer" in png_struct and + "near_time_buffer", which is a local character string in png.c. + +There are seven time-related functions: + + png_convert_to_rfc_1123() in png.c + (formerly png_convert_to_rfc_1152() in error) + png_convert_from_struct_tm() in pngwrite.c, called + in pngwrite.c + png_convert_from_time_t() in pngwrite.c + png_get_tIME() in pngget.c + png_handle_tIME() in pngrutil.c, called in pngread.c + png_set_tIME() in pngset.c + png_write_tIME() in pngwutil.c, called in pngwrite.c + +All appear to handle dates properly in a Y2K environment. The +png_convert_from_time_t() function calls gmtime() to convert from system +clock time, which returns (year - 1900), which we properly convert to +the full 4-digit year. There is a possibility that applications using +libpng are not passing 4-digit years into the png_convert_to_rfc_1123() +function, or that they are incorrectly passing only a 2-digit year +instead of "year - 1900" into the png_convert_from_struct_tm() function, +but this is not under our control. The libpng documentation has always +stated that it works with 4-digit years, and the APIs have been +documented as such. + +The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned +integer to hold the year, and can hold years as large as 65535. + +zlib, upon which libpng depends, is also Y2K compliant. It contains +no date-related code. + + + Glenn Randers-Pehrson + libpng maintainer + PNG Development Group + +.SH NOTE + +Note about libpng version numbers: + +Due to various miscommunications, unforeseen code incompatibilities +and occasional factors outside the authors' control, version numbering +on the library has not always been consistent and straightforward. +The following table summarizes matters since version 0.89c, which was +the first widely used release: + + source png.h png.h shared-lib + version string int version + ------- ------ ----- ---------- + 0.89c ("beta 3") 0.89 89 1.0.89 + 0.90 ("beta 4") 0.90 90 0.90 + 0.95 ("beta 5") 0.95 95 0.95 + 0.96 ("beta 6") 0.96 96 0.96 + 0.97b ("beta 7") 1.00.97 97 1.0.1 + 0.97c 0.97 97 2.0.97 + 0.98 0.98 98 2.0.98 + 0.99 0.99 98 2.0.99 + 0.99a-m 0.99 99 2.0.99 + 1.00 1.00 100 2.1.0 + 1.0.0 1.0.0 100 2.1.0 + 1.0.0 (from here on, the 100 2.1.0 + 1.0.1 png.h string is 10001 2.1.0 + 1.0.1a-e identical to the 10002 from here on, the + 1.0.2 source version) 10002 shared library is 2.V + 1.0.2a-b 10003 where V is the source + 1.0.1 10001 code version except as + 1.0.1a-e 10002 2.1.0.1a-e noted. + 1.0.2 10002 2.1.0.2 + 1.0.2a-b 10003 2.1.0.2a-b + 1.0.3 10003 2.1.0.3 + 1.0.3a-d 10004 2.1.0.3a-d + 1.0.4 10004 2.1.0.4 + 1.0.4a-f 10005 2.1.0.4a-f + 1.0.5 (+ 2 patches) 10005 2.1.0.5 + 1.0.5a-d 10006 2.1.0.5a-d + 1.0.5e-r 10100 2.1.0.5e-r + 1.0.5s-v 10006 2.1.0.5s-v + 1.0.6 (+ 3 patches) 10006 2.1.0.6 + 1.0.6d-g 10007 2.1.0.6d-g + 1.0.6h 10007 10.6h + 1.0.6i 10007 10.6i + 1.0.6j 10007 2.1.0.6j + 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 + 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 + 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 + 1.0.7 1 10007 2.1.0.7 + 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + 1.0.8rc1 1 10008 2.1.0.8rc1 + 1.0.8 1 10008 2.1.0.8 + 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + 1.0.9rc1 1 10009 2.1.0.9rc1 + 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + 1.0.9rc2 1 10009 2.1.0.9rc2 + 1.0.9 1 10009 2.1.0.9 + 1.0.10beta1 1 10010 2.1.0.10beta1 + 1.0.10rc1 1 10010 2.1.0.10rc1 + 1.0.10 1 10010 2.1.0.10 + 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + 1.0.11rc1 1 10011 2.1.0.11rc1 + 1.0.11 1 10011 2.1.0.11 + 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + 1.0.12rc1 2 10012 2.1.0.12rc1 + 1.0.12 2 10012 2.1.0.12 + 1.1.0a-f - 10100 2.1.1.0a-f abandoned + 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + 1.2.0rc1 3 10200 3.1.2.0rc1 + 1.2.0 3 10200 3.1.2.0 + 1.2.1beta-4 3 10201 3.1.2.1beta1-4 + 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + 1.2.1 3 10201 3.1.2.1 + 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + 1.0.13 10 10013 10.so.0.1.0.13 + 1.2.2 12 10202 12.so.0.1.2.2 + 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + 1.2.3 12 10203 12.so.0.1.2.3 + 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + 1.0.14 10 10014 10.so.0.1.0.14 + 1.2.4 13 10204 12.so.0.1.2.4 + 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + 1.0.15rc1 10 10015 10.so.0.1.0.15rc1 + 1.0.15 10 10015 10.so.0.1.0.15 + 1.2.5 13 10205 12.so.0.1.2.5 + 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + 1.2.6rc1-5 13 10206 12.so.0.1.2.6rc1-5 + 1.0.16 10 10016 10.so.0.1.0.16 + 1.2.6 13 10206 12.so.0.1.2.6 + 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 + 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + 1.0.17 10 10017 12.so.0.1.0.17 + 1.2.7 13 10207 12.so.0.1.2.7 + 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 + 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + 1.0.18 10 10018 12.so.0.1.0.18 + 1.2.8 13 10208 12.so.0.1.2.8 + 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + 1.2.9beta4-11 13 10209 12.so.0.9[.0] + 1.2.9rc1 13 10209 12.so.0.9[.0] + 1.2.9 13 10209 12.so.0.9[.0] + 1.2.10beta1-7 13 10210 12.so.0.10[.0] + 1.2.10rc1-2 13 10210 12.so.0.10[.0] + 1.2.10 13 10210 12.so.0.10[.0] + 1.4.0beta1-6 14 10400 14.so.0.0[.0] + 1.2.11beta1-4 13 10210 12.so.0.11[.0] + 1.4.0beta7-8 14 10400 14.so.0.0[.0] + 1.2.11 13 10211 12.so.0.11[.0] + 1.2.12 13 10212 12.so.0.12[.0] + 1.4.0beta9-14 14 10400 14.so.0.0[.0] + 1.2.13 13 10213 12.so.0.13[.0] + 1.4.0beta15-36 14 10400 14.so.0.0[.0] + 1.4.0beta37-87 14 10400 14.so.14.0[.0] + 1.4.0rc01 14 10400 14.so.14.0[.0] + 1.4.0beta88-109 14 10400 14.so.14.0[.0] + 1.4.0rc02-08 14 10400 14.so.14.0[.0] + 1.4.0 14 10400 14.so.14.0[.0] + 1.4.1beta01-03 14 10401 14.so.14.1[.0] + 1.4.1rc01 14 10401 14.so.14.1[.0] + 1.4.1beta04-12 14 10401 14.so.14.1[.0] + 1.4.1 14 10401 14.so.14.1[.0] + 1.4.2 14 10402 14.so.14.2[.0] + 1.4.3 14 10403 14.so.14.3[.0] + 1.4.4 14 10404 14.so.14.4[.0] + 1.5.0beta01-58 15 10500 15.so.15.0[.0] + 1.5.0rc01-07 15 10500 15.so.15.0[.0] + 1.5.0 15 10500 15.so.15.0[.0] + 1.5.1beta01-11 15 10501 15.so.15.1[.0] + 1.5.1rc01-02 15 10501 15.so.15.1[.0] + 1.5.1 15 10501 15.so.15.1[.0] + +Henceforth the source version will match the shared-library minor +and patch numbers; the shared-library major version number will be +used for changes in backward compatibility, as it is intended. The +PNG_PNGLIB_VER macro, which is not used within libpng but is available +for applications, is an unsigned integer of the form xyyzz corresponding +to the source version x.y.z (leading zeros in y and z). Beta versions +were given the previous public release number plus a letter, until +version 1.0.6j; from then on they were given the upcoming public +release number plus "betaNN" or "rcN". + +.SH "SEE ALSO" +.BR "png"(5), " libpngpf"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) + +.LP +.IR libpng : +.IP +http://libpng.sourceforge.net (follow the [DOWNLOAD] link) +http://www.libpng.org/pub/png + +.LP +.IR zlib : +.IP +(generally) at the same location as +.I libpng +or at +.br +ftp://ftp.info-zip.org/pub/infozip/zlib + +.LP +.IR PNG specification: RFC 2083 +.IP +(generally) at the same location as +.I libpng +or at +.br +ftp://ds.internic.net/rfc/rfc2083.txt +.br +or (as a W3C Recommendation) at +.br +http://www.w3.org/TR/REC-png.html + +.LP +In the case of any inconsistency between the PNG specification +and this library, the specification takes precedence. + +.SH AUTHORS +This man page: Glenn Randers-Pehrson + + +The contributing authors would like to thank all those who helped +with testing, bug fixes, and patience. This wouldn't have been +possible without all of you. + +Thanks to Frank J. T. Wojcik for helping with the documentation. + +Libpng version 1.5.1 - February 3, 2011: +Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc. +Currently maintained by Glenn Randers-Pehrson (glennrp at users.sourceforge.net). + +Supported by the PNG development group +.br +png-mng-implement at lists.sf.net +(subscription required; visit +png-mng-implement at lists.sourceforge.net (subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe). + +.SH COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +(This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail.) + +If you modify libpng you may insert additional notices immediately following +this sentence. + +This code is released under the libpng license. + +libpng versions 1.2.6, August 15, 2004, through 1.5.1, February 3, 2011, are +Copyright (c) 2004,2006-2007 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your + enjoyment of the library or against infringement. + There is no warranty that our efforts or the library + will fulfill any of your particular purposes or needs. + This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and + effort is with the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson +Distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and + must not be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from + any source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +February 3, 2011 + +.\" end of man page + diff --git a/contrib/libpng/libpng.pc.in b/contrib/libpng/libpng.pc.in new file mode 100644 index 0000000..3e7e2c5 --- /dev/null +++ b/contrib/libpng/libpng.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ + +Name: libpng +Description: Loads and saves PNG files +Version: @PNGLIB_VERSION@ +Libs: -L${libdir} -lpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ +Libs.private: @LIBS@ +Cflags: -I${includedir} diff --git a/contrib/libpng/libpngpf.3 b/contrib/libpng/libpngpf.3 new file mode 100644 index 0000000..ff6e164 --- /dev/null +++ b/contrib/libpng/libpngpf.3 @@ -0,0 +1,30 @@ +.TH LIBPNGPF 3 "February 3, 2011" +.SH NAME +libpng \- Portable Network Graphics (PNG) Reference Library 1.5.1 +(private functions) +.SH SYNOPSIS +\fB#include \fI"pngpriv.h" + +\fI\fB + +\fBAs of libpng version \fP\fI1.5.1\fP\fB, this section is no longer \fP\fImaintained\fP\fB, now \fIthat + +\fBthe private function prototypes are hidden in pngpriv.h and not \fIaccessible + +\fBto applications. Look in pngpriv.h for the prototypes and a short \fIdescription + +\fBof each \fIfunction. + +\fI\fB + +.SH DESCRIPTION +The functions previously listed here are used privately by libpng +and are not recommended for use by applications. They are +not "exported" to applications using shared libraries. They +are listed alphabetically here as an aid to libpng maintainers. +See pngpriv.h for more information on these functions. + +.SH SEE ALSO +.BR "png"(5), " libpng"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) +.SH AUTHOR +Glenn Randers-Pehrson diff --git a/contrib/libpng/ltmain.sh b/contrib/libpng/ltmain.sh new file mode 100755 index 0000000..3061e3c --- /dev/null +++ b/contrib/libpng/ltmain.sh @@ -0,0 +1,9636 @@ + +# libtool (GNU libtool) 2.4 +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --no-quiet, --no-silent +# print informational messages (default) +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print more informational messages than default +# --no-verbose don't print the extra informational messages +# --version print version information +# -h, --help, --help-all print short, long, or detailed help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. When passed as first option, +# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.4 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . +# GNU libtool home page: . +# General help using GNU software: . + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4 +TIMESTAMP="" +package_revision=1.3293 + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# NLS nuisances: We save the old values to restore during execute mode. +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done +LC_ALL=C +LANGUAGE=C +export LANGUAGE LC_ALL + +$lt_unset CDPATH + + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + + + +: ${CP="cp -f"} +test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} +: ${EGREP="grep -E"} +: ${FGREP="grep -F"} +: ${GREP="grep"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SED="sed"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} # func_dirname may be replaced by extended shell implementation + + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "${1}" | $SED "$basename"` +} # func_basename may be replaced by extended shell implementation + + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` +} # func_dirname_and_basename may be replaced by extended shell implementation + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname may be replaced by extended shell implementation + + +# These SED scripts presuppose an absolute path with a trailing slash. +pathcar='s,^/\([^/]*\).*$,\1,' +pathcdr='s,^/[^/]*,,' +removedotparts=':dotsl + s@/\./@/@g + t dotsl + s,/\.$,/,' +collapseslashes='s@/\{1,\}@/@g' +finalslash='s,/*$,/,' + +# func_normal_abspath PATH +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +# value returned in "$func_normal_abspath_result" +func_normal_abspath () +{ + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` + while :; do + # Processed it all yet? + if test "$func_normal_abspath_tpath" = / ; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result" ; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + +# func_relative_path SRCDIR DSTDIR +# generates a relative path from SRCDIR to DSTDIR, with a trailing +# slash if non-empty, suitable for immediately appending a filename +# without needing to append a separator. +# value returned in "$func_relative_path_result" +func_relative_path () +{ + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test "x$func_relative_path_tlibdir" = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test "x$func_stripname_result" != x ; then + func_relative_path_result=${func_relative_path_result}/${func_stripname_result} + fi + + # Normalisation. If bindir is libdir, return empty string, + # else relative path ending with a slash; either way, target + # file name can be directly appended. + if test ! -z "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} + +# The name of this program: +func_dirname_and_basename "$progpath" +progname=$func_basename_result + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=: + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' + +# Sed substitution that converts a w32 file name or path +# which contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }$*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` + done + my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "$my_tmpdir" +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "$1" | $SED \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + +# func_tr_sh +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $opt_debug + + $SED -n '/(C)/!b go + :more + /\./!{ + N + s/\n# / / + b more + } + :go + /^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $opt_debug + + $SED -n '/^# Usage:/,/^# *.*--help/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + echo + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help [NOEXIT] +# Echo long help message to standard output and exit, +# unless 'noexit' is passed as argument. +func_help () +{ + $opt_debug + + $SED -n '/^# Usage:/,/# Report bugs to/ { + :print + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + p + d + } + /^# .* home page:/b print + /^# General help using/b print + ' < "$progpath" + ret=$? + if test -z "$1"; then + exit $ret + fi +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $opt_debug + + func_error "missing argument for $1." + exit_cmd=exit +} + + +# func_split_short_opt shortopt +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +func_split_short_opt () +{ + my_sed_short_opt='1s/^\(..\).*$/\1/;q' + my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + + func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` + func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` +} # func_split_short_opt may be replaced by extended shell implementation + + +# func_split_long_opt longopt +# Set func_split_long_opt_name and func_split_long_opt_arg shell +# variables after splitting LONGOPT at the `=' sign. +func_split_long_opt () +{ + my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' + my_sed_long_arg='1s/^--[^=]*=//' + + func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` + func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` +} # func_split_long_opt may be replaced by extended shell implementation + +exit_cmd=: + + + + + +magic="%%%MAGIC variable%%%" +magic_exe="%%%MAGIC EXE variable%%%" + +# Global variables. +nonopt= +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "${1}=\$${1}\${2}" +} # func_append may be replaced by extended shell implementation + +# func_append_quoted var value +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +func_append_quoted () +{ + func_quote_for_eval "${2}" + eval "${1}=\$${1}\\ \$func_quote_for_eval_result" +} # func_append_quoted may be replaced by extended shell implementation + + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "${@}"` +} # func_arith may be replaced by extended shell implementation + + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` +} # func_len may be replaced by extended shell implementation + + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` +} # func_lo2o may be replaced by extended shell implementation + + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` +} # func_xform may be replaced by extended shell implementation + + +# func_fatal_configuration arg... +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func_error ${1+"$@"} + func_error "See the $PACKAGE documentation for more information." + func_fatal_error "Fatal configuration error." +} + + +# func_config +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + +# func_features +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + +# func_enable_tag tagname +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname="$1" + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf="/$re_begincf/,/$re_endcf/p" + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# Shorthand for --mode=foo, only valid as the first argument +case $1 in +clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; +compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; +execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; +finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; +install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; +link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; +uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; +esac + + + +# Option defaults: +opt_debug=: +opt_dry_run=false +opt_config=false +opt_preserve_dup_deps=false +opt_features=false +opt_finish=false +opt_help=false +opt_help_all=false +opt_silent=: +opt_verbose=: +opt_silent=false +opt_verbose=false + + +# Parse options once, thoroughly. This comes as soon as possible in the +# script to make things like `--version' happen as quickly as we can. +{ + # this just eases exit handling + while test $# -gt 0; do + opt="$1" + shift + case $opt in + --debug|-x) opt_debug='set -x' + func_echo "enabling shell trace mode" + $opt_debug + ;; + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + --config) + opt_config=: +func_config + ;; + --dlopen|-dlopen) + optarg="$1" + opt_dlopen="${opt_dlopen+$opt_dlopen +}$optarg" + shift + ;; + --preserve-dup-deps) + opt_preserve_dup_deps=: + ;; + --features) + opt_features=: +func_features + ;; + --finish) + opt_finish=: +set dummy --mode finish ${1+"$@"}; shift + ;; + --help) + opt_help=: + ;; + --help-all) + opt_help_all=: +opt_help=': help-all' + ;; + --mode) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_mode="$optarg" +case $optarg in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; +esac + shift + ;; + --no-silent|--no-quiet) + opt_silent=false +func_append preserve_args " $opt" + ;; + --no-verbose) + opt_verbose=false +func_append preserve_args " $opt" + ;; + --silent|--quiet) + opt_silent=: +func_append preserve_args " $opt" + opt_verbose=false + ;; + --verbose|-v) + opt_verbose=: +func_append preserve_args " $opt" +opt_silent=false + ;; + --tag) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_tag="$optarg" +func_append preserve_args " $opt $optarg" +func_enable_tag "$optarg" + shift + ;; + + -\?|-h) func_usage ;; + --help) func_help ;; + --version) func_version ;; + + # Separate optargs to long options: + --*=*) + func_split_long_opt "$opt" + set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-n*|-v*) + func_split_short_opt "$opt" + set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognized option \`$opt'" ;; + *) set dummy "$opt" ${1+"$@"}; shift; break ;; + esac + done + + # Validate options: + + # save first non-option argument + if test "$#" -gt 0; then + nonopt="$opt" + shift + fi + + # preserve --debug + test "$opt_debug" = : || func_append preserve_args " --debug" + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test "$opt_mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$opt_mode' for more information." + } + + + # Bail if the options were screwed + $exit_cmd $EXIT_FAILURE +} + + + + +## ----------- ## +## Main. ## +## ----------- ## + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case "$lt_sysroot:$1" in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result="=$func_stripname_result" + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$lt_sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $opt_debug + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result="" + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $opt_debug + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $opt_debug + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $opt_debug + if test -z "$2" && test -n "$1" ; then + func_error "Could not determine host file name corresponding to" + func_error " \`$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result="$1" + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $opt_debug + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " \`$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result="$3" + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $opt_debug + case $4 in + $1 ) func_to_host_path_result="$3$func_to_host_path_result" + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via `$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $opt_debug + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $opt_debug + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result="$1" +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result="$func_convert_core_msys_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via `$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $opt_debug + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd="func_convert_path_${func_stripname_result}" + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $opt_debug + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result="$1" +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_mode_compile arg... +func_mode_compile () +{ + $opt_debug + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify \`-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + func_append_quoted lastarg "$arg" + done + IFS="$save_ifs" + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with \`-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj="$func_basename_result" + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from \`$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test "$opt_mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$opt_mode'" + ;; + esac + + echo + $ECHO "Try \`$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test "$opt_help" = :; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | sed -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + sed '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "\`$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument \`$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test "$opt_mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test "x$prev" = x-m && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename="" + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname" ; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename="$func_basename_result" + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename" ; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $opt_debug + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $opt_debug + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive which possess that section. Heuristic: eliminate + # all those which have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $opt_debug + if func_cygming_gnu_implib_p "$1" ; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1" ; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result="" + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + if test "$lock_old_archive_extraction" = yes; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test "$lock_old_archive_extraction" = yes; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# Be Bourne compatible +if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +/* declarations of non-ANSI functions */ +#if defined(__MINGW32__) +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined(__CYGWIN__) +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined (other platforms) ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined(_MSC_VER) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +# ifndef _INTPTR_T_DEFINED +# define _INTPTR_T_DEFINED +# define intptr_t int +# endif +#elif defined(__MINGW32__) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined(__CYGWIN__) +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined (other platforms) ... */ +#endif + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#if defined(LT_DEBUGWRAPPER) +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ fputs ("/' -e 's/$/\\n", f);/' + + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $opt_debug + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir="$arg" + prev= + continue + ;; + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-flto*|-fwhopr*|-fuse-linker-plugin) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps ; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + else + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test "$prefer_static_libs" = yes || + test "$prefer_static_libs,$installed" = "built,no"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib="$l" + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$lt_sysroot$libdir" + absdir="$lt_sysroot$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + case "$host" in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + echo + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$opt_mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$opt_mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system can not link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|qnx|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + func_append verstring ":${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + func_append libobjs " $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$opt_mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$opt_mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_apped perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd1 in $cmds; do + IFS="$save_ifs" + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test "$try_normal_branch" = yes \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=${output_objdir}/${output_la}.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\${concat_cmds}$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " ${wl}-bind_at_load" + func_append finalize_command " ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=no + ;; + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + func_append oldobjs " $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test "x$bindir" != x ; + then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$opt_mode" = link || test "$opt_mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=yes ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + odir="$objdir" + else + odir="$dir/$objdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$opt_mode" = uninstall && odir="$dir" + + # Remember odir for removal later, being careful to avoid duplicates + if test "$opt_mode" = clean; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case "$opt_mode" in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$opt_mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + func_append rmfiles " $odir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$opt_mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff --git a/contrib/libpng/missing b/contrib/libpng/missing new file mode 100755 index 0000000..28055d2 --- /dev/null +++ b/contrib/libpng/missing @@ -0,0 +1,376 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2009-04-28.21; # UTC + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006, +# 2008, 2009 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + autom4te touch the output file, or create a stub one + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and +\`g' are ignored when checking the name. + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# normalize program name to check for. +program=`echo "$1" | sed ' + s/^gnu-//; t + s/^gnu//; t + s/^g//; t'` + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). This is about non-GNU programs, so use $1 not +# $program. +case $1 in + lex*|yacc*) + # Not GNU programs, they don't have --version. + ;; + + tar*) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $program in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te*) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison*|yacc*) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex*|flex*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit $? + fi + ;; + + makeinfo*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar*) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case $firstarg in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case $firstarg in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/contrib/libpng/png.5 b/contrib/libpng/png.5 new file mode 100644 index 0000000..9c5f8d3 --- /dev/null +++ b/contrib/libpng/png.5 @@ -0,0 +1,74 @@ +.TH PNG 5 "February 3, 2011" +.SH NAME +png \- Portable Network Graphics (PNG) format +.SH DESCRIPTION +PNG (Portable Network Graphics) is an extensible file format for the +lossless, portable, well-compressed storage of raster images. PNG provides +a patent-free replacement for GIF and can also replace many +common uses of TIFF. Indexed-color, grayscale, and truecolor images are +supported, plus an optional alpha channel. Sample depths range from +1 to 16 bits. +.br + +PNG is designed to work well in online viewing applications, such as the +World Wide Web, so it is fully streamable with a progressive display +option. PNG is robust, providing both full file integrity checking and +fast, simple detection of common transmission errors. Also, PNG can store +gamma and chromaticity data for improved color matching on heterogeneous +platforms. + +.SH "SEE ALSO" +.BR "libpng"(3), " libpngpf"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) +.LP +PNG specification (second edition), November 2003: +.IP +.br + 8) + png_error(png_ptr, "Too many bytes for PNG signature"); + + png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes); +} + +/* Checks whether the supplied bytes match the PNG signature. We allow + * checking less than the full 8-byte signature so that those apps that + * already read the first few bytes of a file to determine the file type + * can simply check the remaining bytes for extra assurance. Returns + * an integer less than, equal to, or greater than zero if sig is found, + * respectively, to be less than, to match, or be greater than the correct + * PNG signature (this is the same behaviour as strcmp, memcmp, etc). + */ +int PNGAPI +png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + + if (num_to_check > 8) + num_to_check = 8; + + else if (num_to_check < 1) + return (-1); + + if (start > 7) + return (-1); + + if (start + num_to_check > 8) + num_to_check = 8 - start; + + return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check))); +} + +#endif /* PNG_READ_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +/* Function to allocate memory for zlib */ +PNG_FUNCTION(voidpf /* PRIVATE */, +png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED) +{ + png_voidp ptr; + png_structp p=(png_structp)png_ptr; + png_uint_32 save_flags=p->flags; + png_alloc_size_t num_bytes; + + if (png_ptr == NULL) + return (NULL); + + if (items > PNG_UINT_32_MAX/size) + { + png_warning (p, "Potential overflow in png_zalloc()"); + return (NULL); + } + num_bytes = (png_alloc_size_t)items * size; + + p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes); + p->flags=save_flags; + + return ((voidpf)ptr); +} + +/* Function to free memory for zlib */ +void /* PRIVATE */ +png_zfree(voidpf png_ptr, voidpf ptr) +{ + png_free((png_structp)png_ptr, (png_voidp)ptr); +} + +/* Reset the CRC variable to 32 bits of 1's. Care must be taken + * in case CRC is > 32 bits to leave the top bits 0. + */ +void /* PRIVATE */ +png_reset_crc(png_structp png_ptr) +{ + png_ptr->crc = crc32(0, Z_NULL, 0); +} + +/* Calculate the CRC over a section of data. We can only pass as + * much data to this routine as the largest single buffer size. We + * also check that this data will actually be used before going to the + * trouble of calculating it. + */ +void /* PRIVATE */ +png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length) +{ + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + + if (need_crc) + png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); +} + +/* Allocate the memory for an info_struct for the application. We don't + * really need the png_ptr, but it could potentially be useful in the + * future. This should be used in favour of malloc(png_sizeof(png_info)) + * and png_info_init() so that applications that want to use a shared + * libpng don't have to be recompiled if png_info changes size. + */ +PNG_FUNCTION(png_infop,PNGAPI +png_create_info_struct,(png_structp png_ptr),PNG_ALLOCATED) +{ + png_infop info_ptr; + + png_debug(1, "in png_create_info_struct"); + + if (png_ptr == NULL) + return (NULL); + +#ifdef PNG_USER_MEM_SUPPORTED + info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO, + png_ptr->malloc_fn, png_ptr->mem_ptr); +#else + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); +#endif + if (info_ptr != NULL) + png_info_init_3(&info_ptr, png_sizeof(png_info)); + + return (info_ptr); +} + +/* This function frees the memory associated with a single info struct. + * Normally, one would use either png_destroy_read_struct() or + * png_destroy_write_struct() to free an info struct, but this may be + * useful for some applications. + */ +void PNGAPI +png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr) +{ + png_infop info_ptr = NULL; + + png_debug(1, "in png_destroy_info_struct"); + + if (png_ptr == NULL) + return; + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + png_info_destroy(png_ptr, info_ptr); + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn, + png_ptr->mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } +} + +/* Initialize the info structure. This is now an internal function (0.89) + * and applications using it are urged to use png_create_info_struct() + * instead. + */ + +void PNGAPI +png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size) +{ + png_infop info_ptr = *ptr_ptr; + + png_debug(1, "in png_info_init_3"); + + if (info_ptr == NULL) + return; + + if (png_sizeof(png_info) > png_info_struct_size) + { + png_destroy_struct(info_ptr); + info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO); + *ptr_ptr = info_ptr; + } + + /* Set everything to 0 */ + png_memset(info_ptr, 0, png_sizeof(png_info)); +} + +void PNGAPI +png_data_freer(png_structp png_ptr, png_infop info_ptr, + int freer, png_uint_32 mask) +{ + png_debug(1, "in png_data_freer"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (freer == PNG_DESTROY_WILL_FREE_DATA) + info_ptr->free_me |= mask; + + else if (freer == PNG_USER_WILL_FREE_DATA) + info_ptr->free_me &= ~mask; + + else + png_warning(png_ptr, + "Unknown freer parameter in png_data_freer"); +} + +void PNGAPI +png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, + int num) +{ + png_debug(1, "in png_free_data"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + +#ifdef PNG_TEXT_SUPPORTED + /* Free text item num or (if num == -1) all text items */ + if ((mask & PNG_FREE_TEXT) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->text && info_ptr->text[num].key) + { + png_free(png_ptr, info_ptr->text[num].key); + info_ptr->text[num].key = NULL; + } + } + + else + { + int i; + for (i = 0; i < info_ptr->num_text; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i); + png_free(png_ptr, info_ptr->text); + info_ptr->text = NULL; + info_ptr->num_text=0; + } + } +#endif + +#ifdef PNG_tRNS_SUPPORTED + /* Free any tRNS entry */ + if ((mask & PNG_FREE_TRNS) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->trans_alpha); + info_ptr->trans_alpha = NULL; + info_ptr->valid &= ~PNG_INFO_tRNS; + } +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* Free any sCAL entry */ + if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) + { +#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) + png_free(png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_height); + info_ptr->scal_s_width = NULL; + info_ptr->scal_s_height = NULL; +#endif + info_ptr->valid &= ~PNG_INFO_sCAL; + } +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* Free any pCAL entry */ + if ((mask & PNG_FREE_PCAL) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->pcal_purpose); + png_free(png_ptr, info_ptr->pcal_units); + info_ptr->pcal_purpose = NULL; + info_ptr->pcal_units = NULL; + if (info_ptr->pcal_params != NULL) + { + int i; + for (i = 0; i < (int)info_ptr->pcal_nparams; i++) + { + png_free(png_ptr, info_ptr->pcal_params[i]); + info_ptr->pcal_params[i] = NULL; + } + png_free(png_ptr, info_ptr->pcal_params); + info_ptr->pcal_params = NULL; + } + info_ptr->valid &= ~PNG_INFO_pCAL; + } +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* Free any iCCP entry */ + if ((mask & PNG_FREE_ICCP) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->iccp_name); + png_free(png_ptr, info_ptr->iccp_profile); + info_ptr->iccp_name = NULL; + info_ptr->iccp_profile = NULL; + info_ptr->valid &= ~PNG_INFO_iCCP; + } +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Free a given sPLT entry, or (if num == -1) all sPLT entries */ + if ((mask & PNG_FREE_SPLT) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->splt_palettes) + { + png_free(png_ptr, info_ptr->splt_palettes[num].name); + png_free(png_ptr, info_ptr->splt_palettes[num].entries); + info_ptr->splt_palettes[num].name = NULL; + info_ptr->splt_palettes[num].entries = NULL; + } + } + + else + { + if (info_ptr->splt_palettes_num) + { + int i; + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes = NULL; + info_ptr->splt_palettes_num = 0; + } + info_ptr->valid &= ~PNG_INFO_sPLT; + } + } +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + if (png_ptr->unknown_chunk.data) + { + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + if ((mask & PNG_FREE_UNKN) & info_ptr->free_me) + { + if (num != -1) + { + if (info_ptr->unknown_chunks) + { + png_free(png_ptr, info_ptr->unknown_chunks[num].data); + info_ptr->unknown_chunks[num].data = NULL; + } + } + + else + { + int i; + + if (info_ptr->unknown_chunks_num) + { + for (i = 0; i < info_ptr->unknown_chunks_num; i++) + png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + info_ptr->unknown_chunks_num = 0; + } + } + } +#endif + +#ifdef PNG_hIST_SUPPORTED + /* Free any hIST entry */ + if ((mask & PNG_FREE_HIST) & info_ptr->free_me) + { + png_free(png_ptr, info_ptr->hist); + info_ptr->hist = NULL; + info_ptr->valid &= ~PNG_INFO_hIST; + } +#endif + + /* Free any PLTE entry that was internally allocated */ + if ((mask & PNG_FREE_PLTE) & info_ptr->free_me) + { + png_zfree(png_ptr, info_ptr->palette); + info_ptr->palette = NULL; + info_ptr->valid &= ~PNG_INFO_PLTE; + info_ptr->num_palette = 0; + } + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Free any image bits attached to the info structure */ + if ((mask & PNG_FREE_ROWS) & info_ptr->free_me) + { + if (info_ptr->row_pointers) + { + int row; + for (row = 0; row < (int)info_ptr->height; row++) + { + png_free(png_ptr, info_ptr->row_pointers[row]); + info_ptr->row_pointers[row] = NULL; + } + png_free(png_ptr, info_ptr->row_pointers); + info_ptr->row_pointers = NULL; + } + info_ptr->valid &= ~PNG_INFO_IDAT; + } +#endif + + if (num != -1) + mask &= ~PNG_FREE_MUL; + + info_ptr->free_me &= ~mask; +} + +/* This is an internal routine to free any memory that the info struct is + * pointing to before re-using it or freeing the struct itself. Recall + * that png_free() checks for NULL pointers for us. + */ +void /* PRIVATE */ +png_info_destroy(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_info_destroy"); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list = NULL; + png_ptr->num_chunk_list = 0; + } +#endif + + png_info_init_3(&info_ptr, png_sizeof(png_info)); +} +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +/* This function returns a pointer to the io_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy() or png_read_destroy() are called. + */ +png_voidp PNGAPI +png_get_io_ptr(png_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return (png_ptr->io_ptr); +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +# ifdef PNG_STDIO_SUPPORTED +/* Initialize the default input/output functions for the PNG file. If you + * use your own read or write routines, you can call either png_set_read_fn() + * or png_set_write_fn() instead of png_init_io(). If you have defined + * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't + * necessarily available. + */ +void PNGAPI +png_init_io(png_structp png_ptr, png_FILE_p fp) +{ + png_debug(1, "in png_init_io"); + + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = (png_voidp)fp; +} +# endif + +# ifdef PNG_TIME_RFC1123_SUPPORTED +/* Convert the supplied time into an RFC 1123 string suitable for use in + * a "Creation Time" or other text-based time string. + */ +png_const_charp PNGAPI +png_convert_to_rfc1123(png_structp png_ptr, png_const_timep ptime) +{ + static PNG_CONST char short_months[12][4] = + {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + + if (png_ptr == NULL) + return (NULL); + + if (png_ptr->time_buffer == NULL) + { + png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* + png_sizeof(char))); + } + +# ifdef USE_FAR_KEYWORD + { + char near_time_buf[29]; + png_snprintf6(near_time_buf, 29, "%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); + png_memcpy(png_ptr->time_buffer, near_time_buf, + 29*png_sizeof(char)); + } +# else + png_snprintf6(png_ptr->time_buffer, 29, "%d %s %d %02d:%02d:%02d +0000", + ptime->day % 32, short_months[(ptime->month - 1) % 12], + ptime->year, ptime->hour % 24, ptime->minute % 60, + ptime->second % 61); +# endif + return png_ptr->time_buffer; +} +# endif /* PNG_TIME_RFC1123_SUPPORTED */ + +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +png_const_charp PNGAPI +png_get_copyright(png_const_structp png_ptr) +{ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ +#ifdef PNG_STRING_COPYRIGHT + return PNG_STRING_COPYRIGHT +#else +# ifdef __STDC__ + return PNG_STRING_NEWLINE \ + "libpng version 1.5.1 - February 3, 2011" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2011 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ + "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ + "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ + PNG_STRING_NEWLINE; +# else + return "libpng version 1.5.1 - February 3, 2011\ + Copyright (c) 1998-2011 Glenn Randers-Pehrson\ + Copyright (c) 1996-1997 Andreas Dilger\ + Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; +# endif +#endif +} + +/* The following return the library version as a short string in the + * format 1.0.0 through 99.99.99zz. To get the version of *.h files + * used with your application, print out PNG_LIBPNG_VER_STRING, which + * is defined in png.h. + * Note: now there is no difference between png_get_libpng_ver() and + * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, + * it is guaranteed that png.c uses the correct version of png.h. + */ +png_const_charp PNGAPI +png_get_libpng_ver(png_const_structp png_ptr) +{ + /* Version of *.c files used when building libpng */ + return png_get_header_ver(png_ptr); +} + +png_const_charp PNGAPI +png_get_header_ver(png_const_structp png_ptr) +{ + /* Version of *.h files used when building libpng */ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ + return PNG_LIBPNG_VER_STRING; +} + +png_const_charp PNGAPI +png_get_header_version(png_const_structp png_ptr) +{ + /* Returns longer string containing both version and date */ + PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ +#ifdef __STDC__ + return PNG_HEADER_VERSION_STRING +# ifndef PNG_READ_SUPPORTED + " (NO READ SUPPORT)" +# endif + PNG_STRING_NEWLINE; +#else + return PNG_HEADER_VERSION_STRING; +#endif +} + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +# ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +int PNGAPI +png_handle_as_unknown(png_structp png_ptr, png_const_bytep chunk_name) +{ + /* Check chunk_name and return "keep" value if it's on the list, else 0 */ + int i; + png_bytep p; + if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0) + return 0; + + p = png_ptr->chunk_list + png_ptr->num_chunk_list*5 - 5; + for (i = png_ptr->num_chunk_list; i; i--, p -= 5) + if (!png_memcmp(chunk_name, p, 4)) + return ((int)*(p + 4)); + return 0; +} +# endif +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ + +#ifdef PNG_READ_SUPPORTED +/* This function, added to libpng-1.0.6g, is untested. */ +int PNGAPI +png_reset_zstream(png_structp png_ptr) +{ + if (png_ptr == NULL) + return Z_STREAM_ERROR; + + return (inflateReset(&png_ptr->zstream)); +} +#endif /* PNG_READ_SUPPORTED */ + +/* This function was added to libpng-1.0.7 */ +png_uint_32 PNGAPI +png_access_version_number(void) +{ + /* Version of *.c files used when building libpng */ + return((png_uint_32)PNG_LIBPNG_VER); +} + + + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) +# ifdef PNG_SIZE_T +/* Added at libpng version 1.2.6 */ + PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size)); +png_size_t PNGAPI +png_convert_size(size_t size) +{ + if (size > (png_size_t)-1) + PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */ + + return ((png_size_t)size); +} +# endif /* PNG_SIZE_T */ + +/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ +# ifdef PNG_CHECK_cHRM_SUPPORTED + +int /* PRIVATE */ +png_check_cHRM_fixed(png_structp png_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + int ret = 1; + unsigned long xy_hi,xy_lo,yx_hi,yx_lo; + + png_debug(1, "in function png_check_cHRM_fixed"); + + if (png_ptr == NULL) + return 0; + + if (white_x < 0 || white_y <= 0 || + red_x < 0 || red_y < 0 || + green_x < 0 || green_y < 0 || + blue_x < 0 || blue_y < 0) + { + png_warning(png_ptr, + "Ignoring attempt to set negative chromaticity value"); + ret = 0; + } + if (white_x > (png_fixed_point)PNG_UINT_31_MAX || + white_y > (png_fixed_point)PNG_UINT_31_MAX || + red_x > (png_fixed_point)PNG_UINT_31_MAX || + red_y > (png_fixed_point)PNG_UINT_31_MAX || + green_x > (png_fixed_point)PNG_UINT_31_MAX || + green_y > (png_fixed_point)PNG_UINT_31_MAX || + blue_x > (png_fixed_point)PNG_UINT_31_MAX || + blue_y > (png_fixed_point)PNG_UINT_31_MAX ) + { + png_warning(png_ptr, + "Ignoring attempt to set chromaticity value exceeding 21474.83"); + ret = 0; + } + if (white_x > 100000L - white_y) + { + png_warning(png_ptr, "Invalid cHRM white point"); + ret = 0; + } + + if (red_x > 100000L - red_y) + { + png_warning(png_ptr, "Invalid cHRM red point"); + ret = 0; + } + + if (green_x > 100000L - green_y) + { + png_warning(png_ptr, "Invalid cHRM green point"); + ret = 0; + } + + if (blue_x > 100000L - blue_y) + { + png_warning(png_ptr, "Invalid cHRM blue point"); + ret = 0; + } + + png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo); + png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo); + + if (xy_hi == yx_hi && xy_lo == yx_lo) + { + png_warning(png_ptr, + "Ignoring attempt to set cHRM RGB triangle with zero area"); + ret = 0; + } + + return ret; +} +# endif /* PNG_CHECK_cHRM_SUPPORTED */ + +void /* PRIVATE */ +png_check_IHDR(png_structp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + int error = 0; + + /* Check for width and height valid values */ + if (width == 0) + { + png_warning(png_ptr, "Image width is zero in IHDR"); + error = 1; + } + + if (height == 0) + { + png_warning(png_ptr, "Image height is zero in IHDR"); + error = 1; + } + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (width > png_ptr->user_width_max || width > PNG_USER_WIDTH_MAX) + +# else + if (width > PNG_USER_WIDTH_MAX) +# endif + { + png_warning(png_ptr, "Image width exceeds user limit in IHDR"); + error = 1; + } + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (height > png_ptr->user_height_max || height > PNG_USER_HEIGHT_MAX) +# else + if (height > PNG_USER_HEIGHT_MAX) +# endif + { + png_warning(png_ptr, "Image height exceeds user limit in IHDR"); + error = 1; + } + + if (width > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image width in IHDR"); + error = 1; + } + + if (height > PNG_UINT_31_MAX) + { + png_warning(png_ptr, "Invalid image height in IHDR"); + error = 1; + } + + if (width > (PNG_UINT_32_MAX + >> 3) /* 8-byte RGBA pixels */ + - 48 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + png_warning(png_ptr, "Width is too large for libpng to process pixels"); + + /* Check other values */ + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && + bit_depth != 8 && bit_depth != 16) + { + png_warning(png_ptr, "Invalid bit depth in IHDR"); + error = 1; + } + + if (color_type < 0 || color_type == 1 || + color_type == 5 || color_type > 6) + { + png_warning(png_ptr, "Invalid color type in IHDR"); + error = 1; + } + + if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || + ((color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_GRAY_ALPHA || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) + { + png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR"); + error = 1; + } + + if (interlace_type >= PNG_INTERLACE_LAST) + { + png_warning(png_ptr, "Unknown interlace method in IHDR"); + error = 1; + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Unknown compression method in IHDR"); + error = 1; + } + +# ifdef PNG_MNG_FEATURES_SUPPORTED + /* Accept filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not read a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) && + png_ptr->mng_features_permitted) + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + + if (filter_type != PNG_FILTER_TYPE_BASE) + { + if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && + ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA))) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } + + if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) + { + png_warning(png_ptr, "Invalid filter method in IHDR"); + error = 1; + } + } + +# else + if (filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Unknown filter method in IHDR"); + error = 1; + } +# endif + + if (error == 1) + png_error(png_ptr, "Invalid IHDR data"); +} + +#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) +/* ASCII to fp functions */ +/* Check an ASCII formated floating point value, see the more detailed + * comments in pngpriv.h + */ +/* The following is used internally to preserve the 'valid' flag */ +#define png_fp_add(state, flags) ((state) |= (flags)) +#define png_fp_set(state, value)\ + ((state) = (value) | ((state) & PNG_FP_WAS_VALID)) + +/* Internal type codes: bits above the base state! */ +#define PNG_FP_SIGN 0 /* [+-] */ +#define PNG_FP_DOT 4 /* . */ +#define PNG_FP_DIGIT 8 /* [0123456789] */ +#define PNG_FP_E 12 /* [Ee] */ + +int /* PRIVATE */ +png_check_fp_number(png_const_charp string, png_size_t size, int *statep, + png_size_tp whereami) +{ + int state = *statep; + png_size_t i = *whereami; + + while (i < size) + { + int type; + /* First find the type of the next character */ + { + char ch = string[i]; + + if (ch >= 48 && ch <= 57) + type = PNG_FP_DIGIT; + + else switch (ch) + { + case 43: case 45: type = PNG_FP_SIGN; break; + case 46: type = PNG_FP_DOT; break; + case 69: case 101: type = PNG_FP_E; break; + default: goto PNG_FP_End; + } + } + + /* Now deal with this type according to the current + * state, the type is arranged to not overlap the + * bits of the PNG_FP_STATE. + */ + switch ((state & PNG_FP_STATE) + type) + { + case PNG_FP_INTEGER + PNG_FP_SIGN: + if (state & PNG_FP_SAW_ANY) + goto PNG_FP_End; /* not a part of the number */ + + png_fp_add(state, PNG_FP_SAW_SIGN); + break; + + case PNG_FP_INTEGER + PNG_FP_DOT: + /* Ok as trailer, ok as lead of fraction. */ + if (state & PNG_FP_SAW_DOT) /* two dots */ + goto PNG_FP_End; + + else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */ + png_fp_add(state, PNG_FP_SAW_DOT); + + else + png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); + + break; + + case PNG_FP_INTEGER + PNG_FP_DIGIT: + if (state & PNG_FP_SAW_DOT) /* delayed fraction */ + png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); + + png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID); + + break; + case PNG_FP_INTEGER + PNG_FP_E: + if ((state & PNG_FP_SAW_DIGIT) == 0) + goto PNG_FP_End; + + png_fp_set(state, PNG_FP_EXPONENT); + + break; + + /* case PNG_FP_FRACTION + PNG_FP_SIGN: + goto PNG_FP_End; ** no sign in exponent */ + + /* case PNG_FP_FRACTION + PNG_FP_DOT: + goto PNG_FP_End; ** Because SAW_DOT is always set */ + + case PNG_FP_FRACTION + PNG_FP_DIGIT: + png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID); + break; + + case PNG_FP_FRACTION + PNG_FP_E: + /* This is correct because the trailing '.' on an + * integer is handled above - so we can only get here + * with the sequence ".E" (with no preceding digits). + */ + if ((state & PNG_FP_SAW_DIGIT) == 0) + goto PNG_FP_End; + + png_fp_set(state, PNG_FP_EXPONENT); + + break; + + case PNG_FP_EXPONENT + PNG_FP_SIGN: + if (state & PNG_FP_SAW_ANY) + goto PNG_FP_End; /* not a part of the number */ + + png_fp_add(state, PNG_FP_SAW_SIGN); + + break; + + /* case PNG_FP_EXPONENT + PNG_FP_DOT: + goto PNG_FP_End; */ + + case PNG_FP_EXPONENT + PNG_FP_DIGIT: + png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID); + + break; + + /* case PNG_FP_EXPONEXT + PNG_FP_E: + goto PNG_FP_End; */ + + default: goto PNG_FP_End; /* I.e. break 2 */ + } + + /* The character seems ok, continue. */ + ++i; + } + +PNG_FP_End: + /* Here at the end, update the state and return the correct + * return code. + */ + *statep = state; + *whereami = i; + + return (state & PNG_FP_SAW_DIGIT) != 0; +} + + +/* The same but for a complete string. */ +int +png_check_fp_string(png_const_charp string, png_size_t size) +{ + int state=0; + png_size_t char_index=0; + + return png_check_fp_number(string, size, &state, &char_index) && + (char_index == size || string[char_index] == 0); +} +#endif /* pCAL or sCAL */ + +#ifdef PNG_READ_sCAL_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +/* Utility used below - a simple accurate power of ten from an integral + * exponent. + */ +static double +png_pow10(int power) +{ + int recip = 0; + double d = 1; + + /* Handle negative exponent with a reciprocal at the end because + * 10 is exact whereas .1 is inexact in base 2 + */ + if (power < 0) + { + if (power < DBL_MIN_10_EXP) return 0; + recip = 1, power = -power; + } + + if (power > 0) + { + /* Decompose power bitwise. */ + double mult = 10; + do + { + if (power & 1) d *= mult; + mult *= mult; + power >>= 1; + } + while (power > 0); + + if (recip) d = 1/d; + } + /* else power is 0 and d is 1 */ + + return d; +} + +/* Function to format a floating point value in ASCII with a given + * precision. + */ +void /* PRIVATE */ +png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size, + double fp, unsigned int precision) +{ + /* We use standard functions from math.h, but not printf because + * that would require stdio. The caller must supply a buffer of + * sufficient size or we will png_error. The tests on size and + * the space in ascii[] consumed are indicated below. + */ + if (precision < 1) + precision = DBL_DIG; + + /* Enforce the limit of the implementation precision too. */ + if (precision > DBL_DIG+1) + precision = DBL_DIG+1; + + /* Basic sanity checks */ + if (size >= precision+5) /* See the requirements below. */ + { + if (fp < 0) + { + fp = -fp; + *ascii++ = 45; /* '-' PLUS 1 TOTAL 1*/ + --size; + } + + if (fp >= DBL_MIN && fp <= DBL_MAX) + { + int exp_b10; /* A base 10 exponent */ + double base; /* 10^exp_b10 */ + + /* First extract a base 10 exponent of the number, + * the calculation below rounds down when converting + * from base 2 to base 10 (multiply by log10(2) - + * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to + * be increased. Note that the arithmetic shift + * performs a floor() unlike C arithmetic - using a + * C multiply would break the following for negative + * exponents. + */ + (void)frexp(fp, &exp_b10); /* exponent to base 2 */ + + exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */ + + /* Avoid underflow here. */ + base = png_pow10(exp_b10); /* May underflow */ + + while (base < DBL_MIN || base < fp) + { + /* And this may overflow. */ + double test = png_pow10(exp_b10+1); + + if (test <= DBL_MAX) + ++exp_b10, base = test; + + else + break; + } + + /* Normalize fp and correct exp_b10, after this fp is in the + * range [.1,1) and exp_b10 is both the exponent and the digit + * *before* which the decimal point should be inserted + * (starting with 0 for the first digit). Note that this + * works even if 10^exp_b10 is out of range because of the + * test on DBL_MAX above. + */ + fp /= base; + while (fp >= 1) fp /= 10, ++exp_b10; + + /* Because of the code above fp may, at this point, be + * less than .1, this is ok because the code below can + * handle the leading zeros this generates, so no attempt + * is made to correct that here. + */ + + { + int czero, clead, cdigits; + char exponent[10]; + + /* Allow up to two leading zeros - this will not lengthen + * the number compared to using E-n. + */ + if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ + { + czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */ + exp_b10 = 0; /* Dot added below before first output. */ + } + else + czero = 0; /* No zeros to add */ + + /* Generate the digit list, stripping trailing zeros and + * inserting a '.' before a digit if the exponent is 0. + */ + clead = czero; /* Count of leading zeros */ + cdigits = 0; /* Count of digits in list. */ + + do + { + double d; + + fp *= 10; + /* Use modf here, not floor and subtract, so that + * the separation is done in one step. At the end + * of the loop don't break the number into parts so + * that the final digit is rounded. + */ + if (cdigits+czero-clead+1 < (int)precision) + fp = modf(fp, &d); + + else + { + d = floor(fp + .5); + + if (d > 9) + { + /* Rounding up to 10, handle that here. */ + if (czero > 0) + { + --czero, d = 1; + if (cdigits == 0) --clead; + } + else + { + while (cdigits > 0 && d > 9) + { + int ch = *--ascii; + + if (exp_b10 != (-1)) + ++exp_b10; + + else if (ch == 46) + { + ch = *--ascii, ++size; + /* Advance exp_b10 to '1', so that the + * decimal point happens after the + * previous digit. + */ + exp_b10 = 1; + } + + --cdigits; + d = ch - 47; /* I.e. 1+(ch-48) */ + } + + /* Did we reach the beginning? If so adjust the + * exponent but take into account the leading + * decimal point. + */ + if (d > 9) /* cdigits == 0 */ + { + if (exp_b10 == (-1)) + { + /* Leading decimal point (plus zeros?), if + * we lose the decimal point here it must + * be reentered below. + */ + int ch = *--ascii; + + if (ch == 46) + ++size, exp_b10 = 1; + + /* Else lost a leading zero, so 'exp_b10' is + * still ok at (-1) + */ + } + else + ++exp_b10; + + /* In all cases we output a '1' */ + d = 1; + } + } + } + fp = 0; /* Guarantees termination below. */ + } + + if (d == 0) + { + ++czero; + if (cdigits == 0) ++clead; + } + else + { + /* Included embedded zeros in the digit count. */ + cdigits += czero - clead; + clead = 0; + + while (czero > 0) + { + /* exp_b10 == (-1) means we just output the decimal + * place - after the DP don't adjust 'exp_b10' any + * more! + */ + if (exp_b10 != (-1)) + { + if (exp_b10 == 0) *ascii++ = 46, --size; + /* PLUS 1: TOTAL 4 */ + --exp_b10; + } + *ascii++ = 48, --czero; + } + + if (exp_b10 != (-1)) + { + if (exp_b10 == 0) *ascii++ = 46, --size; /* counted + above */ + --exp_b10; + } + *ascii++ = (char)(48 + (int)d), ++cdigits; + } + } + while (cdigits+czero-clead < (int)precision && fp > DBL_MIN); + + /* The total output count (max) is now 4+precision */ + + /* Check for an exponent, if we don't need one we are + * done and just need to terminate the string. At + * this point exp_b10==(-1) is effectively if flag - it got + * to '-1' because of the decrement after outputing + * the decimal point above (the exponent required is + * *not* -1!) + */ + if (exp_b10 >= (-1) && exp_b10 <= 2) + { + /* The following only happens if we didn't output the + * leading zeros above for negative exponent, so this + * doest add to the digit requirement. Note that the + * two zeros here can only be output if the two leading + * zeros were *not* output, so this doesn't increase + * the output count. + */ + while (--exp_b10 >= 0) *ascii++ = 48; + + *ascii = 0; + + /* Total buffer requirement (including the '\0') is + * 5+precision - see check at the start. + */ + return; + } + + /* Here if an exponent is required, adjust size for + * the digits we output but did not count. The total + * digit output here so far is at most 1+precision - no + * decimal point and no leading or trailing zeros have + * been output. + */ + size -= cdigits; + + *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision*/ + if (exp_b10 < 0) + { + *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ + exp_b10 = -exp_b10; + } + + cdigits = 0; + + while (exp_b10 > 0) + { + exponent[cdigits++] = (char)(48 + exp_b10 % 10); + exp_b10 /= 10; + } + + /* Need another size check here for the exponent digits, so + * this need not be considered above. + */ + if ((int)size > cdigits) + { + while (cdigits > 0) *ascii++ = exponent[--cdigits]; + + *ascii = 0; + + return; + } + } + } + else if (!(fp >= DBL_MIN)) + { + *ascii++ = 48; /* '0' */ + *ascii = 0; + return; + } + else + { + *ascii++ = 105; /* 'i' */ + *ascii++ = 110; /* 'n' */ + *ascii++ = 102; /* 'f' */ + *ascii = 0; + return; + } + } + + /* Here on buffer too small. */ + png_error(png_ptr, "ASCII conversion buffer too small"); +} + +# endif /* FLOATING_POINT */ + +# ifdef PNG_FIXED_POINT_SUPPORTED +/* Function to format a fixed point value in ASCII. + */ +void /* PRIVATE */ +png_ascii_from_fixed(png_structp png_ptr, png_charp ascii, png_size_t size, + png_fixed_point fp) +{ + /* Require space for 10 decimal digits, a decimal point, a minus sign and a + * trailing \0, 13 characters: + */ + if (size > 12) + { + png_uint_32 num; + + /* Avoid overflow here on the minimum integer. */ + if (fp < 0) + *ascii++ = 45, --size, num = -fp; + else + num = fp; + + if (num <= 0x80000000U) /* else overflowed */ + { + unsigned int ndigits = 0, first = 16/*flag value*/; + char digits[10]; + + while (num) + { + /* Split the low digit off num: */ + unsigned int tmp = num/10; + num -= tmp*10; + digits[ndigits++] = (char)(48 + num); + /* Record the first non-zero digit, note that this is a number + * starting at 1, it's not actually the array index. + */ + if (first == 16 && num > 0) + first = ndigits; + num = tmp; + } + + if (ndigits > 0) + { + while (ndigits > 5) *ascii++ = digits[--ndigits]; + /* The remaining digits are fractional digits, ndigits is '5' or + * smaller at this point. It is certainly not zero. Check for a + * non-zero fractional digit: + */ + if (first <= 5) + { + unsigned int i; + *ascii++ = 46; /* decimal point */ + /* ndigits may be <5 for small numbers, output leading zeros + * then ndigits digits to first: + */ + i = 5; + while (ndigits < i) *ascii++ = 48, --i; + while (ndigits >= first) *ascii++ = digits[--ndigits]; + /* Don't output the trailing zeros! */ + } + } + else + *ascii++ = 48; + + /* And null terminate the string: */ + *ascii = 0; + return; + } + } + + /* Here on buffer too small. */ + png_error(png_ptr, "ASCII conversion buffer too small"); +} +# endif /* FIXED_POINT */ +#endif /* READ_SCAL */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) +png_fixed_point +png_fixed(png_structp png_ptr, double fp, png_const_charp text) +{ + double r = floor(100000 * fp + .5); + + if (r > 2147483647. || r < -2147483648.) + png_fixed_error(png_ptr, text); + + return (png_fixed_point)r; +} +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || \ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG__READ_pHYs_SUPPORTED) +/* muldiv functions */ +/* This API takes signed arguments and rounds the result to the nearest + * integer (or, for a fixed point number - the standard argument - to + * the nearest .00001). Overflow and divide by zero are signalled in + * the result, a boolean - true on success, false on overflow. + */ +int +png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, + png_int_32 divisor) +{ + /* Return a * times / divisor, rounded. */ + if (divisor != 0) + { + if (a == 0 || times == 0) + { + *res = 0; + return 1; + } + else + { +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = a; + r *= times; + r /= divisor; + r = floor(r+.5); + + /* A png_fixed_point is a 32 bit integer. */ + if (r <= 2147483647. && r >= -2147483648.) + { + *res = (png_fixed_point)r; + return 1; + } +#else + int negative = 0; + png_uint_32 A, T, D; + png_uint_32 s16, s32, s00; + + if (a < 0) + negative = 1, A = -a; + else + A = a; + + if (times < 0) + negative = !negative, T = -times; + else + T = times; + + if (divisor < 0) + negative = !negative, D = -divisor; + else + D = divisor; + + /* Following can't overflow because the arguments only + * have 31 bits each, however the result may be 32 bits. + */ + s16 = (A >> 16) * (T & 0xffff) + + (A & 0xffff) * (T >> 16); + /* Can't overflow because the a*times bit is only 30 + * bits at most. + */ + s32 = (A >> 16) * (T >> 16) + (s16 >> 16); + s00 = (A & 0xffff) * (T & 0xffff); + + s16 = (s16 & 0xffff) << 16; + s00 += s16; + + if (s00 < s16) + ++s32; /* carry */ + + if (s32 < D) /* else overflow */ + { + /* s32.s00 is now the 64 bit product, do a standard + * division, we know that s32 < D, so the maximum + * required shift is 31. + */ + int bitshift = 32; + png_fixed_point result = 0; /* NOTE: signed */ + + while (--bitshift >= 0) + { + png_uint_32 d32, d00; + + if (bitshift > 0) + d32 = D >> (32-bitshift), d00 = D << bitshift; + + else + d32 = 0, d00 = D; + + if (s32 > d32) + { + if (s00 < d00) --s32; /* carry */ + s32 -= d32, s00 -= d00, result += 1<= d00) + s32 = 0, s00 -= d00, result += 1<= (D >> 1)) + ++result; + + if (negative) + result = -result; + + /* Check for overflow. */ + if ((negative && result <= 0) || (!negative && result >= 0)) + { + *res = result; + return 1; + } + } +#endif + } + } + + return 0; +} +#endif /* READ_GAMMA || INCH_CONVERSIONS */ + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) +/* The following is for when the caller doesn't much care about the + * result. + */ +png_fixed_point +png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times, + png_int_32 divisor) +{ + png_fixed_point result; + + if (png_muldiv(&result, a, times, divisor)) + return result; + + png_warning(png_ptr, "fixed point overflow ignored"); + return 0; +} +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED /* more fixed point functions for gammma */ +/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */ +png_fixed_point +png_reciprocal(png_fixed_point a) +{ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(1E10/a+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + png_fixed_point res; + + if (png_muldiv(&res, 100000, 100000, a)) + return res; +#endif + + return 0; /* error/overflow */ +} + +/* A local convenience routine. */ +static png_fixed_point +png_product2(png_fixed_point a, png_fixed_point b) +{ + /* The required result is 1/a * 1/b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = a * 1E-5; + r *= b; + r = floor(r+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + png_fixed_point res; + + if (png_muldiv(&res, a, b, 100000)) + return res; +#endif + + return 0; /* overflow */ +} + +/* The inverse of the above. */ +png_fixed_point +png_reciprocal2(png_fixed_point a, png_fixed_point b) +{ + /* The required result is 1/a * 1/b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = 1E15/a; + r /= b; + r = floor(r+.5); + + if (r <= 2147483647. && r >= -2147483648.) + return (png_fixed_point)r; +#else + /* This may overflow because the range of png_fixed_point isn't symmetric, + * but this API is only used for the product of file and screen gamma so it + * doesn't matter that the smallest number it can produce is 1/21474, not + * 1/100000 + */ + png_fixed_point res = png_product2(a, b); + + if (res != 0) + return png_reciprocal(res); +#endif + + return 0; /* overflow */ +} +#endif /* READ_GAMMA */ + +#ifdef PNG_CHECK_cHRM_SUPPORTED +/* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2, + * 2010: moved from pngset.c) */ +/* + * Multiply two 32-bit numbers, V1 and V2, using 32-bit + * arithmetic, to produce a 64 bit result in the HI/LO words. + * + * A B + * x C D + * ------ + * AD || BD + * AC || CB || 0 + * + * where A and B are the high and low 16-bit words of V1, + * C and D are the 16-bit words of V2, AD is the product of + * A and D, and X || Y is (X << 16) + Y. +*/ + +void /* PRIVATE */ +png_64bit_product (long v1, long v2, unsigned long *hi_product, + unsigned long *lo_product) +{ + int a, b, c, d; + long lo, hi, x, y; + + a = (v1 >> 16) & 0xffff; + b = v1 & 0xffff; + c = (v2 >> 16) & 0xffff; + d = v2 & 0xffff; + + lo = b * d; /* BD */ + x = a * d + c * b; /* AD + CB */ + y = ((lo >> 16) & 0xffff) + x; + + lo = (lo & 0xffff) | ((y & 0xffff) << 16); + hi = (y >> 16) & 0xffff; + + hi += a * c; /* AC */ + + *hi_product = (unsigned long)hi; + *lo_product = (unsigned long)lo; +} +#endif /* CHECK_cHRM */ + +#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */ +#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* Fixed point gamma. + * + * To calculate gamma this code implements fast log() and exp() calls using only + * fixed point arithmetic. This code has sufficient precision for either 8 or + * 16 bit sample values. + * + * The tables used here were calculated using simple 'bc' programs, but C double + * precision floating point arithmetic would work fine. The programs are given + * at the head of each table. + * + * 8 bit log table + * This is a table of -log(value/255)/log(2) for 'value' in the range 128 to + * 255, so it's the base 2 logarithm of a normalized 8 bit floating point + * mantissa. The numbers are 32 bit fractions. + */ +static png_uint_32 +png_8bit_l2[128] = +{ +# if PNG_DO_BC + for (i=128;i<256;++i) { .5 - l(i/255)/l(2)*65536*65536; } +# endif + 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U, + 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U, + 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U, + 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U, + 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U, + 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U, + 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U, + 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U, + 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U, + 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U, + 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U, + 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U, + 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U, + 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U, + 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U, + 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U, + 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U, + 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U, + 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U, + 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U, + 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U, + 24347096U, 0U +#if 0 + /* The following are the values for 16 bit tables - these work fine for the 8 + * bit conversions but produce very slightly larger errors in the 16 bit log + * (about 1.2 as opposed to 0.7 absolute error in the final value). To use + * these all the shifts below must be adjusted appropriately. + */ + 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054, + 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803, + 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068, + 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782, + 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887, + 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339, + 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098, + 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132, + 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415, + 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523, + 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495, + 1119, 744, 372 +#endif +}; + +static png_int_32 +png_log8bit(unsigned int x) +{ + unsigned int lg2 = 0; + /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log, + * because the log is actually negate that means adding 1. The final + * returned value thus has the range 0 (for 255 input) to 7.994 (for 1 + * input), return 7.99998 for the overflow (log 0) case - so the result is + * always at most 19 bits. + */ + if ((x &= 0xff) == 0) + return 0xffffffff; + + if ((x & 0xf0) == 0) + lg2 = 4, x <<= 4; + + if ((x & 0xc0) == 0) + lg2 += 2, x <<= 2; + + if ((x & 0x80) == 0) + lg2 += 1, x <<= 1; + + /* result is at most 19 bits, so this cast is safe: */ + return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16)); +} + +/* The above gives exact (to 16 binary places) log2 values for 8 bit images, + * for 16 bit images we use the most significant 8 bits of the 16 bit value to + * get an approximation then multiply the approximation by a correction factor + * determined by the remaining up to 8 bits. This requires an additional step + * in the 16 bit case. + * + * We want log2(value/65535), we have log2(v'/255), where: + * + * value = v' * 256 + v'' + * = v' * f + * + * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128 + * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less + * than 258. The final factor also needs to correct for the fact that our 8 bit + * value is scaled by 255, whereas the 16 bit values must be scaled by 65535. + * + * This gives a final formula using a calculated value 'x' which is value/v' and + * scaling by 65536 to match the above table: + * + * log2(x/257) * 65536 + * + * Since these numbers are so close to '1' we can use simple linear + * interpolation between the two end values 256/257 (result -368.61) and 258/257 + * (result 367.179). The values used below are scaled by a further 64 to give + * 16 bit precision in the interpolation: + * + * Start (256): -23591 + * Zero (257): 0 + * End (258): 23499 + */ +static png_int_32 +png_log16bit(png_uint_32 x) +{ + unsigned int lg2 = 0; + + /* As above, but now the input has 16 bits. */ + if ((x &= 0xffff) == 0) + return 0xffffffff; + + if ((x & 0xff00) == 0) + lg2 = 8, x <<= 8; + + if ((x & 0xf000) == 0) + lg2 += 4, x <<= 4; + + if ((x & 0xc000) == 0) + lg2 += 2, x <<= 2; + + if ((x & 0x8000) == 0) + lg2 += 1, x <<= 1; + + /* Calculate the base logarithm from the top 8 bits as a 28 bit fractional + * value. + */ + lg2 <<= 28; + lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4; + + /* Now we need to interpolate the factor, this requires a division by the top + * 8 bits. Do this with maximum precision. + */ + x = ((x << 16) + (x >> 9)) / (x >> 8); + + /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24, + * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly + * 16 bits to interpolate to get the low bits of the result. Round the + * answer. Note that the end point values are scaled by 64 to retain overall + * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust + * the overall scaling by 6-12. Round at every step. + */ + x -= 1U << 24; + + if (x <= 65536U) /* <= '257' */ + lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12); + + else + lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12); + + /* Safe, because the result can't have more than 20 bits: */ + return (png_int_32)((lg2 + 2048) >> 12); +} + +/* The 'exp()' case must invert the above, taking a 20 bit fixed point + * logarithmic value and returning a 16 or 8 bit number as appropriate. In + * each case only the low 16 bits are relevant - the fraction - since the + * integer bits (the top 4) simply determine a shift. + * + * The worst case is the 16 bit distinction between 65535 and 65534, this + * requires perhaps spurious accuracty in the decoding of the logarithm to + * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance + * of getting this accuracy in practice. + * + * To deal with this the following exp() function works out the exponent of the + * frational part of the logarithm by using an accurate 32 bit value from the + * top four fractional bits then multiplying in the remaining bits. + */ +static png_uint_32 +png_32bit_exp[16] = +{ +# if PNG_DO_BC + for (i=0;i<16;++i) { .5 + e(-i/16*l(2))*2^32; } +# endif + /* NOTE: the first entry is deliberately set to the maximum 32 bit value. */ + 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U, + 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U, + 2553802834U, 2445529972U, 2341847524U, 2242560872U +}; + +/* Adjustment table; provided to explain the numbers in the code below. */ +#if PNG_DO_BC +for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"} + 11 44937.64284865548751208448 + 10 45180.98734845585101160448 + 9 45303.31936980687359311872 + 8 45364.65110595323018870784 + 7 45395.35850361789624614912 + 6 45410.72259715102037508096 + 5 45418.40724413220722311168 + 4 45422.25021786898173001728 + 3 45424.17186732298419044352 + 2 45425.13273269940811464704 + 1 45425.61317555035558641664 + 0 45425.85339951654943850496 +#endif + +static png_uint_32 +png_exp(png_fixed_point x) +{ + if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */ + { + /* Obtain a 4 bit approximation */ + png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf]; + + /* Incorporate the low 12 bits - these decrease the returned value by + * multiplying by a number less than 1 if the bit is set. The multiplier + * is determined by the above table and the shift. Notice that the values + * converge on 45426 and this is used to allow linear interpolation of the + * low bits. + */ + if (x & 0x800) + e -= (((e >> 16) * 44938U) + 16U) >> 5; + + if (x & 0x400) + e -= (((e >> 16) * 45181U) + 32U) >> 6; + + if (x & 0x200) + e -= (((e >> 16) * 45303U) + 64U) >> 7; + + if (x & 0x100) + e -= (((e >> 16) * 45365U) + 128U) >> 8; + + if (x & 0x080) + e -= (((e >> 16) * 45395U) + 256U) >> 9; + + if (x & 0x040) + e -= (((e >> 16) * 45410U) + 512U) >> 10; + + /* And handle the low 6 bits in a single block. */ + e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9; + + /* Handle the upper bits of x. */ + e >>= x >> 16; + return e; + } + + /* Check for overflow */ + if (x <= 0) + return png_32bit_exp[0]; + + /* Else underflow */ + return 0; +} + +static png_byte +png_exp8bit(png_fixed_point lg2) +{ + /* Get a 32 bit value: */ + png_uint_32 x = png_exp(lg2); + + /* Convert the 32 bit value to 0..255 by multiplying by 256-1, note that the + * second, rounding, step can't overflow because of the first, subtraction, + * step. + */ + x -= x >> 8; + return (png_byte)((x + 0x7fffffU) >> 24); +} + +static png_uint_16 +png_exp16bit(png_fixed_point lg2) +{ + /* Get a 32 bit value: */ + png_uint_32 x = png_exp(lg2); + + /* Convert the 32 bit value to 0..65535 by multiplying by 65536-1: */ + x -= x >> 16; + return (png_uint_16)((x + 32767U) >> 16); +} +#endif /* FLOATING_ARITHMETIC */ + +png_byte +png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val) +{ + if (value > 0 && value < 255) + { +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(255*pow(value/255.,gamma_val*.00001)+.5); + return (png_byte)r; +# else + png_int_32 lg2 = png_log8bit(value); + png_fixed_point res; + + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) + return png_exp8bit(res); + + /* Overflow. */ + value = 0; +# endif + } + + return (png_byte)value; +} + +png_uint_16 +png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) +{ + if (value > 0 && value < 65535) + { +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5); + return (png_uint_16)r; +# else + png_int_32 lg2 = png_log16bit(value); + png_fixed_point res; + + if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1)) + return png_exp16bit(res); + + /* Overflow. */ + value = 0; +# endif + } + + return (png_uint_16)value; +} + +/* This does the right thing based on the bit_depth field of the + * png_struct, interpreting values as 8 or 16 bit. While the result + * is nominally a 16 bit value if bit depth is 8 then the result is + * 8 bit (as are the arguments.) + */ +png_uint_16 /* PRIVATE */ +png_gamma_correct(png_structp png_ptr, unsigned int value, + png_fixed_point gamma_val) +{ + if (png_ptr->bit_depth == 8) + return png_gamma_8bit_correct(value, gamma_val); + + else + return png_gamma_16bit_correct(value, gamma_val); +} + +/* This is the shared test on whether a gamma value is 'significant' - whether + * it is worth doing gamma correction. + */ +int /* PRIVATE */ +png_gamma_significant(png_fixed_point gamma_val) +{ + return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED || + gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED; +} + +/* Internal function to build a single 16 bit table - the table consists of + * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount + * to shift the input values right (or 16-number_of_signifiant_bits). + * + * The caller is responsible for ensuring that the table gets cleaned up on + * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument + * should be somewhere that will be cleaned. + */ +static void +png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable, + PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) +{ + /* Various values derived from 'shift': */ + PNG_CONST unsigned int num = 1U << (8U - shift); + PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + PNG_CONST unsigned int max_by_2 = 1U << (15U-shift); + unsigned int i; + + png_uint_16pp table = *ptable = + (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p)); + + for (i = 0; i < num; i++) + { + png_uint_16p sub_table = table[i] = + (png_uint_16p)png_malloc(png_ptr, 256 * png_sizeof(png_uint_16)); + + /* The 'threshold' test is repeated here because it can arise for one of + * the 16 bit tables even if the others don't hit it. + */ + if (png_gamma_significant(gamma_val)) + { + /* The old code would overflow at the end and this would cause the + * 'pow' function to return a result >1, resulting in an + * arithmetic error. This code follows the spec exactly; ig is + * the recovered input sample, it always has 8-16 bits. + * + * We want input * 65535/max, rounded, the arithmetic fits in 32 + * bits (unsigned) so long as max <= 32767. + */ + unsigned int j; + for (j = 0; j < 256; j++) + { + png_uint_32 ig = (j << (8-shift)) + i; +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + /* Inline the 'max' scaling operation: */ + double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5); + sub_table[j] = (png_uint_16)d; +# else + if (shift) + ig = (ig * 65535U + max_by_2)/max; + + sub_table[j] = png_gamma_16bit_correct(ig, gamma_val); +# endif + } + } + else + { + /* We must still build a table, but do it the fast way. */ + unsigned int j; + + for (j = 0; j < 256; j++) + { + png_uint_32 ig = (j << (8-shift)) + i; + + if (shift) + ig = (ig * 65535U + max_by_2)/max; + + sub_table[j] = (png_uint_16)ig; + } + } + } +} + +/* NOTE: this function expects the *inverse* of the overall gamma transformation + * required. + */ +static void +png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable, + PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) +{ + PNG_CONST unsigned int num = 1U << (8U - shift); + PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + unsigned int i; + png_uint_32 last; + + png_uint_16pp table = *ptable = + (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p)); + + /* 'num' is the number of tables and also the number of low bits of low + * bits of the input 16 bit value used to select a table. Each table is + * itself index by the high 8 bits of the value. + */ + for (i = 0; i < num; i++) + table[i] = (png_uint_16p)png_malloc(png_ptr, + 256 * png_sizeof(png_uint_16)); + + /* 'gamma_val' is set to the reciprocal of the value calculated above, so + * pow(out,g) is an *input* value. 'last' is the last input value set. + * + * In the loop 'i' is used to find output values. Since the output is 8 + * bit there are only 256 possible values. The tables are set up to + * select the closest possible output value for each input by finding + * the input value at the boundary between each pair of output values + * and filling the table up to that boundary with the lower output + * value. + * + * The boundary values are 0.5,1.5..253.5,254.5. Since these are 9 bit + * values the code below uses a 16 bit value in i; the values start at + * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last + * entries are filled with 255). Start i at 128 and fill all 'last' + * table entries <= 'max' + */ + last = 0; + for (i = 0; i < 255; ++i) /* 8 bit output value */ + { + /* Find the corresponding maximum input value */ + png_uint_16 out = (png_uint_16)(i * 257U); /* 16 bit output value */ + + /* Find the boundary value in 16 bits: */ + png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val); + + /* Adjust (round) to (16-shift) bits: */ + bound = (bound * max + 32768U)/65535U + 1U; + + while (last < bound) + { + table[last & (0xffU >> shift)][last >> (8U - shift)] = out; + last++; + } + } + + /* And fill in the final entries. */ + while (last < (num << 8)) + { + table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U; + last++; + } +} + +/* Build a single 8 bit table: same as the 16 bit case but much simpler (and + * typically much faster). Note that libpng currently does no sBIT processing + * (apparently contrary to the spec) so a 256 entry table is always generated. + */ +static void +png_build_8bit_table(png_structp png_ptr, png_bytepp ptable, + PNG_CONST png_fixed_point gamma_val) +{ + unsigned int i; + png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); + + if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++) + table[i] = png_gamma_8bit_correct(i, gamma_val); + + else for (i=0; i<256; ++i) + table[i] = (png_byte)i; +} + +/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit + * tables, we don't make a full table if we are reducing to 8-bit in + * the future. Note also how the gamma_16 tables are segmented so that + * we don't need to allocate > 64K chunks for a full 16-bit table. + */ +void /* PRIVATE */ +png_build_gamma_table(png_structp png_ptr, int bit_depth) +{ + png_debug(1, "in png_build_gamma_table"); + + if (bit_depth <= 8) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_table, + png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma, + png_ptr->screen_gamma) : PNG_FP_1); + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) + { + png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, + png_reciprocal(png_ptr->gamma)); + + png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, + png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : + png_ptr->gamma/* Probably doing rgb_to_gray */); + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } + else + { + png_byte shift, sig_bit; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + sig_bit = png_ptr->sig_bit.red; + + if (png_ptr->sig_bit.green > sig_bit) + sig_bit = png_ptr->sig_bit.green; + + if (png_ptr->sig_bit.blue > sig_bit) + sig_bit = png_ptr->sig_bit.blue; + } + else + sig_bit = png_ptr->sig_bit.gray; + + /* 16 bit gamma code uses this equation: + * + * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] + * + * Where 'iv' is the input color value and 'ov' is the output value - + * pow(iv, gamma). + * + * Thus the gamma table consists of up to 256 256 entry tables. The table + * is selected by the (8-gamma_shift) most significant of the low 8 bits of + * the color value then indexed by the upper 8 bits: + * + * table[low bits][high 8 bits] + * + * So the table 'n' corresponds to all those 'iv' of: + * + * ..<(n+1 << gamma_shift)-1> + * + */ + if (sig_bit > 0 && sig_bit < 16U) + shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */ + + else + shift = 0; /* keep all 16 bits */ + + if (png_ptr->transformations & PNG_16_TO_8) + { + /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively + * the significant bits in the *input* when the output will + * eventually be 8 bits. By default it is 11. + */ + if (shift < (16U - PNG_MAX_GAMMA_8)) + shift = (16U - PNG_MAX_GAMMA_8); + } + + if (shift > 8U) + shift = 8U; /* Guarantees at least one table! */ + + png_ptr->gamma_shift = shift; + +#ifdef PNG_16BIT_SUPPORTED + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) +#endif + png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma, + png_ptr->screen_gamma) : PNG_FP_1); + +#ifdef PNG_16BIT_SUPPORTED + else + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma, + png_ptr->screen_gamma) : PNG_FP_1); +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) + if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) + { + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, + png_reciprocal(png_ptr->gamma)); + + /* Notice that the '16 from 1' table should be full precision, however + * the lookup on this table still uses gamma_shift, so it can't be. + * TODO: fix this. + */ + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, + png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : + png_ptr->gamma/* Probably doing rgb_to_gray */); + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ + } +} +#endif /* READ_GAMMA */ +#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff --git a/contrib/libpng/png.h b/contrib/libpng/png.h new file mode 100644 index 0000000..100f56d --- /dev/null +++ b/contrib/libpng/png.h @@ -0,0 +1,2280 @@ + +/* png.h - header file for PNG reference library + * + * libpng version 1.5.1 - February 3, 2011 + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license (See LICENSE, below) + * + * Authors and maintainers: + * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat + * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.5.1 - February 3, 2011: Glenn + * See also "Contributing Authors", below. + * + * Note about libpng version numbers: + * + * Due to various miscommunications, unforeseen code incompatibilities + * and occasional factors outside the authors' control, version numbering + * on the library has not always been consistent and straightforward. + * The following table summarizes matters since version 0.89c, which was + * the first widely used release: + * + * source png.h png.h shared-lib + * version string int version + * ------- ------ ----- ---------- + * 0.89c "1.0 beta 3" 0.89 89 1.0.89 + * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] + * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] + * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] + * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] + * 0.97c 0.97 97 2.0.97 + * 0.98 0.98 98 2.0.98 + * 0.99 0.99 98 2.0.99 + * 0.99a-m 0.99 99 2.0.99 + * 1.00 1.00 100 2.1.0 [100 should be 10000] + * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] + * 1.0.1 png.h string is 10001 2.1.0 + * 1.0.1a-e identical to the 10002 from here on, the shared library + * 1.0.2 source version) 10002 is 2.V where V is the source code + * 1.0.2a-b 10003 version, except as noted. + * 1.0.3 10003 + * 1.0.3a-d 10004 + * 1.0.4 10004 + * 1.0.4a-f 10005 + * 1.0.5 (+ 2 patches) 10005 + * 1.0.5a-d 10006 + * 1.0.5e-r 10100 (not source compatible) + * 1.0.5s-v 10006 (not binary compatible) + * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) + * 1.0.6d-f 10007 (still binary incompatible) + * 1.0.6g 10007 + * 1.0.6h 10007 10.6h (testing xy.z so-numbering) + * 1.0.6i 10007 10.6i + * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) + * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) + * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) + * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) + * 1.0.7 1 10007 (still compatible) + * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 + * 1.0.8rc1 1 10008 2.1.0.8rc1 + * 1.0.8 1 10008 2.1.0.8 + * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 + * 1.0.9rc1 1 10009 2.1.0.9rc1 + * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 + * 1.0.9rc2 1 10009 2.1.0.9rc2 + * 1.0.9 1 10009 2.1.0.9 + * 1.0.10beta1 1 10010 2.1.0.10beta1 + * 1.0.10rc1 1 10010 2.1.0.10rc1 + * 1.0.10 1 10010 2.1.0.10 + * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 + * 1.0.11rc1 1 10011 2.1.0.11rc1 + * 1.0.11 1 10011 2.1.0.11 + * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 + * 1.0.12rc1 2 10012 2.1.0.12rc1 + * 1.0.12 2 10012 2.1.0.12 + * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) + * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 + * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 + * 1.2.0rc1 3 10200 3.1.2.0rc1 + * 1.2.0 3 10200 3.1.2.0 + * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 + * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 + * 1.2.1 3 10201 3.1.2.1 + * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 + * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 + * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 + * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 + * 1.0.13 10 10013 10.so.0.1.0.13 + * 1.2.2 12 10202 12.so.0.1.2.2 + * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 + * 1.2.3 12 10203 12.so.0.1.2.3 + * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 + * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 + * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 + * 1.0.14 10 10014 10.so.0.1.0.14 + * 1.2.4 13 10204 12.so.0.1.2.4 + * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 + * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 + * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 + * 1.0.15 10 10015 10.so.0.1.0.15 + * 1.2.5 13 10205 12.so.0.1.2.5 + * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 + * 1.0.16 10 10016 10.so.0.1.0.16 + * 1.2.6 13 10206 12.so.0.1.2.6 + * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 + * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 + * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 + * 1.0.17 10 10017 12.so.0.1.0.17 + * 1.2.7 13 10207 12.so.0.1.2.7 + * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 + * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 + * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 + * 1.0.18 10 10018 12.so.0.1.0.18 + * 1.2.8 13 10208 12.so.0.1.2.8 + * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 + * 1.2.9beta4-11 13 10209 12.so.0.9[.0] + * 1.2.9rc1 13 10209 12.so.0.9[.0] + * 1.2.9 13 10209 12.so.0.9[.0] + * 1.2.10beta1-7 13 10210 12.so.0.10[.0] + * 1.2.10rc1-2 13 10210 12.so.0.10[.0] + * 1.2.10 13 10210 12.so.0.10[.0] + * 1.4.0beta1-5 14 10400 14.so.0.0[.0] + * 1.2.11beta1-4 13 10211 12.so.0.11[.0] + * 1.4.0beta7-8 14 10400 14.so.0.0[.0] + * 1.2.11 13 10211 12.so.0.11[.0] + * 1.2.12 13 10212 12.so.0.12[.0] + * 1.4.0beta9-14 14 10400 14.so.0.0[.0] + * 1.2.13 13 10213 12.so.0.13[.0] + * 1.4.0beta15-36 14 10400 14.so.0.0[.0] + * 1.4.0beta37-87 14 10400 14.so.14.0[.0] + * 1.4.0rc01 14 10400 14.so.14.0[.0] + * 1.4.0beta88-109 14 10400 14.so.14.0[.0] + * 1.4.0rc02-08 14 10400 14.so.14.0[.0] + * 1.4.0 14 10400 14.so.14.0[.0] + * 1.4.1beta01-03 14 10401 14.so.14.1[.0] + * 1.4.1rc01 14 10401 14.so.14.1[.0] + * 1.4.1beta04-12 14 10401 14.so.14.1[.0] + * 1.4.1 14 10401 14.so.14.1[.0] + * 1.4.2 14 10402 14.so.14.2[.0] + * 1.4.3 14 10403 14.so.14.3[.0] + * 1.4.4 14 10404 14.so.14.4[.0] + * 1.5.0beta01-58 15 10500 15.so.15.0[.0] + * 1.5.0rc01-07 15 10500 15.so.15.0[.0] + * 1.5.0 15 10500 15.so.15.0[.0] + * 1.5.1beta01-11 15 10501 15.so.15.1[.0] + * 1.5.1rc01-02 15 10501 15.so.15.1[.0] + * 1.5.1 15 10501 15.so.15.1[.0] + * + * Henceforth the source version will match the shared-library major + * and minor numbers; the shared-library major version number will be + * used for changes in backward compatibility, as it is intended. The + * PNG_LIBPNG_VER macro, which is not used within libpng but is available + * for applications, is an unsigned integer of the form xyyzz corresponding + * to the source version x.y.z (leading zeros in y and z). Beta versions + * were given the previous public release number plus a letter, until + * version 1.0.6j; from then on they were given the upcoming public + * release number plus "betaNN" or "rcN". + * + * Binary incompatibility exists only when applications make direct access + * to the info_ptr or png_ptr members through png.h, and the compiled + * application is loaded with a different version of the library. + * + * DLLNUM will change each time there are forward or backward changes + * in binary compatibility (e.g., when a new feature is added). + * + * See libpng-manual.txt or libpng.3 for more information. The PNG + * specification is available as a W3C Recommendation and as an ISO + * Specification, +# endif + +/* Need the time information for converting tIME chunks, it + * defines struct tm: + */ +#ifdef PNG_CONVERT_tIME_SUPPORTED + /* "time.h" functions are not supported on all operating systems */ +# include +#endif + +/* Machine specific configuration. */ +# include "pngconf.h" +#endif + +/* + * Added at libpng-1.2.8 + * + * Ref MSDN: Private as priority over Special + * VS_FF_PRIVATEBUILD File *was not* built using standard release + * procedures. If this value is given, the StringFileInfo block must + * contain a PrivateBuild string. + * + * VS_FF_SPECIALBUILD File *was* built by the original company using + * standard release procedures but is a variation of the standard + * file of the same version number. If this value is given, the + * StringFileInfo block must contain a SpecialBuild string. + */ + +#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */ +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE) +#else +# ifdef PNG_LIBPNG_SPECIALBUILD +# define PNG_LIBPNG_BUILD_TYPE \ + (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL) +# else +# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE) +# endif +#endif + +#ifndef PNG_VERSION_INFO_ONLY + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Version information for C files, stored in png.c. This had better match + * the version above. + */ +#define png_libpng_ver png_get_header_ver(NULL) + +/* This file is arranged in several sections: + * + * 1. Any configuration options that can be specified by for the application + * code when it is built. (Build time configuration is in pnglibconf.h) + * 2. Type definitions (base types are defined in pngconf.h), structure + * definitions. + * 3. Exported library functions. + * + * The library source code has additional files (principally pngpriv.h) that + * allow configuration of the library. + */ +/* Section 1: run time configuration + * See pnglibconf.h for build time configuration + * + * Run time configuration allows the application to choose between + * implementations of certain arithmetic APIs. The default is set + * at build time and recorded in pnglibconf.h, but it is safe to + * override these (and only these) settings. Note that this won't + * change what the library does, only application code, and the + * settings can (and probably should) be made on a per-file basis + * by setting the #defines before including png.h + * + * Use macros to read integers from PNG data or use the exported + * functions? + * PNG_USE_READ_MACROS: use the macros (see below) Note that + * the macros evaluate their argument multiple times. + * PNG_NO_USE_READ_MACROS: call the relevant library function. + * + * Use the alternative algorithm for compositing alpha samples that + * does not use division? + * PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division' + * algorithm. + * PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm. + * + * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is + * false? + * PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error + * APIs to png_warning. + * Otherwise the calls are mapped to png_error. + */ + +/* Section 2: type definitions, including structures and compile time + * constants. + * See pngconf.h for base types that vary by machine/system + */ + +/* This triggers a compiler error in png.c, if png.c and png.h + * do not agree upon the version number. + */ +typedef char* png_libpng_version_1_5_1; + +/* Three color definitions. The order of the red, green, and blue, (and the + * exact size) is not important, although the size of the fields need to + * be png_byte or png_uint_16 (as defined below). + */ +typedef struct png_color_struct +{ + png_byte red; + png_byte green; + png_byte blue; +} png_color; +typedef png_color FAR * png_colorp; +typedef PNG_CONST png_color FAR * png_const_colorp; +typedef png_color FAR * FAR * png_colorpp; + +typedef struct png_color_16_struct +{ + png_byte index; /* used for palette files */ + png_uint_16 red; /* for use in red green blue files */ + png_uint_16 green; + png_uint_16 blue; + png_uint_16 gray; /* for use in grayscale files */ +} png_color_16; +typedef png_color_16 FAR * png_color_16p; +typedef PNG_CONST png_color_16 FAR * png_const_color_16p; +typedef png_color_16 FAR * FAR * png_color_16pp; + +typedef struct png_color_8_struct +{ + png_byte red; /* for use in red green blue files */ + png_byte green; + png_byte blue; + png_byte gray; /* for use in grayscale files */ + png_byte alpha; /* for alpha channel files */ +} png_color_8; +typedef png_color_8 FAR * png_color_8p; +typedef PNG_CONST png_color_8 FAR * png_const_color_8p; +typedef png_color_8 FAR * FAR * png_color_8pp; + +/* + * The following two structures are used for the in-core representation + * of sPLT chunks. + */ +typedef struct png_sPLT_entry_struct +{ + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + png_uint_16 alpha; + png_uint_16 frequency; +} png_sPLT_entry; +typedef png_sPLT_entry FAR * png_sPLT_entryp; +typedef PNG_CONST png_sPLT_entry FAR * png_const_sPLT_entryp; +typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp; + +/* When the depth of the sPLT palette is 8 bits, the color and alpha samples + * occupy the LSB of their respective members, and the MSB of each member + * is zero-filled. The frequency member always occupies the full 16 bits. + */ + +typedef struct png_sPLT_struct +{ + png_charp name; /* palette name */ + png_byte depth; /* depth of palette samples */ + png_sPLT_entryp entries; /* palette entries */ + png_int_32 nentries; /* number of palette entries */ +} png_sPLT_t; +typedef png_sPLT_t FAR * png_sPLT_tp; +typedef PNG_CONST png_sPLT_t FAR * png_const_sPLT_tp; +typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; + +#ifdef PNG_TEXT_SUPPORTED +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, + * and whether that contents is compressed or not. The "key" field + * points to a regular zero-terminated C string. The "text", "lang", and + * "lang_key" fields can be regular C strings, empty strings, or NULL pointers. + * However, the * structure returned by png_get_text() will always contain + * regular zero-terminated C strings (possibly empty), never NULL pointers, + * so they can be safely used in printf() and other string-handling functions. + */ +typedef struct png_text_struct +{ + int compression; /* compression value: + -1: tEXt, none + 0: zTXt, deflate + 1: iTXt, none + 2: iTXt, deflate */ + png_charp key; /* keyword, 1-79 character description of "text" */ + png_charp text; /* comment, may be an empty string (ie "") + or a NULL pointer */ + png_size_t text_length; /* length of the text string */ + png_size_t itxt_length; /* length of the itxt string */ + png_charp lang; /* language code, 0-79 characters + or a NULL pointer */ + png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + chars or a NULL pointer */ +} png_text; +typedef png_text FAR * png_textp; +typedef PNG_CONST png_text FAR * png_const_textp; +typedef png_text FAR * FAR * png_textpp; +#endif + +/* Supported compression types for text in PNG files (tEXt, and zTXt). + * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */ +#define PNG_TEXT_COMPRESSION_NONE_WR -3 +#define PNG_TEXT_COMPRESSION_zTXt_WR -2 +#define PNG_TEXT_COMPRESSION_NONE -1 +#define PNG_TEXT_COMPRESSION_zTXt 0 +#define PNG_ITXT_COMPRESSION_NONE 1 +#define PNG_ITXT_COMPRESSION_zTXt 2 +#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */ + +/* png_time is a way to hold the time in an machine independent way. + * Two conversions are provided, both from time_t and struct tm. There + * is no portable way to convert to either of these structures, as far + * as I know. If you know of a portable way, send it to me. As a side + * note - PNG has always been Year 2000 compliant! + */ +typedef struct png_time_struct +{ + png_uint_16 year; /* full year, as in, 1995 */ + png_byte month; /* month of year, 1 - 12 */ + png_byte day; /* day of month, 1 - 31 */ + png_byte hour; /* hour of day, 0 - 23 */ + png_byte minute; /* minute of hour, 0 - 59 */ + png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ +} png_time; +typedef png_time FAR * png_timep; +typedef PNG_CONST png_time FAR * png_const_timep; +typedef png_time FAR * FAR * png_timepp; + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) +/* png_unknown_chunk is a structure to hold queued chunks for which there is + * no specific support. The idea is that we can use this to queue + * up private chunks for output even though the library doesn't actually + * know about their semantics. + */ +typedef struct png_unknown_chunk_t +{ + png_byte name[5]; + png_byte *data; + png_size_t size; + + /* libpng-using applications should NOT directly modify this byte. */ + png_byte location; /* mode of operation at read time */ +} +png_unknown_chunk; +typedef png_unknown_chunk FAR * png_unknown_chunkp; +typedef PNG_CONST png_unknown_chunk FAR * png_const_unknown_chunkp; +typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; +#endif + +typedef struct png_info_def png_info; +typedef png_info FAR * png_infop; +typedef PNG_CONST png_info FAR * png_const_infop; +typedef png_info FAR * FAR * png_infopp; + +/* Maximum positive integer used in PNG is (2^31)-1 */ +#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) +#define PNG_UINT_32_MAX ((png_uint_32)(-1)) +#define PNG_SIZE_MAX ((png_size_t)(-1)) + +/* These are constants for fixed point values encoded in the + * PNG specification manner (x100000) + */ +#define PNG_FP_1 100000 +#define PNG_FP_HALF 50000 + +/* These describe the color_type field in png_info. */ +/* color type masks */ +#define PNG_COLOR_MASK_PALETTE 1 +#define PNG_COLOR_MASK_COLOR 2 +#define PNG_COLOR_MASK_ALPHA 4 + +/* color types. Note that not all combinations are legal */ +#define PNG_COLOR_TYPE_GRAY 0 +#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) +#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) +#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) +#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA) +/* aliases */ +#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA +#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA + +/* This is for compression type. PNG 1.0-1.2 only define the single type. */ +#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */ +#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE + +/* This is for filter type. PNG 1.0-1.2 only define the single type. */ +#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */ +#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */ +#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE + +/* These are for the interlacing type. These values should NOT be changed. */ +#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */ +#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */ +#define PNG_INTERLACE_LAST 2 /* Not a valid value */ + +/* These are for the oFFs chunk. These values should NOT be changed. */ +#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */ +#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */ +#define PNG_OFFSET_LAST 2 /* Not a valid value */ + +/* These are for the pCAL chunk. These values should NOT be changed. */ +#define PNG_EQUATION_LINEAR 0 /* Linear transformation */ +#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */ +#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */ +#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */ +#define PNG_EQUATION_LAST 4 /* Not a valid value */ + +/* These are for the sCAL chunk. These values should NOT be changed. */ +#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */ +#define PNG_SCALE_METER 1 /* meters per pixel */ +#define PNG_SCALE_RADIAN 2 /* radians per pixel */ +#define PNG_SCALE_LAST 3 /* Not a valid value */ + +/* These are for the pHYs chunk. These values should NOT be changed. */ +#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */ +#define PNG_RESOLUTION_METER 1 /* pixels/meter */ +#define PNG_RESOLUTION_LAST 2 /* Not a valid value */ + +/* These are for the sRGB chunk. These values should NOT be changed. */ +#define PNG_sRGB_INTENT_PERCEPTUAL 0 +#define PNG_sRGB_INTENT_RELATIVE 1 +#define PNG_sRGB_INTENT_SATURATION 2 +#define PNG_sRGB_INTENT_ABSOLUTE 3 +#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ + +/* This is for text chunks */ +#define PNG_KEYWORD_MAX_LENGTH 79 + +/* Maximum number of entries in PLTE/sPLT/tRNS arrays */ +#define PNG_MAX_PALETTE_LENGTH 256 + +/* These determine if an ancillary chunk's data has been successfully read + * from the PNG header, or if the application has filled in the corresponding + * data in the info_struct to be written into the output file. The values + * of the PNG_INFO_ defines should NOT be changed. + */ +#define PNG_INFO_gAMA 0x0001 +#define PNG_INFO_sBIT 0x0002 +#define PNG_INFO_cHRM 0x0004 +#define PNG_INFO_PLTE 0x0008 +#define PNG_INFO_tRNS 0x0010 +#define PNG_INFO_bKGD 0x0020 +#define PNG_INFO_hIST 0x0040 +#define PNG_INFO_pHYs 0x0080 +#define PNG_INFO_oFFs 0x0100 +#define PNG_INFO_tIME 0x0200 +#define PNG_INFO_pCAL 0x0400 +#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ +#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ +#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ +#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ +#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ + +/* This is used for the transformation routines, as some of them + * change these values for the row. It also should enable using + * the routines for other purposes. + */ +typedef struct png_row_info_struct +{ + png_uint_32 width; /* width of row */ + png_size_t rowbytes; /* number of bytes in row */ + png_byte color_type; /* color type of row */ + png_byte bit_depth; /* bit depth of row */ + png_byte channels; /* number of channels (1, 2, 3, or 4) */ + png_byte pixel_depth; /* bits per pixel (depth * channels) */ +} png_row_info; + +typedef png_row_info FAR * png_row_infop; +typedef png_row_info FAR * FAR * png_row_infopp; + +/* These are the function types for the I/O functions and for the functions + * that allow the user to override the default I/O functions with his or her + * own. The png_error_ptr type should match that of user-supplied warning + * and error functions, while the png_rw_ptr type should match that of the + * user read/write data functions. Note that the 'write' function must not + * modify the buffer it is passed. The 'read' function, on the other hand, is + * expected to return the read data in the buffer. + */ +typedef struct png_struct_def png_struct; +typedef PNG_CONST png_struct FAR * png_const_structp; +typedef png_struct FAR * png_structp; + +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp), ); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t), ); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp), ); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int), ); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int), ); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, + (png_structp, png_infop), ); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, + (png_structp, png_infop), ); +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, + (png_structp, png_bytep, png_uint_32, int), ); +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +typedef PNG_CALLBACK(void, *png_user_transform_ptr, + (png_structp, png_row_infop, png_bytep), ); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp), ); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp), ); +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This must match the function definition in , and the + * application must include this before png.h to obtain the definition + * of jmp_buf. The function is required to be PNG_NORETURN. (Note that + * PNG_PTR_NORETURN is used here because current versions of the Microsoft + * C compiler do not support the PNG_NORETURN attribute on a pointer.) + * + * If you get a type warning from the compiler when linking against this line + * then your compiler has 'longjmp' that does not match the requirements of the + * compiler that built libpng. You will have to write a wrapper function for + * your compiler's longjmp and call png_set_longjmp_fn directly (not via the + * png_jmpbuf macro.) + * + * If you get a warning here while building the library you will need to make + * changes to ensure that pnglibconf.h records the calling convention used by + * your compiler. This may be very difficult - try using a different compiler + * to build the library! + */ +typedef PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), + PNG_PTR_NORETURN); +#endif + +/* Transform masks for the high-level interface */ +#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ +#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ +#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ +#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ +#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ +#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ +#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ +#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ +#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ +#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ +#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ +#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ +#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ +/* Added to libpng-1.2.34 */ +#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER +#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ +/* Added to libpng-1.4.0 */ +#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ + +/* Flags for MNG supported features */ +#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 +#define PNG_FLAG_MNG_FILTER_64 0x04 +#define PNG_ALL_MNG_FEATURES 0x05 + +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, + * this allowed the zlib default functions to be used on Windows + * platforms. In 1.5 the zlib default malloc (which just calls malloc and + * ignores the first argument) should be completely compatible with the + * following. + */ +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t), ); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp), ); + +typedef png_struct FAR * FAR * png_structpp; + +/* Section 3: exported functions + * Here are the function definitions most commonly used. This is not + * the place to find out how to use libpng. See libpng-manual.txt for the + * full explanation, see example.c for the summary. This just provides + * a simple one line description of the use of each function. + * + * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in + * pngconf.h and in the *.dfn files in the scripts directory. + * + * PNG_EXPORT(ordinal, type, name, (args)); + * + * ordinal: ordinal that is used while building + * *.def files. The ordinal value is only + * relevant when preprocessing png.h with + * the *.dfn files for building symbol table + * entries, and are removed by pngconf.h. + * type: return type of the function + * name: function name + * args: function arguments, with types + * + * When we wish to append attributes to a function prototype we use + * the PNG_EXPORTA() macro instead. + * + * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * + * ordinal, type, name, and args: same as in PNG_EXPORT(). + * attributes: function attributes + */ + +/* Returns the version number of the library */ +PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); + +/* Tell lib we have already handled the first magic bytes. + * Handling more than 8 bytes from the beginning of the file is an error. + */ +PNG_EXPORT(2, void, png_set_sig_bytes, (png_structp png_ptr, int num_bytes)); + +/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a + * PNG file. Returns zero if the supplied bytes match the 8-byte PNG + * signature, and non-zero otherwise. Having num_to_check == 0 or + * start > 7 will always fail (ie return non-zero). + */ +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, + png_size_t num_to_check)); + +/* Simple signature checking function. This is the same as calling + * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). + */ +#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) + +/* Allocate and initialize png_ptr struct for reading, and any other memory. */ +PNG_EXPORTA(4, png_structp, png_create_read_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); + +/* Allocate and initialize png_ptr struct for writing, and any other memory */ +PNG_EXPORTA(5, png_structp, png_create_write_struct, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn), + PNG_ALLOCATED); + +PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, + (png_const_structp png_ptr)); + +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr, + png_size_t size)); + +/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp + * match up. + */ +#ifdef PNG_SETJMP_SUPPORTED +/* This function returns the jmp_buf built in to *png_ptr. It must be + * supplied with an appropriate 'longjmp' function to use on that jmp_buf + * unless the default error function is overridden in which case NULL is + * acceptable. The size of the jmp_buf is checked against the actual size + * allocated by the library - the call will return NULL on a mismatch + * indicating an ABI mismatch. + */ +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr, + png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +# define png_jmpbuf(png_ptr) \ + (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) +#else +# define png_jmpbuf(png_ptr) \ + (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) +#endif +/* This function should be used by libpng applications in place of + * longjmp(png_ptr->jmpbuf, val). If longjmp_fn() has been set, it + * will use it; otherwise it will call PNG_ABORT(). This function was + * added in libpng-1.5.0. + */ +PNG_EXPORTA(9, void, png_longjmp, (png_structp png_ptr, int val), + PNG_NORETURN); + +#ifdef PNG_READ_SUPPORTED +/* Reset the compression stream */ +PNG_EXPORT(10, int, png_reset_zstream, (png_structp png_ptr)); +#endif + +/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(11, png_structp, png_create_read_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(12, png_structp, png_create_write_struct_2, + (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +#endif + +/* Write the PNG file signature. */ +PNG_EXPORT(13, void, png_write_sig, (png_structp png_ptr)); + +/* Write a PNG chunk - size, type, (optional) data, CRC. */ +PNG_EXPORT(14, void, png_write_chunk, (png_structp png_ptr, png_const_bytep + chunk_name, png_const_bytep data, png_size_t length)); + +/* Write the start of a PNG chunk - length and chunk name. */ +PNG_EXPORT(15, void, png_write_chunk_start, (png_structp png_ptr, + png_const_bytep chunk_name, png_uint_32 length)); + +/* Write the data of a PNG chunk started with png_write_chunk_start(). */ +PNG_EXPORT(16, void, png_write_chunk_data, (png_structp png_ptr, + png_const_bytep data, png_size_t length)); + +/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ +PNG_EXPORT(17, void, png_write_chunk_end, (png_structp png_ptr)); + +/* Allocate and initialize the info structure */ +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr), + PNG_ALLOCATED); + +PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr, + png_size_t png_info_struct_size)); + +/* Writes all the PNG information before the image. */ +PNG_EXPORT(20, void, png_write_info_before_PLTE, + (png_structp png_ptr, png_infop info_ptr)); +PNG_EXPORT(21, void, png_write_info, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. */ +PNG_EXPORT(22, void, png_read_info, + (png_structp png_ptr, png_infop info_ptr)); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +PNG_EXPORT(23, png_const_charp, png_convert_to_rfc1123, + (png_structp png_ptr, + png_const_timep ptime)); +#endif + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* Convert from a struct tm to png_time */ +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, + PNG_CONST struct tm FAR * ttime)); + +/* Convert from time_t to png_time. Uses gmtime() */ +PNG_EXPORT(25, void, png_convert_from_time_t, + (png_timep ptime, time_t ttime)); +#endif /* PNG_CONVERT_tIME_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ +PNG_EXPORT(26, void, png_set_expand, (png_structp png_ptr)); +PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structp png_ptr)); +PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structp png_ptr)); +PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Use blue, green, red order for pixels. */ +PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand the grayscale to 24-bit RGB if necessary. */ +PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB to grayscale. */ +PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr, + int error_action, double red, double green)); +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr, + int error_action, png_fixed_point red, png_fixed_point green)); + +PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp + png_ptr)); +#endif + +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, + png_colorp palette)); + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +PNG_EXPORT(37, void, png_set_swap_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +PNG_EXPORT(38, void, png_set_invert_alpha, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +PNG_EXPORT(39, void, png_set_filler, (png_structp png_ptr, png_uint_32 filler, + int flags)); +/* The values of the PNG_FILLER_ defines should NOT be changed */ +# define PNG_FILLER_BEFORE 0 +# define PNG_FILLER_AFTER 1 +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +PNG_EXPORT(40, void, png_set_add_alpha, + (png_structp png_ptr, png_uint_32 filler, + int flags)); +#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swap bytes in 16-bit depth files. */ +PNG_EXPORT(41, void, png_set_swap, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ +PNG_EXPORT(42, void, png_set_packing, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Swap packing order of pixels in bytes. */ +PNG_EXPORT(43, void, png_set_packswap, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +/* Converts files to legal bit depths. */ +PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_color_8p + true_bits)); +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +/* Have the code handle the interlacing. Returns the number of passes. + * MUST be called before png_read_update_info or png_start_read_image, + * otherwise it will not have the desired effect. Note that it is still + * necessary to call png_read_row or png_read_rows png_get_image_height + * times for each pass. +*/ +PNG_EXPORT(45, int, png_set_interlace_handling, (png_structp png_ptr)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +/* Invert monochrome files */ +PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS by replacing with a background color. */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma)); +PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma)); +#endif +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# define PNG_BACKGROUND_GAMMA_UNKNOWN 0 +# define PNG_BACKGROUND_GAMMA_SCREEN 1 +# define PNG_BACKGROUND_GAMMA_FILE 2 +# define PNG_BACKGROUND_GAMMA_UNIQUE 3 +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Strip the second byte of information from a 16-bit depth file. */ +PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Turn on quantizing, and reduce the palette to the number of colors + * available. + */ +PNG_EXPORT(49, void, png_set_quantize, + (png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_const_uint_16p histogram, + int full_quantize)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* The threshold on gamma processing is configurable but hard-wired into the + * library. The following is the floating point variant. + */ +#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) + +/* Handle gamma correction. Screen_gamma=(display_exponent) */ +PNG_FP_EXPORT(50, void, png_set_gamma, + (png_structp png_ptr, double screen_gamma, + double default_file_gamma)); +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr, + png_fixed_point screen_gamma, png_fixed_point default_file_gamma)); +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set how many lines between output flushes - 0 for no flushing */ +PNG_EXPORT(51, void, png_set_flush, (png_structp png_ptr, int nrows)); +/* Flush the current PNG output buffer */ +PNG_EXPORT(52, void, png_write_flush, (png_structp png_ptr)); +#endif + +/* Optional update palette with requested transformations */ +PNG_EXPORT(53, void, png_start_read_image, (png_structp png_ptr)); + +/* Optional call to update the users info structure */ +PNG_EXPORT(54, void, png_read_update_info, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. */ +PNG_EXPORT(55, void, png_read_rows, (png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read a row of data. */ +PNG_EXPORT(56, void, png_read_row, (png_structp png_ptr, png_bytep row, + png_bytep display_row)); +#endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the whole image into memory at once. */ +PNG_EXPORT(57, void, png_read_image, (png_structp png_ptr, png_bytepp image)); +#endif + +/* Write a row of image data */ +PNG_EXPORT(58, void, png_write_row, + (png_structp png_ptr, png_const_bytep row)); + +/* Write a few rows of image data: (*row) is not written; however, the type + * is declared as writeable to maintain compatibility with previous versions + * of libpng and to allow the 'display_row' array from read_rows to be passed + * unchanged to write_rows. + */ +PNG_EXPORT(59, void, png_write_rows, (png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows)); + +/* Write the image data */ +PNG_EXPORT(60, void, png_write_image, + (png_structp png_ptr, png_bytepp image)); + +/* Write the end of the PNG file. */ +PNG_EXPORT(61, void, png_write_end, + (png_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. */ +PNG_EXPORT(62, void, png_read_end, (png_structp png_ptr, png_infop info_ptr)); +#endif + +/* Free any memory associated with the png_info_struct */ +PNG_EXPORT(63, void, png_destroy_info_struct, (png_structp png_ptr, + png_infopp info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); + +/* Free any memory associated with the png_struct and the png_info_structs */ +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, + png_infopp info_ptr_ptr)); + +/* Set the libpng method of handling chunk CRC errors */ +PNG_EXPORT(66, void, png_set_crc_action, + (png_structp png_ptr, int crit_action, int ancil_action)); + +/* Values for png_set_crc_action() say how to handle CRC errors in + * ancillary and critical chunks, and whether to use the data contained + * therein. Note that it is impossible to "discard" data in a critical + * chunk. For versions prior to 0.90, the action was always error/quit, + * whereas in version 0.90 and later, the action for CRC errors in ancillary + * chunks is warn/discard. These values should NOT be changed. + * + * value action:critical action:ancillary + */ +#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ +#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ +#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ +#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ +#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ +#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ + +/* These functions give the user control over the scan-line filtering in + * libpng and the compression methods used by zlib. These functions are + * mainly useful for testing, as the defaults should work with most users. + * Those users who are tight on memory or want faster performance at the + * expense of compression can modify them. See the compression library + * header file (zlib.h) for an explination of the compression functions. + */ + +/* Set the filtering method(s) used by libpng. Currently, the only valid + * value for "method" is 0. + */ +PNG_EXPORT(67, void, png_set_filter, + (png_structp png_ptr, int method, int filters)); + +/* Flags for png_set_filter() to say which filters to use. The flags + * are chosen so that they don't conflict with real filter types + * below, in case they are supplied instead of the #defined constants. + * These values should NOT be changed. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_FILTER_NONE 0x08 +#define PNG_FILTER_SUB 0x10 +#define PNG_FILTER_UP 0x20 +#define PNG_FILTER_AVG 0x40 +#define PNG_FILTER_PAETH 0x80 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + +/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. + * These defines should NOT be changed. + */ +#define PNG_FILTER_VALUE_NONE 0 +#define PNG_FILTER_VALUE_SUB 1 +#define PNG_FILTER_VALUE_UP 2 +#define PNG_FILTER_VALUE_AVG 3 +#define PNG_FILTER_VALUE_PAETH 4 +#define PNG_FILTER_VALUE_LAST 5 + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ +/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ + * defines, either the default (minimum-sum-of-absolute-differences), or + * the experimental method (weighted-minimum-sum-of-absolute-differences). + * + * Weights are factors >= 1.0, indicating how important it is to keep the + * filter type consistent between rows. Larger numbers mean the current + * filter is that many times as likely to be the same as the "num_weights" + * previous filters. This is cumulative for each previous row with a weight. + * There needs to be "num_weights" values in "filter_weights", or it can be + * NULL if the weights aren't being specified. Weights have no influence on + * the selection of the first row filter. Well chosen weights can (in theory) + * improve the compression for a given image. + * + * Costs are factors >= 1.0 indicating the relative decoding costs of a + * filter type. Higher costs indicate more decoding expense, and are + * therefore less likely to be selected over a filter with lower computational + * costs. There needs to be a value in "filter_costs" for each valid filter + * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't + * setting the costs. Costs try to improve the speed of decompression without + * unduly increasing the compressed image size. + * + * A negative weight or cost indicates the default value is to be used, and + * values in the range [0.0, 1.0) indicate the value is to remain unchanged. + * The default values for both weights and costs are currently 1.0, but may + * change if good general weighting/cost heuristics can be found. If both + * the weights and costs are set to 1.0, this degenerates the WEIGHTED method + * to the UNWEIGHTED method, but with added encoding time/computation. + */ +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs)); +PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, + (png_structp png_ptr, + int heuristic_method, int num_weights, png_const_fixed_point_p + filter_weights, png_const_fixed_point_p filter_costs)); +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +/* Heuristic used for row filter selection. These defines should NOT be + * changed. + */ +#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ +#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ +#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ +#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ + +/* Set the library compression level. Currently, valid values range from + * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 + * (0 - no compression, 9 - "maximal" compression). Note that tests have + * shown that zlib compression levels 3-6 usually perform as well as level 9 + * for PNG images, and do considerably fewer caclulations. In the future, + * these values may not correspond directly to the zlib compression levels. + */ +PNG_EXPORT(69, void, png_set_compression_level, + (png_structp png_ptr, int level)); + +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr, + int mem_level)); + +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr, + int strategy)); + +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr, + int window_bits)); + +PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr, + int method)); + +/* These next functions are called for input/output, memory, and error + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * and call standard C I/O routines such as fread(), fwrite(), and + * fprintf(). These functions can be made to use other I/O routines + * at run time for those applications that need to handle I/O in a + * different manner by calling png_set_???_fn(). See libpng-manual.txt for + * more information. + */ + +#ifdef PNG_STDIO_SUPPORTED +/* Initialize the input/output for the PNG file to the default functions. */ +PNG_EXPORT(74, void, png_init_io, (png_structp png_ptr, png_FILE_p fp)); +#endif + +/* Replace the (error and abort), and warning functions with user + * supplied functions. If no messages are to be printed you must still + * write and use replacement functions. The replacement error_fn should + * still do a longjmp to the last setjmp location if you are using this + * method of error handling. If error_fn or warning_fn is NULL, the + * default function will be used. + */ + +PNG_EXPORT(75, void, png_set_error_fn, + (png_structp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn)); + +/* Return the user pointer associated with the error functions */ +PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structp png_ptr)); + +/* Replace the default data output functions with a user supplied one(s). + * If buffered output is not used, then output_flush_fn can be set to NULL. + * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time + * output_flush_fn will be ignored (and thus can be NULL). + * It is probably a mistake to use NULL for output_flush_fn if + * write_data_fn is not also NULL unless you have built libpng with + * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's + * default flush function, which uses the standard *FILE structure, will + * be used. + */ +PNG_EXPORT(77, void, png_set_write_fn, (png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); + +/* Replace the default data input function with a user supplied one. */ +PNG_EXPORT(78, void, png_set_read_fn, (png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn)); + +/* Return the user pointer associated with the I/O functions */ +PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_structp png_ptr)); + +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr, + png_read_status_ptr read_row_fn)); + +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structp png_ptr, + png_write_status_ptr write_row_fn)); + +#ifdef PNG_USER_MEM_SUPPORTED +/* Replace the default memory allocation functions with user supplied one(s). */ +PNG_EXPORT(82, void, png_set_mem_fn, (png_structp png_ptr, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +/* Return the user pointer associated with the memory functions */ +PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structp png_ptr)); +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structp png_ptr, + png_user_transform_ptr read_user_transform_fn)); +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr, + png_user_transform_ptr write_user_transform_fn)); +#endif + +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, + int user_transform_channels)); +/* Return the user pointer associated with the user transform functions */ +PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, + (png_const_structp png_ptr)); +#endif + +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED +/* Return information about the row currently being processed. Note that these + * APIs do not fail but will return unexpected results if called outside a user + * transform callback. Also note that when transforming an interlaced image the + * row number is still the row in the final, de-interlaced, image but the row + * only contains the data of the current pass - consult png_row_info for the + * actual width of the row! + */ +PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structp)); +PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structp)); +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structp png_ptr, + png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structp png_ptr)); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +/* Sets the function callbacks for the push reader, and a pointer to a + * user-defined structure available to the callback functions. + */ +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, + png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); + +/* Returns the user pointer associated with the push read functions */ +PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, (png_const_structp png_ptr)); + +/* Function to be called when data becomes available */ +PNG_EXPORT(92, void, png_process_data, + (png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size)); + +/* A function which may be called *only* within png_process_data to stop the + * processing of any more data. The function returns the number of bytes + * remaining, excluding any that libpng has cached internally. A subsequent + * call to png_process_data must supply these bytes again. If the argument + * 'save' is set to true the routine will first save all the pending data and + * will always return 0. + */ +PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save)); + +/* A function which may be called *only* outside (after) a call to + * png_process_data. It returns the number of bytes of data to skip in the + * input. Normally it will return 0, but if it returns a non-zero value the + * application must skip than number of bytes of input data and pass the + * following data to the next call to png_process_data. + */ +PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structp)); + +/* Function that combines rows. 'new_row' is a flag that should come from + * the callback and be non-NULL if anything needs to be done; the library + * stores its own version of the new data internally and ignores the passed + * in value. + */ +PNG_EXPORT(93, void, png_progressive_combine_row, (png_structp png_ptr, + png_bytep old_row, png_const_bytep new_row)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +PNG_EXPORTA(94, png_voidp, png_malloc, + (png_structp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); +/* Added at libpng version 1.4.0 */ +PNG_EXPORTA(95, png_voidp, png_calloc, + (png_structp png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); + +/* Added at libpng version 1.2.4 */ +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_structp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); + +/* Frees a pointer allocated by png_malloc() */ +PNG_EXPORT(97, void, png_free, (png_structp png_ptr, png_voidp ptr)); + +/* Free data that was allocated internally */ +PNG_EXPORT(98, void, png_free_data, + (png_structp png_ptr, png_infop info_ptr, png_uint_32 free_me, int num)); + +/* Reassign responsibility for freeing existing data, whether allocated + * by libpng or by the application */ +PNG_EXPORT(99, void, png_data_freer, + (png_structp png_ptr, png_infop info_ptr, int freer, png_uint_32 mask)); + +/* Assignments for png_data_freer */ +#define PNG_DESTROY_WILL_FREE_DATA 1 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 +/* Flags for png_ptr->free_me and info_ptr->free_me */ +#define PNG_FREE_HIST 0x0008 +#define PNG_FREE_ICCP 0x0010 +#define PNG_FREE_SPLT 0x0020 +#define PNG_FREE_ROWS 0x0040 +#define PNG_FREE_PCAL 0x0080 +#define PNG_FREE_SCAL 0x0100 +#define PNG_FREE_UNKN 0x0200 +#define PNG_FREE_LIST 0x0400 +#define PNG_FREE_PLTE 0x1000 +#define PNG_FREE_TRNS 0x2000 +#define PNG_FREE_TEXT 0x4000 +#define PNG_FREE_ALL 0x7fff +#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ + +#ifdef PNG_USER_MEM_SUPPORTED +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr, + png_alloc_size_t size), PNG_ALLOCATED); +PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr)); +#endif + +#ifdef PNG_ERROR_TEXT_SUPPORTED +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(102, void, png_error, + (png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN); + +/* The same, but the chunk name is prepended to the error string. */ +PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#else +/* Fatal error in PNG image of libpng - can't continue */ +PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN); +#endif + +/* Non-fatal error in libpng. Can continue, but may have a problem. */ +PNG_EXPORT(105, void, png_warning, (png_structp png_ptr, + png_const_charp warning_message)); + +/* Non-fatal error in libpng, chunk name is prepended to message. */ +PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr, + png_const_charp warning_message)); + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +/* Benign error in libpng. Can continue, but may have a problem. + * User can choose whether to handle as a fatal error or as a warning. */ +# undef png_benign_error +PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr, + png_const_charp warning_message)); + +/* Same, chunk name is prepended to message. */ +# undef png_chunk_benign_error +PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr, + png_const_charp warning_message)); + +PNG_EXPORT(109, void, png_set_benign_errors, + (png_structp png_ptr, int allowed)); +#else +# ifdef PNG_ALLOW_BENIGN_ERRORS +# define png_benign_error png_warning +# define png_chunk_benign_error png_chunk_warning +# else +# define png_benign_error png_error +# define png_chunk_benign_error png_chunk_error +# endif +#endif + +/* The png_set_ functions are for storing values in the png_info_struct. + * Similarly, the png_get_ calls are used to read values from the + * png_info_struct, either storing the parameters in the passed variables, or + * setting pointers into the png_info_struct where the data is stored. The + * png_get_ functions return a non-zero value if the data was available + * in info_ptr, or return zero and do not change any of the parameters if the + * data was not available. + * + * These functions should be used instead of directly accessing png_info + * to avoid problems with future changes in the size and internal layout of + * png_info_struct. + */ +/* Returns "flag" if chunk data is valid in info_ptr. */ +PNG_EXPORT(110, png_uint_32, png_get_valid, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 flag)); + +/* Returns number of bytes needed to hold a transformed row. */ +PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* Returns row_pointers, which is an array of pointers to scanlines that was + * returned from png_read_png(). + */ +PNG_EXPORT(112, png_bytepp, png_get_rows, + (png_const_structp png_ptr, png_const_infop info_ptr)); +/* Set row_pointers, which is an array of pointers to scanlines for use + * by png_write_png(). + */ +PNG_EXPORT(113, void, png_set_rows, (png_structp png_ptr, + png_infop info_ptr, png_bytepp row_pointers)); +#endif + +/* Returns number of color channels in image. */ +PNG_EXPORT(114, png_byte, png_get_channels, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Returns image width in pixels. */ +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image height in pixels. */ +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image bit_depth. */ +PNG_EXPORT(117, png_byte, png_get_bit_depth, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns image color_type. */ +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image filter_type. */ +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image interlace_type. */ +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image compression_type. */ +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structp png_ptr, + png_const_infop info_ptr)); + +/* Returns image resolution in pixels per meter, from pHYs chunk data. */ +PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns pixel aspect ratio, computed from pHYs chunk data. */ +PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ +PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, + (png_const_structp png_ptr, png_const_infop info_ptr)); +PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +/* Returns pointer to signature string read from PNG header */ +PNG_EXPORT(130, png_const_bytep, png_get_signature, + (png_const_structp png_ptr, png_infop info_ptr)); + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(131, png_uint_32, png_get_bKGD, + (png_const_structp png_ptr, png_infop info_ptr, + png_color_16p *background)); +#endif + +#ifdef PNG_bKGD_SUPPORTED +PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr, + png_const_color_16p background)); +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr, + png_const_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, + double *blue_y)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */ +PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, + (png_const_structp png_ptr, + png_const_infop info_ptr, png_fixed_point *int_white_x, + png_fixed_point *int_white_y, png_fixed_point *int_red_x, + png_fixed_point *int_red_y, png_fixed_point *int_green_x, + png_fixed_point *int_green_y, png_fixed_point *int_blue_x, + png_fixed_point *int_blue_y)); +#endif +#endif + +#ifdef PNG_cHRM_SUPPORTED +PNG_FP_EXPORT(135, void, png_set_cHRM, + (png_structp png_ptr, png_infop info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y)); +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, + (png_const_structp png_ptr, png_const_infop info_ptr, + double *file_gamma)); +PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *int_file_gamma)); +#endif + +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr, + png_infop info_ptr, double file_gamma)); +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_file_gamma)); +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(141, png_uint_32, png_get_hIST, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_16p *hist)); +#endif + +#ifdef PNG_hIST_SUPPORTED +PNG_EXPORT(142, void, png_set_hIST, (png_structp png_ptr, + png_infop info_ptr, png_const_uint_16p hist)); +#endif + +PNG_EXPORT(143, png_uint_32, png_get_IHDR, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, + int *interlace_method, int *compression_method, int *filter_method)); + +PNG_EXPORT(144, void, png_set_IHDR, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, + int interlace_method, int compression_method, int filter_method)); + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(145, png_uint_32, png_get_oFFs, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)); +#endif + +#ifdef PNG_oFFs_SUPPORTED +PNG_EXPORT(146, void, png_set_oFFs, + (png_structp png_ptr, png_infop info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(147, png_uint_32, png_get_pCAL, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, + int *nparams, + png_charp *units, png_charpp *params)); +#endif + +#ifdef PNG_pCAL_SUPPORTED +PNG_EXPORT(148, void, png_set_pCAL, (png_structp png_ptr, + png_infop info_ptr, + png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, + int nparams, png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(149, png_uint_32, png_get_pHYs, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); +#endif + +#ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(150, void, png_set_pHYs, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +#endif + +PNG_EXPORT(151, png_uint_32, png_get_PLTE, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_colorp *palette, int *num_palette)); + +PNG_EXPORT(152, void, png_set_PLTE, + (png_structp png_ptr, png_infop info_ptr, + png_const_colorp palette, int num_palette)); + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(153, png_uint_32, png_get_sBIT, + (png_const_structp png_ptr, png_infop info_ptr, + png_color_8p *sig_bit)); +#endif + +#ifdef PNG_sBIT_SUPPORTED +PNG_EXPORT(154, void, png_set_sBIT, + (png_structp png_ptr, png_infop info_ptr, png_const_color_8p sig_bit)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structp png_ptr, + png_const_infop info_ptr, int *file_srgb_intent)); +#endif + +#ifdef PNG_sRGB_SUPPORTED +PNG_EXPORT(156, void, png_set_sRGB, + (png_structp png_ptr, png_infop info_ptr, int srgb_intent)); +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_structp png_ptr, + png_infop info_ptr, int srgb_intent)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(158, png_uint_32, png_get_iCCP, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_charpp name, int *compression_type, png_bytepp profile, + png_uint_32 *proflen)); +#endif + +#ifdef PNG_iCCP_SUPPORTED +PNG_EXPORT(159, void, png_set_iCCP, + (png_structp png_ptr, png_infop info_ptr, + png_const_charp name, int compression_type, png_const_bytep profile, + png_uint_32 proflen)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(160, png_uint_32, png_get_sPLT, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_sPLT_tpp entries)); +#endif + +#ifdef PNG_sPLT_SUPPORTED +PNG_EXPORT(161, void, png_set_sPLT, + (png_structp png_ptr, png_infop info_ptr, + png_const_sPLT_tp entries, int nentries)); +#endif + +#ifdef PNG_TEXT_SUPPORTED +/* png_get_text also returns the number of text chunks in *num_text */ +PNG_EXPORT(162, png_uint_32, png_get_text, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_textp *text_ptr, int *num_text)); +#endif + +/* Note while png_set_text() will accept a structure whose text, + * language, and translated keywords are NULL pointers, the structure + * returned by png_get_text will always contain regular + * zero-terminated C strings. They might be empty strings but + * they will never be NULL pointers. + */ + +#ifdef PNG_TEXT_SUPPORTED +PNG_EXPORT(163, void, png_set_text, + (png_structp png_ptr, png_infop info_ptr, + png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(164, png_uint_32, png_get_tIME, + (png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)); +#endif + +#ifdef PNG_tIME_SUPPORTED +PNG_EXPORT(165, void, png_set_tIME, + (png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(166, png_uint_32, png_get_tRNS, + (png_const_structp png_ptr, png_infop info_ptr, + png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)); +#endif + +#ifdef PNG_tRNS_SUPPORTED +PNG_EXPORT(167, void, png_set_tRNS, + (png_structp png_ptr, png_infop info_ptr, + png_const_bytep trans_alpha, int num_trans, + png_const_color_16p trans_color)); +#endif + +#ifdef PNG_sCAL_SUPPORTED +PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, + (png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, double *width, double *height)); +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED +/* NOTE: this API is currently implemented using floating point arithmetic, + * consequently it can only be used on systems with floating point support. + * In any case the range of values supported by png_fixed_point is small and it + * is highly recommended that png_get_sCAL_s be used instead. + */ +PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, + (png_structp png_ptr, png_const_infop info_ptr, int *unit, + png_fixed_point *width, + png_fixed_point *height)); +#endif +PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, + (png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, png_charpp swidth, png_charpp sheight)); + +PNG_FP_EXPORT(170, void, png_set_sCAL, + (png_structp png_ptr, png_infop info_ptr, + int unit, double width, double height)); +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr, + png_infop info_ptr, int unit, png_fixed_point width, + png_fixed_point height)); +PNG_EXPORT(171, void, png_set_sCAL_s, + (png_structp png_ptr, png_infop info_ptr, + int unit, png_const_charp swidth, png_const_charp sheight)); +#endif /* PNG_sCAL_SUPPORTED */ + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +/* Provide a list of chunks and how they are to be handled, if the built-in + handling or default unknown chunk handling is not desired. Any chunks not + listed will be handled in the default manner. The IHDR and IEND chunks + must not be listed. + keep = 0: follow default behaviour + = 1: do not keep + = 2: keep only if safe-to-copy + = 3: keep even if unsafe-to-copy +*/ +PNG_EXPORT(172, void, png_set_keep_unknown_chunks, + (png_structp png_ptr, int keep, + png_const_bytep chunk_list, int num_chunks)); +PNG_EXPORT(173, int, png_handle_as_unknown, (png_structp png_ptr, + png_const_bytep chunk_name)); +#endif +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structp png_ptr, + png_infop info_ptr, png_const_unknown_chunkp unknowns, + int num_unknowns)); +PNG_EXPORT(175, void, png_set_unknown_chunk_location, + (png_structp png_ptr, png_infop info_ptr, int chunk, int location)); +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structp png_ptr, + png_const_infop info_ptr, png_unknown_chunkpp entries)); +#endif + +/* Png_free_data() will turn off the "valid" flag for anything it frees. + * If you need to turn it off for a chunk that your application has freed, + * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); + */ +PNG_EXPORT(177, void, png_set_invalid, + (png_structp png_ptr, png_infop info_ptr, int mask)); + +#ifdef PNG_INFO_IMAGE_SUPPORTED +/* The "params" pointer is currently not used and is for future expansion. */ +PNG_EXPORT(178, void, png_read_png, (png_structp png_ptr, png_infop info_ptr, + int transforms, png_voidp params)); +PNG_EXPORT(179, void, png_write_png, (png_structp png_ptr, png_infop info_ptr, + int transforms, png_voidp params)); +#endif + +PNG_EXPORT(180, png_const_charp, png_get_copyright, + (png_const_structp png_ptr)); +PNG_EXPORT(181, png_const_charp, png_get_header_ver, + (png_const_structp png_ptr)); +PNG_EXPORT(182, png_const_charp, png_get_header_version, + (png_const_structp png_ptr)); +PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, + (png_const_structp png_ptr)); + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr, + png_uint_32 mng_features_permitted)); +#endif + +/* For use in png_set_keep_unknown, added to version 1.2.6 */ +#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 +#define PNG_HANDLE_CHUNK_NEVER 1 +#define PNG_HANDLE_CHUNK_IF_SAFE 2 +#define PNG_HANDLE_CHUNK_ALWAYS 3 + +/* Strip the prepended error numbers ("#nnn ") from error and warning + * messages before passing them to the error or warning handler. + */ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +PNG_EXPORT(185, void, png_set_strip_error_numbers, + (png_structp png_ptr, + png_uint_32 strip_mode)); +#endif + +/* Added in libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +PNG_EXPORT(186, void, png_set_user_limits, (png_structp png_ptr, + png_uint_32 user_width_max, png_uint_32 user_height_max)); +PNG_EXPORT(187, png_uint_32, png_get_user_width_max, + (png_const_structp png_ptr)); +PNG_EXPORT(188, png_uint_32, png_get_user_height_max, + (png_const_structp png_ptr)); +/* Added in libpng-1.4.0 */ +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structp png_ptr, + png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, + (png_const_structp png_ptr)); +/* Added in libpng-1.4.1 */ +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structp png_ptr, + png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, + (png_const_structp png_ptr)); +#endif + +#if defined(PNG_INCH_CONVERSIONS_SUPPORTED) +PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, + (png_const_structp png_ptr, png_const_infop info_ptr)); + +PNG_FP_EXPORT(196, float, png_get_x_offset_inches, + (png_const_structp png_ptr, png_const_infop info_ptr)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, + (png_structp png_ptr, png_const_infop info_ptr)); +#endif + +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr, + png_const_infop info_ptr)); +#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, + (png_structp png_ptr, png_const_infop info_ptr)); +#endif + +# ifdef PNG_pHYs_SUPPORTED +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr, + png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, + int *unit_type)); +# endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ + +/* Added in libpng-1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_structp png_ptr)); + +PNG_EXPORTA(200, png_const_bytep, png_get_io_chunk_name, + (png_structp png_ptr), PNG_DEPRECATED); +PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, + (png_const_structp png_ptr)); + +/* The flags returned by png_get_io_state() are the following: */ +# define PNG_IO_NONE 0x0000 /* no I/O at this moment */ +# define PNG_IO_READING 0x0001 /* currently reading */ +# define PNG_IO_WRITING 0x0002 /* currently writing */ +# define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ +# define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ +# define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ +# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ +# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ +# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +/* Interlace support. The following macros are always defined so that if + * libpng interlace handling is turned off the macros may be used to handle + * interlaced images within the application. + */ +#define PNG_INTERLACE_ADAM7_PASSES 7 + +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) + +/* For the progressive reader it is necessary to find the row in the output + * image given a row in an interlaced image, so two more macros: + */ +#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ + (((yIn)<>(((7-(off))-(pass))<<2)) & 0xFU) | \ + ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U)) + +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED +/* With these routines we avoid an integer divide, which will be slower on + * most machines. However, it does take more operations than the corresponding + * divide method, so it may be slower on a few RISC systems. There are two + * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. + * + * Note that the rounding factors are NOT supposed to be the same! 128 and + * 32768 are correct for the NODIV code; 127 and 32767 are correct for the + * standard method. + * + * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] + */ + + /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ + +# define png_composite(composite, fg, alpha, bg) \ + { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ + * (png_uint_16)(alpha) \ + + (png_uint_16)(bg)*(png_uint_16)(255 \ + - (png_uint_16)(alpha)) + (png_uint_16)128); \ + (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } + +# define png_composite_16(composite, fg, alpha, bg) \ + { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ + * (png_uint_32)(alpha) \ + + (png_uint_32)(bg)*(png_uint_32)(65535L \ + - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ + (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } + +#else /* Standard method using integer division */ + +# define png_composite(composite, fg, alpha, bg) \ + (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ + (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ + (png_uint_16)127) / 255) + +# define png_composite_16(composite, fg, alpha, bg) \ + (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ + (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ + (png_uint_32)32767) / (png_uint_32)65535L) +#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); +PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); +PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +#endif + +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_structp png_ptr, + png_const_bytep buf)); +/* No png_get_int_16 -- may be added if there's a real need for it. */ + +/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +#endif +#ifdef PNG_SAVE_INT_32_SUPPORTED +PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +/* No png_save_int_16 -- may be added if there's a real need for it. */ +#endif + +#ifdef PNG_USE_READ_MACROS +/* Inline macros to do direct reads of bytes from the input buffer. + * The png_get_int_32() routine assumes we are using two's complement + * format for negative values, which is almost certainly true. + */ +# define png_get_uint_32(buf) \ + (((png_uint_32)(*(buf)) << 24) + \ + ((png_uint_32)(*((buf) + 1)) << 16) + \ + ((png_uint_32)(*((buf) + 2)) << 8) + \ + ((png_uint_32)(*((buf) + 3)))) + + /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the + * function) incorrectly returned a value of type png_uint_32. + */ +# define png_get_uint_16(buf) \ + ((png_uint_16) \ + (((unsigned int)(*(buf)) << 8) + \ + ((unsigned int)(*((buf) + 1))))) + +# define png_get_int_32(buf) \ + ((png_int_32)((*(buf) & 0x80) \ + ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ + : (png_int_32)png_get_uint_32(buf))) +#endif + +/* Maintainer: Put new public prototypes here ^, in libpng.3, and project + * defs + */ + +/* The last ordinal number (this is the *last* one already used; the next + * one to use is one more than this.) Maintainer, remember to add an entry to + * scripts/symbols.def as well. + */ +#ifdef PNG_EXPORT_LAST_ORDINAL + PNG_EXPORT_LAST_ORDINAL(220); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PNG_VERSION_INFO_ONLY */ +/* Do not put anything past this line */ +#endif /* PNG_H */ diff --git a/contrib/libpng/pngbar.jpg b/contrib/libpng/pngbar.jpg new file mode 100644 index 0000000..70ba8d8 Binary files /dev/null and b/contrib/libpng/pngbar.jpg differ diff --git a/contrib/libpng/pngbar.png b/contrib/libpng/pngbar.png new file mode 100644 index 0000000..49798c8 Binary files /dev/null and b/contrib/libpng/pngbar.png differ diff --git a/contrib/libpng/pngconf.h b/contrib/libpng/pngconf.h new file mode 100644 index 0000000..2633bf8 --- /dev/null +++ b/contrib/libpng/pngconf.h @@ -0,0 +1,632 @@ + +/* pngconf.h - machine configurable file for libpng + * + * libpng version 1.5.1 - February 3, 2011 + * + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +/* Any machine specific code is near the front of this file, so if you + * are configuring libpng for a machine, you may want to read the section + * starting here down to where it starts to typedef png_color, png_text, + * and png_info. + */ + +#ifndef PNGCONF_H +#define PNGCONF_H + +/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C + * definition file for machine specific limits, this may impact the + * correctness of the definitons below (see uses of INT_MAX). + */ +#ifndef PNG_NO_LIMITS_H +# include +#endif + +/* For the memory copy APIs (i.e. the standard definitions of these), + * because this file defines png_memcpy and so on the base APIs must + * be defined here. + */ +#ifdef BSD +# include +#else +# include +#endif + +/* For png_FILE_p - this provides the standard definition of a + * FILE + */ +#ifdef PNG_STDIO_SUPPORTED +# include +#endif + +/* This controls optimization of the reading of 16 and 32 bit values + * from PNG files. It can be set on a per-app-file basis - it + * just changes whether a macro is used to the function is called. + * The library builder sets the default, if read functions are not + * built into the library the macro implementation is forced on. + */ +#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED +# define PNG_USE_READ_MACROS +#endif +#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) +# if PNG_DEFAULT_READ_MACROS +# define PNG_USE_READ_MACROS +# endif +#endif + +/* COMPILER SPECIFIC OPTIONS. + * + * These options are provided so that a variety of difficult compilers + * can be used. Some are fixed at build time (e.g. PNG_API_RULE + * below) but still have compiler specific implementations, others + * may be changed on a per-file basis when compiling against libpng. + */ + +/* The PNGARG macro protects us against machines that don't have function + * prototypes (ie K&R style headers). If your compiler does not handle + * function prototypes, define this macro and use the included ansi2knr. + * I've always been able to use _NO_PROTO as the indicator, but you may + * need to drag the empty declaration out in front of here, or change the + * ifdef to suit your own needs. + */ +#ifndef PNGARG + +# ifdef OF /* zlib prototype munger */ +# define PNGARG(arglist) OF(arglist) +# else + +# ifdef _NO_PROTO +# define PNGARG(arglist) () +# else +# define PNGARG(arglist) arglist +# endif /* _NO_PROTO */ + +# endif /* OF */ + +#endif /* PNGARG */ + +/* Function calling conventions. + * ============================= + * Normally it is not necessary to specify to the compiler how to call + * a function - it just does it - however on x86 systems derived from + * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems + * and some others) there are multiple ways to call a function and the + * default can be changed on the compiler command line. For this reason + * libpng specifies the calling convention of every exported function and + * every function called via a user supplied function pointer. This is + * done in this file by defining the following macros: + * + * PNGAPI Calling convention for exported functions. + * PNGCBAPI Calling convention for user provided (callback) functions. + * PNGCAPI Calling convention used by the ANSI-C library (required + * for longjmp callbacks and sometimes used internally to + * specify the calling convention for zlib). + * + * These macros should never be overridden. If it is necessary to + * change calling convention in a private build this can be done + * by setting PNG_API_RULE (which defaults to 0) to one of the values + * below to select the correct 'API' variants. + * + * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. + * This is correct in every known environment. + * PNG_API_RULE=1 Use the operating system convention for PNGAPI and + * the 'C' calling convention (from PNGCAPI) for + * callbacks (PNGCBAPI). This is no longer required + * in any known environment - if it has to be used + * please post an explanation of the problem to the + * libpng mailing list. + * + * These cases only differ if the operating system does not use the C + * calling convention, at present this just means the above cases + * (x86 DOS/Windows sytems) and, even then, this does not apply to + * Cygwin running on those systems. + * + * Note that the value must be defined in pnglibconf.h so that what + * the application uses to call the library matches the conventions + * set when building the library. + */ + +/* Symbol export + * ============= + * When building a shared library it is almost always necessary to tell + * the compiler which symbols to export. The png.h macro 'PNG_EXPORT' + * is used to mark the symbols. On some systems these symbols can be + * extracted at link time and need no special processing by the compiler, + * on other systems the symbols are flagged by the compiler and just + * the declaration requires a special tag applied (unfortunately) in a + * compiler dependent way. Some systems can do either. + * + * A small number of older systems also require a symbol from a DLL to + * be flagged to the program that calls it. This is a problem because + * we do not know in the header file included by application code that + * the symbol will come from a shared library, as opposed to a statically + * linked one. For this reason the application must tell us by setting + * the magic flag PNG_USE_DLL to turn on the special processing before + * it includes png.h. + * + * Four additional macros are used to make this happen: + * + * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from + * the build or imported if PNG_USE_DLL is set - compiler + * and system specific. + * + * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to + * 'type', compiler specific. + * + * PNG_DLL_EXPORT Set to the magic to use during a libpng build to + * make a symbol exported from the DLL. + * + * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come + * from a DLL - used to define PNG_IMPEXP when + * PNG_USE_DLL is set. + */ + +/* System specific discovery. + * ========================== + * This code is used at build time to find PNG_IMPEXP, the API settings + * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL + * import processing is possible. On Windows/x86 systems it also sets + * compiler-specific macros to the values required to change the calling + * conventions of the various functions. + */ +#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ + defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\ + ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\ + defined(_M_X64) || defined(_M_IA64) ) + /* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes + * builds under Cygwin or MinGW. Also includes Watcom builds but these need + * special treatment because they are not compatible with GCC or Visual C + * because of different calling conventions. + */ +# if PNG_API_RULE == 2 + /* If this line results in an error, either because __watcall is not + * understood or because of a redefine just below you cannot use *this* + * build of the library with the compiler you are using. *This* build was + * build using Watcom and applications must also be built using Watcom! + */ +# define PNGCAPI __watcall +# endif + +# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) +# define PNGCAPI __cdecl +# if PNG_API_RULE == 1 +# define PNGAPI __stdcall +# endif +# else + /* An older compiler, or one not detected (erroneously) above, + * if necessary override on the command line to get the correct + * variants for the compiler. + */ +# ifndef PNGCAPI +# define PNGCAPI _cdecl +# endif +# if PNG_API_RULE == 1 && !defined(PNGAPI) +# define PNGAPI _stdcall +# endif +# endif /* compiler/api */ + /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ + +# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) + ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed +# endif + +# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ + (defined(__BORLANDC__) && __BORLANDC__ < 0x500) + /* older Borland and MSC + * compilers used '__export' and required this to be after + * the type. + */ +# ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP +# endif +# define PNG_DLL_EXPORT __export +# else /* newer compiler */ +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) +# endif +# endif /* compiler */ + +#else /* !Windows/x86 */ +# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) +# define PNGAPI _System +# else /* !Windows/x86 && !OS/2 */ + /* Use the defaults, or define PNG*API on the command line (but + * this will have to be done for every compile!) + */ +# endif /* other system, !OS/2 */ +#endif /* !Windows/x86 */ + +/* Now do all the defaulting . */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif + +/* The default for PNG_IMPEXP depends on whether the library is + * being built or used. + */ +#ifndef PNG_IMPEXP +# ifdef PNGLIB_BUILD + /* Building the library */ +# if (defined(DLL_EXPORT)/*from libtool*/ ||\ + defined(_WINDLL) || defined(_DLL) || defined(__DLL__) ||\ + defined(_USRDLL) ||\ + defined(PNG_BUILD_DLL)) && defined(PNG_DLL_EXPORT) + /* Building a DLL. */ +# define PNG_IMPEXP PNG_DLL_EXPORT +# endif /* DLL */ +# else + /* Using the library */ +# if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT) + /* This forces use of a DLL, disallowing static linking */ +# define PNG_IMPEXP PNG_DLL_IMPORT +# endif +# endif + +# ifndef PNG_IMPEXP +# define PNG_IMPEXP +# endif +#endif + +/* THe following complexity is concerned with getting the 'attributes' of the + * declared function in the correct place. This potentially requires a separate + * PNG_EXPORT function for every compiler. + */ +#ifndef PNG_FUNCTION +# ifdef __GNUC__ +# define PNG_FUNCTION(type, name, args, attributes)\ + attributes type name args +# else /* !GNUC */ +# ifdef _MSC_VER +# define PNG_FUNCTION(type, name, args, attributes)\ + attributes type name args +# else /* !MSC */ +# define PNG_FUNCTION(type, name, args, attributes)\ + type name args +# endif +# endif +#endif + +#ifndef PNG_EXPORT_TYPE +# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type +#endif + + /* The ordinal value is only relevant when preprocessing png.h for symbol + * table entries, so we discard it here. See the .dfn files in the + * scripts directory. + */ +#ifndef PNG_EXPORTA +# define PNG_EXPORTA(ordinal, type, name, args, attributes)\ + extern PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args),\ + attributes) +#endif + +#define PNG_EXPORT(ordinal, type, name, args)\ + PNG_EXPORTA(ordinal, type, name, args, ) + +/* Use PNG_REMOVED to comment out a removed interface. */ +#ifndef PNG_REMOVED +# define PNG_REMOVED(ordinal, type, name, args, attributes) +#endif + +#ifndef PNG_CALLBACK +# define PNG_CALLBACK(type, name, args, attributes)\ + type (PNGCBAPI name) PNGARG(args) attributes +#endif + +/* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. + * + * Added at libpng-1.2.41. + */ + +#ifndef PNG_NO_PEDANTIC_WARNINGS +# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED +# define PNG_PEDANTIC_WARNINGS_SUPPORTED +# endif +#endif + +#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED + /* Support for compiler specific function attributes. These are used + * so that where compiler support is available incorrect use of API + * functions in png.h will generate compiler warnings. Added at libpng + * version 1.2.41. + */ +# ifdef __GNUC__ +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __attribute__((__noreturn__)) +# endif +# ifndef PNG_PTR_NORETURN +# define PNG_PTR_NORETURN __attribute__((__noreturn__)) +# endif +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __attribute__((__malloc__)) +# endif + + /* This specifically protects structure members that should only be + * accessed from within the library, therefore should be empty during + * a library build. + */ +# ifndef PNGLIB_BUILD +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __attribute__((__deprecated__)) +# endif +# ifndef PNG_DEPSTRUCT +# define PNG_DEPSTRUCT __attribute__((__deprecated__)) +# endif +# ifndef PNG_PRIVATE +# if 0 /* Doesn't work so we use deprecated instead*/ +# define PNG_PRIVATE \ + __attribute__((warning("This function is not exported by libpng."))) +# else +# define PNG_PRIVATE \ + __attribute__((__deprecated__)) +# endif +# endif /* PNG_PRIVATE */ +# endif /* PNGLIB_BUILD */ +# endif /* __GNUC__ */ +# ifdef _MSC_VER /* may need to check value */ +# ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /*not supported*/ +# endif +# ifndef PNG_NORETURN +# define PNG_NORETURN __declspec(noreturn) +# endif +# ifndef PNG_PTR_NORETURN +# define PNG_PTR_NORETURN /*not supported*/ +# endif +# ifndef PNG_ALLOCATED +# define PNG_ALLOCATED __declspec(restrict) +# endif + + /* This specifically protects structure members that should only be + * accessed from within the library, therefore should be empty during + * a library build. + */ +# ifndef PNGLIB_BUILD +# ifndef PNG_DEPRECATED +# define PNG_DEPRECATED __declspec(deprecated) +# endif +# ifndef PNG_DEPSTRUCT +# define PNG_DEPSTRUCT __declspec(deprecated) +# endif +# ifndef PNG_PRIVATE +# define PNG_PRIVATE __declspec(deprecated) +# endif /* PNG_PRIVATE */ +# endif /* PNGLIB_BUILD */ +# endif /* __GNUC__ */ +#endif /* PNG_PEDANTIC_WARNINGS */ + +#ifndef PNG_DEPRECATED +# define PNG_DEPRECATED /* Use of this function is deprecated */ +#endif +#ifndef PNG_USE_RESULT +# define PNG_USE_RESULT /* The result of this function must be checked */ +#endif +#ifndef PNG_NORETURN +# define PNG_NORETURN /* This function does not return */ +#endif +#ifndef PNG_ALLOCATED +# define PNG_ALLOCATED /* The result of the function is new memory */ +#endif +#ifndef PNG_DEPSTRUCT +# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */ +#endif +#ifndef PNG_PRIVATE +# define PNG_PRIVATE /* This is a private libpng function */ +#endif +#ifndef PNG_FP_EXPORT /* A floating point API. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define PNG_FP_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args) +# else /* No floating point APIs */ +# define PNG_FP_EXPORT(ordinal, type, name, args) +# endif +#endif +#ifndef PNG_FIXED_EXPORT /* A fixed point API. */ +# ifdef PNG_FIXED_POINT_SUPPORTED +# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ + PNG_EXPORT(ordinal, type, name, args) +# else /* No fixed point APIs */ +# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# endif +#endif + +/* The following uses const char * instead of char * for error + * and warning message functions, so some compilers won't complain. + * If you do not want to use const, define PNG_NO_CONST here. + * + * This should not change how the APIs are called, so it can be done + * on a per-file basis in the application. + */ +#ifndef PNG_CONST +# ifndef PNG_NO_CONST +# define PNG_CONST const +# else +# define PNG_CONST +# endif +#endif + +/* Some typedefs to get us started. These should be safe on most of the + * common platforms. The typedefs should be at least as large as the + * numbers suggest (a png_uint_32 must be at least 32 bits long), but they + * don't have to be exactly that size. Some compilers dislike passing + * unsigned shorts as function parameters, so you may be better off using + * unsigned int for png_uint_16. + */ + +#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL) +typedef unsigned int png_uint_32; +typedef int png_int_32; +#else +typedef unsigned long png_uint_32; +typedef long png_int_32; +#endif +typedef unsigned short png_uint_16; +typedef short png_int_16; +typedef unsigned char png_byte; + +#ifdef PNG_NO_SIZE_T +typedef unsigned int png_size_t; +#else +typedef size_t png_size_t; +#endif +#define png_sizeof(x) (sizeof (x)) + +/* The following is needed for medium model support. It cannot be in the + * pngpriv.h header. Needs modification for other compilers besides + * MSC. Model independent support declares all arrays and pointers to be + * large using the far keyword. The zlib version used must also support + * model independent data. As of version zlib 1.0.4, the necessary changes + * have been made in zlib. The USE_FAR_KEYWORD define triggers other + * changes that are needed. (Tim Wegner) + */ + +/* Separate compiler dependencies (problem here is that zlib.h always + * defines FAR. (SJT) + */ +#ifdef __BORLANDC__ +# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) +# define LDATA 1 +# else +# define LDATA 0 +# endif + /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ +# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) +# define PNG_MAX_MALLOC_64K /* only used in build */ +# if (LDATA != 1) +# ifndef FAR +# define FAR __far +# endif +# define USE_FAR_KEYWORD +# endif /* LDATA != 1 */ + /* Possibly useful for moving data out of default segment. + * Uncomment it if you want. Could also define FARDATA as + * const if your compiler supports it. (SJT) +# define FARDATA FAR + */ +# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ +#endif /* __BORLANDC__ */ + + +/* Suggest testing for specific compiler first before testing for + * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, + * making reliance oncertain keywords suspect. (SJT) + */ + +/* MSC Medium model */ +#ifdef FAR +# ifdef M_I86MM +# define USE_FAR_KEYWORD +# define FARDATA FAR +# include +# endif +#endif + +/* SJT: default case */ +#ifndef FAR +# define FAR +#endif + +/* At this point FAR is always defined */ +#ifndef FARDATA +# define FARDATA +#endif + +/* Typedef for floating-point numbers that are converted + * to fixed-point with a multiple of 100,000, e.g., gamma + */ +typedef png_int_32 png_fixed_point; + +/* Add typedefs for pointers */ +typedef void FAR * png_voidp; +typedef PNG_CONST void FAR * png_const_voidp; +typedef png_byte FAR * png_bytep; +typedef PNG_CONST png_byte FAR * png_const_bytep; +typedef png_uint_32 FAR * png_uint_32p; +typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p; +typedef png_int_32 FAR * png_int_32p; +typedef PNG_CONST png_int_32 FAR * png_const_int_32p; +typedef png_uint_16 FAR * png_uint_16p; +typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p; +typedef png_int_16 FAR * png_int_16p; +typedef PNG_CONST png_int_16 FAR * png_const_int_16p; +typedef char FAR * png_charp; +typedef PNG_CONST char FAR * png_const_charp; +typedef png_fixed_point FAR * png_fixed_point_p; +typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p; +typedef png_size_t FAR * png_size_tp; +typedef PNG_CONST png_size_t FAR * png_const_size_tp; + +#ifdef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * png_doublep; +typedef PNG_CONST double FAR * png_const_doublep; +#endif + +/* Pointers to pointers; i.e. arrays */ +typedef png_byte FAR * FAR * png_bytepp; +typedef png_uint_32 FAR * FAR * png_uint_32pp; +typedef png_int_32 FAR * FAR * png_int_32pp; +typedef png_uint_16 FAR * FAR * png_uint_16pp; +typedef png_int_16 FAR * FAR * png_int_16pp; +typedef PNG_CONST char FAR * FAR * png_const_charpp; +typedef char FAR * FAR * png_charpp; +typedef png_fixed_point FAR * FAR * png_fixed_point_pp; +#ifdef PNG_FLOATING_POINT_SUPPORTED +typedef double FAR * FAR * png_doublepp; +#endif + +/* Pointers to pointers to pointers; i.e., pointer to array */ +typedef char FAR * FAR * FAR * png_charppp; + +/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, + * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 + * to png_alloc_size_t are not necessary; in fact, it is recommended + * not to use them at all so that the compiler can complain when something + * turns out to be problematic. + * Casts in the other direction (from png_alloc_size_t to png_size_t or + * png_uint_32) should be explicitly applied; however, we do not expect + * to encounter practical situations that require such conversions. + */ +#if defined(__TURBOC__) && !defined(__FLAT__) + typedef unsigned long png_alloc_size_t; +#else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + typedef unsigned long png_alloc_size_t; +# else + /* This is an attempt to detect an old Windows system where (int) is + * actually 16 bits, in that case png_malloc must have an argument with a + * bigger size to accomodate the requirements of the library. + */ +# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \ + (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) + typedef DWORD png_alloc_size_t; +# else + typedef png_size_t png_alloc_size_t; +# endif +# endif +#endif + +#endif /* PNGCONF_H */ diff --git a/contrib/libpng/pngdebug.h b/contrib/libpng/pngdebug.h new file mode 100644 index 0000000..16f81fd --- /dev/null +++ b/contrib/libpng/pngdebug.h @@ -0,0 +1,157 @@ + +/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c + * + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* Define PNG_DEBUG at compile time for debugging information. Higher + * numbers for PNG_DEBUG mean more debugging information. This has + * only been added since version 0.95 so it is not implemented throughout + * libpng yet, but more support will be added as needed. + * + * png_debug[1-2]?(level, message ,arg{0-2}) + * Expands to a statement (either a simple expression or a compound + * do..while(0) statement) that outputs a message with parameter + * substitution if PNG_DEBUG is defined to 2 or more. If PNG_DEBUG + * is undefined, 0 or 1 every png_debug expands to a simple expression + * (actually ((void)0)). + * + * level: level of detail of message, starting at 0. A level 'n' + * message is preceded by 'n' tab characters (not implemented + * on Microsoft compilers unless PNG_DEBUG_FILE is also + * defined, to allow debug DLL compilation with no standard IO). + * message: a printf(3) style text string. A trailing '\n' is added + * to the message. + * arg: 0 to 2 arguments for printf(3) style substitution in message. + */ +#ifndef PNGDEBUG_H +#define PNGDEBUG_H +/* These settings control the formatting of messages in png.c and pngerror.c */ +/* Moved to pngdebug.h at 1.5.0 */ +# ifndef PNG_LITERAL_SHARP +# define PNG_LITERAL_SHARP 0x23 +# endif +# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET +# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b +# endif +# ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET +# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d +# endif +# ifndef PNG_STRING_NEWLINE +# define PNG_STRING_NEWLINE "\n" +# endif + +#ifdef PNG_DEBUG +# if (PNG_DEBUG > 0) +# if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER) +# include +# if (PNG_DEBUG > 1) +# ifndef _DEBUG +# define _DEBUG +# endif +# ifndef png_debug +# define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) +# endif +# endif +# else /* PNG_DEBUG_FILE || !_MSC_VER */ +# ifndef PNG_STDIO_SUPPORTED +# include /* not included yet */ +# endif +# ifndef PNG_DEBUG_FILE +# define PNG_DEBUG_FILE stderr +# endif /* PNG_DEBUG_FILE */ + +# if (PNG_DEBUG > 1) +/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on + * non-ISO compilers + */ +# ifdef __STDC__ +# ifndef png_debug +# define png_debug(l,m) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \ + } while (0) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \ + } while (0) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + do { \ + int num_tabs=l; \ + fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \ + } while (0) +# endif +# else /* __STDC __ */ +# ifndef png_debug +# define png_debug(l,m) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format); \ + } while (0) +# endif +# ifndef png_debug1 +# define png_debug1(l,m,p1) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1); \ + } while (0) +# endif +# ifndef png_debug2 +# define png_debug2(l,m,p1,p2) \ + do { \ + int num_tabs=l; \ + char format[256]; \ + snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ + m,PNG_STRING_NEWLINE); \ + fprintf(PNG_DEBUG_FILE,format,p1,p2); \ + } while (0) +# endif +# endif /* __STDC __ */ +# endif /* (PNG_DEBUG > 1) */ + +# endif /* _MSC_VER */ +# endif /* (PNG_DEBUG > 0) */ +#endif /* PNG_DEBUG */ +#ifndef png_debug +# define png_debug(l, m) ((void)0) +#endif +#ifndef png_debug1 +# define png_debug1(l, m, p1) ((void)0) +#endif +#ifndef png_debug2 +# define png_debug2(l, m, p1, p2) ((void)0) +#endif +#endif /* PNGDEBUG_H */ diff --git a/contrib/libpng/pngerror.c b/contrib/libpng/pngerror.c new file mode 100644 index 0000000..8290bb4 --- /dev/null +++ b/contrib/libpng/pngerror.c @@ -0,0 +1,447 @@ + +/* pngerror.c - stub functions for i/o and memory allocation + * + * Last changed in libpng 1.5.1 [February 3, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all error handling. Users who + * need special error handling are expected to write replacement functions + * and use png_set_error_fn() to use those functions. See the instructions + * at each function. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +static PNG_FUNCTION(void, png_default_error,PNGARG((png_structp png_ptr, + png_const_charp error_message)),PNG_NORETURN); + +#ifdef PNG_WARNINGS_SUPPORTED +static void /* PRIVATE */ +png_default_warning PNGARG((png_structp png_ptr, + png_const_charp warning_message)); +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called whenever there is a fatal error. This function + * should not be changed. If there is a need to handle errors differently, + * you should supply a replacement error function and use png_set_error_fn() + * to replace the error function at run-time. + */ +#ifdef PNG_ERROR_TEXT_SUPPORTED +PNG_FUNCTION(void,PNGAPI +png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN) +{ +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + char msg[16]; + if (png_ptr != NULL) + { + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) + { + if (*error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + for (offset = 1; offset<15; offset++) + if (error_message[offset] == ' ') + break; + + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + int i; + for (i = 0; i < offset - 1; i++) + msg[i] = error_message[i + 1]; + msg[i - 1] = '\0'; + error_message = msg; + } + + else + error_message += offset; + } + + else + { + if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT) + { + msg[0] = '0'; + msg[1] = '\0'; + error_message = msg; + } + } + } + } +#endif + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, error_message); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, error_message); +} +#else +PNG_FUNCTION(void,PNGAPI +png_err,(png_structp png_ptr),PNG_NORETURN) +{ + if (png_ptr != NULL && png_ptr->error_fn != NULL) + (*(png_ptr->error_fn))(png_ptr, '\0'); + + /* If the custom handler doesn't exist, or if it returns, + use the default handler, which will not return. */ + png_default_error(png_ptr, '\0'); +} +#endif /* PNG_ERROR_TEXT_SUPPORTED */ + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called whenever there is a non-fatal error. This function + * should not be changed. If there is a need to handle warnings differently, + * you should supply a replacement warning function and use + * png_set_error_fn() to replace the warning function at run-time. + */ +void PNGAPI +png_warning(png_structp png_ptr, png_const_charp warning_message) +{ + int offset = 0; + if (png_ptr != NULL) + { +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (png_ptr->flags& + (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) +#endif + { + if (*warning_message == PNG_LITERAL_SHARP) + { + for (offset = 1; offset < 15; offset++) + if (warning_message[offset] == ' ') + break; + } + } + } + if (png_ptr != NULL && png_ptr->warning_fn != NULL) + (*(png_ptr->warning_fn))(png_ptr, warning_message + offset); + else + png_default_warning(png_ptr, warning_message + offset); +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_benign_error(png_structp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + png_warning(png_ptr, error_message); + else + png_error(png_ptr, error_message); +} +#endif + +/* These utilities are used internally to build an error message that relates + * to the current chunk. The chunk name comes from png_ptr->chunk_name, + * this is used to prefix the message. The message is limited in length + * to 63 bytes, the name characters are output as hex digits wrapped in [] + * if the character is invalid. + */ +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) +static PNG_CONST char png_digit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' +}; + +#define PNG_MAX_ERROR_TEXT 64 +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED) +static void /* PRIVATE */ +png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp + error_message) +{ + int iout = 0, iin = 0; + + while (iin < 4) + { + int c = png_ptr->chunk_name[iin++]; + if (isnonalpha(c)) + { + buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET; + buffer[iout++] = png_digit[(c & 0xf0) >> 4]; + buffer[iout++] = png_digit[c & 0x0f]; + buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET; + } + + else + { + buffer[iout++] = (png_byte)c; + } + } + + if (error_message == NULL) + buffer[iout] = '\0'; + + else + { + buffer[iout++] = ':'; + buffer[iout++] = ' '; + png_memcpy(buffer + iout, error_message, PNG_MAX_ERROR_TEXT); + buffer[iout + PNG_MAX_ERROR_TEXT - 1] = '\0'; + } +} +#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ + +#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) +PNG_FUNCTION(void,PNGAPI +png_chunk_error,(png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_error(png_ptr, error_message); + + else + { + png_format_buffer(png_ptr, msg, error_message); + png_error(png_ptr, msg); + } +} +#endif /* PNG_READ_SUPPORTED && PNG_ERROR_TEXT_SUPPORTED */ + +#ifdef PNG_WARNINGS_SUPPORTED +void PNGAPI +png_chunk_warning(png_structp png_ptr, png_const_charp warning_message) +{ + char msg[18+PNG_MAX_ERROR_TEXT]; + if (png_ptr == NULL) + png_warning(png_ptr, warning_message); + + else + { + png_format_buffer(png_ptr, msg, warning_message); + png_warning(png_ptr, msg); + } +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +#ifdef PNG_READ_SUPPORTED +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_chunk_benign_error(png_structp png_ptr, png_const_charp error_message) +{ + if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) + png_chunk_warning(png_ptr, error_message); + + else + png_chunk_error(png_ptr, error_message); +} +#endif +#endif /* PNG_READ_SUPPORTED */ + +#ifdef PNG_ERROR_TEXT_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_FUNCTION(void, +png_fixed_error,(png_structp png_ptr, png_const_charp name),PNG_NORETURN) +{ +# define fixed_message "fixed point overflow in " +# define fixed_message_ln ((sizeof fixed_message)-1) + int iin; + char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; + png_memcpy(msg, fixed_message, fixed_message_ln); + iin = 0; + if (name != NULL) while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0) + { + msg[fixed_message_ln + iin] = name[iin]; + ++iin; + } + msg[fixed_message_ln + iin] = 0; + png_error(png_ptr, msg); +} +#endif +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* This API only exists if ANSI-C style error handling is used, + * otherwise it is necessary for png_default_error to be overridden. + */ +jmp_buf* PNGAPI +png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn, + size_t jmp_buf_size) +{ + if (png_ptr == NULL || jmp_buf_size != png_sizeof(jmp_buf)) + return NULL; + + png_ptr->longjmp_fn = longjmp_fn; + return &png_ptr->png_jmpbuf; +} +#endif + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static PNG_FUNCTION(void /* PRIVATE */, +png_default_error,(png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*error_message == PNG_LITERAL_SHARP) + { + /* Strip "#nnnn " from beginning of error message. */ + int offset; + char error_number[16]; + for (offset = 0; offset<15; offset++) + { + error_number[offset] = error_message[offset + 1]; + if (error_message[offset] == ' ') + break; + } + + if ((offset > 1) && (offset < 15)) + { + error_number[offset - 1] = '\0'; + fprintf(stderr, "libpng error no. %s: %s", + error_number, error_message + offset + 1); + fprintf(stderr, PNG_STRING_NEWLINE); + } + + else + { + fprintf(stderr, "libpng error: %s, offset=%d", + error_message, offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +#endif + { + fprintf(stderr, "libpng error: %s", error_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#endif +#ifndef PNG_CONSOLE_IO_SUPPORTED + PNG_UNUSED(error_message) /* Make compiler happy */ +#endif + png_longjmp(png_ptr, 1); +} + +PNG_FUNCTION(void,PNGAPI +png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN) +{ +#ifdef PNG_SETJMP_SUPPORTED + if (png_ptr && png_ptr->longjmp_fn) + { +# ifdef USE_FAR_KEYWORD + { + jmp_buf png_jmpbuf; + png_memcpy(png_jmpbuf, png_ptr->png_jmpbuf, png_sizeof(jmp_buf)); + png_ptr->longjmp_fn(png_jmpbuf, val); + } + +# else + png_ptr->longjmp_fn(png_ptr->png_jmpbuf, val); +# endif + } +#endif + /* Here if not setjmp support or if png_ptr is null. */ + PNG_ABORT(); +} + +#ifdef PNG_WARNINGS_SUPPORTED +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want them to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void /* PRIVATE */ +png_default_warning(png_structp png_ptr, png_const_charp warning_message) +{ +#ifdef PNG_CONSOLE_IO_SUPPORTED +# ifdef PNG_ERROR_NUMBERS_SUPPORTED + if (*warning_message == PNG_LITERAL_SHARP) + { + int offset; + char warning_number[16]; + for (offset = 0; offset < 15; offset++) + { + warning_number[offset] = warning_message[offset + 1]; + if (warning_message[offset] == ' ') + break; + } + + if ((offset > 1) && (offset < 15)) + { + warning_number[offset + 1] = '\0'; + fprintf(stderr, "libpng warning no. %s: %s", + warning_number, warning_message + offset); + fprintf(stderr, PNG_STRING_NEWLINE); + } + + else + { + fprintf(stderr, "libpng warning: %s", + warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } + } + else +# endif + + { + fprintf(stderr, "libpng warning: %s", warning_message); + fprintf(stderr, PNG_STRING_NEWLINE); + } +#else + PNG_UNUSED(warning_message) /* Make compiler happy */ +#endif + PNG_UNUSED(png_ptr) /* Make compiler happy */ +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +/* This function is called when the application wants to use another method + * of handling errors and warnings. Note that the error function MUST NOT + * return to the calling routine or serious problems will occur. The return + * method used in the default routine calls longjmp(png_ptr->png_jmpbuf, 1) + */ +void PNGAPI +png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warning_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->error_ptr = error_ptr; + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; +} + + +/* This function returns a pointer to the error_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_error_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return NULL; + + return ((png_voidp)png_ptr->error_ptr); +} + + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED +void PNGAPI +png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode) +{ + if (png_ptr != NULL) + { + png_ptr->flags &= + ((~(PNG_FLAG_STRIP_ERROR_NUMBERS | + PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); + } +} +#endif +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/contrib/libpng/pngget.c b/contrib/libpng/pngget.c new file mode 100644 index 0000000..b5e5798 --- /dev/null +++ b/contrib/libpng/pngget.c @@ -0,0 +1,1032 @@ + +/* pngget.c - retrieval of values from info struct + * + * Last changed in libpng 1.5.1 [February 3, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +png_uint_32 PNGAPI +png_get_valid(png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 flag) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->valid & flag); + + return(0); +} + +png_size_t PNGAPI +png_get_rowbytes(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->rowbytes); + + return(0); +} + +#ifdef PNG_INFO_IMAGE_SUPPORTED +png_bytepp PNGAPI +png_get_rows(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->row_pointers); + + return(0); +} +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED +/* Easy access to info, added in libpng-0.99 */ +png_uint_32 PNGAPI +png_get_image_width(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->width; + + return (0); +} + +png_uint_32 PNGAPI +png_get_image_height(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->height; + + return (0); +} + +png_byte PNGAPI +png_get_bit_depth(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->bit_depth; + + return (0); +} + +png_byte PNGAPI +png_get_color_type(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->color_type; + + return (0); +} + +png_byte PNGAPI +png_get_filter_type(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->filter_type; + + return (0); +} + +png_byte PNGAPI +png_get_interlace_type(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->interlace_type; + + return (0); +} + +png_byte PNGAPI +png_get_compression_type(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->compression_type; + + return (0); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", + "png_get_x_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) + return (info_ptr->x_pixels_per_unit); + } +#endif + + return (0); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", + "png_get_y_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) + return (info_ptr->y_pixels_per_unit); + } +#endif + + return (0); +} + +png_uint_32 PNGAPI +png_get_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter"); + + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER && + info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit) + return (info_ptr->x_pixels_per_unit); + } +#endif + + return (0); +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_READ_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio"); + + if (info_ptr->x_pixels_per_unit != 0) + return ((float)((float)info_ptr->y_pixels_per_unit + /(float)info_ptr->x_pixels_per_unit)); + } +#endif + + return ((float)0.0); +} +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED +png_fixed_point PNGAPI +png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr, + png_const_infop info_ptr) +{ +#ifdef PNG_READ_pHYs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) + && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 + && info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX + && info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX) + { + png_fixed_point res; + + png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed"); + + /* The following casts work because a PNG 4 byte integer only has a valid + * range of 0..2^31-1; otherwise the cast might overflow. + */ + if (png_muldiv(&res, (png_int_32)info_ptr->y_pixels_per_unit, PNG_FP_1, + (png_int_32)info_ptr->x_pixels_per_unit)) + return res; + } +#endif + + return 0; +} +#endif + +png_int_32 PNGAPI +png_get_x_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) + return (info_ptr->x_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) + return (info_ptr->y_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_x_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) + return (info_ptr->x_offset); + } +#endif + + return (0); +} + +png_int_32 PNGAPI +png_get_y_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr) +{ +#ifdef PNG_oFFs_SUPPORTED + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels"); + + if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) + return (info_ptr->y_offset); + } +#endif + + return (0); +} + +#ifdef PNG_INCH_CONVERSIONS_SUPPORTED +static png_uint_32 +ppi_from_ppm(png_uint_32 ppm) +{ +#if 0 + /* The conversion is *(2.54/100), in binary (32 digits): + * .00000110100000001001110101001001 + */ + png_uint_32 t1001, t1101; + ppm >>= 1; /* .1 */ + t1001 = ppm + (ppm >> 3); /* .1001 */ + t1101 = t1001 + (ppm >> 1); /* .1101 */ + ppm >>= 20; /* .000000000000000000001 */ + t1101 += t1101 >> 15; /* .1101000000000001101 */ + t1001 >>= 11; /* .000000000001001 */ + t1001 += t1001 >> 12; /* .000000000001001000000001001 */ + ppm += t1001; /* .000000000001001000001001001 */ + ppm += t1101; /* .110100000001001110101001001 */ + return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */ +#else + /* The argument is a PNG unsigned integer, so it is not permitted + * to be bigger than 2^31. + */ + png_fixed_point result; + if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127, + 5000)) + return result; + + /* Overflow. */ + return 0; +#endif +} + +png_uint_32 PNGAPI +png_get_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) +{ + return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr)); +} + +png_uint_32 PNGAPI +png_get_x_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) +{ + return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr)); +} + +png_uint_32 PNGAPI +png_get_y_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr) +{ + return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr)); +} + +#ifdef PNG_FIXED_POINT_SUPPORTED +static png_fixed_point +png_fixed_inches_from_microns(png_structp png_ptr, png_int_32 microns) +{ + /* Convert from metres * 1,000,000 to inches * 100,000, meters to + * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. + * Notice that this can overflow - a warning is output and 0 is + * returned. + */ + return png_muldiv_warn(png_ptr, microns, 500, 127); +} + +png_fixed_point PNGAPI +png_get_x_offset_inches_fixed(png_structp png_ptr, + png_const_infop info_ptr) +{ + return png_fixed_inches_from_microns(png_ptr, + png_get_x_offset_microns(png_ptr, info_ptr)); +} +#endif + +#ifdef PNG_FIXED_POINT_SUPPORTED +png_fixed_point PNGAPI +png_get_y_offset_inches_fixed(png_structp png_ptr, + png_const_infop info_ptr) +{ + return png_fixed_inches_from_microns(png_ptr, + png_get_y_offset_microns(png_ptr, info_ptr)); +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_x_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr) +{ + /* To avoid the overflow do the conversion directly in floating + * point. + */ + return (float)(png_get_x_offset_microns(png_ptr, info_ptr) * .00003937); +} +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED +float PNGAPI +png_get_y_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr) +{ + /* To avoid the overflow do the conversion directly in floating + * point. + */ + return (float)(png_get_y_offset_microns(png_ptr, info_ptr) * .00003937); +} +#endif + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs_dpi(png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + + if (*unit_type == 1) + { + if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50); + if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50); + } + } + } + + return (retval); +} +#endif /* PNG_pHYs_SUPPORTED */ +#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */ + +/* png_get_channels really belongs in here, too, but it's been around longer */ + +#endif /* PNG_EASY_ACCESS_SUPPORTED */ + +png_byte PNGAPI +png_get_channels(png_const_structp png_ptr, png_const_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->channels); + + return (0); +} + +png_const_bytep PNGAPI +png_get_signature(png_const_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr != NULL && info_ptr != NULL) + return(info_ptr->signature); + + return (NULL); +} + +#ifdef PNG_bKGD_SUPPORTED +png_uint_32 PNGAPI +png_get_bKGD(png_const_structp png_ptr, png_infop info_ptr, + png_color_16p *background) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) + && background != NULL) + { + png_debug1(1, "in %s retrieval function", "bKGD"); + + *background = &(info_ptr->background); + return (PNG_INFO_bKGD); + } + + return (0); +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM(png_const_structp png_ptr, png_const_infop info_ptr, + double *white_x, double *white_y, double *red_x, double *red_y, + double *green_x, double *green_y, double *blue_x, double *blue_y) +{ + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (white_x != NULL) + *white_x = png_float(png_ptr, info_ptr->x_white, "cHRM white X"); + if (white_y != NULL) + *white_y = png_float(png_ptr, info_ptr->y_white, "cHRM white Y"); + if (red_x != NULL) + *red_x = png_float(png_ptr, info_ptr->x_red, "cHRM red X"); + if (red_y != NULL) + *red_y = png_float(png_ptr, info_ptr->y_red, "cHRM red Y"); + if (green_x != NULL) + *green_x = png_float(png_ptr, info_ptr->x_green, "cHRM green X"); + if (green_y != NULL) + *green_y = png_float(png_ptr, info_ptr->y_green, "cHRM green Y"); + if (blue_x != NULL) + *blue_x = png_float(png_ptr, info_ptr->x_blue, "cHRM blue X"); + if (blue_y != NULL) + *blue_y = png_float(png_ptr, info_ptr->y_blue, "cHRM blue Y"); + return (PNG_INFO_cHRM); + } + + return (0); +} +# endif + +# ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_cHRM_fixed(png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, + png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, + png_fixed_point *blue_x, png_fixed_point *blue_y) +{ + png_debug1(1, "in %s retrieval function", "cHRM"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + { + if (white_x != NULL) + *white_x = info_ptr->x_white; + if (white_y != NULL) + *white_y = info_ptr->y_white; + if (red_x != NULL) + *red_x = info_ptr->x_red; + if (red_y != NULL) + *red_y = info_ptr->y_red; + if (green_x != NULL) + *green_x = info_ptr->x_green; + if (green_y != NULL) + *green_y = info_ptr->y_green; + if (blue_x != NULL) + *blue_x = info_ptr->x_blue; + if (blue_y != NULL) + *blue_y = info_ptr->y_blue; + return (PNG_INFO_cHRM); + } + + return (0); +} +# endif +#endif + +#ifdef PNG_gAMA_SUPPORTED +png_uint_32 PNGFAPI +png_get_gAMA_fixed(png_const_structp png_ptr, png_const_infop info_ptr, + png_fixed_point *file_gamma) +{ + png_debug1(1, "in %s retrieval function", "gAMA"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) + && file_gamma != NULL) + { + *file_gamma = info_ptr->gamma; + return (PNG_INFO_gAMA); + } + + return (0); +} +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_gAMA(png_const_structp png_ptr, png_const_infop info_ptr, + double *file_gamma) +{ + png_fixed_point igamma; + png_uint_32 ok = png_get_gAMA_fixed(png_ptr, info_ptr, &igamma); + + if (ok) + *file_gamma = png_float(png_ptr, igamma, "png_get_gAMA"); + + return ok; +} + +# endif +#endif + +#ifdef PNG_sRGB_SUPPORTED +png_uint_32 PNGAPI +png_get_sRGB(png_const_structp png_ptr, png_const_infop info_ptr, + int *file_srgb_intent) +{ + png_debug1(1, "in %s retrieval function", "sRGB"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB) + && file_srgb_intent != NULL) + { + *file_srgb_intent = (int)info_ptr->srgb_intent; + return (PNG_INFO_sRGB); + } + + return (0); +} +#endif + +#ifdef PNG_iCCP_SUPPORTED +png_uint_32 PNGAPI +png_get_iCCP(png_const_structp png_ptr, png_const_infop info_ptr, + png_charpp name, int *compression_type, + png_bytepp profile, png_uint_32 *proflen) +{ + png_debug1(1, "in %s retrieval function", "iCCP"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) + && name != NULL && profile != NULL && proflen != NULL) + { + *name = info_ptr->iccp_name; + *profile = info_ptr->iccp_profile; + /* Compression_type is a dummy so the API won't have to change + * if we introduce multiple compression types later. + */ + *proflen = (int)info_ptr->iccp_proflen; + *compression_type = (int)info_ptr->iccp_compression; + return (PNG_INFO_iCCP); + } + + return (0); +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +png_uint_32 PNGAPI +png_get_sPLT(png_const_structp png_ptr, png_const_infop info_ptr, + png_sPLT_tpp spalettes) +{ + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) + { + *spalettes = info_ptr->splt_palettes; + return ((png_uint_32)info_ptr->splt_palettes_num); + } + + return (0); +} +#endif + +#ifdef PNG_hIST_SUPPORTED +png_uint_32 PNGAPI +png_get_hIST(png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_16p *hist) +{ + png_debug1(1, "in %s retrieval function", "hIST"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) + && hist != NULL) + { + *hist = info_ptr->hist; + return (PNG_INFO_hIST); + } + + return (0); +} +#endif + +png_uint_32 PNGAPI +png_get_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, + int *color_type, int *interlace_type, int *compression_type, + int *filter_type) + +{ + png_debug1(1, "in %s retrieval function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL || width == NULL || + height == NULL || bit_depth == NULL || color_type == NULL) + return (0); + + *width = info_ptr->width; + *height = info_ptr->height; + *bit_depth = info_ptr->bit_depth; + *color_type = info_ptr->color_type; + + if (compression_type != NULL) + *compression_type = info_ptr->compression_type; + + if (filter_type != NULL) + *filter_type = info_ptr->filter_type; + + if (interlace_type != NULL) + *interlace_type = info_ptr->interlace_type; + + /* This is redundant if we can be sure that the info_ptr values were all + * assigned in png_set_IHDR(). We do the check anyhow in case an + * application has ignored our advice not to mess with the members + * of info_ptr directly. + */ + png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + return (1); +} + +#ifdef PNG_oFFs_SUPPORTED +png_uint_32 PNGAPI +png_get_oFFs(png_const_structp png_ptr, png_const_infop info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) +{ + png_debug1(1, "in %s retrieval function", "oFFs"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) + && offset_x != NULL && offset_y != NULL && unit_type != NULL) + { + *offset_x = info_ptr->x_offset; + *offset_y = info_ptr->y_offset; + *unit_type = (int)info_ptr->offset_unit_type; + return (PNG_INFO_oFFs); + } + + return (0); +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +png_uint_32 PNGAPI +png_get_pCAL(png_const_structp png_ptr, png_const_infop info_ptr, + png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, + png_charp *units, png_charpp *params) +{ + png_debug1(1, "in %s retrieval function", "pCAL"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) + && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL && + nparams != NULL && units != NULL && params != NULL) + { + *purpose = info_ptr->pcal_purpose; + *X0 = info_ptr->pcal_X0; + *X1 = info_ptr->pcal_X1; + *type = (int)info_ptr->pcal_type; + *nparams = (int)info_ptr->pcal_nparams; + *units = info_ptr->pcal_units; + *params = info_ptr->pcal_params; + return (PNG_INFO_pCAL); + } + + return (0); +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +# ifdef PNG_FIXED_POINT_SUPPORTED +# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL_fixed(png_structp png_ptr, png_const_infop info_ptr, + int *unit, png_fixed_point *width, png_fixed_point *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + /*TODO: make this work without FP support */ + *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width"); + *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height), + "sCAL height"); + return (PNG_INFO_sCAL); + } + + return(0); +} +# endif /* FLOATING_ARITHMETIC */ +# endif /* FIXED_POINT */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 PNGAPI +png_get_sCAL(png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, double *width, double *height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = atof(info_ptr->scal_s_width); + *height = atof(info_ptr->scal_s_height); + return (PNG_INFO_sCAL); + } + + return(0); +} +# endif /* FLOATING POINT */ +png_uint_32 PNGAPI +png_get_sCAL_s(png_const_structp png_ptr, png_const_infop info_ptr, + int *unit, png_charpp width, png_charpp height) +{ + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_sCAL)) + { + *unit = info_ptr->scal_unit; + *width = info_ptr->scal_s_width; + *height = info_ptr->scal_s_height; + return (PNG_INFO_sCAL); + } + + return(0); +} +#endif /* sCAL */ + +#ifdef PNG_pHYs_SUPPORTED +png_uint_32 PNGAPI +png_get_pHYs(png_const_structp png_ptr, png_const_infop info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) +{ + png_uint_32 retval = 0; + + png_debug1(1, "in %s retrieval function", "pHYs"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_pHYs)) + { + if (res_x != NULL) + { + *res_x = info_ptr->x_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (res_y != NULL) + { + *res_y = info_ptr->y_pixels_per_unit; + retval |= PNG_INFO_pHYs; + } + + if (unit_type != NULL) + { + *unit_type = (int)info_ptr->phys_unit_type; + retval |= PNG_INFO_pHYs; + } + } + + return (retval); +} +#endif /* pHYs */ + +png_uint_32 PNGAPI +png_get_PLTE(png_const_structp png_ptr, png_const_infop info_ptr, + png_colorp *palette, int *num_palette) +{ + png_debug1(1, "in %s retrieval function", "PLTE"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE) + && palette != NULL) + { + *palette = info_ptr->palette; + *num_palette = info_ptr->num_palette; + png_debug1(3, "num_palette = %d", *num_palette); + return (PNG_INFO_PLTE); + } + + return (0); +} + +#ifdef PNG_sBIT_SUPPORTED +png_uint_32 PNGAPI +png_get_sBIT(png_const_structp png_ptr, png_infop info_ptr, + png_color_8p *sig_bit) +{ + png_debug1(1, "in %s retrieval function", "sBIT"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) + && sig_bit != NULL) + { + *sig_bit = &(info_ptr->sig_bit); + return (PNG_INFO_sBIT); + } + + return (0); +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +png_uint_32 PNGAPI +png_get_text(png_const_structp png_ptr, png_const_infop info_ptr, + png_textp *text_ptr, int *num_text) +{ + if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) + { + png_debug1(1, "in %s retrieval function", + (png_ptr->chunk_name[0] == '\0' ? "text" : + (png_const_charp)png_ptr->chunk_name)); + + if (text_ptr != NULL) + *text_ptr = info_ptr->text; + + if (num_text != NULL) + *num_text = info_ptr->num_text; + + return ((png_uint_32)info_ptr->num_text); + } + + if (num_text != NULL) + *num_text = 0; + + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +png_uint_32 PNGAPI +png_get_tIME(png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time) +{ + png_debug1(1, "in %s retrieval function", "tIME"); + + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) + && mod_time != NULL) + { + *mod_time = &(info_ptr->mod_time); + return (PNG_INFO_tIME); + } + + return (0); +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +png_uint_32 PNGAPI +png_get_tRNS(png_const_structp png_ptr, png_infop info_ptr, + png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color) +{ + png_uint_32 retval = 0; + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_debug1(1, "in %s retrieval function", "tRNS"); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (trans_alpha != NULL) + { + *trans_alpha = info_ptr->trans_alpha; + retval |= PNG_INFO_tRNS; + } + + if (trans_color != NULL) + *trans_color = &(info_ptr->trans_color); + } + + else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ + { + if (trans_color != NULL) + { + *trans_color = &(info_ptr->trans_color); + retval |= PNG_INFO_tRNS; + } + + if (trans_alpha != NULL) + *trans_alpha = NULL; + } + + if (num_trans != NULL) + { + *num_trans = info_ptr->num_trans; + retval |= PNG_INFO_tRNS; + } + } + + return (retval); +} +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +int PNGAPI +png_get_unknown_chunks(png_const_structp png_ptr, png_const_infop info_ptr, + png_unknown_chunkpp unknowns) +{ + if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) + { + *unknowns = info_ptr->unknown_chunks; + return info_ptr->unknown_chunks_num; + } + + return (0); +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +png_byte PNGAPI +png_get_rgb_to_gray_status (png_const_structp png_ptr) +{ + return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0); +} +#endif + +#ifdef PNG_USER_CHUNKS_SUPPORTED +png_voidp PNGAPI +png_get_user_chunk_ptr(png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_ptr : NULL); +} +#endif + +png_size_t PNGAPI +png_get_compression_buffer_size(png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->zbuf_size : 0L); +} + + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* These functions were added to libpng 1.2.6 and were enabled + * by default in libpng-1.4.0 */ +png_uint_32 PNGAPI +png_get_user_width_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_width_max : 0); +} + +png_uint_32 PNGAPI +png_get_user_height_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_height_max : 0); +} + +/* This function was added to libpng 1.4.0 */ +png_uint_32 PNGAPI +png_get_chunk_cache_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_cache_max : 0); +} + +/* This function was added to libpng 1.4.1 */ +png_alloc_size_t PNGAPI +png_get_chunk_malloc_max (png_const_structp png_ptr) +{ + return (png_ptr ? png_ptr->user_chunk_malloc_max : 0); +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + +/* These functions were added to libpng 1.4.0 */ +#ifdef PNG_IO_STATE_SUPPORTED +png_uint_32 PNGAPI +png_get_io_state (png_structp png_ptr) +{ + return png_ptr->io_state; +} + +png_uint_32 PNGAPI +png_get_io_chunk_type (png_const_structp png_ptr) +{ + return ((png_ptr->chunk_name[0] << 24) + + (png_ptr->chunk_name[1] << 16) + + (png_ptr->chunk_name[2] << 8) + + (png_ptr->chunk_name[3])); +} + +png_const_bytep PNGAPI +png_get_io_chunk_name (png_structp png_ptr) +{ + return png_ptr->chunk_name; +} +#endif /* ?PNG_IO_STATE_SUPPORTED */ + +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/contrib/libpng/pnginfo.h b/contrib/libpng/pnginfo.h new file mode 100644 index 0000000..fa19f85 --- /dev/null +++ b/contrib/libpng/pnginfo.h @@ -0,0 +1,270 @@ + +/* pnginfo.h - header file for PNG reference library + * + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + + /* png_info is a structure that holds the information in a PNG file so + * that the application can find out the characteristics of the image. + * If you are reading the file, this structure will tell you what is + * in the PNG file. If you are writing the file, fill in the information + * you want to put into the PNG file, using png_set_*() functions, then + * call png_write_info(). + * + * The names chosen should be very close to the PNG specification, so + * consult that document for information about the meaning of each field. + * + * With libpng < 0.95, it was only possible to directly set and read the + * the values in the png_info_struct, which meant that the contents and + * order of the values had to remain fixed. With libpng 0.95 and later, + * however, there are now functions that abstract the contents of + * png_info_struct from the application, so this makes it easier to use + * libpng with dynamic libraries, and even makes it possible to use + * libraries that don't have all of the libpng ancillary chunk-handing + * functionality. In libpng-1.5.0 this was moved into a separate private + * file that is not visible to applications. + * + * The following members may have allocated storage attached that should be + * cleaned up before the structure is discarded: palette, trans, text, + * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, + * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these + * are automatically freed when the info structure is deallocated, if they were + * allocated internally by libpng. This behavior can be changed by means + * of the png_data_freer() function. + * + * More allocation details: all the chunk-reading functions that + * change these members go through the corresponding png_set_* + * functions. A function to clear these members is available: see + * png_free_data(). The png_set_* functions do not depend on being + * able to point info structure members to any of the storage they are + * passed (they make their own copies), EXCEPT that the png_set_text + * functions use the same storage passed to them in the text_ptr or + * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns + * functions do not make their own copies. + */ +#ifndef PNGINFO_H +#define PNGINFO_H + +struct png_info_def +{ + /* the following are necessary for every PNG file */ + png_uint_32 width; /* width of image in pixels (from IHDR) */ + png_uint_32 height; /* height of image in pixels (from IHDR) */ + png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ + png_size_t rowbytes; /* bytes needed to hold an untransformed row */ + png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ + png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ + png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ + png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ + png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ + /* The following three should have been named *_method not *_type */ + png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ + png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ + png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + + /* The following is informational only on read, and not used on writes. */ + png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte spare_byte; /* to align the data, and for future use */ + png_byte signature[8]; /* magic bytes read by libpng from start of file */ + + /* The rest of the data is optional. If you are reading, check the + * valid field to see if the information in these are valid. If you + * are writing, set the valid field to those chunks you want written, + * and initialize the appropriate fields below. + */ + +#if defined(PNG_gAMA_SUPPORTED) + /* The gAMA chunk describes the gamma characteristics of the system + * on which the image was created, normally in the range [1.0, 2.5]. + * Data is valid if (valid & PNG_INFO_gAMA) is non-zero. + */ + png_fixed_point gamma; +#endif + +#ifdef PNG_sRGB_SUPPORTED + /* GR-P, 0.96a */ + /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */ + png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */ +#endif + +#ifdef PNG_TEXT_SUPPORTED + /* The tEXt, and zTXt chunks contain human-readable textual data in + * uncompressed, compressed, and optionally compressed forms, respectively. + * The data in "text" is an array of pointers to uncompressed, + * null-terminated C strings. Each chunk has a keyword that describes the + * textual data contained in that chunk. Keywords are not required to be + * unique, and the text string may be empty. Any number of text chunks may + * be in an image. + */ + int num_text; /* number of comments read or comments to write */ + int max_text; /* current size of text array */ + png_textp text; /* array of comments read or comments to write */ +#endif /* PNG_TEXT_SUPPORTED */ + +#ifdef PNG_tIME_SUPPORTED + /* The tIME chunk holds the last time the displayed image data was + * modified. See the png_time struct for the contents of this struct. + */ + png_time mod_time; +#endif + +#ifdef PNG_sBIT_SUPPORTED + /* The sBIT chunk specifies the number of significant high-order bits + * in the pixel data. Values are in the range [1, bit_depth], and are + * only specified for the channels in the pixel data. The contents of + * the low-order bits is not specified. Data is valid if + * (valid & PNG_INFO_sBIT) is non-zero. + */ + png_color_8 sig_bit; /* significant bits in color channels */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \ +defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The tRNS chunk supplies transparency data for paletted images and + * other image types that don't need a full alpha channel. There are + * "num_trans" transparency values for a paletted image, stored in the + * same order as the palette colors, starting from index 0. Values + * for the data are in the range [0, 255], ranging from fully transparent + * to fully opaque, respectively. For non-paletted images, there is a + * single color specified that should be treated as fully transparent. + * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. + */ + png_bytep trans; /* alpha values for paletted image */ + png_bytep trans_alpha; /* alpha values for paletted image */ + png_color_16 trans_color; /* transparent color for non-palette image */ +#endif + +#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + /* The bKGD chunk gives the suggested image background color if the + * display program does not have its own background color and the image + * is needs to composited onto a background before display. The colors + * in "background" are normally in the same color space/depth as the + * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero. + */ + png_color_16 background; +#endif + +#ifdef PNG_oFFs_SUPPORTED + /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards + * and downwards from the top-left corner of the display, page, or other + * application-specific co-ordinate space. See the PNG_OFFSET_ defines + * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero. + */ + png_int_32 x_offset; /* x offset on page */ + png_int_32 y_offset; /* y offset on page */ + png_byte offset_unit_type; /* offset units type */ +#endif + +#ifdef PNG_pHYs_SUPPORTED + /* The pHYs chunk gives the physical pixel density of the image for + * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_ + * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero. + */ + png_uint_32 x_pixels_per_unit; /* horizontal pixel density */ + png_uint_32 y_pixels_per_unit; /* vertical pixel density */ + png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ +#endif + +#ifdef PNG_hIST_SUPPORTED + /* The hIST chunk contains the relative frequency or importance of the + * various palette entries, so that a viewer can intelligently select a + * reduced-color palette, if required. Data is an array of "num_palette" + * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) + * is non-zero. + */ + png_uint_16p hist; +#endif + +#ifdef PNG_cHRM_SUPPORTED + /* The cHRM chunk describes the CIE color characteristics of the monitor + * on which the PNG was created. This data allows the viewer to do gamut + * mapping of the input image to ensure that the viewer sees the same + * colors in the image as the creator. Values are in the range + * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero. + */ + png_fixed_point x_white; + png_fixed_point y_white; + png_fixed_point x_red; + png_fixed_point y_red; + png_fixed_point x_green; + png_fixed_point y_green; + png_fixed_point x_blue; + png_fixed_point y_blue; +#endif + +#ifdef PNG_pCAL_SUPPORTED + /* The pCAL chunk describes a transformation between the stored pixel + * values and original physical data values used to create the image. + * The integer range [0, 2^bit_depth - 1] maps to the floating-point + * range given by [pcal_X0, pcal_X1], and are further transformed by a + * (possibly non-linear) transformation function given by "pcal_type" + * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_ + * defines below, and the PNG-Group's PNG extensions document for a + * complete description of the transformations and how they should be + * implemented, and for a description of the ASCII parameter strings. + * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. + */ + png_charp pcal_purpose; /* pCAL chunk description string */ + png_int_32 pcal_X0; /* minimum value */ + png_int_32 pcal_X1; /* maximum value */ + png_charp pcal_units; /* Latin-1 string giving physical units */ + png_charpp pcal_params; /* ASCII strings containing parameter values */ + png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ + png_byte pcal_nparams; /* number of parameters given in pcal_params */ +#endif + +/* New members added in libpng-1.0.6 */ + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \ + defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) + /* Storage for unknown chunks that the library doesn't recognize. */ + png_unknown_chunkp unknown_chunks; + int unknown_chunks_num; +#endif + +#ifdef PNG_iCCP_SUPPORTED + /* iCCP chunk data. */ + png_charp iccp_name; /* profile name */ + png_bytep iccp_profile; /* International Color Consortium profile data */ + png_uint_32 iccp_proflen; /* ICC profile data length */ + png_byte iccp_compression; /* Always zero */ +#endif + +#ifdef PNG_sPLT_SUPPORTED + /* Data on sPLT chunks (there may be more than one). */ + png_sPLT_tp splt_palettes; + png_uint_32 splt_palettes_num; +#endif + +#ifdef PNG_sCAL_SUPPORTED + /* The sCAL chunk describes the actual physical dimensions of the + * subject matter of the graphic. The chunk contains a unit specification + * a byte value, and two ASCII strings representing floating-point + * values. The values are width and height corresponsing to one pixel + * in the image. Data values are valid if (valid & PNG_INFO_sCAL) is + * non-zero. + */ + png_byte scal_unit; /* unit of physical scale */ + png_charp scal_s_width; /* string containing height */ + png_charp scal_s_height; /* string containing width */ +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED + /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) + non-zero */ + /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ + png_bytepp row_pointers; /* the image bits */ +#endif + +}; +#endif /* PNGINFO_H */ diff --git a/contrib/libpng/pngmem.c b/contrib/libpng/pngmem.c new file mode 100644 index 0000000..a15d8b0 --- /dev/null +++ b/contrib/libpng/pngmem.c @@ -0,0 +1,658 @@ + +/* pngmem.c - stub functions for memory allocation + * + * Last changed in libpng 1.5.1 [February 3, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all memory allocation. Users who + * need special memory handling are expected to supply replacement + * functions for png_malloc() and png_free(), and to use + * png_create_read_struct_2() and png_create_write_struct_2() to + * identify the replacement functions. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +/* Borland DOS special memory handler */ +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* If you change this, be sure to change the one in png.h also */ + +/* Allocate memory for a png_struct. The malloc and memset can be replaced + by a single call to calloc() if this is thought to improve performance. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct,(int type),PNG_ALLOCATED) +{ +# ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, NULL, NULL)); +} + +/* Alternate version of png_create_struct, for use with user-defined malloc. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr), + PNG_ALLOCATED) +{ +# endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + + else + return (png_get_copyright(NULL)); + +# ifdef PNG_USER_MEM_SUPPORTED + if (malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); + } + + else +# endif /* PNG_USER_MEM_SUPPORTED */ + struct_ptr = (png_voidp)farmalloc(size); + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +# ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, NULL, NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +# endif + if (struct_ptr != NULL) + { +# ifdef PNG_USER_MEM_SUPPORTED + if (free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } + +# endif /* PNG_USER_MEM_SUPPORTED */ + farfree (struct_ptr); + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * Borland seems to have a problem in DOS mode for exactly 64K. + * It gives you a segment with an offset of 8 (perhaps to store its + * memory stuff). zlib doesn't like this at all, so we have to + * detect and deal with it. This code should not be needed in + * Windows or OS/2 modes, and only in 16 bit mode. This code has + * been updated by Alexander Lehmann for version 0.89 to waste less + * memory. + * + * Note that we can't use png_size_t for the "size" declaration, + * since on some systems a png_size_t is a 16-bit quantity, and as a + * result, we would be truncating potentially larger memory requests + * (which should cause a fatal error) and introducing major problems. + */ +PNG_FUNCTION(png_voidp,PNGAPI +png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + ret = (png_malloc(png_ptr, size)); + + if (ret != NULL) + png_memset(ret,0,(png_size_t)size); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + if (png_ptr == NULL || size == 0) + return (NULL); + +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + + else + ret = (png_malloc_default(png_ptr, size)); + + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory"); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; +# endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +# ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { + png_warning(png_ptr, "Cannot Allocate > 64K"); + ret = NULL; + } + + else +# endif + + if (size != (size_t)size) + ret = NULL; + + else if (size == (png_uint_32)65536L) + { + if (png_ptr->offset_table == NULL) + { + /* Try to see if we need to do any of this fancy stuff */ + ret = farmalloc(size); + if (ret == NULL || ((png_size_t)ret & 0xffff)) + { + int num_blocks; + png_uint_32 total_size; + png_bytep table; + int i; + png_byte huge * hptr; + + if (ret != NULL) + { + farfree(ret); + ret = NULL; + } + + if (png_ptr->zlib_window_bits > 14) + num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); + + else + num_blocks = 1; + + if (png_ptr->zlib_mem_level >= 7) + num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); + + else + num_blocks++; + + total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16; + + table = farmalloc(total_size); + + if (table == NULL) + { +# ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of Memory"); /* Note "O", "M" */ + + else + png_warning(png_ptr, "Out Of Memory"); +# endif + return (NULL); + } + + if ((png_size_t)table & 0xfff0) + { +# ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, + "Farmalloc didn't return normalized pointer"); + + else + png_warning(png_ptr, + "Farmalloc didn't return normalized pointer"); +# endif + return (NULL); + } + + png_ptr->offset_table = table; + png_ptr->offset_table_ptr = farmalloc(num_blocks * + png_sizeof(png_bytep)); + + if (png_ptr->offset_table_ptr == NULL) + { +# ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out Of memory"); /* Note "O", "m" */ + + else + png_warning(png_ptr, "Out Of memory"); +# endif + return (NULL); + } + + hptr = (png_byte huge *)table; + if ((png_size_t)hptr & 0xf) + { + hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); + hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */ + } + + for (i = 0; i < num_blocks; i++) + { + png_ptr->offset_table_ptr[i] = (png_bytep)hptr; + hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */ + } + + png_ptr->offset_table_number = num_blocks; + png_ptr->offset_table_count = 0; + png_ptr->offset_table_count_free = 0; + } + } + + if (png_ptr->offset_table_count >= png_ptr->offset_table_number) + { +# ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); /* Note "o" and "M" */ + + else + png_warning(png_ptr, "Out of Memory"); +# endif + return (NULL); + } + + ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++]; + } + + else + ret = farmalloc(size); + +# ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL) + { + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of memory"); /* Note "o" and "m" */ + + else + png_warning(png_ptr, "Out of memory"); /* Note "o" and "m" */ + } +# endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). In the default + * configuration, png_ptr is not used, but is passed in case it + * is needed. If ptr is NULL, return without taking any action. + */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + + else + png_free_default(png_ptr, ptr); +} + +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ +# endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || ptr == NULL) + return; + + if (png_ptr->offset_table != NULL) + { + int i; + + for (i = 0; i < png_ptr->offset_table_count; i++) + { + if (ptr == png_ptr->offset_table_ptr[i]) + { + ptr = NULL; + png_ptr->offset_table_count_free++; + break; + } + } + if (png_ptr->offset_table_count_free == png_ptr->offset_table_count) + { + farfree(png_ptr->offset_table); + farfree(png_ptr->offset_table_ptr); + png_ptr->offset_table = NULL; + png_ptr->offset_table_ptr = NULL; + } + } + + if (ptr != NULL) + farfree(ptr); +} + +#else /* Not the Borland DOS special memory handler */ + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct,(int type),PNG_ALLOCATED) +{ +# ifdef PNG_USER_MEM_SUPPORTED + return (png_create_struct_2(type, NULL, NULL)); +} + +/* Allocate memory for a png_struct or a png_info. The malloc and + memset can be replaced by a single call to calloc() if this is thought + to improve performance noticably. */ +PNG_FUNCTION(png_voidp /* PRIVATE */, +png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr), + PNG_ALLOCATED) +{ +# endif /* PNG_USER_MEM_SUPPORTED */ + png_size_t size; + png_voidp struct_ptr; + + if (type == PNG_STRUCT_INFO) + size = png_sizeof(png_info); + + else if (type == PNG_STRUCT_PNG) + size = png_sizeof(png_struct); + + else + return (NULL); + +# ifdef PNG_USER_MEM_SUPPORTED + if (malloc_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(png_ptr, size); + + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); + } +# endif /* PNG_USER_MEM_SUPPORTED */ + +# if defined(__TURBOC__) && !defined(__FLAT__) + struct_ptr = (png_voidp)farmalloc(size); +# else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + struct_ptr = (png_voidp)halloc(size, 1); +# else + struct_ptr = (png_voidp)malloc(size); +# endif +# endif + + if (struct_ptr != NULL) + png_memset(struct_ptr, 0, size); + + return (struct_ptr); +} + + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct(png_voidp struct_ptr) +{ +# ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2(struct_ptr, NULL, NULL); +} + +/* Free memory allocated by a png_create_struct() call */ +void /* PRIVATE */ +png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn, + png_voidp mem_ptr) +{ +# endif /* PNG_USER_MEM_SUPPORTED */ + if (struct_ptr != NULL) + { +# ifdef PNG_USER_MEM_SUPPORTED + if (free_fn != NULL) + { + png_struct dummy_struct; + png_structp png_ptr = &dummy_struct; + png_ptr->mem_ptr=mem_ptr; + (*(free_fn))(png_ptr, struct_ptr); + return; + } +# endif /* PNG_USER_MEM_SUPPORTED */ +# if defined(__TURBOC__) && !defined(__FLAT__) + farfree(struct_ptr); + +# else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(struct_ptr); + +# else + free(struct_ptr); + +# endif +# endif + } +} + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + */ + +PNG_FUNCTION(png_voidp,PNGAPI +png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + + ret = (png_malloc(png_ptr, size)); + + if (ret != NULL) + png_memset(ret,0,(png_size_t)size); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; + +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr == NULL || size == 0) + return (NULL); + + if (png_ptr->malloc_fn != NULL) + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + + else + ret = (png_malloc_default(png_ptr, size)); + + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); + + return (ret); +} + +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ret; +# endif /* PNG_USER_MEM_SUPPORTED */ + + if (png_ptr == NULL || size == 0) + return (NULL); + +# ifdef PNG_MAX_MALLOC_64K + if (size > (png_uint_32)65536L) + { +# ifndef PNG_USER_MEM_SUPPORTED + if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Cannot Allocate > 64K"); + + else +# endif + return NULL; + } +# endif + + /* Check for overflow */ +# if defined(__TURBOC__) && !defined(__FLAT__) + + if (size != (unsigned long)size) + ret = NULL; + + else + ret = farmalloc(size); + +# else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + if (size != (unsigned long)size) + ret = NULL; + + else + ret = halloc(size, 1); + +# else + if (size != (size_t)size) + ret = NULL; + + else + ret = malloc((size_t)size); +# endif +# endif + +# ifndef PNG_USER_MEM_SUPPORTED + if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) + png_error(png_ptr, "Out of Memory"); +# endif + + return (ret); +} + +/* Free a pointer allocated by png_malloc(). If ptr is NULL, return + * without taking any action. + */ +void PNGAPI +png_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr->free_fn != NULL) + { + (*(png_ptr->free_fn))(png_ptr, ptr); + return; + } + + else + png_free_default(png_ptr, ptr); +} + +void PNGAPI +png_free_default(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL || ptr == NULL) + return; + +# endif /* PNG_USER_MEM_SUPPORTED */ + +# if defined(__TURBOC__) && !defined(__FLAT__) + farfree(ptr); + +# else +# if defined(_MSC_VER) && defined(MAXSEG_64K) + hfree(ptr); + +# else + free(ptr); + +# endif +# endif +} +#endif /* Not Borland DOS special memory handler */ + +/* This function was added at libpng version 1.2.3. The png_malloc_warn() + * function will set up png_malloc() to issue a png_warning and return NULL + * instead of issuing a png_error, if it fails to allocate the requested + * memory. + */ +PNG_FUNCTION(png_voidp,PNGAPI +png_malloc_warn,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +{ + png_voidp ptr; + png_uint_32 save_flags; + if (png_ptr == NULL) + return (NULL); + + save_flags = png_ptr->flags; + png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK; + ptr = (png_voidp)png_malloc((png_structp)png_ptr, size); + png_ptr->flags=save_flags; + return(ptr); +} + + +#ifdef PNG_USER_MEM_SUPPORTED +/* This function is called when the application wants to use another method + * of allocating and freeing memory. + */ +void PNGAPI +png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr + malloc_fn, png_free_ptr free_fn) +{ + if (png_ptr != NULL) + { + png_ptr->mem_ptr = mem_ptr; + png_ptr->malloc_fn = malloc_fn; + png_ptr->free_fn = free_fn; + } +} + +/* This function returns a pointer to the mem_ptr associated with the user + * functions. The application should free any memory associated with this + * pointer before png_write_destroy and png_read_destroy are called. + */ +png_voidp PNGAPI +png_get_mem_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return ((png_voidp)png_ptr->mem_ptr); +} +#endif /* PNG_USER_MEM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/contrib/libpng/pngnow.png b/contrib/libpng/pngnow.png new file mode 100644 index 0000000..82793eb Binary files /dev/null and b/contrib/libpng/pngnow.png differ diff --git a/contrib/libpng/pngpread.c b/contrib/libpng/pngpread.c new file mode 100644 index 0000000..7b1149b --- /dev/null +++ b/contrib/libpng/pngpread.c @@ -0,0 +1,1854 @@ + +/* pngpread.c - read a png file in push mode + * + * Last changed in libpng 1.5.1 [February 3, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + +/* Push model modes */ +#define PNG_READ_SIG_MODE 0 +#define PNG_READ_CHUNK_MODE 1 +#define PNG_READ_IDAT_MODE 2 +#define PNG_SKIP_MODE 3 +#define PNG_READ_tEXt_MODE 4 +#define PNG_READ_zTXt_MODE 5 +#define PNG_READ_DONE_MODE 6 +#define PNG_READ_iTXt_MODE 7 +#define PNG_ERROR_MODE 8 + +void PNGAPI +png_process_data(png_structp png_ptr, png_infop info_ptr, + png_bytep buffer, png_size_t buffer_size) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_push_restore_buffer(png_ptr, buffer, buffer_size); + + while (png_ptr->buffer_size) + { + png_process_some_data(png_ptr, info_ptr); + } +} + +png_size_t PNGAPI +png_process_data_pause(png_structp png_ptr, int save) +{ + if (png_ptr != NULL) + { + /* It's easiest for the caller if we do the save, then the caller doesn't + * have to supply the same data again: + */ + if (save) + png_push_save_buffer(png_ptr); + else + { + /* This includes any pending saved bytes: */ + png_size_t remaining = png_ptr->buffer_size; + png_ptr->buffer_size = 0; + + /* So subtract the saved buffer size, unless all the data + * is actually 'saved', in which case we just return 0 + */ + if (png_ptr->save_buffer_size < remaining) + return remaining - png_ptr->save_buffer_size; + } + } + + return 0; +} + +png_uint_32 PNGAPI +png_process_data_skip(png_structp png_ptr) +{ + png_uint_32 remaining = 0; + + if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE && + png_ptr->skip_length > 0) + { + /* At the end of png_process_data the buffer size must be 0 (see the loop + * above) so we can detect a broken call here: + */ + if (png_ptr->buffer_size != 0) + png_error(png_ptr, + "png_process_data_skip called inside png_process_data"); + + /* If is impossible for there to be a saved buffer at this point - + * otherwise we could not be in SKIP mode. This will also happen if + * png_process_skip is called inside png_process_data (but only very + * rarely.) + */ + if (png_ptr->save_buffer_size != 0) + png_error(png_ptr, "png_process_data_skip called with saved data"); + + remaining = png_ptr->skip_length; + png_ptr->skip_length = 0; + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + + return remaining; +} + +/* What we do with the incoming data depends on what we were previously + * doing before we ran out of data... + */ +void /* PRIVATE */ +png_process_some_data(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr == NULL) + return; + + switch (png_ptr->process_mode) + { + case PNG_READ_SIG_MODE: + { + png_push_read_sig(png_ptr, info_ptr); + break; + } + + case PNG_READ_CHUNK_MODE: + { + png_push_read_chunk(png_ptr, info_ptr); + break; + } + + case PNG_READ_IDAT_MODE: + { + png_push_read_IDAT(png_ptr); + break; + } + +#ifdef PNG_READ_tEXt_SUPPORTED + case PNG_READ_tEXt_MODE: + { + png_push_read_tEXt(png_ptr, info_ptr); + break; + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + case PNG_READ_zTXt_MODE: + { + png_push_read_zTXt(png_ptr, info_ptr); + break; + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + case PNG_READ_iTXt_MODE: + { + png_push_read_iTXt(png_ptr, info_ptr); + break; + } + +#endif + case PNG_SKIP_MODE: + { + png_push_crc_finish(png_ptr); + break; + } + + default: + { + png_ptr->buffer_size = 0; + break; + } + } +} + +/* Read any remaining signature bytes from the stream and compare them with + * the correct PNG signature. It is possible that this routine is called + * with bytes already read from the signature, either because they have been + * checked by the calling application, or because of multiple calls to this + * routine. + */ +void /* PRIVATE */ +png_push_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked = png_ptr->sig_bytes, + num_to_check = 8 - num_checked; + + if (png_ptr->buffer_size < num_to_check) + { + num_to_check = png_ptr->buffer_size; + } + + png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), + num_to_check); + png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + else + { + if (png_ptr->sig_bytes >= 8) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } + } +} + +void /* PRIVATE */ +png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) +{ + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_sCAL; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_sRGB; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_sPLT; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_zTXt; +#endif + + /* First we make sure we have enough data for the 4 byte chunk name + * and the 4 byte chunk length before proceeding with decoding the + * chunk data. To fully decode each of these chunks, we also make + * sure we have enough data in the buffer for the 4 byte CRC at the + * end of every chunk (except IDAT, which is handled separately). + */ + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) + { + if (png_ptr->push_length != 13) + png_error(png_ptr, "Invalid IHDR length"); + + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + + png_ptr->process_mode = PNG_READ_DONE_MODE; + png_push_have_end(png_ptr, info_ptr); + } + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + + png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + + if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + } + } + +#endif + else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); + } + + else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + /* If we reach an IDAT chunk, this means we have read all of the + * header chunks, and we can start reading the image (or if this + * is called after the image has been read - we have an error). + */ + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + { + if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + if (png_ptr->push_length == 0) + return; + + if (png_ptr->mode & PNG_AFTER_IDAT) + png_benign_error(png_ptr, "Too many IDATs found"); + } + + png_ptr->idat_size = png_ptr->push_length; + png_ptr->mode |= PNG_HAVE_IDAT; + png_ptr->process_mode = PNG_READ_IDAT_MODE; + png_push_have_info(png_ptr, info_ptr); + png_ptr->zstream.avail_out = + (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + png_ptr->zstream.next_out = png_ptr->row_buf; + return; + } + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); + } +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); + } + +#endif + else + { + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); + } + + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; +} + +void /* PRIVATE */ +png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) +{ + png_ptr->process_mode = PNG_SKIP_MODE; + png_ptr->skip_length = skip; +} + +void /* PRIVATE */ +png_push_crc_finish(png_structp png_ptr) +{ + if (png_ptr->skip_length && png_ptr->save_buffer_size) + { + png_size_t save_size = png_ptr->save_buffer_size; + png_uint_32 skip_length = png_ptr->skip_length; + + /* We want the smaller of 'skip_length' and 'save_buffer_size', but + * they are of different types and we don't know which variable has the + * fewest bits. Carefully select the smaller and cast it to the type of + * the larger - this cannot overflow. Do not cast in the following test + * - it will break on either 16 or 64 bit platforms. + */ + if (skip_length < save_size) + save_size = (png_size_t)skip_length; + + else + skip_length = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->skip_length -= skip_length; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (png_ptr->skip_length && png_ptr->current_buffer_size) + { + png_size_t save_size = png_ptr->current_buffer_size; + png_uint_32 skip_length = png_ptr->skip_length; + + /* We want the smaller of 'skip_length' and 'current_buffer_size', here, + * the same problem exists as above and the same solution. + */ + if (skip_length < save_size) + save_size = (png_size_t)skip_length; + + else + skip_length = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->skip_length -= skip_length; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->skip_length) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + } +} + +void PNGCBAPI +png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +{ + png_bytep ptr; + + if (png_ptr == NULL) + return; + + ptr = buffer; + if (png_ptr->save_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->save_buffer_size) + save_size = length; + + else + save_size = png_ptr->save_buffer_size; + + png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); + length -= save_size; + ptr += save_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + if (length && png_ptr->current_buffer_size) + { + png_size_t save_size; + + if (length < png_ptr->current_buffer_size) + save_size = length; + + else + save_size = png_ptr->current_buffer_size; + + png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } +} + +void /* PRIVATE */ +png_push_save_buffer(png_structp png_ptr) +{ + if (png_ptr->save_buffer_size) + { + if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) + { + png_size_t i, istop; + png_bytep sp; + png_bytep dp; + + istop = png_ptr->save_buffer_size; + for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; + i < istop; i++, sp++, dp++) + { + *dp = *sp; + } + } + } + if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > + png_ptr->save_buffer_max) + { + png_size_t new_max; + png_bytep old_buffer; + + if (png_ptr->save_buffer_size > PNG_SIZE_MAX - + (png_ptr->current_buffer_size + 256)) + { + png_error(png_ptr, "Potential overflow of save_buffer"); + } + + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; + old_buffer = png_ptr->save_buffer; + png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, + (png_size_t)new_max); + + if (png_ptr->save_buffer == NULL) + { + png_free(png_ptr, old_buffer); + png_error(png_ptr, "Insufficient memory for save_buffer"); + } + + png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); + png_free(png_ptr, old_buffer); + png_ptr->save_buffer_max = new_max; + } + if (png_ptr->current_buffer_size) + { + png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, + png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); + png_ptr->save_buffer_size += png_ptr->current_buffer_size; + png_ptr->current_buffer_size = 0; + } + png_ptr->save_buffer_ptr = png_ptr->save_buffer; + png_ptr->buffer_size = 0; +} + +void /* PRIVATE */ +png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + png_ptr->current_buffer = buffer; + png_ptr->current_buffer_size = buffer_length; + png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; + png_ptr->current_buffer_ptr = png_ptr->current_buffer; +} + +void /* PRIVATE */ +png_push_read_IDAT(png_structp png_ptr) +{ + PNG_IDAT; + if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) + { + png_byte chunk_length[4]; + + if (png_ptr->buffer_size < 8) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_fill_buffer(png_ptr, chunk_length, 4); + png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); + png_reset_crc(png_ptr); + png_crc_read(png_ptr, png_ptr->chunk_name, 4); + png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; + + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + png_error(png_ptr, "Not enough compressed data"); + + return; + } + + png_ptr->idat_size = png_ptr->push_length; + } + if (png_ptr->idat_size && png_ptr->save_buffer_size) + { + png_size_t save_size = png_ptr->save_buffer_size; + png_uint_32 idat_size = png_ptr->idat_size; + + /* We want the smaller of 'idat_size' and 'current_buffer_size', but they + * are of different types and we don't know which variable has the fewest + * bits. Carefully select the smaller and cast it to the type of the + * larger - this cannot overflow. Do not cast in the following test - it + * will break on either 16 or 64 bit platforms. + */ + if (idat_size < save_size) + save_size = (png_size_t)idat_size; + + else + idat_size = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); + + png_ptr->idat_size -= idat_size; + png_ptr->buffer_size -= save_size; + png_ptr->save_buffer_size -= save_size; + png_ptr->save_buffer_ptr += save_size; + } + + if (png_ptr->idat_size && png_ptr->current_buffer_size) + { + png_size_t save_size = png_ptr->current_buffer_size; + png_uint_32 idat_size = png_ptr->idat_size; + + /* We want the smaller of 'idat_size' and 'current_buffer_size', but they + * are of different types and we don't know which variable has the fewest + * bits. Carefully select the smaller and cast it to the type of the + * larger - this cannot overflow. + */ + if (idat_size < save_size) + save_size = (png_size_t)idat_size; + + else + idat_size = (png_uint_32)save_size; + + png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); + + png_ptr->idat_size -= idat_size; + png_ptr->buffer_size -= save_size; + png_ptr->current_buffer_size -= save_size; + png_ptr->current_buffer_ptr += save_size; + } + if (!png_ptr->idat_size) + { + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_crc_finish(png_ptr, 0); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + png_ptr->mode |= PNG_AFTER_IDAT; + } +} + +void /* PRIVATE */ +png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, + png_size_t buffer_length) +{ + /* The caller checks for a non-zero buffer length. */ + if (!(buffer_length > 0) || buffer == NULL) + png_error(png_ptr, "No IDAT data (internal error)"); + + /* This routine must process all the data it has been given + * before returning, calling the row callback as required to + * handle the uncompressed results. + */ + png_ptr->zstream.next_in = buffer; + png_ptr->zstream.avail_in = (uInt)buffer_length; + + /* Keep going until the decompressed data is all processed + * or the stream marked as finished. + */ + while (png_ptr->zstream.avail_in > 0 && + !(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { + int ret; + + /* We have data for zlib, but we must check that zlib + * has someplace to put the results. It doesn't matter + * if we don't expect any results -- it may be the input + * data is just the LZ end code. + */ + if (!(png_ptr->zstream.avail_out > 0)) + { + png_ptr->zstream.avail_out = + (uInt) PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1; + + png_ptr->zstream.next_out = png_ptr->row_buf; + } + + /* Using Z_SYNC_FLUSH here means that an unterminated + * LZ stream (a stream with a missing end code) can still + * be handled, otherwise (Z_NO_FLUSH) a future zlib + * implementation might defer output and therefore + * change the current behavior (see comments in inflate.c + * for why this doesn't happen at present with zlib 1.2.5). + */ + ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH); + + /* Check for any failure before proceeding. */ + if (ret != Z_OK && ret != Z_STREAM_END) + { + /* Terminate the decompression. */ + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + + /* This may be a truncated stream (missing or + * damaged end code). Treat that as a warning. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + png_warning(png_ptr, "Truncated compressed data in IDAT"); + + else + png_error(png_ptr, "Decompression error in IDAT"); + + /* Skip the check on unprocessed input */ + return; + } + + /* Did inflate output any data? */ + if (png_ptr->zstream.next_out != png_ptr->row_buf) + { + /* Is this unexpected data after the last row? + * If it is, artificially terminate the LZ output + * here. + */ + if (png_ptr->row_number >= png_ptr->num_rows || + png_ptr->pass > 6) + { + /* Extra data. */ + png_warning(png_ptr, "Extra compressed data in IDAT"); + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + + /* Do no more processing; skip the unprocessed + * input check below. + */ + return; + } + + /* Do we have a complete row? */ + if (png_ptr->zstream.avail_out == 0) + png_push_process_row(png_ptr); + } + + /* And check for the end of the stream. */ + if (ret == Z_STREAM_END) + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + } + + /* All the data should have been processed, if anything + * is left at this point we have bytes of IDAT data + * after the zlib end code. + */ + if (png_ptr->zstream.avail_in > 0) + png_warning(png_ptr, "Extra compression data in IDAT"); +} + +void /* PRIVATE */ +png_push_process_row(png_structp png_ptr) +{ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); + + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) +/* old interface (pre-1.0.9): + png_do_read_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + switch (png_ptr->pass) + { + case 0: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 0; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */ + } + + if (png_ptr->pass == 2) /* Pass 1 might be empty */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 4 && png_ptr->height <= 4) + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + if (png_ptr->pass == 6 && png_ptr->height <= 4) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 1: + { + int i; + for (i = 0; i < 8 && png_ptr->pass == 1; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 2) /* Skip top 4 generated rows */ + { + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 2: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 4 && png_ptr->pass == 2; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Pass 3 might be empty */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 3: + { + int i; + + for (i = 0; i < 4 && png_ptr->pass == 3; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 4) /* Skip top two generated rows */ + { + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + + break; + } + + case 4: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + for (i = 0; i < 2 && png_ptr->pass == 4; i++) + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Pass 5 might be empty */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + case 5: + { + int i; + + for (i = 0; i < 2 && png_ptr->pass == 5; i++) + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } + + if (png_ptr->pass == 6) /* Skip top generated row */ + { + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + + break; + } + + default: + case 6: + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + + if (png_ptr->pass != 6) + break; + + png_push_have_row(png_ptr, NULL); + png_read_push_finish_row(png_ptr); + } + } + } + else +#endif + { + png_push_have_row(png_ptr, png_ptr->row_buf + 1); + png_read_push_finish_row(png_ptr); + } +} + +void /* PRIVATE */ +png_read_push_finish_row(png_structp png_ptr) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; + + /* Height of interlace block. This is not currently used - if you need + * it, uncomment it here and in png.h + PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; + */ + + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + do + { + png_ptr->pass++; + if ((png_ptr->pass == 1 && png_ptr->width < 5) || + (png_ptr->pass == 3 && png_ptr->width < 3) || + (png_ptr->pass == 5 && png_ptr->width < 2)) + png_ptr->pass++; + + if (png_ptr->pass > 7) + png_ptr->pass--; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ +} + +#ifdef PNG_READ_tEXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + png_error(png_ptr, "Out of place tEXt"); + /*NOT REACHED*/ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_size_t)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_tEXt_MODE; +} + +void /* PRIVATE */ +png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; + text_ptr->itxt_length = 0; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + png_ptr->current_text = NULL; + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk"); + } +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + png_error(png_ptr, "Out of place zTXt"); + /*NOT REACHED*/ + } + +#ifdef PNG_MAX_MALLOC_64K + /* We can't handle zTXt chunks > 64K, since we don't have enough space + * to be able to store the uncompressed data. Actually, the threshold + * is probably around 32K, but it isn't as definite as 64K is. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_push_crc_skip(png_ptr, length); + return; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_size_t)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_zTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp text; + png_charp key; + int ret; + png_size_t text_size, key_size; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + + key = png_ptr->current_text; + + for (text = key; *text; text++) + /* Empty loop */ ; + + /* zTXt can't have zero text */ + if (text >= key + png_ptr->current_text_size) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */ + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + return; + } + + text++; + + png_ptr->zstream.next_in = (png_bytep)text; + png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - + (text - key)); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + key_size = text - key; + text_size = 0; + text = NULL; + ret = Z_STREAM_END; + + while (png_ptr->zstream.avail_in) + { + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + { + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) + { + if (text == NULL) + { + text = (png_charp)png_malloc(png_ptr, + (png_ptr->zbuf_size + - png_ptr->zstream.avail_out + key_size + 1)); + + png_memcpy(text + key_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + png_memcpy(text, key, key_size); + + text_size = key_size + png_ptr->zbuf_size - + png_ptr->zstream.avail_out; + + *(text + text_size) = '\0'; + } + + else + { + png_charp tmp; + + tmp = text; + text = (png_charp)png_malloc(png_ptr, text_size + + (png_ptr->zbuf_size + - png_ptr->zstream.avail_out + 1)); + + png_memcpy(text, tmp, text_size); + png_free(png_ptr, tmp); + + png_memcpy(text + text_size, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + + text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; + *(text + text_size) = '\0'; + } + + if (ret != Z_STREAM_END) + { + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + else + { + break; + } + + if (ret == Z_STREAM_END) + break; + } + + inflateReset(&png_ptr->zstream); + png_ptr->zstream.avail_in = 0; + + if (ret != Z_STREAM_END) + { + png_ptr->current_text = NULL; + png_free(png_ptr, key); + png_free(png_ptr, text); + return; + } + + png_ptr->current_text = NULL; + png_free(png_ptr, key); + key = text; + text += key_size; + + text_ptr = (png_textp)png_malloc(png_ptr, + png_sizeof(png_text)); + text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr->key = key; + text_ptr->itxt_length = 0; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->text = text; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, key); + png_free(png_ptr, text_ptr); + + if (ret) + png_warning(png_ptr, "Insufficient memory to store text chunk"); + } +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +void /* PRIVATE */ +png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) + { + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + png_error(png_ptr, "Out of place iTXt"); + /*NOT REACHED*/ + } + +#ifdef PNG_MAX_MALLOC_64K + png_ptr->skip_length = 0; /* This may not be necessary */ + + if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_ptr->skip_length = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_ptr->current_text = (png_charp)png_malloc(png_ptr, + (png_size_t)(length + 1)); + png_ptr->current_text[length] = '\0'; + png_ptr->current_text_ptr = png_ptr->current_text; + png_ptr->current_text_size = (png_size_t)length; + png_ptr->current_text_left = (png_size_t)length; + png_ptr->process_mode = PNG_READ_iTXt_MODE; +} + +void /* PRIVATE */ +png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) +{ + + if (png_ptr->buffer_size && png_ptr->current_text_left) + { + png_size_t text_size; + + if (png_ptr->buffer_size < png_ptr->current_text_left) + text_size = png_ptr->buffer_size; + + else + text_size = png_ptr->current_text_left; + + png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); + png_ptr->current_text_left -= text_size; + png_ptr->current_text_ptr += text_size; + } + + if (!(png_ptr->current_text_left)) + { + png_textp text_ptr; + png_charp key; + int comp_flag; + png_charp lang; + png_charp lang_key; + png_charp text; + int ret; + + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_push_crc_finish(png_ptr); + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->skip_length) + return; +#endif + + key = png_ptr->current_text; + + for (lang = key; *lang; lang++) + /* Empty loop */ ; + + if (lang < key + png_ptr->current_text_size - 3) + lang++; + + comp_flag = *lang++; + lang++; /* Skip comp_type, always zero */ + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + + lang_key++; /* Skip NUL separator */ + + text=lang_key; + + if (lang_key < key + png_ptr->current_text_size - 1) + { + for (; *text; text++) + /* Empty loop */ ; + } + + if (text < key + png_ptr->current_text_size) + text++; + + text_ptr = (png_textp)png_malloc(png_ptr, + png_sizeof(png_text)); + + text_ptr->compression = comp_flag + 2; + text_ptr->key = key; + text_ptr->lang = lang; + text_ptr->lang_key = lang_key; + text_ptr->text = text; + text_ptr->text_length = 0; + text_ptr->itxt_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_ptr->current_text = NULL; + + png_free(png_ptr, text_ptr); + if (ret) + png_warning(png_ptr, "Insufficient memory to store iTXt chunk"); + } +} +#endif + +/* This function is called when we haven't found a handler for this + * chunk. If there isn't a problem with the chunk itself (ie a bad chunk + * name or a critical chunk), the chunk is (currently) silently ignored. + */ +void /* PRIVATE */ +png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 + length) +{ + png_uint_32 skip = 0; + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + + PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1] + = '\0'; + + png_ptr->unknown_chunk.size = (png_size_t)length; + + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, + (png_size_t)length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) + png_chunk_error(png_ptr, "unknown critical chunk"); + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + else +#endif + skip=length; + png_push_crc_skip(png_ptr, skip); +} + +void /* PRIVATE */ +png_push_have_info(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->info_fn != NULL) + (*(png_ptr->info_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_end(png_structp png_ptr, png_infop info_ptr) +{ + if (png_ptr->end_fn != NULL) + (*(png_ptr->end_fn))(png_ptr, info_ptr); +} + +void /* PRIVATE */ +png_push_have_row(png_structp png_ptr, png_bytep row) +{ + if (png_ptr->row_fn != NULL) + (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, + (int)png_ptr->pass); +} + +void PNGAPI +png_progressive_combine_row (png_structp png_ptr, png_bytep old_row, + png_const_bytep new_row) +{ + PNG_CONST int FARDATA png_pass_dsp_mask[7] = + {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; + + if (png_ptr == NULL) + return; + + if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ + png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); +} + +void PNGAPI +png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, + png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, + png_progressive_end_ptr end_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->info_fn = info_fn; + png_ptr->row_fn = row_fn; + png_ptr->end_fn = end_fn; + + png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); +} + +png_voidp PNGAPI +png_get_progressive_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return png_ptr->io_ptr; +} +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ diff --git a/contrib/libpng/pngpriv.h b/contrib/libpng/pngpriv.h new file mode 100644 index 0000000..30ac004 --- /dev/null +++ b/contrib/libpng/pngpriv.h @@ -0,0 +1,1239 @@ + +/* pngpriv.h - private declarations for use inside libpng + * + * For conditions of distribution and use, see copyright notice in png.h + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The symbols declared in this file (including the functions declared + * as PNG_EXTERN) are PRIVATE. They are not part of the libpng public + * interface, and are not recommended for use by regular applications. + * Some of them may become public in the future; others may stay private, + * change in an incompatible way, or even disappear. + * Although the libpng users are not forbidden to include this header, + * they should be well aware of the issues that may arise from doing so. + */ + +#ifndef PNGPRIV_H +#define PNGPRIV_H + +/* This is required for the definition of abort(), used as a last ditch + * error handler when all else fails. + */ +#include + +#define PNGLIB_BUILD +#ifdef PNG_USER_CONFIG +# include "pngusr.h" + /* These should have been defined in pngusr.h */ +# ifndef PNG_USER_PRIVATEBUILD +# define PNG_USER_PRIVATEBUILD "Custom libpng build" +# endif +# ifndef PNG_USER_DLLFNAME_POSTFIX +# define PNG_USER_DLLFNAME_POSTFIX "Cb" +# endif +#endif +#include "png.h" +#include "pnginfo.h" +#include "pngstruct.h" + +/* This is used for 16 bit gamma tables - only the top level pointers are const, + * this could be changed: + */ +typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; + +/* Added at libpng-1.2.9 */ +/* Moved to pngpriv.h at libpng-1.5.0 */ + +/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure" + * script. We may need it here to get the correct configuration on things + * like limits. + */ +#ifdef PNG_CONFIGURE_LIBPNG +# ifdef HAVE_CONFIG_H +# include "config.h" +# endif +#endif + +/* Moved to pngpriv.h at libpng-1.5.0 */ +/* NOTE: some of these may have been used in external applications as + * these definitions were exposed in pngconf.h prior to 1.5. + */ + +/* If you are running on a machine where you cannot allocate more + * than 64K of memory at once, uncomment this. While libpng will not + * normally need that much memory in a chunk (unless you load up a very + * large file), zlib needs to know how big of a chunk it can use, and + * libpng thus makes sure to check any memory allocation to verify it + * will fit into memory. + * + * zlib provides 'MAXSEG_64K' which, if defined, indicates the + * same limit and pngconf.h (already included) sets the limit + * if certain operating systems are detected. + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) +# define PNG_MAX_MALLOC_64K +#endif + +/* Unused formal parameter warnings are silenced using the following macro + * which is expected to have no bad effects on performance (optimizing + * compilers will probably remove it entirely). Note that if you replace + * it with something other than whitespace, you must include the terminating + * semicolon. + */ +#define PNG_UNUSED(param) (void)param; + +/* Just a little check that someone hasn't tried to define something + * contradictory. + */ +#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) +# undef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 65536L +#endif + +/* If warnings or errors are turned off the code is disabled + * or redirected here. + */ +#ifndef PNG_WARNINGS_SUPPORTED +# define png_warning(s1,s2) ((void)0) +# define png_chunk_warning(s1,s2) ((void)0) +#endif +#ifndef PNG_ERROR_TEXT_SUPPORTED +# define png_error(s1,s2) png_err(s1) +# define png_chunk_error(s1,s2) png_err(s1) +# define png_fixed_error(s1,s2) png_err(s1) +#endif + +#ifndef PNG_EXTERN +/* The functions exported by PNG_EXTERN are internal functions, which + * aren't usually used outside the library (as far as I know), so it is + * debatable if they should be exported at all. In the future, when it + * is possible to have run-time registry of chunk-handling functions, + * some of these might be made available again. +# define PNG_EXTERN extern + */ +# define PNG_EXTERN +#endif + +/* Some fixed point APIs are still required even if not exported because + * they get used by the corresponding floating point APIs. This magic + * deals with this: + */ +#ifdef PNG_FIXED_POINT_SUPPORTED +# define PNGFAPI PNGAPI +#else +# define PNGFAPI /* PRIVATE */ +#endif + +/* Other defines specific to compilers can go here. Try to keep + * them inside an appropriate ifdef/endif pair for portability. + */ +#if defined(PNG_FLOATING_POINT_SUPPORTED) ||\ + defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) + /* png.c requires the following ANSI-C constants if the conversion of + * floating point to ASCII is implemented therein: + * + * DBL_DIG Maximum number of decimal digits (can be set to any constant) + * DBL_MIN Smallest normalized fp number (can be set to an arbitrary value) + * DBL_MAX Maximum floating point number (can be set to an arbitrary value) + */ +# include + +# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ + defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) + /* We need to check that hasn't already been included earlier + * as it seems it doesn't agree with , yet we should really use + * if possible. + */ +# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__) +# include +# endif +# else +# include +# endif +# if defined(_AMIGA) && defined(__SASC) && defined(_M68881) + /* Amiga SAS/C: We must include builtin FPU functions when compiling using + * MATH=68881 + */ +# include +# endif +#endif + +/* This provides the non-ANSI (far) memory allocation routines. */ +#if defined(__TURBOC__) && defined(__MSDOS__) +# include +# include +#endif + +#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ + defined(_WIN32) || defined(__WIN32__) +# include /* defines _WINDOWS_ macro */ +#endif + +/* Moved here around 1.5.0beta36 from pngconf.h */ +/* Users may want to use these so they are not private. Any library + * functions that are passed far data must be model-independent. + */ + +/* Memory model/platform independent fns */ +#ifndef PNG_ABORT +# ifdef _WINDOWS_ +# define PNG_ABORT() ExitProcess(0) +# else +# define PNG_ABORT() abort() +# endif +#endif + +#ifdef USE_FAR_KEYWORD +/* Use this to make far-to-near assignments */ +# define CHECK 1 +# define NOCHECK 0 +# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) +# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) +# define png_strcpy _fstrcpy +# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ +# define png_strlen _fstrlen +# define png_memcmp _fmemcmp /* SJT: added */ +# define png_memcpy _fmemcpy +# define png_memset _fmemset +# define png_sprintf sprintf +#else +# ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strcpy lstrcpyA +# define png_strncpy lstrcpynA +# define png_strlen lstrlenA +# define png_memcmp memcmp +# define png_memcpy CopyMemory +# define png_memset memset +# define png_sprintf wsprintfA +# else +# define CVT_PTR(ptr) (ptr) +# define CVT_PTR_NOCHECK(ptr) (ptr) +# define png_strcpy strcpy +# define png_strncpy strncpy /* Added to v 1.2.6 */ +# define png_strlen strlen +# define png_memcmp memcmp /* SJT: added */ +# define png_memcpy memcpy +# define png_memset memset +# define png_sprintf sprintf +# endif +#endif +/* End of memory model/platform independent support */ + +#ifndef PNG_NO_SNPRINTF +# ifdef _MSC_VER +# define png_snprintf _snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 _snprintf +# define png_snprintf6 _snprintf +# else +# define png_snprintf snprintf /* Added to v 1.2.19 */ +# define png_snprintf2 snprintf +# define png_snprintf6 snprintf +# endif +#else + /* You don't have or don't want to use snprintf(). Caution: Using + * sprintf instead of snprintf exposes your application to accidental + * or malevolent buffer overflows. If you don't have snprintf() + * as a general rule you should provide one (you can get one from + * Portable OpenSSH). + */ +# define png_snprintf(s1,n,fmt,x1) png_sprintf(s1,fmt,x1) +# define png_snprintf2(s1,n,fmt,x1,x2) png_sprintf(s1,fmt,x1,x2) +# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ + png_sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) +#endif +/* End of 1.5.0beta36 move from pngconf.h */ + +/* CONSTANTS and UTILITY MACROS + * These are used internally by libpng and not exposed in the API + */ + +/* Various modes of operation. Note that after an init, mode is set to + * zero automatically when the structure is created. + */ +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_HAVE_IDAT 0x04 +#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +#define PNG_HAVE_IEND 0x10 +#define PNG_HAVE_gAMA 0x20 +#define PNG_HAVE_cHRM 0x40 +#define PNG_HAVE_sRGB 0x80 +#define PNG_HAVE_CHUNK_HEADER 0x100 +#define PNG_WROTE_tIME 0x200 +#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 +#define PNG_BACKGROUND_IS_GRAY 0x800 +#define PNG_HAVE_PNG_SIGNATURE 0x1000 +#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ + +/* Flags for the transformations the PNG library does on the image data */ +#define PNG_BGR 0x0001 +#define PNG_INTERLACE 0x0002 +#define PNG_PACK 0x0004 +#define PNG_SHIFT 0x0008 +#define PNG_SWAP_BYTES 0x0010 +#define PNG_INVERT_MONO 0x0020 +#define PNG_QUANTIZE 0x0040 +#define PNG_BACKGROUND 0x0080 +#define PNG_BACKGROUND_EXPAND 0x0100 + /* 0x0200 unused */ +#define PNG_16_TO_8 0x0400 +#define PNG_RGBA 0x0800 +#define PNG_EXPAND 0x1000 +#define PNG_GAMMA 0x2000 +#define PNG_GRAY_TO_RGB 0x4000 +#define PNG_FILLER 0x8000L +#define PNG_PACKSWAP 0x10000L +#define PNG_SWAP_ALPHA 0x20000L +#define PNG_STRIP_ALPHA 0x40000L +#define PNG_INVERT_ALPHA 0x80000L +#define PNG_USER_TRANSFORM 0x100000L +#define PNG_RGB_TO_GRAY_ERR 0x200000L +#define PNG_RGB_TO_GRAY_WARN 0x400000L +#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ + /* 0x800000L Unused */ +#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ +#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +/* Flags for png_create_struct */ +#define PNG_STRUCT_PNG 0x0001 +#define PNG_STRUCT_INFO 0x0002 + +/* Scaling factor for filter heuristic weighting calculations */ +#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) +#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) + +/* Flags for the png_ptr->flags rather than declaring a byte for each one */ +#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 +#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002 +#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004 +#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008 +#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010 +#define PNG_FLAG_ZLIB_FINISHED 0x0020 +#define PNG_FLAG_ROW_INIT 0x0040 +#define PNG_FLAG_FILLER_AFTER 0x0080 +#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 +#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 +#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 +#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 + /* 0x1000 unused */ + /* 0x2000 unused */ + /* 0x4000 unused */ +#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L +#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L +#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L +#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L +#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L +#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L +#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ +#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ +#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000L /* Added to libpng-1.4.0 */ + /* 0x1000000L unused */ + /* 0x2000000L unused */ + /* 0x4000000L unused */ + /* 0x8000000L unused */ + /* 0x10000000L unused */ + /* 0x20000000L unused */ + /* 0x40000000L unused */ + +#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ + PNG_FLAG_CRC_ANCILLARY_NOWARN) + +#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \ + PNG_FLAG_CRC_CRITICAL_IGNORE) + +#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \ + PNG_FLAG_CRC_CRITICAL_MASK) + +/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib + * can handle at once. This type need be no larger than 16 bits (so maximum of + * 65535), this define allows us to discover how big it is, but limited by the + * maximuum for png_size_t. The value can be overriden in a library build + * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably + * lower value (e.g. 255 works). A lower value may help memory usage (slightly) + * and may even improve performance on some systems (and degrade it on others.) + */ +#ifndef ZLIB_IO_MAX +# define ZLIB_IO_MAX ((uInt)-1) +#endif + +/* Save typing and make code easier to understand */ + +#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ + abs((int)((c1).green) - (int)((c2).green)) + \ + abs((int)((c1).blue) - (int)((c2).blue))) + +/* Added to libpng-1.2.6 JB */ +#define PNG_ROWBYTES(pixel_bits, width) \ + ((pixel_bits) >= 8 ? \ + ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ + (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + +/* PNG_OUT_OF_RANGE returns true if value is outside the range + * ideal-delta..ideal+delta. Each argument is evaluated twice. + * "ideal" and "delta" should be constants, normally simple + * integers, "value" a variable. Added to libpng-1.2.6 JB + */ +#define PNG_OUT_OF_RANGE(value, ideal, delta) \ + ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) ) + +/* Conversions between fixed and floating point, only defined if + * required (to make sure the code doesn't accidentally use float + * when it is supposedly disabled.) + */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* The floating point conversion can't overflow, though it can and + * does lose accuracy relative to the original fixed point value. + * In practice this doesn't matter because png_fixed_point only + * stores numbers with very low precision. The png_ptr and s + * arguments are unused by default but are there in case error + * checking becomes a requirement. + */ +#define png_float(png_ptr, fixed, s) (.00001 * (fixed)) + +/* The fixed point conversion performs range checking and evaluates + * its argument multiple times, so must be used with care. The + * range checking uses the PNG specification values for a signed + * 32 bit fixed point value except that the values are deliberately + * rounded-to-zero to an integral value - 21474 (21474.83 is roughly + * (2^31-1) * 100000). 's' is a string that describes the value being + * converted. + * + * NOTE: this macro will raise a png_error if the range check fails, + * therefore it is normally only appropriate to use this on values + * that come from API calls or other sources where an out of range + * error indicates a programming error, not a data error! + * + * NOTE: by default this is off - the macro is not used - because the + * function call saves a lot of code. + */ +#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED +#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\ + ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0)) +#else +PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp, + png_const_charp text)); +#endif +#endif + +/* Constant strings for known chunk types. If you need to add a chunk, + * define the name here, and add an invocation of the macro wherever it's + * needed. + */ +#define PNG_IHDR PNG_CONST png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'} +#define PNG_IDAT PNG_CONST png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'} +#define PNG_IEND PNG_CONST png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'} +#define PNG_PLTE PNG_CONST png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'} +#define PNG_bKGD PNG_CONST png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'} +#define PNG_cHRM PNG_CONST png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'} +#define PNG_gAMA PNG_CONST png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'} +#define PNG_hIST PNG_CONST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'} +#define PNG_iCCP PNG_CONST png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'} +#define PNG_iTXt PNG_CONST png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'} +#define PNG_oFFs PNG_CONST png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'} +#define PNG_pCAL PNG_CONST png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'} +#define PNG_sCAL PNG_CONST png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'} +#define PNG_pHYs PNG_CONST png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'} +#define PNG_sBIT PNG_CONST png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'} +#define PNG_sPLT PNG_CONST png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'} +#define PNG_sRGB PNG_CONST png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'} +#define PNG_sTER PNG_CONST png_byte png_sTER[5] = {115, 84, 69, 82, '\0'} +#define PNG_tEXt PNG_CONST png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'} +#define PNG_tIME PNG_CONST png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} +#define PNG_tRNS PNG_CONST png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} +#define PNG_zTXt PNG_CONST png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} + + +/* Inhibit C++ name-mangling for libpng functions but not for system calls. */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* These functions are used internally in the code. They generally + * shouldn't be used unless you are writing code to add or replace some + * functionality in libpng. More information about most functions can + * be found in the files where the functions are located. + */ + +/* Allocate memory for an internal libpng struct */ +PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct,PNGARG((int type)), + PNG_ALLOCATED); + +/* Free memory from internal libpng struct */ +PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)); + +PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct_2, + PNGARG((int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)), + PNG_ALLOCATED); +PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr, + png_free_ptr free_fn, png_voidp mem_ptr)); + +/* Free any memory that info_ptr points to and reset struct. */ +PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* Function to allocate memory for zlib. PNGAPI is disallowed. */ +PNG_EXTERN PNG_FUNCTION(voidpf,png_zalloc,PNGARG((voidpf png_ptr, uInt items, + uInt size)),PNG_ALLOCATED); + +/* Function to free memory for zlib. PNGAPI is disallowed. */ +PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)); + +/* Next four functions are used internally as callbacks. PNGCBAPI is required + * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3, changed to + * PNGCBAPI at 1.5.0 + */ + +PNG_EXTERN void PNGCBAPI png_default_read_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void PNGCBAPI png_push_fill_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t length)); +#endif + +PNG_EXTERN void PNGCBAPI png_default_write_data PNGARG((png_structp png_ptr, + png_bytep data, png_size_t length)); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_STDIO_SUPPORTED +PNG_EXTERN void PNGCBAPI png_default_flush PNGARG((png_structp png_ptr)); +# endif +#endif + +/* Reset the CRC variable */ +PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)); + +/* Write the "data" buffer to whatever output you are using */ +PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, + png_const_bytep data, png_size_t length)); + +/* Read and check the PNG file signature */ +PNG_EXTERN void png_read_sig PNGARG((png_structp png_ptr, png_infop info_ptr)); + +/* Read the chunk header (length + type name) */ +PNG_EXTERN png_uint_32 png_read_chunk_header PNGARG((png_structp png_ptr)); + +/* Read data from whatever input you are using into the "data" buffer */ +PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +/* Read bytes into buf, and update png_ptr->crc */ +PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, + png_size_t length)); + +/* Decompress data in a chunk that uses compression */ +#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ + defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) +PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr, + int comp_type, png_size_t chunklength, png_size_t prefix_length, + png_size_t *data_length)); +#endif + +/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ +PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)); + +/* Read the CRC from the file and compare it to the libpng calculated CRC */ +PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)); + +/* Calculate the CRC over a section of data. Note that we are only + * passing a maximum of 64K on systems that have this as a memory limit, + * since this is the maximum buffer size we can specify. + */ +PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, + png_const_bytep ptr, png_size_t length)); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)); +#endif + +/* Write various chunks */ + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. + */ +PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width, + png_uint_32 height, + int bit_depth, int color_type, int compression_method, int filter_method, + int interlace_method)); + +PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, + png_const_colorp palette, png_uint_32 num_pal)); + +PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data, + png_size_t length)); + +PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)); + +#ifdef PNG_WRITE_gAMA_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma)); +# endif +# ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr, + png_fixed_point file_gamma)); +# endif +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, + png_const_color_8p sbit, int color_type)); +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +# ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr, + double white_x, double white_y, + double red_x, double red_y, double green_x, double green_y, + double blue_x, double blue_y)); +# endif +PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr, + int intent)); +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr, + png_const_charp name, int compression_type, + png_const_charp profile, int proflen)); + /* Note to maintainer: profile should be png_bytep */ +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr, + png_const_sPLT_tp palette)); +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, + png_const_bytep trans, png_const_color_16p values, int number, + int color_type)); +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr, + png_const_color_16p values, int color_type)); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, + png_const_uint_16p hist, int num_hist)); +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, + png_const_charp key, png_charpp new_key)); +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_const_charp key, + png_const_charp text, png_size_t text_len)); +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_const_charp key, + png_const_charp text, png_size_t text_len, int compression)); +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr, + int compression, png_const_charp key, png_const_charp lang, + png_const_charp lang_key, png_const_charp text)); +#endif + +#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */ +PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr, + png_infop info_ptr, png_const_textp text_ptr, int num_text)); +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type)); +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED +PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose, + png_int_32 X0, png_int_32 X1, int type, int nparams, + png_const_charp units, png_charpp params)); +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr, + png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, + int unit_type)); +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr, + png_const_timep mod_time)); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr, + int unit, png_const_charp width, png_const_charp height)); +#endif + +/* Called when finished processing a row of data */ +PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); + +/* Internal use only. Called before first row of data */ +PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)); + +/* Combine a row of data, dealing with alpha, etc. if requested */ +PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row, + int mask)); + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Expand an interlaced row */ +/* OLD pre-1.0.9 interface: +PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass, png_uint_32 transformations)); + */ +PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)); +#endif + +/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Grab pixels out of a row for an interlaced pass */ +PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info, + png_bytep row, int pass)); +#endif + +/* Unfilter a row */ +PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row, png_const_bytep prev_row, + int filter)); + +/* Choose the best filter to use and filter the row data */ +PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, + png_row_infop row_info)); + +/* Write out the filtered row. */ +PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, + png_bytep filtered_row)); +/* Finish a row while reading, dealing with interlacing passes, etc. */ +PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); + +/* Initialize the row buffers, etc. */ +PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); +/* Optional call to update the users info structure */ +PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); + +/* These are the functions that do the transformations */ +#ifdef PNG_READ_FILLER_SUPPORTED +PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 filler, png_uint_32 flags)); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 flags)); +#endif + +#ifdef PNG_16BIT_SUPPORTED +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info, + png_bytep row)); +#endif +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ + defined(PNG_WRITE_PACKSWAP_SUPPORTED) +PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, + png_row_infop row_info, png_bytep row)); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED +PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, + png_bytep row, png_const_color_8p sig_bits)); +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +PNG_EXTERN void png_do_quantize PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep palette_lookup, + png_const_bytep quantize_lookup)); + +# ifdef PNG_CORRECT_PALETTE_SUPPORTED +PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr, + png_colorp palette, int num_palette)); +# endif +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED +PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info, + png_bytep row, png_uint_32 bit_depth)); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, + png_bytep row, png_const_color_8p bit_depth)); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +# ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, + png_bytep row, png_const_color_16p trans_color, + png_const_color_16p background, png_const_color_16p background_1, + png_const_bytep gamma_table, png_const_bytep gamma_from_1, + png_const_bytep gamma_to_1, png_const_uint_16pp gamma_16, + png_const_uint_16pp gamma_16_from_1, png_const_uint_16pp gamma_16_to_1, + int gamma_shift)); +# else +PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, + png_bytep row, png_const_color_16p trans_color, + png_const_color_16p background)); +# endif +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep gamma_table, + png_const_uint_16pp gamma_16_table, int gamma_shift)); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info, + png_bytep row, png_const_colorp palette, png_const_bytep trans, + int num_trans)); +PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, + png_bytep row, png_const_color_16p trans_color)); +#endif + +/* The following decodes the appropriate chunks, and does error correction, + * then calls the appropriate callback for the chunk if it is valid. + */ + +/* Decode the IHDR chunk */ +PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); + +#ifdef PNG_READ_bKGD_SUPPORTED +PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED +PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED +PNG_EXTERN void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_iTXt_SUPPORTED +PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED +PNG_EXTERN void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_sRGB_SUPPORTED +PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED +PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr, + png_uint_32 length)); +#endif + +PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); + +PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, + png_const_bytep chunk_name)); + +/* Handle the transformations for reading and writing */ +PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); + +PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr, + png_uint_32 length)); +PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr, + png_bytep buffer, png_size_t buffer_length)); +PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)); +PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row)); +PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr, + png_infop info_ptr)); +PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr)); +# ifdef PNG_READ_tEXt_SUPPORTED +PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +# endif +# ifdef PNG_READ_zTXt_SUPPORTED +PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +# endif +# ifdef PNG_READ_iTXt_SUPPORTED +PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr, png_uint_32 length)); +PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr, + png_infop info_ptr)); +# endif + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +/* Added at libpng version 1.4.0 */ +#ifdef PNG_CHECK_cHRM_SUPPORTED +PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point + int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, + png_fixed_point int_blue_y)); +#endif + +#ifdef PNG_CHECK_cHRM_SUPPORTED +/* Added at libpng version 1.2.34 and 1.4.0 */ +/* Currently only used by png_check_cHRM_fixed */ +PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2, + unsigned long *hi_product, unsigned long *lo_product)); +#endif + +/* Added at libpng version 1.4.0 */ +PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type)); + +/* Free all memory used by the read (old method - NOT DLL EXPORTED) */ +PNG_EXTERN void png_read_destroy PNGARG((png_structp png_ptr, + png_infop info_ptr, png_infop end_info_ptr)); + +/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */ +PNG_EXTERN void png_write_destroy PNGARG((png_structp png_ptr)); + +#ifdef USE_FAR_KEYWORD /* memory model conversion function */ +PNG_EXTERN void *png_far_to_near PNGARG((png_structp png_ptr, png_voidp ptr, + int check)); +#endif /* USE_FAR_KEYWORD */ + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) +PNG_EXTERN PNG_FUNCTION(void, png_fixed_error, (png_structp png_ptr, + png_const_charp name),PNG_NORETURN); +#endif + +/* ASCII to FP interfaces, currently only implemented if sCAL + * support is required. + */ +#if defined(PNG_READ_sCAL_SUPPORTED) +/* MAX_DIGITS is actually the maximum number of characters in an sCAL + * width or height, derived from the precision (number of significant + * digits - a build time settable option) and assumpitions about the + * maximum ridiculous exponent. + */ +#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/) + +#ifdef PNG_FLOATING_POINT_SUPPORTED +PNG_EXTERN void png_ascii_from_fp PNGARG((png_structp png_ptr, png_charp ascii, + png_size_t size, double fp, unsigned int precision)); +#endif /* FLOATING_POINT */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr, + png_charp ascii, png_size_t size, png_fixed_point fp)); +#endif /* FIXED_POINT */ +#endif /* READ_sCAL */ + +#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) +/* An internal API to validate the format of a floating point number. + * The result is the index of the next character. If the number is + * not valid it will be the index of a character in the supposed number. + * + * The format of a number is defined in the PNG extensions specification + * and this API is strictly conformant to that spec, not anyone elses! + * + * The format as a regular expression is: + * + * [+-]?[0-9]+.?([Ee][+-]?[0-9]+)? + * + * or: + * + * [+-]?.[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)? + * + * The complexity is that either integer or fraction must be present and the + * fraction is permitted to have no digits only if the integer is present. + * + * NOTE: The dangling E problem. + * There is a PNG valid floating point number in the following: + * + * PNG floating point numb1.ers are not greedy. + * + * Working this out requires *TWO* character lookahead (because of the + * sign), the parser does not do this - it will fail at the 'r' - this + * doesn't matter for PNG sCAL chunk values, but it requires more care + * if the value were ever to be embedded in something more complex. Use + * ANSI-C strtod if you need the lookahead. + */ +/* State table for the parser. */ +#define PNG_FP_INTEGER 0 /* before or in integer */ +#define PNG_FP_FRACTION 1 /* before or in fraction */ +#define PNG_FP_EXPONENT 2 /* before or in exponent */ +#define PNG_FP_STATE 3 /* mask for the above */ +#define PNG_FP_SAW_SIGN 4 /* Saw +/- in current state */ +#define PNG_FP_SAW_DIGIT 8 /* Saw a digit in current state */ +#define PNG_FP_SAW_DOT 16 /* Saw a dot in current state */ +#define PNG_FP_SAW_E 32 /* Saw an E (or e) in current state */ +#define PNG_FP_SAW_ANY 60 /* Saw any of the above 4 */ +#define PNG_FP_WAS_VALID 64 /* Preceding substring is a valid fp number */ +#define PNG_FP_INVALID 128 /* Available for callers as a distinct value */ + +/* Result codes for the parser (boolean - true meants ok, false means + * not ok yet.) + */ +#define PNG_FP_MAYBE 0 /* The number may be valid in the future */ +#define PNG_FP_OK 1 /* The number is valid */ + +/* The actual parser. This can be called repeatedly, it updates + * the index into the string and the state variable (which must + * be initialzed to 0). It returns a result code, as above. There + * is no point calling the parser any more if it fails to advance to + * the end of the string - it is stuck on an invalid character (or + * terminated by '\0'). + * + * Note that the pointer will consume an E or even an E+ then leave + * a 'maybe' state even though a preceding integer.fraction is valid. + * The PNG_FP_WAS_VALID flag indicates that a preceding substring was + * a valid number. It's possible to recover from this by calling + * the parser again (from the start, with state 0) but with a string + * that omits the last character (i.e. set the size to the index of + * the problem character.) This has not been tested within libpng. + */ +PNG_EXTERN int png_check_fp_number PNGARG((png_const_charp string, + png_size_t size, int *statep, png_size_tp whereami)); + +/* This is the same but it checks a complete string and returns true + * only if it just contains a floating point number. + */ +PNG_EXTERN int png_check_fp_string PNGARG((png_const_charp string, + png_size_t size)); +#endif /* pCAL || sCAL */ + +#if defined(PNG_READ_GAMMA_SUPPORTED) ||\ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) +/* Added at libpng version 1.5.0 */ +/* This is a utility to provide a*times/div (rounded) and indicate + * if there is an overflow. The result is a boolean - false (0) + * for overflow, true (1) if no overflow, in which case *res + * holds the result. + */ +PNG_EXTERN int png_muldiv PNGARG((png_fixed_point_p res, png_fixed_point a, + png_int_32 times, png_int_32 div)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) +/* Same deal, but issue a warning on overflow and return 0. */ +PNG_EXTERN png_fixed_point png_muldiv_warn PNGARG((png_structp png_ptr, + png_fixed_point a, png_int_32 times, png_int_32 div)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Calculate a reciprocal - used for gamma values. This returns + * 0 if the argument is 0 in order to maintain an undefined value, + * there are no warnings. + */ +PNG_EXTERN png_fixed_point png_reciprocal PNGARG((png_fixed_point a)); + +/* The same but gives a reciprocal of the product of two fixed point + * values. Accuracy is suitable for gamma calculations but this is + * not exact - use png_muldiv for that. + */ +PNG_EXTERN png_fixed_point png_reciprocal2 PNGARG((png_fixed_point a, + png_fixed_point b)); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Internal fixed point gamma correction. These APIs are called as + * required to convert single values - they don't need to be fast, + * they are not used when processing image pixel values. + * + * While the input is an 'unsigned' value it must actually be the + * correct bit value - 0..255 or 0..65535 as required. + */ +PNG_EXTERN png_uint_16 png_gamma_correct PNGARG((png_structp png_ptr, + unsigned int value, png_fixed_point gamma)); +PNG_EXTERN int png_gamma_significant PNGARG((png_fixed_point gamma)); +PNG_EXTERN png_uint_16 png_gamma_16bit_correct PNGARG((unsigned int value, + png_fixed_point gamma)); +PNG_EXTERN png_byte png_gamma_8bit_correct PNGARG((unsigned int value, + png_fixed_point gamma)); +PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr, + int bit_depth)); +#endif + +/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ + + +#include "pngdebug.h" + +#ifdef __cplusplus +} +#endif + +#endif /* PNGPRIV_H */ diff --git a/contrib/libpng/pngread.c b/contrib/libpng/pngread.c new file mode 100644 index 0000000..2c8f2cd --- /dev/null +++ b/contrib/libpng/pngread.c @@ -0,0 +1,1466 @@ + +/* pngread.c - read a PNG file + * + * Last changed in libpng 1.5.1 [$RDATE%] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that an application calls directly to + * read a PNG file or stream. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Create a PNG structure for reading, and allocate any memory needed. */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) +{ + +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL)); +} + +/* Alternate create PNG structure for reading, and allocate any memory + * needed. + */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; + volatile int png_cleanup_needed = 0; + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf png_jmpbuf; +#endif +#endif + + int i; + + png_debug(1, "in png_create_read_struct"); + +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + malloc_fn, mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif + if (png_ptr == NULL) + return (NULL); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; + +# ifdef PNG_USER_CHUNK_CACHE_MAX + /* Added at libpng-1.2.43 and 1.4.0 */ + png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; +# endif + +# ifdef PNG_SET_USER_CHUNK_MALLOC_MAX + /* Added at libpng-1.2.43 and 1.4.1 */ + png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; +# endif +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then + encounter a png_error() will longjmp here. Since the jmpbuf is + then meaningless we abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(png_jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */ +#endif + PNG_ABORT(); +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), png_jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif /* PNG_SETJMP_SUPPORTED */ + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif + + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + if (user_png_ver) + { + i = 0; + + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } + + else + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#ifdef PNG_CONSOLE_IO_SUPPORTED + char msg[80]; + if (user_png_ver) + { + png_snprintf2(msg, 80, + "Application built with libpng-%.20s" + " but running with %.20s", + user_png_ver, + png_libpng_ver); + png_warning(png_ptr, msg); + } +#else + png_warning(png_ptr, + "Incompatible libpng version in application and library"); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + + png_cleanup_needed = 1; + } + } + + if (!png_cleanup_needed) + { + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size); + + if (png_ptr->zbuf == NULL) + png_cleanup_needed = 1; + } + + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + if (!png_cleanup_needed) + { + switch (inflateInit(&png_ptr->zstream)) + { + case Z_OK: + break; /* Do nothing */ + + case Z_MEM_ERROR: + png_warning(png_ptr, "zlib memory error"); + png_cleanup_needed = 1; + break; + + case Z_STREAM_ERROR: + png_warning(png_ptr, "zlib stream error"); + png_cleanup_needed = 1; + break; + + case Z_VERSION_ERROR: + png_warning(png_ptr, "zlib version error"); + png_cleanup_needed = 1; + break; + + default: png_warning(png_ptr, "Unknown zlib error"); + png_cleanup_needed = 1; + } + } + + if (png_cleanup_needed) + { + /* Clean up PNG structure and deallocate any memory. */ + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + + png_set_read_fn(png_ptr, NULL, NULL); + + + return (png_ptr); +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the information before the actual image data. This has been + * changed in v0.90 to allow reading a file that already has the magic + * bytes read from the stream. You can tell libpng how many bytes have + * been read from the beginning of the stream (up to the maximum of 8) + * via png_set_sig_bytes(), and we will only check the remaining bytes + * here. The application can then have access to the signature bytes we + * read if it is determined that this isn't a valid PNG file. + */ +void PNGAPI +png_read_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Read and check the PNG file signature. */ + png_read_sig(png_ptr, info_ptr); + + for (;;) + { + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_sCAL; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_sPLT; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_sRGB; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_zTXt; +#endif + png_uint_32 length = png_read_chunk_header(png_ptr); + PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; + + /* This should be a binary subdivision search or a hash for + * matching the chunk name rather than a linear search. + */ + if (!png_memcmp(chunk_name, png_IDAT, 4)) + if (png_ptr->mode & PNG_AFTER_IDAT) + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + + if (!png_memcmp(chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + + else if (!png_memcmp(chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, chunk_name)) + { + if (!png_memcmp(chunk_name, png_IDAT, 4)) + png_ptr->mode |= PNG_HAVE_IDAT; + + png_handle_unknown(png_ptr, info_ptr, length); + + if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + break; + } + } +#endif + else if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before IDAT"); + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + png_error(png_ptr, "Missing PLTE before IDAT"); + + png_ptr->idat_size = length; + png_ptr->mode |= PNG_HAVE_IDAT; + break; + } + +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + + else + png_handle_unknown(png_ptr, info_ptr, length); + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Optional call to update the users info_ptr structure */ +void PNGAPI +png_read_update_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_update_info"); + + if (png_ptr == NULL) + return; + + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + + else + png_warning(png_ptr, + "Ignoring extra png_read_update_info() call;" + " row buffer not reallocated"); + + png_read_transform_info(png_ptr, info_ptr); +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Initialize palette, background, etc, after transformations + * are set, but before any reading takes place. This allows + * the user to obtain a gamma-corrected palette, for example. + * If the user doesn't call this, we will do it ourselves. + */ +void PNGAPI +png_start_read_image(png_structp png_ptr) +{ + png_debug(1, "in png_start_read_image"); + + if (png_ptr == NULL) + return; + + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + else + png_warning(png_ptr, + "Ignoring extra png_start_read_image() call;" + " row buffer not reallocated"); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +void PNGAPI +png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) +{ + PNG_IDAT; + PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, + 0xff}; + PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; + int ret; + + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_read_row (row %lu, pass %d)", + (unsigned long)png_ptr->row_number, png_ptr->pass); + + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + png_read_start_row(png_ptr); + + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Check for transforms that have been set but were defined out */ +#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + !defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined"); +#endif + +#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined"); +#endif + } + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* If interlaced and we do not need a new row, combine row and return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + png_read_finish_row(png_ptr); + return; + } + break; + + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + if (dsp_row != NULL && (png_ptr->row_number & 4)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 3: + if ((png_ptr->row_number & 3) || png_ptr->width < 3) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + + case 4: + if ((png_ptr->row_number & 3) != 2) + { + if (dsp_row != NULL && (png_ptr->row_number & 2)) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + case 5: + if ((png_ptr->row_number & 1) || png_ptr->width < 2) + { + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, + png_pass_dsp_mask[png_ptr->pass]); + + png_read_finish_row(png_ptr); + return; + } + break; + + default: + case 6: + if (!(png_ptr->row_number & 1)) + { + png_read_finish_row(png_ptr); + return; + } + break; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "Invalid attempt to read row data"); + + png_ptr->zstream.next_out = png_ptr->row_buf; + png_ptr->zstream.avail_out = + (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth, + png_ptr->iwidth) + 1); + + do + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_crc_finish(png_ptr, 0); + + png_ptr->idat_size = png_read_chunk_header(png_ptr); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + } + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + png_crc_read(png_ptr, png_ptr->zbuf, + (png_size_t)png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + + if (ret == Z_STREAM_END) + { + if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_benign_error(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression error"); + + } while (png_ptr->zstream.avail_out); + + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->iwidth; + png_ptr->row_info.channels = png_ptr->channels; + png_ptr->row_info.bit_depth = png_ptr->bit_depth; + png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + if (png_ptr->row_buf[0]) + png_read_filter_row(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->prev_row + 1, + (int)(png_ptr->row_buf[0])); + + png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + + if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) + png_do_read_transformations(png_ptr); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Blow up interlaced rows to full size */ + if (png_ptr->interlaced && + (png_ptr->transformations & PNG_INTERLACE)) + { + if (png_ptr->pass < 6) + /* Old interface (pre-1.0.9): + * png_do_read_interlace(&(png_ptr->row_info), + * png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); + */ + png_do_read_interlace(png_ptr); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, png_pass_dsp_mask[png_ptr->pass]); + + if (row != NULL) + png_combine_row(png_ptr, row, png_pass_mask[png_ptr->pass]); + } + + else +#endif + { + if (row != NULL) + png_combine_row(png_ptr, row, 0xff); + + if (dsp_row != NULL) + png_combine_row(png_ptr, dsp_row, 0xff); + } + png_read_finish_row(png_ptr); + + if (png_ptr->read_row_fn != NULL) + (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read one or more rows of image data. If the image is interlaced, + * and png_set_interlace_handling() has been called, the rows need to + * contain the contents of the rows from the previous pass. If the + * image has alpha or transparency, and png_handle_alpha()[*] has been + * called, the rows contents must be initialized to the contents of the + * screen. + * + * "row" holds the actual image, and pixels are placed in it + * as they arrive. If the image is displayed after each pass, it will + * appear to "sparkle" in. "display_row" can be used to display a + * "chunky" progressive image, with finer detail added as it becomes + * available. If you do not want this "chunky" display, you may pass + * NULL for display_row. If you do not want the sparkle display, and + * you have not called png_handle_alpha(), you may pass NULL for rows. + * If you have called png_handle_alpha(), and the image has either an + * alpha channel or a transparency chunk, you must provide a buffer for + * rows. In this case, you do not have to provide a display_row buffer + * also, but you may. If the image is not interlaced, or if you have + * not called png_set_interlace_handling(), the display_row buffer will + * be ignored, so pass NULL to it. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ + +void PNGAPI +png_read_rows(png_structp png_ptr, png_bytepp row, + png_bytepp display_row, png_uint_32 num_rows) +{ + png_uint_32 i; + png_bytepp rp; + png_bytepp dp; + + png_debug(1, "in png_read_rows"); + + if (png_ptr == NULL) + return; + + rp = row; + dp = display_row; + if (rp != NULL && dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp++; + png_bytep dptr = *dp++; + + png_read_row(png_ptr, rptr, dptr); + } + + else if (rp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep rptr = *rp; + png_read_row(png_ptr, rptr, NULL); + rp++; + } + + else if (dp != NULL) + for (i = 0; i < num_rows; i++) + { + png_bytep dptr = *dp; + png_read_row(png_ptr, NULL, dptr); + dp++; + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the entire image. If the image has an alpha channel or a tRNS + * chunk, and you have called png_handle_alpha()[*], you will need to + * initialize the image to the current image that PNG will be overlaying. + * We set the num_rows again here, in case it was incorrectly set in + * png_read_start_row() by a call to png_read_update_info() or + * png_start_read_image() if png_set_interlace_handling() wasn't called + * prior to either of these functions like it should have been. You can + * only call this function once. If you desire to have an image for + * each pass of a interlaced image, use png_read_rows() instead. + * + * [*] png_handle_alpha() does not exist yet, as of this version of libpng + */ +void PNGAPI +png_read_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i, image_height; + int pass, j; + png_bytepp rp; + + png_debug(1, "in png_read_image"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + { + pass = png_set_interlace_handling(png_ptr); + /* And make sure transforms are initialized. */ + png_start_read_image(png_ptr); + } + else + { + if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE)) + { + /* Caller called png_start_read_image or png_read_update_info without + * first turning on the PNG_INTERLACE transform. We can fix this here, + * but the caller should do it! + */ + png_warning(png_ptr, "Interlace handling should be turned on when " + "using png_read_image"); + /* Make sure this is set correctly */ + png_ptr->num_rows = png_ptr->height; + } + + /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in + * the above error case. + */ + pass = png_set_interlace_handling(png_ptr); + } +#else + if (png_ptr->interlaced) + png_error(png_ptr, + "Cannot read interlaced image -- interlace handler disabled"); + + pass = 1; +#endif + + image_height=png_ptr->height; + + for (j = 0; j < pass; j++) + { + rp = image; + for (i = 0; i < image_height; i++) + { + png_read_row(png_ptr, *rp, NULL); + rp++; + } + } +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +/* Read the end of the PNG file. Will not read past the end of the + * file, will verify the end is accurate, and will read any comments + * or time information at the end of the file, if info is not NULL. + */ +void PNGAPI +png_read_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_end"); + + if (png_ptr == NULL) + return; + + png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ + + do + { + PNG_IHDR; + PNG_IDAT; + PNG_IEND; + PNG_PLTE; +#ifdef PNG_READ_bKGD_SUPPORTED + PNG_bKGD; +#endif +#ifdef PNG_READ_cHRM_SUPPORTED + PNG_cHRM; +#endif +#ifdef PNG_READ_gAMA_SUPPORTED + PNG_gAMA; +#endif +#ifdef PNG_READ_hIST_SUPPORTED + PNG_hIST; +#endif +#ifdef PNG_READ_iCCP_SUPPORTED + PNG_iCCP; +#endif +#ifdef PNG_READ_iTXt_SUPPORTED + PNG_iTXt; +#endif +#ifdef PNG_READ_oFFs_SUPPORTED + PNG_oFFs; +#endif +#ifdef PNG_READ_pCAL_SUPPORTED + PNG_pCAL; +#endif +#ifdef PNG_READ_pHYs_SUPPORTED + PNG_pHYs; +#endif +#ifdef PNG_READ_sBIT_SUPPORTED + PNG_sBIT; +#endif +#ifdef PNG_READ_sCAL_SUPPORTED + PNG_sCAL; +#endif +#ifdef PNG_READ_sPLT_SUPPORTED + PNG_sPLT; +#endif +#ifdef PNG_READ_sRGB_SUPPORTED + PNG_sRGB; +#endif +#ifdef PNG_READ_tEXt_SUPPORTED + PNG_tEXt; +#endif +#ifdef PNG_READ_tIME_SUPPORTED + PNG_tIME; +#endif +#ifdef PNG_READ_tRNS_SUPPORTED + PNG_tRNS; +#endif +#ifdef PNG_READ_zTXt_SUPPORTED + PNG_zTXt; +#endif + png_uint_32 length = png_read_chunk_header(png_ptr); + PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; + + if (!png_memcmp(chunk_name, png_IHDR, 4)) + png_handle_IHDR(png_ptr, info_ptr, length); + + else if (!png_memcmp(chunk_name, png_IEND, 4)) + png_handle_IEND(png_ptr, info_ptr, length); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + else if (png_handle_as_unknown(png_ptr, chunk_name)) + { + if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found"); + } + png_handle_unknown(png_ptr, info_ptr, length); + if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_ptr->mode |= PNG_HAVE_PLTE; + } +#endif + + else if (!png_memcmp(chunk_name, png_IDAT, 4)) + { + /* Zero length IDATs are legal after the last IDAT has been + * read, but not after other chunks have been read. + */ + if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) + png_benign_error(png_ptr, "Too many IDATs found"); + + png_crc_finish(png_ptr, length); + } + else if (!png_memcmp(chunk_name, png_PLTE, 4)) + png_handle_PLTE(png_ptr, info_ptr, length); + +#ifdef PNG_READ_bKGD_SUPPORTED + else if (!png_memcmp(chunk_name, png_bKGD, 4)) + png_handle_bKGD(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED + else if (!png_memcmp(chunk_name, png_cHRM, 4)) + png_handle_cHRM(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_gAMA_SUPPORTED + else if (!png_memcmp(chunk_name, png_gAMA, 4)) + png_handle_gAMA(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + else if (!png_memcmp(chunk_name, png_hIST, 4)) + png_handle_hIST(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED + else if (!png_memcmp(chunk_name, png_oFFs, 4)) + png_handle_oFFs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_pCAL, 4)) + png_handle_pCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED + else if (!png_memcmp(chunk_name, png_sCAL, 4)) + png_handle_sCAL(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED + else if (!png_memcmp(chunk_name, png_pHYs, 4)) + png_handle_pHYs(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sBIT, 4)) + png_handle_sBIT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED + else if (!png_memcmp(chunk_name, png_sRGB, 4)) + png_handle_sRGB(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iCCP_SUPPORTED + else if (!png_memcmp(chunk_name, png_iCCP, 4)) + png_handle_iCCP(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_sPLT_SUPPORTED + else if (!png_memcmp(chunk_name, png_sPLT, 4)) + png_handle_sPLT(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_tEXt, 4)) + png_handle_tEXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tIME_SUPPORTED + else if (!png_memcmp(chunk_name, png_tIME, 4)) + png_handle_tIME(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_tRNS_SUPPORTED + else if (!png_memcmp(chunk_name, png_tRNS, 4)) + png_handle_tRNS(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_zTXt, 4)) + png_handle_zTXt(png_ptr, info_ptr, length); +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED + else if (!png_memcmp(chunk_name, png_iTXt, 4)) + png_handle_iTXt(png_ptr, info_ptr, length); +#endif + + else + png_handle_unknown(png_ptr, info_ptr, length); + } while (!(png_ptr->mode & PNG_HAVE_IEND)); +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +/* Free all memory used by the read */ +void PNGAPI +png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, + png_infopp end_info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL, end_info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_read_struct"); + + if (png_ptr_ptr != NULL) + png_ptr = *png_ptr_ptr; + if (png_ptr == NULL) + return; + +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (end_info_ptr_ptr != NULL) + end_info_ptr = *end_info_ptr_ptr; + + png_read_destroy(png_ptr, info_ptr, end_info_ptr); + + if (info_ptr != NULL) + { +#ifdef PNG_TEXT_SUPPORTED + png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (end_info_ptr != NULL) + { +#ifdef PNG_READ_TEXT_SUPPORTED + png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); +#endif +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)end_info_ptr); +#endif + *end_info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + +/* Free all memory used by the read (old method) */ +void /* PRIVATE */ +png_read_destroy(png_structp png_ptr, png_infop info_ptr, + png_infop end_info_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_read_destroy"); + + if (info_ptr != NULL) + png_info_destroy(png_ptr, info_ptr); + + if (end_info_ptr != NULL) + png_info_destroy(png_ptr, end_info_ptr); + + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->big_row_buf); + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->chunkdata); + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_free(png_ptr, png_ptr->palette_lookup); + png_free(png_ptr, png_ptr->quantize_index); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + png_free(png_ptr, png_ptr->gamma_table); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + png_free(png_ptr, png_ptr->gamma_from_1); + png_free(png_ptr, png_ptr->gamma_to_1); +#endif + + if (png_ptr->free_me & PNG_FREE_PLTE) + png_zfree(png_ptr, png_ptr->palette); + png_ptr->free_me &= ~PNG_FREE_PLTE; + +#if defined(PNG_tRNS_SUPPORTED) || \ + defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->free_me & PNG_FREE_TRNS) + png_free(png_ptr, png_ptr->trans_alpha); + png_ptr->free_me &= ~PNG_FREE_TRNS; +#endif + +#ifdef PNG_READ_hIST_SUPPORTED + if (png_ptr->free_me & PNG_FREE_HIST) + png_free(png_ptr, png_ptr->hist); + png_ptr->free_me &= ~PNG_FREE_HIST; +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if (png_ptr->gamma_16_table != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_table[i]); + } + png_free(png_ptr, png_ptr->gamma_16_table); + } + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->gamma_16_from_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_from_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_from_1); + } + if (png_ptr->gamma_16_to_1 != NULL) + { + int i; + int istop = (1 << (8 - png_ptr->gamma_shift)); + for (i = 0; i < istop; i++) + { + png_free(png_ptr, png_ptr->gamma_16_to_1[i]); + } + png_free(png_ptr, png_ptr->gamma_16_to_1); + } +#endif +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_free(png_ptr, png_ptr->time_buffer); +#endif + + inflateEnd(&png_ptr->zstream); + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_free(png_ptr, png_ptr->save_buffer); +#endif + +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED +#ifdef PNG_TEXT_SUPPORTED + png_free(png_ptr, png_ptr->current_text); +#endif /* PNG_TEXT_SUPPORTED */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + + /* Save the important info out of the png_struct, in case it is + * being used again. + */ +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(tmp_jmp, png_ptr->png_jmpbuf, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->png_jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); +#endif + +} + +void PNGAPI +png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->read_row_fn = read_row_fn; +} + + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_read_png(png_structp png_ptr, png_infop info_ptr, + int transforms, + voidp params) +{ + int row; + + if (png_ptr == NULL) + return; + + /* png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). + */ + png_read_info(png_ptr, info_ptr); + if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) + png_error(png_ptr, "Image is too high to process with png_read_png()"); + + /* -------------- image transformations start here ------------------- */ + +#ifdef PNG_READ_16_TO_8_SUPPORTED + /* Tell libpng to strip 16 bit/color files down to 8 bits per color. + */ + if (transforms & PNG_TRANSFORM_STRIP_16) + png_set_strip_16(png_ptr); +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + /* Strip alpha bytes from the input data without combining with + * the background (not recommended). + */ + if (transforms & PNG_TRANSFORM_STRIP_ALPHA) + png_set_strip_alpha(png_ptr); +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) + /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). + */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + /* Expand paletted colors into true RGB triplets + * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel + * Expand paletted or RGB images with transparency to full alpha + * channels so the data will be available as RGBA quartets. + */ + if (transforms & PNG_TRANSFORM_EXPAND) + if ((png_ptr->bit_depth < 8) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || + (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) + png_set_expand(png_ptr); +#endif + + /* We don't handle background color or gamma transformation or quantizing. + */ + +#ifdef PNG_READ_INVERT_SUPPORTED + /* Invert monochrome files to have 0 as white and 1 as black + */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) + { + png_color_8p sig_bit; + + png_get_sBIT(png_ptr, info_ptr, &sig_bit); + png_set_shift(png_ptr, sig_bit); + } +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#ifdef PNG_READ_SWAP_SUPPORTED + /* Swap bytes of 16 bit files to least significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +/* Added at libpng-1.2.41 */ +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + +/* Added at libpng-1.2.41 */ +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* Expand grayscale image to RGB */ + if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) + png_set_gray_to_rgb(png_ptr); +#endif + + /* We don't handle adding filler bytes */ + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (i.e., you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* -------------- image transformations end here ------------------- */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + if (info_ptr->row_pointers == NULL) + { + png_uint_32 iptr; + + info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, + info_ptr->height * png_sizeof(png_bytep)); + for (iptr=0; iptrheight; iptr++) + info_ptr->row_pointers[iptr] = NULL; + + info_ptr->free_me |= PNG_FREE_ROWS; + + for (row = 0; row < (int)info_ptr->height; row++) + info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr)); + } + + png_read_image(png_ptr, info_ptr->row_pointers); + info_ptr->valid |= PNG_INFO_IDAT; + + /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ + png_read_end(png_ptr, info_ptr); + + PNG_UNUSED(transforms) /* Quiet compiler warnings */ + PNG_UNUSED(params) + +} +#endif /* PNG_INFO_IMAGE_SUPPORTED */ +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/contrib/libpng/pngrio.c b/contrib/libpng/pngrio.c new file mode 100644 index 0000000..e9c381c --- /dev/null +++ b/contrib/libpng/pngrio.c @@ -0,0 +1,176 @@ + +/* pngrio.c - functions for data input + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all input. Users who need + * special handling are expected to write a function that has the same + * arguments as this and performs a similar function, but that possibly + * has a different input method. Note that you shouldn't change this + * function, but rather write a replacement function and then make + * libpng use it at run time with png_set_read_fn(...). + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Read the data from whatever input you are using. The default routine + * reads from a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered reads. This should never be asked + * to read more then 64K on a 16 bit machine. + */ +void /* PRIVATE */ +png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_debug1(4, "reading %d bytes", (int)length); + + if (png_ptr->read_data_fn != NULL) + (*(png_ptr->read_data_fn))(png_ptr, data, length); + + else + png_error(png_ptr, "Call to NULL read function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ +# ifndef USE_FAR_KEYWORD +void PNGCBAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + check = fread(data, 1, length, (png_FILE_p)png_ptr->io_ptr); + + if (check != length) + png_error(png_ptr, "Read Error"); +} +# else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGCBAPI +png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + png_byte *n_data; + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + + if ((png_bytep)n_data == data) + { + check = fread(n_data, 1, length, io_ptr); + } + + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + err = fread(buf, 1, read, io_ptr); + png_memcpy(data, buf, read); /* copy far buffer to near buffer */ + + if (err != read) + break; + + else + check += err; + + data += read; + remaining -= read; + } + while (remaining != 0); + } + + if ((png_uint_32)check != (png_uint_32)length) + png_error(png_ptr, "read Error"); +} +# endif +#endif + +/* This function allows the application to supply a new input function + * for libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * + * png_ptr - pointer to a png input data structure + * + * io_ptr - pointer to user supplied structure containing info about + * the input functions. May be NULL. + * + * read_data_fn - pointer to a new input function that takes as its + * arguments a pointer to a png_struct, a pointer to + * a location where input data can be stored, and a 32-bit + * unsigned int that is the number of bytes to be read. + * To exit and output any fatal error messages the new write + * function should call png_error(png_ptr, "Error msg"). + * May be NULL, in which case libpng's default function will + * be used. + */ +void PNGAPI +png_set_read_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr read_data_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (read_data_fn != NULL) + png_ptr->read_data_fn = read_data_fn; + + else + png_ptr->read_data_fn = png_default_read_data; +#else + png_ptr->read_data_fn = read_data_fn; +#endif + + /* It is an error to write to a read device */ + if (png_ptr->write_data_fn != NULL) + { + png_ptr->write_data_fn = NULL; + png_warning(png_ptr, + "Can't set both read_data_fn and write_data_fn in the" + " same structure"); + } + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->output_flush_fn = NULL; +#endif +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/contrib/libpng/pngrtran.c b/contrib/libpng/pngrtran.c new file mode 100644 index 0000000..e6e0c46 --- /dev/null +++ b/contrib/libpng/pngrtran.c @@ -0,0 +1,4224 @@ + +/* pngrtran.c - transforms the data in a row for PNG readers + * + * Last changed in libpng 1.5.1 [February 3, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains functions optionally called by an application + * in order to tell libpng how to handle data when reading a PNG. + * Transformations that are used in both reading and writing are + * in pngtrans.c. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* Set the action on getting a CRC error for an ancillary or critical chunk. */ +void PNGAPI +png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action) +{ + png_debug(1, "in png_set_crc_action"); + + if (png_ptr == NULL) + return; + + /* Tell libpng how we react to CRC errors in critical chunks */ + switch (crit_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE | + PNG_FLAG_CRC_CRITICAL_IGNORE; + break; + + case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ + png_warning(png_ptr, + "Can't discard critical data on CRC error"); + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; + break; + } + + /* Tell libpng how we react to CRC errors in ancillary chunks */ + switch (ancil_action) + { + case PNG_CRC_NO_CHANGE: /* Leave setting as is */ + break; + + case PNG_CRC_WARN_USE: /* Warn/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE; + break; + + case PNG_CRC_QUIET_USE: /* Quiet/use data */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE | + PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_ERROR_QUIT: /* Error/quit */ + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN; + break; + + case PNG_CRC_WARN_DISCARD: /* Warn/discard data */ + + case PNG_CRC_DEFAULT: + default: + png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK; + break; + } +} + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Handle alpha and tRNS via a background color */ +void PNGFAPI +png_set_background_fixed(png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, png_fixed_point background_gamma) +{ + png_debug(1, "in png_set_background_fixed"); + + if (png_ptr == NULL) + return; + + if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) + { + png_warning(png_ptr, "Application must supply a known background gamma"); + return; + } + + png_ptr->transformations |= PNG_BACKGROUND; + png_memcpy(&(png_ptr->background), background_color, + png_sizeof(png_color_16)); + png_ptr->background_gamma = background_gamma; + png_ptr->background_gamma_type = (png_byte)(background_gamma_code); + png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_background(png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, + int need_expand, double background_gamma) +{ + png_set_background_fixed(png_ptr, background_color, background_gamma_code, + need_expand, png_fixed(png_ptr, background_gamma, "png_set_background")); +} +# endif /* FLOATING_POINT */ +#endif /* READ_BACKGROUND */ + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Strip 16 bit depth files to 8 bit depth */ +void PNGAPI +png_set_strip_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_16"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_16_TO_8; +} +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +void PNGAPI +png_set_strip_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_strip_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; +} +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* Dither file to 8 bit. Supply a palette, the current number + * of elements in the palette, the maximum number of elements + * allowed, and a histogram if possible. If the current number + * of colors is greater then the maximum number, the palette will be + * modified to fit in the maximum number. "full_quantize" indicates + * whether we need a quantizing cube set up for RGB images, or if we + * simply are reducing the number of colors in a paletted image. + */ + +typedef struct png_dsort_struct +{ + struct png_dsort_struct FAR * next; + png_byte left; + png_byte right; +} png_dsort; +typedef png_dsort FAR * png_dsortp; +typedef png_dsort FAR * FAR * png_dsortpp; + +void PNGAPI +png_set_quantize(png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_const_uint_16p histogram, + int full_quantize) +{ + png_debug(1, "in png_set_quantize"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_QUANTIZE; + + if (!full_quantize) + { + int i; + + png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + for (i = 0; i < num_palette; i++) + png_ptr->quantize_index[i] = (png_byte)i; + } + + if (num_palette > maximum_colors) + { + if (histogram != NULL) + { + /* This is easy enough, just throw out the least used colors. + * Perhaps not the best solution, but good enough. + */ + + int i; + + /* Initialize an array to sort colors */ + png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the quantize_sort array */ + for (i = 0; i < num_palette; i++) + png_ptr->quantize_sort[i] = (png_byte)i; + + /* Find the least used palette entries by starting a + * bubble sort, and running it until we have sorted + * out enough colors. Note that we don't care about + * sorting all the colors, just finding which are + * least used. + */ + + for (i = num_palette - 1; i >= maximum_colors; i--) + { + int done; /* To stop early if the list is pre-sorted */ + int j; + + done = 1; + for (j = 0; j < i; j++) + { + if (histogram[png_ptr->quantize_sort[j]] + < histogram[png_ptr->quantize_sort[j + 1]]) + { + png_byte t; + + t = png_ptr->quantize_sort[j]; + png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; + png_ptr->quantize_sort[j + 1] = t; + done = 0; + } + } + + if (done) + break; + } + + /* Swap the palette around, and set up a table, if necessary */ + if (full_quantize) + { + int j = num_palette; + + /* Put all the useful colors within the max, but don't + * move the others. + */ + for (i = 0; i < maximum_colors; i++) + { + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + { + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + + palette[i] = palette[j]; + } + } + } + else + { + int j = num_palette; + + /* Move all the used colors inside the max limit, and + * develop a translation table. + */ + for (i = 0; i < maximum_colors; i++) + { + /* Only move the colors we need to */ + if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + { + png_color tmp_color; + + do + j--; + while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + + tmp_color = palette[j]; + palette[j] = palette[i]; + palette[i] = tmp_color; + /* Indicate where the color went */ + png_ptr->quantize_index[j] = (png_byte)i; + png_ptr->quantize_index[i] = (png_byte)j; + } + } + + /* Find closest color for those colors we are not using */ + for (i = 0; i < num_palette; i++) + { + if ((int)png_ptr->quantize_index[i] >= maximum_colors) + { + int min_d, k, min_k, d_index; + + /* Find the closest color to one we threw out */ + d_index = png_ptr->quantize_index[i]; + min_d = PNG_COLOR_DIST(palette[d_index], palette[0]); + for (k = 1, min_k = 0; k < maximum_colors; k++) + { + int d; + + d = PNG_COLOR_DIST(palette[d_index], palette[k]); + + if (d < min_d) + { + min_d = d; + min_k = k; + } + } + /* Point to closest color */ + png_ptr->quantize_index[i] = (png_byte)min_k; + } + } + } + png_free(png_ptr, png_ptr->quantize_sort); + png_ptr->quantize_sort = NULL; + } + else + { + /* This is much harder to do simply (and quickly). Perhaps + * we need to go through a median cut routine, but those + * don't always behave themselves with only a few colors + * as input. So we will just find the closest two colors, + * and throw out one of them (chosen somewhat randomly). + * [We don't understand this at all, so if someone wants to + * work on improving it, be our guest - AED, GRP] + */ + int i; + int max_d; + int num_new_palette; + png_dsortp t; + png_dsortpp hash; + + t = NULL; + + /* Initialize palette index arrays */ + png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(num_palette * png_sizeof(png_byte))); + + /* Initialize the sort array */ + for (i = 0; i < num_palette; i++) + { + png_ptr->index_to_palette[i] = (png_byte)i; + png_ptr->palette_to_index[i] = (png_byte)i; + } + + hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * + png_sizeof(png_dsortp))); + + num_new_palette = num_palette; + + /* Initial wild guess at how far apart the farthest pixel + * pair we will be eliminating will be. Larger + * numbers mean more areas will be allocated, Smaller + * numbers run the risk of not saving enough data, and + * having to do this all over again. + * + * I have not done extensive checking on this number. + */ + max_d = 96; + + while (num_new_palette > maximum_colors) + { + for (i = 0; i < num_new_palette - 1; i++) + { + int j; + + for (j = i + 1; j < num_new_palette; j++) + { + int d; + + d = PNG_COLOR_DIST(palette[i], palette[j]); + + if (d <= max_d) + { + + t = (png_dsortp)png_malloc_warn(png_ptr, + (png_uint_32)(png_sizeof(png_dsort))); + + if (t == NULL) + break; + + t->next = hash[d]; + t->left = (png_byte)i; + t->right = (png_byte)j; + hash[d] = t; + } + } + if (t == NULL) + break; + } + + if (t != NULL) + for (i = 0; i <= max_d; i++) + { + if (hash[i] != NULL) + { + png_dsortp p; + + for (p = hash[i]; p; p = p->next) + { + if ((int)png_ptr->index_to_palette[p->left] + < num_new_palette && + (int)png_ptr->index_to_palette[p->right] + < num_new_palette) + { + int j, next_j; + + if (num_new_palette & 0x01) + { + j = p->left; + next_j = p->right; + } + else + { + j = p->right; + next_j = p->left; + } + + num_new_palette--; + palette[png_ptr->index_to_palette[j]] + = palette[num_new_palette]; + if (!full_quantize) + { + int k; + + for (k = 0; k < num_palette; k++) + { + if (png_ptr->quantize_index[k] == + png_ptr->index_to_palette[j]) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[next_j]; + + if ((int)png_ptr->quantize_index[k] == + num_new_palette) + png_ptr->quantize_index[k] = + png_ptr->index_to_palette[j]; + } + } + + png_ptr->index_to_palette[png_ptr->palette_to_index + [num_new_palette]] = png_ptr->index_to_palette[j]; + + png_ptr->palette_to_index[png_ptr->index_to_palette[j]] + = png_ptr->palette_to_index[num_new_palette]; + + png_ptr->index_to_palette[j] = + (png_byte)num_new_palette; + + png_ptr->palette_to_index[num_new_palette] = + (png_byte)j; + } + if (num_new_palette <= maximum_colors) + break; + } + if (num_new_palette <= maximum_colors) + break; + } + } + + for (i = 0; i < 769; i++) + { + if (hash[i] != NULL) + { + png_dsortp p = hash[i]; + while (p) + { + t = p->next; + png_free(png_ptr, p); + p = t; + } + } + hash[i] = 0; + } + max_d += 96; + } + png_free(png_ptr, hash); + png_free(png_ptr, png_ptr->palette_to_index); + png_free(png_ptr, png_ptr->index_to_palette); + png_ptr->palette_to_index = NULL; + png_ptr->index_to_palette = NULL; + } + num_palette = maximum_colors; + } + if (png_ptr->palette == NULL) + { + png_ptr->palette = palette; + } + png_ptr->num_palette = (png_uint_16)num_palette; + + if (full_quantize) + { + int i; + png_bytep distance; + int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + + PNG_QUANTIZE_BLUE_BITS; + int num_red = (1 << PNG_QUANTIZE_RED_BITS); + int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); + int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); + png_size_t num_entries = ((png_size_t)1 << total_bits); + + png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, + (png_uint_32)(num_entries * png_sizeof(png_byte))); + + distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * + png_sizeof(png_byte))); + + png_memset(distance, 0xff, num_entries * png_sizeof(png_byte)); + + for (i = 0; i < num_palette; i++) + { + int ir, ig, ib; + int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS)); + int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS)); + int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS)); + + for (ir = 0; ir < num_red; ir++) + { + /* int dr = abs(ir - r); */ + int dr = ((ir > r) ? ir - r : r - ir); + int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS + + PNG_QUANTIZE_GREEN_BITS)); + + for (ig = 0; ig < num_green; ig++) + { + /* int dg = abs(ig - g); */ + int dg = ((ig > g) ? ig - g : g - ig); + int dt = dr + dg; + int dm = ((dr > dg) ? dr : dg); + int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS); + + for (ib = 0; ib < num_blue; ib++) + { + int d_index = index_g | ib; + /* int db = abs(ib - b); */ + int db = ((ib > b) ? ib - b : b - ib); + int dmax = ((dm > db) ? dm : db); + int d = dmax + dt + db; + + if (d < (int)distance[d_index]) + { + distance[d_index] = (png_byte)d; + png_ptr->palette_lookup[d_index] = (png_byte)i; + } + } + } + } + } + + png_free(png_ptr, distance); + } +} +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Transform the image from the file_gamma to the screen_gamma. We + * only do transformations on images where the file_gamma and screen_gamma + * are not close reciprocals, otherwise it slows things down slightly, and + * also needlessly introduces small errors. + * + * We will turn off gamma transformation later if no semitransparent entries + * are present in the tRNS array for palette images. We can't do it here + * because we don't necessarily have the tRNS chunk yet. + */ +static int /* PRIVATE */ +png_gamma_threshold(png_fixed_point scrn_gamma, png_fixed_point file_gamma) +{ + /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma + * correction as a difference of the overall transform from 1.0 + * + * We want to compare the threshold with s*f - 1, if we get + * overflow here it is because of wacky gamma values so we + * turn on processing anyway. + */ + png_fixed_point gtest; + return !png_muldiv(>est, scrn_gamma, file_gamma, PNG_FP_1) || + png_gamma_significant(gtest); +} + +void PNGFAPI +png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma, + png_fixed_point file_gamma) +{ + png_debug(1, "in png_set_gamma_fixed"); + + if (png_ptr == NULL) + return; + + if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || + png_gamma_threshold(scrn_gamma, file_gamma)) + png_ptr->transformations |= PNG_GAMMA; + png_ptr->gamma = file_gamma; + png_ptr->screen_gamma = scrn_gamma; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) +{ + png_set_gamma_fixed(png_ptr, + png_fixed(png_ptr, scrn_gamma, "png_set_gamma screen gamma"), + png_fixed(png_ptr, file_gamma, "png_set_gamma file gamma")); +} +# endif /* FLOATING_POINT_SUPPORTED */ +#endif /* READ_GAMMA */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expand paletted images to RGB, expand grayscale images of + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks + * to alpha channels. + */ +void PNGAPI +png_set_expand(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +/* GRR 19990627: the following three functions currently are identical + * to png_set_expand(). However, it is entirely reasonable that someone + * might wish to expand an indexed image to RGB but *not* expand a single, + * fully transparent palette entry to a full alpha channel--perhaps instead + * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace + * the transparent color with a particular RGB value, or drop tRNS entirely. + * IOW, a future version of the library may make the transformations flag + * a bit more fine-grained, with separate bits for each of these three + * functions. + * + * More to the point, these functions make it obvious what libpng will be + * doing, whereas "expand" can (and does) mean any number of things. + * + * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified + * to expand only the sample depth but not to expand the tRNS to alpha + * and its name was changed to png_set_expand_gray_1_2_4_to_8(). + */ + +/* Expand paletted images to RGB. */ +void PNGAPI +png_set_palette_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_palette_to_rgb"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + +/* Expand grayscale images of less than 8-bit depth to 8 bits. */ +void PNGAPI +png_set_expand_gray_1_2_4_to_8(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_EXPAND; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} + + + +/* Expand tRNS chunks to alpha channels. */ +void PNGAPI +png_set_tRNS_to_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_tRNS_to_alpha"); + + png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; +} +#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +void PNGAPI +png_set_gray_to_rgb(png_structp png_ptr) +{ + png_debug(1, "in png_set_gray_to_rgb"); + + if (png_ptr != NULL) + { + /* Because rgb must be 8 bits or more: */ + png_set_expand_gray_1_2_4_to_8(png_ptr); + png_ptr->transformations |= PNG_GRAY_TO_RGB; + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; + } +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +void PNGFAPI +png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, + png_fixed_point red, png_fixed_point green) +{ + png_debug(1, "in png_set_rgb_to_gray"); + + if (png_ptr == NULL) + return; + + switch(error_action) + { + case 1: + png_ptr->transformations |= PNG_RGB_TO_GRAY; + break; + + case 2: + png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; + break; + + case 3: + png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; + break; + + default: + png_error(png_ptr, "invalid error action to rgb_to_gray"); + break; + } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#ifdef PNG_READ_EXPAND_SUPPORTED + png_ptr->transformations |= PNG_EXPAND; +#else + { + png_warning(png_ptr, + "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED"); + + png_ptr->transformations &= ~PNG_RGB_TO_GRAY; + } +#endif + { + png_uint_16 red_int, green_int; + if (red < 0 || green < 0) + { + red_int = 6968; /* .212671 * 32768 + .5 */ + green_int = 23434; /* .715160 * 32768 + .5 */ + } + + else if (red + green < 100000L) + { + red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); + green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); + } + + else + { + png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); + red_int = 6968; + green_int = 23434; + } + + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; + png_ptr->rgb_to_gray_blue_coeff = + (png_uint_16)(32768 - red_int - green_int); + } +} + +#ifdef PNG_FLOATING_POINT_SUPPORTED +/* Convert a RGB image to a grayscale of the same width. This allows us, + * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. + */ + +void PNGAPI +png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red, + double green) +{ + if (png_ptr == NULL) + return; + + png_set_rgb_to_gray_fixed(png_ptr, error_action, + png_fixed(png_ptr, red, "rgb to gray red coefficient"), + png_fixed(png_ptr, green, "rgb to gray green coefficient")); +} +#endif /* FLOATING POINT */ + +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +void PNGAPI +png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + read_user_transform_fn) +{ + png_debug(1, "in png_set_read_user_transform_fn"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->read_user_transform_fn = read_user_transform_fn; +#endif +} +#endif + +/* Initialize everything needed for the read. This includes modifying + * the palette. + */ +void /* PRIVATE */ +png_init_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_init_read_transformations"); + + { +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_SHIFT_SUPPORTED) || \ + defined(PNG_READ_GAMMA_SUPPORTED) + int color_type = png_ptr->color_type; +#endif + +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* Detect gray background and attempt to enable optimization + * for gray --> RGB case + * + * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or + * RGB_ALPHA (in which case need_expand is superfluous anyway), the + * background color might actually be gray yet not be flagged as such. + * This is not a problem for the current code, which uses + * PNG_BACKGROUND_IS_GRAY only to decide when to do the + * png_do_gray_to_rgb() transformation. + */ + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + !(color_type & PNG_COLOR_MASK_COLOR)) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + } + + else if ((png_ptr->transformations & PNG_BACKGROUND) && + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_GRAY_TO_RGB) && + png_ptr->background.red == png_ptr->background.green && + png_ptr->background.red == png_ptr->background.blue) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + png_ptr->background.gray = png_ptr->background.red; + } +#endif + + if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + (png_ptr->transformations & PNG_EXPAND)) + { + if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ + { + /* Expand background and tRNS chunks */ + switch (png_ptr->bit_depth) + { + case 1: + png_ptr->background.gray *= (png_uint_16)0xff; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.gray *= (png_uint_16)0xff; + png_ptr->trans_color.red = png_ptr->trans_color.green + = png_ptr->trans_color.blue = png_ptr->trans_color.gray; + } + break; + + case 2: + png_ptr->background.gray *= (png_uint_16)0x55; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.gray *= (png_uint_16)0x55; + png_ptr->trans_color.red = png_ptr->trans_color.green + = png_ptr->trans_color.blue = png_ptr->trans_color.gray; + } + break; + + case 4: + png_ptr->background.gray *= (png_uint_16)0x11; + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + png_ptr->trans_color.gray *= (png_uint_16)0x11; + png_ptr->trans_color.red = png_ptr->trans_color.green + = png_ptr->trans_color.blue = png_ptr->trans_color.gray; + } + break; + + default: + + case 8: + + case 16: + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + break; + } + } + else if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.red = + png_ptr->palette[png_ptr->background.index].red; + png_ptr->background.green = + png_ptr->palette[png_ptr->background.index].green; + png_ptr->background.blue = + png_ptr->palette[png_ptr->background.index].blue; + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + { +#ifdef PNG_READ_EXPAND_SUPPORTED + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) +#endif + { + /* Invert the alpha channel (in tRNS) unless the pixels are + * going to be expanded, in which case leave it for later + */ + int i, istop; + istop=(int)png_ptr->num_trans; + for (i=0; itrans_alpha[i] = (png_byte)(255 - + png_ptr->trans_alpha[i]); + } + } +#endif + + } + } +#endif + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + png_ptr->background_1 = png_ptr->background; +#endif +#ifdef PNG_READ_GAMMA_SUPPORTED + + if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) + && png_gamma_threshold(png_ptr->screen_gamma, png_ptr->gamma)) + { + int i, k; + k=0; + for (i=0; inum_trans; i++) + { + if (png_ptr->trans_alpha[i] != 0 && png_ptr->trans_alpha[i] != 0xff) + k=1; /* Partial transparency is present */ + } + if (k == 0) + png_ptr->transformations &= ~PNG_GAMMA; + } + + if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && + png_ptr->gamma != 0) + { + png_build_gamma_table(png_ptr, png_ptr->bit_depth); + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->transformations & PNG_BACKGROUND) + { + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + /* Could skip if no transparency */ + png_color back, back_1; + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) + { + + back.red = png_ptr->gamma_table[png_ptr->background.red]; + back.green = png_ptr->gamma_table[png_ptr->background.green]; + back.blue = png_ptr->gamma_table[png_ptr->background.blue]; + + back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; + back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; + back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; + } + else + { + png_fixed_point g, gs; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = (png_ptr->screen_gamma); + gs = PNG_FP_1; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = png_reciprocal(png_ptr->gamma); + gs = png_reciprocal2(png_ptr->gamma, + png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = png_reciprocal(png_ptr->background_gamma); + gs = png_reciprocal2(png_ptr->background_gamma, + png_ptr->screen_gamma); + break; + default: + g = PNG_FP_1; /* back_1 */ + gs = PNG_FP_1; /* back */ + break; + } + + if (png_gamma_significant(gs)) + { + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + } + + else + { + back.red = png_gamma_8bit_correct(png_ptr->background.red, + gs); + back.green = png_gamma_8bit_correct(png_ptr->background.green, + gs); + back.blue = png_gamma_8bit_correct(png_ptr->background.blue, + gs); + } + back_1.red = png_gamma_8bit_correct(png_ptr->background.red, g); + back_1.green = png_gamma_8bit_correct(png_ptr->background.green, + g); + back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, + g); + } + for (i = 0; i < num_palette; i++) + { + if (i < (int)png_ptr->num_trans && + png_ptr->trans_alpha[i] != 0xff) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + else /* if (png_ptr->trans_alpha[i] != 0xff) */ + { + png_byte v, w; + + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; + + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } + } + else + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + } + /* Prevent the transformations being done again, and make sure + * that the now spurious alpha channel is stripped - the code + * has just reduced background composition and gamma correction + * to a simple alpha channel strip. + */ + png_ptr->transformations &= ~PNG_BACKGROUND; + png_ptr->transformations &= ~PNG_GAMMA; + png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; + } + + /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ + else + /* color_type != PNG_COLOR_TYPE_PALETTE */ + { + png_fixed_point g = PNG_FP_1; + png_fixed_point gs = PNG_FP_1; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + g = png_ptr->screen_gamma; + /* gs = PNG_FP_1; */ + break; + + case PNG_BACKGROUND_GAMMA_FILE: + g = png_reciprocal(png_ptr->gamma); + gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + g = png_reciprocal(png_ptr->background_gamma); + gs = png_reciprocal2(png_ptr->background_gamma, + png_ptr->screen_gamma); + break; + + default: + png_error(png_ptr, "invalid background gamma type"); + } + + png_ptr->background_1.gray = png_gamma_correct(png_ptr, + png_ptr->background.gray, g); + + png_ptr->background.gray = png_gamma_correct(png_ptr, + png_ptr->background.gray, gs); + + if ((png_ptr->background.red != png_ptr->background.green) || + (png_ptr->background.red != png_ptr->background.blue) || + (png_ptr->background.red != png_ptr->background.gray)) + { + /* RGB or RGBA with color background */ + png_ptr->background_1.red = png_gamma_correct(png_ptr, + png_ptr->background.red, g); + + png_ptr->background_1.green = png_gamma_correct(png_ptr, + png_ptr->background.green, g); + + png_ptr->background_1.blue = png_gamma_correct(png_ptr, + png_ptr->background.blue, g); + + png_ptr->background.red = png_gamma_correct(png_ptr, + png_ptr->background.red, gs); + + png_ptr->background.green = png_gamma_correct(png_ptr, + png_ptr->background.green, gs); + + png_ptr->background.blue = png_gamma_correct(png_ptr, + png_ptr->background.blue, gs); + } + + else + { + /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ + png_ptr->background_1.red = png_ptr->background_1.green + = png_ptr->background_1.blue = png_ptr->background_1.gray; + + png_ptr->background.red = png_ptr->background.green + = png_ptr->background.blue = png_ptr->background.gray; + } + } + } + else + /* Transformation does not include PNG_BACKGROUND */ +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + png_colorp palette = png_ptr->palette; + int num_palette = png_ptr->num_palette; + int i; + + for (i = 0; i < num_palette; i++) + { + palette[i].red = png_ptr->gamma_table[palette[i].red]; + palette[i].green = png_ptr->gamma_table[palette[i].green]; + palette[i].blue = png_ptr->gamma_table[palette[i].blue]; + } + + /* Done the gamma correction. */ + png_ptr->transformations &= ~PNG_GAMMA; + } + } +#ifdef PNG_READ_BACKGROUND_SUPPORTED + else +#endif +#endif /* PNG_READ_GAMMA_SUPPORTED */ +#ifdef PNG_READ_BACKGROUND_SUPPORTED + /* No GAMMA transformation */ + if ((png_ptr->transformations & PNG_BACKGROUND) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + int i; + int istop = (int)png_ptr->num_trans; + png_color back; + png_colorp palette = png_ptr->palette; + + back.red = (png_byte)png_ptr->background.red; + back.green = (png_byte)png_ptr->background.green; + back.blue = (png_byte)png_ptr->background.blue; + + for (i = 0; i < istop; i++) + { + if (png_ptr->trans_alpha[i] == 0) + { + palette[i] = back; + } + + else if (png_ptr->trans_alpha[i] != 0xff) + { + /* The png_composite() macro is defined in png.h */ + png_composite(palette[i].red, palette[i].red, + png_ptr->trans_alpha[i], back.red); + + png_composite(palette[i].green, palette[i].green, + png_ptr->trans_alpha[i], back.green); + + png_composite(palette[i].blue, palette[i].blue, + png_ptr->trans_alpha[i], back.blue); + } + } + + /* Handled alpha, still need to strip the channel. */ + png_ptr->transformations &= ~PNG_BACKGROUND; + png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + +#ifdef PNG_READ_SHIFT_SUPPORTED + if ((png_ptr->transformations & PNG_SHIFT) && + (color_type == PNG_COLOR_TYPE_PALETTE)) + { + png_uint_16 i; + png_uint_16 istop = png_ptr->num_palette; + int sr = 8 - png_ptr->sig_bit.red; + int sg = 8 - png_ptr->sig_bit.green; + int sb = 8 - png_ptr->sig_bit.blue; + + if (sr < 0 || sr > 8) + sr = 0; + + if (sg < 0 || sg > 8) + sg = 0; + + if (sb < 0 || sb > 8) + sb = 0; + + for (i = 0; i < istop; i++) + { + png_ptr->palette[i].red >>= sr; + png_ptr->palette[i].green >>= sg; + png_ptr->palette[i].blue >>= sb; + } + } +#endif /* PNG_READ_SHIFT_SUPPORTED */ + } +#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ + && !defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr) + return; +#endif +} + +/* Modify the info structure to reflect the transformations. The + * info should be updated so a PNG file could be written with it, + * assuming the transformations result in valid PNG data. + */ +void /* PRIVATE */ +png_read_transform_info(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_read_transform_info"); + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + + else + info_ptr->color_type = PNG_COLOR_TYPE_RGB; + + info_ptr->bit_depth = 8; + info_ptr->num_trans = 0; + } + else + { + if (png_ptr->num_trans) + { + if (png_ptr->transformations & PNG_EXPAND_tRNS) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } + if (info_ptr->bit_depth < 8) + info_ptr->bit_depth = 8; + + info_ptr->num_trans = 0; + } + } +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (png_ptr->transformations & PNG_BACKGROUND) + { + info_ptr->color_type = (png_byte)(info_ptr->color_type & + ~PNG_COLOR_MASK_ALPHA); + info_ptr->num_trans = 0; + info_ptr->background = png_ptr->background; + } +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if (png_ptr->transformations & PNG_GAMMA) + { + info_ptr->gamma = png_ptr->gamma; + } +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +#ifdef PNG_READ_16BIT_SUPPORTED + if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) + info_ptr->bit_depth = 8; +#else + /* Force chopping 16-bit input down to 8 */ + if (info_ptr->bit_depth == 16) + { + png_ptr->transformations |=PNG_16_TO_8; + info_ptr->bit_depth = 8; + } +#endif +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + info_ptr->color_type |= PNG_COLOR_MASK_COLOR; +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR; +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) && + png_ptr->palette_lookup && info_ptr->bit_depth == 8) + { + info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; + } + } +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) + info_ptr->bit_depth = 8; +#endif + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + + else + info_ptr->channels = 1; + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) + info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; +#endif + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + +#ifdef PNG_READ_FILLER_SUPPORTED + /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */ + if ((png_ptr->transformations & PNG_FILLER) && + ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) || + (info_ptr->color_type == PNG_COLOR_TYPE_GRAY))) + { + info_ptr->channels++; + /* If adding a true alpha channel not just filler */ + if (png_ptr->transformations & PNG_ADD_ALPHA) + info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; + } +#endif + +#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \ +defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (info_ptr->bit_depth < png_ptr->user_transform_depth) + info_ptr->bit_depth = png_ptr->user_transform_depth; + + if (info_ptr->channels < png_ptr->user_transform_channels) + info_ptr->channels = png_ptr->user_transform_channels; + } +#endif + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * + info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); + +#ifndef PNG_READ_EXPAND_SUPPORTED + if (png_ptr) + return; +#endif +} + +/* Transform the row. The order of transformations is significant, + * and is very touchy. If you add a transformation, take care to + * decide how it fits in with the other transformations here. + */ +void /* PRIVATE */ +png_do_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_read_transformations"); + + if (png_ptr->row_buf == NULL) + { +#ifdef PNG_CONSOLE_IO_SUPPORTED + char msg[50]; + + png_snprintf2(msg, 50, + "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number, + png_ptr->pass); + png_error(png_ptr, msg); +#else + png_error(png_ptr, "NULL row buffer"); +#endif + } +#ifdef PNG_WARN_UNINITIALIZED_ROW + if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) + /* Application has failed to call either png_read_start_image() + * or png_read_update_info() after setting transforms that expand + * pixels. This check added to libpng-1.2.19 + */ +#if (PNG_WARN_UNINITIALIZED_ROW==1) + png_error(png_ptr, "Uninitialized row"); +#else + png_warning(png_ptr, "Uninitialized row"); +#endif +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE) + { + png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); + } + else + { + if (png_ptr->num_trans && + (png_ptr->transformations & PNG_EXPAND_tRNS)) + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_color)); + else + + png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, + NULL); + } + } +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + { + int rgb_error = + png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), + png_ptr->row_buf + 1); + + if (rgb_error) + { + png_ptr->rgb_to_gray_status=1; + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_WARN) + png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == + PNG_RGB_TO_GRAY_ERR) + png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel"); + } + } +#endif + +/* From Andreas Dilger e-mail to png-implement, 26 March 1998: + * + * In most cases, the "simple transparency" should be done prior to doing + * gray-to-RGB, or you will have to test 3x as many bytes to check if a + * pixel is transparent. You would also need to make sure that the + * transparency information is upgraded to RGB. + * + * To summarize, the current flow is: + * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite + * with background "in place" if transparent, + * convert to RGB if necessary + * - Gray + alpha -> composite with gray background and remove alpha bytes, + * convert to RGB if necessary + * + * To support RGB backgrounds for gray images we need: + * - Gray + simple transparency -> convert to RGB + simple transparency, + * compare 3 or 6 bytes and composite with + * background "in place" if transparent + * (3x compare/pixel compared to doing + * composite with gray bkgrnd) + * - Gray + alpha -> convert to RGB + alpha, composite with background and + * remove alpha bytes (3x float + * operations/pixel compared with composite + * on gray background) + * + * Greg's change will do this. The reason it wasn't done before is for + * performance, as this increases the per-pixel operations. If we would check + * in advance if the background was gray or RGB, and position the gray-to-RGB + * transform appropriately, then it would save a lot of work/time. + */ + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* If gray -> RGB, do so now only if background is non-gray; else do later + * for performance reasons + */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if ((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) + png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->trans_color), &(png_ptr->background) +#ifdef PNG_READ_GAMMA_SUPPORTED + , &(png_ptr->background_1), + png_ptr->gamma_table, png_ptr->gamma_from_1, + png_ptr->gamma_to_1, png_ptr->gamma_16_table, + png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, + png_ptr->gamma_shift +#endif + ); +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED + if ((png_ptr->transformations & PNG_GAMMA) && +#ifdef PNG_READ_BACKGROUND_SUPPORTED + !((png_ptr->transformations & PNG_BACKGROUND) && + ((png_ptr->num_trans != 0) || + (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && +#endif + (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) + png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->gamma_table, png_ptr->gamma_16_table, + png_ptr->gamma_shift); +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_16_TO_8) + png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + if (png_ptr->transformations & PNG_QUANTIZE) + { + png_do_quantize(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->palette_lookup, png_ptr->quantize_index); + + if (png_ptr->row_info.rowbytes == 0) + png_error(png_ptr, "png_do_quantize returned rowbytes=0"); + } +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +#ifdef PNG_READ_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#ifdef PNG_READ_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /* If gray -> RGB, do so now only if we did not do so above */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->filler, png_ptr->flags); +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_16BIT_SUPPORTED +#ifdef PNG_READ_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +#endif + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + if (png_ptr->read_user_transform_fn != NULL) + (*(png_ptr->read_user_transform_fn)) /* User read transform function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + if (png_ptr->user_transform_depth) + png_ptr->row_info.bit_depth = png_ptr->user_transform_depth; + + if (png_ptr->user_transform_channels) + png_ptr->row_info.channels = png_ptr->user_transform_channels; +#endif + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + } +#endif + +} + +#ifdef PNG_READ_PACK_SUPPORTED +/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel, + * without changing the actual values. Thus, if you had a row with + * a bit depth of 1, you would end up with bytes that only contained + * the numbers 0 or 1. If you would rather they contain 0 and 255, use + * png_do_shift() after this. + */ +void /* PRIVATE */ +png_do_unpack(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_unpack"); + + if (row_info->bit_depth < 8) + { + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + switch (row_info->bit_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x01); + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + + png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x03); + + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); + png_bytep dp = row + (png_size_t)row_width - 1; + png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + *dp = (png_byte)((*sp >> shift) & 0x0f); + + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift = 4; + + dp--; + } + break; + } + + default: + break; + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SHIFT_SUPPORTED +/* Reverse the effects of png_do_shift. This routine merely shifts the + * pixels back to their significant bits values. Thus, if you have + * a row of bit depth 8, but only 5 are significant, this will shift + * the values back to 0 through 31. + */ +void /* PRIVATE */ +png_do_unshift(png_row_infop row_info, png_bytep row, + png_const_color_8p sig_bits) +{ + png_debug(1, "in png_do_unshift"); + + if ( + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift[4]; + int channels = 0; + int c; + png_uint_16 value = 0; + png_uint_32 row_width = row_info->width; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift[channels++] = row_info->bit_depth - sig_bits->red; + shift[channels++] = row_info->bit_depth - sig_bits->green; + shift[channels++] = row_info->bit_depth - sig_bits->blue; + } + + else + { + shift[channels++] = row_info->bit_depth - sig_bits->gray; + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift[channels++] = row_info->bit_depth - sig_bits->alpha; + } + + for (c = 0; c < channels; c++) + { + if (shift[c] <= 0) + shift[c] = 0; + + else + value = 1; + } + + if (!value) + return; + + switch (row_info->bit_depth) + { + default: + break; + + case 2: + { + png_bytep bp; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (bp = row, i = 0; i < istop; i++) + { + *bp >>= 1; + *bp++ &= 0x55; + } + break; + } + + case 4: + { + png_bytep bp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) | + (png_byte)((int)0xf >> shift[0])); + + for (i = 0; i < istop; i++) + { + *bp >>= shift[0]; + *bp++ &= mask; + } + break; + } + + case 8: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = row_width * channels; + + for (i = 0; i < istop; i++) + { + *bp++ >>= shift[i%channels]; + } + break; + } + +#ifdef PNG_READ_16BIT_SUPPORTED + case 16: + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_width; + + for (i = 0; i < istop; i++) + { + value = (png_uint_16)((*bp << 8) + *(bp + 1)); + value >>= shift[i%channels]; + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + break; + } +#endif + } + } +} +#endif + +#ifdef PNG_READ_16_TO_8_SUPPORTED +/* Chop rows of bit depth 16 down to 8 */ +void /* PRIVATE */ +png_do_chop(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_chop"); + + if (row_info->bit_depth == 16) + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 i; + png_uint_32 istop = row_info->width * row_info->channels; + + for (i = 0; i> 8)) >> 8; + * + * Approximate calculation with shift/add instead of multiply/divide: + * *dp = ((((png_uint_32)(*sp) << 8) | + * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; + * + * What we actually do to avoid extra shifting and conversion: + */ + + *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); +#else + /* Simply discard the low order byte */ + *dp = *sp; +#endif + } + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} +#endif + +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_swap_alpha"); + + { + png_uint_32 row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } +#endif + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This converts from GGAA to AAGG */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_byte save[2]; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; + } + } +#endif + } + } +} +#endif + +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_uint_32 row_width; + png_debug(1, "in png_do_read_invert_alpha"); + + row_width = row_info->width; + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in RGBA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=3; + dp=sp; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + /* This inverts the alpha channel in RRGGBBAA */ + else + { + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); + +/* This does nothing: + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + We can replace it with: +*/ + sp-=6; + dp=sp; + } + } +#endif + } + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in GA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = *(--sp); + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in GGAA */ + png_bytep sp = row + row_info->rowbytes; + png_bytep dp = sp; + png_uint_32 i; + + for (i = 0; i < row_width; i++) + { + *(--dp) = (png_byte)(255 - *(--sp)); + *(--dp) = (png_byte)(255 - *(--sp)); +/* + *(--dp) = *(--sp); + *(--dp) = *(--sp); +*/ + sp-=2; + dp=sp; + } + } +#endif + } +} +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED +/* Add filler channel if we have RGB color */ +void /* PRIVATE */ +png_do_read_filler(png_row_infop row_info, png_bytep row, + png_uint_32 filler, png_uint_32 flags) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + +#ifdef PNG_READ_16BIT_SUPPORTED + png_byte hi_filler = (png_byte)((filler>>8) & 0xff); +#endif + png_byte lo_filler = (png_byte)(filler & 0xff); + + png_debug(1, "in png_do_read_filler"); + + if ( + row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from G to GX */ + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + + else + { + /* This changes the data from G to XG */ + png_bytep sp = row + (png_size_t)row_width; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from GG to GGXX */ + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + + else + { + /* This changes the data from GG to XXGG */ + png_bytep sp = row + (png_size_t)row_width * 2; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + row_info->channels = 2; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } +#endif + } /* COLOR_TYPE == GRAY */ + else if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from RGB to RGBX */ + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 1; i < row_width; i++) + { + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + + else + { + /* This changes the data from RGB to XRGB */ + png_bytep sp = row + (png_size_t)row_width * 3; + png_bytep dp = sp + (png_size_t)row_width; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = lo_filler; + } + row_info->channels = 4; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + } + } + +#ifdef PNG_READ_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This changes the data from RRGGBB to RRGGBBXX */ + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 1; i < row_width; i++) + { + *(--dp) = hi_filler; + *(--dp) = lo_filler; + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + } + *(--dp) = hi_filler; + *(--dp) = lo_filler; + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + + else + { + /* This changes the data from RRGGBB to XXRRGGBB */ + png_bytep sp = row + (png_size_t)row_width * 6; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = hi_filler; + *(--dp) = lo_filler; + } + + row_info->channels = 4; + row_info->pixel_depth = 64; + row_info->rowbytes = row_width * 8; + } + } +#endif + } /* COLOR_TYPE == RGB */ +} +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* Expand grayscale files to RGB, with or without alpha */ +void /* PRIVATE */ +png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) +{ + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_gray_to_rgb"); + + if (row_info->bit_depth >= 8 && + !(row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + if (row_info->bit_depth == 8) + { + /* This changes G to RGB */ + png_bytep sp = row + (png_size_t)row_width - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + + else + { + /* This changes GG to RRGGBB */ + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This changes GA to RGBA */ + png_bytep sp = row + (png_size_t)row_width * 2 - 1; + png_bytep dp = sp + (png_size_t)row_width * 2; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *sp; + *(dp--) = *(sp--); + } + } + + else + { + /* This changes GGAA to RRGGBBAA */ + png_bytep sp = row + (png_size_t)row_width * 4 - 1; + png_bytep dp = sp + (png_size_t)row_width * 4; + for (i = 0; i < row_width; i++) + { + *(dp--) = *(sp--); + *(dp--) = *(sp--); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *sp; + *(dp--) = *(sp - 1); + *(dp--) = *(sp--); + *(dp--) = *(sp--); + } + } + } + row_info->channels += (png_byte)2; + row_info->color_type |= PNG_COLOR_MASK_COLOR; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } +} +#endif + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Reduce RGB files to grayscale, with or without alpha + * using the equation given in Poynton's ColorFAQ at + * (THIS LINK IS DEAD June 2008) + * New link: + * + * Charles Poynton poynton at poynton.com + * + * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B + * + * We approximate this with + * + * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B + * + * which can be expressed with integers as + * + * Y = (6969 * R + 23434 * G + 2365 * B)/32768 + * + * The calculation is to be done in a linear colorspace. + * + * Other integer coefficents can be used via png_set_rgb_to_gray(). + */ +int /* PRIVATE */ +png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) + +{ + png_uint_32 i; + + png_uint_32 row_width = row_info->width; + int rgb_error = 0; + + png_debug(1, "in png_do_rgb_to_gray"); + + if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) && + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = png_ptr->gamma_from_1[ + (rc*red + gc*green + bc*blue)>>15]; + } + + else + *(dp++) = *(sp - 1); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + + if (red != green || red != blue) + { + rgb_error |= 1; + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + } + + else + *(dp++) = *(sp - 1); + } + } + } + + else /* RGB bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red == green && red == blue) + w = red; + + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) + >> png_ptr->gamma_shift][red>>8]; + png_uint_16 green_1 = + png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) + >> png_ptr->gamma_shift][blue>>8]; + png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + + bc*blue_1)>>15); + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red != green || red != blue) + rgb_error |= 1; + + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + } + } + } + } + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = png_ptr->gamma_to_1[*(sp++)]; + png_byte green = png_ptr->gamma_to_1[*(sp++)]; + png_byte blue = png_ptr->gamma_to_1[*(sp++)]; + + if (red != green || red != blue) + rgb_error |= 1; + + *(dp++) = png_ptr->gamma_from_1 + [(rc*red + gc*green + bc*blue)>>15]; + + *(dp++) = *(sp++); /* alpha */ + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_byte red = *(sp++); + png_byte green = *(sp++); + png_byte blue = *(sp++); + if (red != green || red != blue) + rgb_error |= 1; + + *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = *(sp++); /* alpha */ + } + } + } + else /* RGBA bit_depth == 16 */ + { +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + if (png_ptr->gamma_16_to_1 != NULL && + png_ptr->gamma_16_from_1 != NULL) + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, w; + + red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2; + + if (red == green && red == blue) + w = red; + + else + { + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >> + png_ptr->gamma_shift][red>>8]; + + png_uint_16 green_1 = + png_ptr->gamma_16_to_1[(green&0xff) >> + png_ptr->gamma_shift][green>>8]; + + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >> + png_ptr->gamma_shift][blue>>8]; + + png_uint_16 gray16 = (png_uint_16)((rc * red_1 + + gc * green_1 + bc * blue_1)>>15); + + w = png_ptr->gamma_16_from_1[(gray16&0xff) >> + png_ptr->gamma_shift][gray16 >> 8]; + + rgb_error |= 1; + } + + *(dp++) = (png_byte)((w>>8) & 0xff); + *(dp++) = (png_byte)(w & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + else +#endif + { + png_bytep sp = row; + png_bytep dp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 red, green, blue, gray16; + red = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2; + green = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2; + blue = (png_uint_16)((*(sp)<<8) | *(sp + 1)); sp += 2; + + if (red != green || red != blue) + rgb_error |= 1; + + gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((gray16>>8) & 0xff); + *(dp++) = (png_byte)(gray16 & 0xff); + *(dp++) = *(sp++); /* alpha */ + *(dp++) = *(sp++); + } + } + } + } + row_info->channels -= 2; + row_info->color_type = (png_byte)(row_info->color_type & + ~PNG_COLOR_MASK_COLOR); + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + return rgb_error; +} +#endif + +/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth + * large of png_color. This lets grayscale images be treated as + * paletted. Most useful for gamma correction and simplification + * of code. + */ +void PNGAPI +png_build_grayscale_palette(int bit_depth, png_colorp palette) +{ + int num_palette; + int color_inc; + int i; + int v; + + png_debug(1, "in png_do_build_grayscale_palette"); + + if (palette == NULL) + return; + + switch (bit_depth) + { + case 1: + num_palette = 2; + color_inc = 0xff; + break; + + case 2: + num_palette = 4; + color_inc = 0x55; + break; + + case 4: + num_palette = 16; + color_inc = 0x11; + break; + + case 8: + num_palette = 256; + color_inc = 1; + break; + + default: + num_palette = 0; + color_inc = 0; + break; + } + + for (i = 0, v = 0; i < num_palette; i++, v += color_inc) + { + palette[i].red = (png_byte)v; + palette[i].green = (png_byte)v; + palette[i].blue = (png_byte)v; + } +} + + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* Replace any alpha or transparency with the supplied background color. + * "background" is already in the screen gamma, while "background_1" is + * at a gamma of 1.0. Paletted files have already been taken care of. + */ +void /* PRIVATE */ +png_do_background(png_row_infop row_info, png_bytep row, + png_const_color_16p trans_color, png_const_color_16p background +#ifdef PNG_READ_GAMMA_SUPPORTED + , png_const_color_16p background_1, png_const_bytep gamma_table, + png_const_bytep gamma_from_1, png_const_bytep gamma_to_1, + png_const_uint_16pp gamma_16, png_const_uint_16pp gamma_16_from_1, + png_const_uint_16pp gamma_16_to_1, int gamma_shift +#endif + ) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + int shift; + + png_debug(1, "in png_do_background"); + + if (background != NULL && + (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || + (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_color))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_GRAY: + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == trans_color->gray) + { + *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + + if (!shift) + { + shift = 7; + sp++; + } + + else + shift--; + } + break; + } + + case 2: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_color->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x03); + png_byte g = (png_byte)((gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03); + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + + if (!shift) + { + shift = 6; + sp++; + } + + else + shift -= 2; + } + } + + else +#endif + { + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x03) + == trans_color->gray) + { + *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + + if (!shift) + { + shift = 6; + sp++; + } + + else + shift -= 2; + } + } + break; + } + + case 4: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_color->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + + else + { + png_byte p = (png_byte)((*sp >> shift) & 0x0f); + png_byte g = (png_byte)((gamma_table[p | + (p << 4)] >> 4) & 0x0f); + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(g << shift); + } + + if (!shift) + { + shift = 4; + sp++; + } + + else + shift -= 4; + } + } + + else +#endif + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x0f) + == trans_color->gray) + { + *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *sp |= (png_byte)(background->gray << shift); + } + + if (!shift) + { + shift = 4; + sp++; + } + + else + shift -= 4; + } + } + break; + } + + case 8: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_color->gray) + *sp = (png_byte)background->gray; + + else + *sp = gamma_table[*sp]; + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp++) + { + if (*sp == trans_color->gray) + *sp = (png_byte)background->gray; + } + } + break; + } + + case 16: + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + if (v == trans_color->gray) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + + else + { + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 v; + + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + if (v == trans_color->gray) + { + *sp = (png_byte)((background->gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->gray & 0xff); + } + } + } + break; + } + + default: + break; + } + break; + } + + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_color->red && + *(sp + 1) == trans_color->green && + *(sp + 2) == trans_color->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == trans_color->red && + *(sp + 1) == trans_color->green && + *(sp + 2) == trans_color->blue) + { + *sp = (png_byte)background->red; + *(sp + 1) = (png_byte)background->green; + *(sp + 2) = (png_byte)background->blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == trans_color->red && g == trans_color->green && + b == trans_color->blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } + } + } + + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == trans_color->red && g == trans_color->green && + b == trans_color->blue) + { + *sp = (png_byte)((background->red >> 8) & 0xff); + *(sp + 1) = (png_byte)(background->red & 0xff); + *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(sp + 3) = (png_byte)(background->green & 0xff); + *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(background->blue & 0xff); + } + } + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + *dp = gamma_table[*sp]; + + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)background->gray; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->gray); + *dp = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 2, dp++) + { + png_byte a = *(sp + 1); + + if (a == 0xff) + *dp = *sp; + +#ifdef PNG_READ_GAMMA_SUPPORTED + else if (a == 0) + *dp = (png_byte)background->gray; + + else + png_composite(*dp, *sp, a, background_1->gray); + +#else + *dp = (png_byte)background->gray; +#endif + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } + +#ifdef PNG_READ_GAMMA_SUPPORTED + else if (a == 0) +#else + else +#endif + { + /* Background is already in screen gamma */ + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } + +#ifdef PNG_READ_GAMMA_SUPPORTED + else + { + png_uint_16 g, v, w; + + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, background_1->gray); + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + *dp = (png_byte)((w >> 8) & 0xff); + *(dp + 1) = (png_byte)(w & 0xff); + } +#endif + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 2) + { + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == (png_uint_16)0xffff) + png_memcpy(dp, sp, 2); + +#ifdef PNG_READ_GAMMA_SUPPORTED + else if (a == 0) +#else + else +#endif + { + *dp = (png_byte)((background->gray >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->gray & 0xff); + } + +#ifdef PNG_READ_GAMMA_SUPPORTED + else + { + png_uint_16 g, v; + + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, background_1->gray); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + } +#endif + } + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = gamma_table[*sp]; + *(dp + 1) = gamma_table[*(sp + 1)]; + *(dp + 2) = gamma_table[*(sp + 2)]; + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, background_1->red); + *dp = gamma_from_1[w]; + + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, background_1->green); + *(dp + 1) = gamma_from_1[w]; + + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, background_1->blue); + *(dp + 2) = gamma_from_1[w]; + } + } + } + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 4, dp += 3) + { + png_byte a = *(sp + 3); + + if (a == 0xff) + { + *dp = *sp; + *(dp + 1) = *(sp + 1); + *(dp + 2) = *(sp + 2); + } + + else if (a == 0) + { + *dp = (png_byte)background->red; + *(dp + 1) = (png_byte)background->green; + *(dp + 2) = (png_byte)background->blue; + } + + else + { + png_composite(*dp, *sp, a, background->red); + + png_composite(*(dp + 1), *(sp + 1), a, + background->green); + + png_composite(*(dp + 2), *(sp + 2), a, + background->blue); + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; + + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + + else if (a == 0) + { + /* Background is already in screen gamma */ + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + + else + { + png_uint_16 v, w, x; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, background_1->red); + + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *dp = (png_byte)((x >> 8) & 0xff); + *(dp + 1) = (png_byte)(x & 0xff); + + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, background_1->green); + + x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *(dp + 2) = (png_byte)((x >> 8) & 0xff); + *(dp + 3) = (png_byte)(x & 0xff); + + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, background_1->blue); + + x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; + *(dp + 4) = (png_byte)((x >> 8) & 0xff); + *(dp + 5) = (png_byte)(x & 0xff); + } + } + } + + else +#endif + { + sp = row; + dp = row; + for (i = 0; i < row_width; i++, sp += 8, dp += 6) + { + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); + + if (a == (png_uint_16)0xffff) + { + png_memcpy(dp, sp, 6); + } + + else if (a == 0) + { + *dp = (png_byte)((background->red >> 8) & 0xff); + *(dp + 1) = (png_byte)(background->red & 0xff); + *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); + *(dp + 3) = (png_byte)(background->green & 0xff); + *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); + *(dp + 5) = (png_byte)(background->blue & 0xff); + } + + else + { + png_uint_16 v; + + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + png_composite_16(v, r, a, background->red); + *dp = (png_byte)((v >> 8) & 0xff); + *(dp + 1) = (png_byte)(v & 0xff); + + png_composite_16(v, g, a, background->green); + *(dp + 2) = (png_byte)((v >> 8) & 0xff); + *(dp + 3) = (png_byte)(v & 0xff); + + png_composite_16(v, b, a, background->blue); + *(dp + 4) = (png_byte)((v >> 8) & 0xff); + *(dp + 5) = (png_byte)(v & 0xff); + } + } + } + } + break; + } + + default: + break; + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + row_info->color_type = (png_byte)(row_info->color_type & + ~PNG_COLOR_MASK_ALPHA); + row_info->channels--; + row_info->pixel_depth = (png_byte)(row_info->channels * + row_info->bit_depth); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + } +} +#endif + +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Gamma correct the image, avoiding the alpha channel. Make sure + * you do this after you deal with the transparency issue on grayscale + * or RGB images. If your bit depth is 8, use gamma_table, if it + * is 16, use gamma_16_table and gamma_shift. Build these with + * build_gamma_table(). + */ +void /* PRIVATE */ +png_do_gamma(png_row_infop row_info, png_bytep row, + png_const_bytep gamma_table, png_const_uint_16pp gamma_16_table, + int gamma_shift) +{ + png_bytep sp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_gamma"); + + if (((row_info->bit_depth <= 8 && gamma_table != NULL) || + (row_info->bit_depth == 16 && gamma_16_table != NULL))) + { + switch (row_info->color_type) + { + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + *sp = gamma_table[*sp]; + sp++; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + + *sp = gamma_table[*sp]; + sp++; + + *sp = gamma_table[*sp]; + sp++; + + sp++; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + + v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp += 2; + } + } + + else /* if (row_info->bit_depth == 16) */ + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 4; + } + } + break; + } + + case PNG_COLOR_TYPE_GRAY: + { + if (row_info->bit_depth == 2) + { + sp = row; + for (i = 0; i < row_width; i += 4) + { + int a = *sp & 0xc0; + int b = *sp & 0x30; + int c = *sp & 0x0c; + int d = *sp & 0x03; + + *sp = (png_byte)( + ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| + ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| + ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| + ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); + sp++; + } + } + + if (row_info->bit_depth == 4) + { + sp = row; + for (i = 0; i < row_width; i += 2) + { + int msb = *sp & 0xf0; + int lsb = *sp & 0x0f; + + *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) + | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); + sp++; + } + } + + else if (row_info->bit_depth == 8) + { + sp = row; + for (i = 0; i < row_width; i++) + { + *sp = gamma_table[*sp]; + sp++; + } + } + + else if (row_info->bit_depth == 16) + { + sp = row; + for (i = 0; i < row_width; i++) + { + png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + sp += 2; + } + } + break; + } + + default: + break; + } + } +} +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* Expands a palette row to an RGB or RGBA row depending + * upon whether you supply trans and num_trans. + */ +void /* PRIVATE */ +png_do_expand_palette(png_row_infop row_info, png_bytep row, + png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand_palette"); + + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 1; + + else + *dp = 0; + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)value; + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((row_width & 0x01) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)value; + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift += 4; + + dp--; + } + break; + } + + default: + break; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (row_info->bit_depth == 8) + { + { + if (trans_alpha != NULL) + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + + for (i = 0; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + + else + *dp-- = trans_alpha[*sp]; + + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + } + + else + { + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width * 3) - 1; + + for (i = 0; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + } + } + } + } +} + +/* If the bit depth < 8, it is expanded to 8. Also, if the already + * expanded transparency value is supplied, an alpha channel is built. + */ +void /* PRIVATE */ +png_do_expand(png_row_infop row_info, png_bytep row, + png_const_color_16p trans_value) +{ + int shift, value; + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_expand"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); + + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) + { + case 1: + { + gray = (png_uint_16)((gray & 0x01) * 0xff); + sp = row + (png_size_t)((row_width - 1) >> 3); + dp = row + (png_size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) + { + if ((*sp >> shift) & 0x01) + *dp = 0xff; + + else + *dp = 0; + + if (shift == 7) + { + shift = 0; + sp--; + } + + else + shift++; + + dp--; + } + break; + } + + case 2: + { + gray = (png_uint_16)((gray & 0x03) * 0x55); + sp = row + (png_size_t)((row_width - 1) >> 2); + dp = row + (png_size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } + + else + shift += 2; + + dp--; + } + break; + } + + case 4: + { + gray = (png_uint_16)((gray & 0x0f) * 0x11); + sp = row + (png_size_t)((row_width - 1) >> 1); + dp = row + (png_size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); + for (i = 0; i < row_width; i++) + { + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) + { + shift = 0; + sp--; + } + + else + shift = 4; + + dp--; + } + break; + } + + default: + break; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + if (trans_value != NULL) + { + if (row_info->bit_depth == 8) + { + gray = gray & 0xff; + sp = row + (png_size_t)row_width - 1; + dp = row + (png_size_t)(row_width << 1) - 1; + + for (i = 0; i < row_width; i++) + { + if (*sp == gray) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + } + } + + else if (row_info->bit_depth == 16) + { + png_byte gray_high = (png_byte)((gray >> 8) & 0xff); + png_byte gray_low = (png_byte)(gray & 0xff); + sp = row + row_info->rowbytes - 1; + dp = row + (row_info->rowbytes << 1) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 1) == gray_high && *(sp) == gray_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + } + } + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) + { + if (row_info->bit_depth == 8) + { + png_byte red = (png_byte)(trans_value->red & 0xff); + png_byte green = (png_byte)(trans_value->green & 0xff); + png_byte blue = (png_byte)(trans_value->blue & 0xff); + sp = row + (png_size_t)row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (png_byte)((trans_value->red >> 8) & 0xff); + png_byte green_high = (png_byte)((trans_value->green >> 8) & 0xff); + png_byte blue_high = (png_byte)((trans_value->blue >> 8) & 0xff); + png_byte red_low = (png_byte)(trans_value->red & 0xff); + png_byte green_low = (png_byte)(trans_value->green & 0xff); + png_byte blue_low = (png_byte)(trans_value->blue & 0xff); + sp = row + row_info->rowbytes - 1; + dp = row + (png_size_t)(row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + } +} +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +void /* PRIVATE */ +png_do_quantize(png_row_infop row_info, png_bytep row, + png_const_bytep palette_lookup, png_const_bytep quantize_lookup) +{ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width=row_info->width; + + png_debug(1, "in png_do_quantize"); + + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + + /* This looks real messy, but the compiler will reduce + * it down to a reasonable formula. For example, with + * 5 bits per color, we get: + * p = (((r >> 3) & 0x1f) << 10) | + * (((g >> 3) & 0x1f) << 5) | + * ((b >> 3) & 0x1f); + */ + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + palette_lookup != NULL) + { + int r, g, b, p; + sp = row; + dp = row; + for (i = 0; i < row_width; i++) + { + r = *sp++; + g = *sp++; + b = *sp++; + sp++; + + p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) & + ((1 << PNG_QUANTIZE_RED_BITS) - 1)) << + (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) | + (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) & + ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) << + (PNG_QUANTIZE_BLUE_BITS)) | + ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) & + ((1 << PNG_QUANTIZE_BLUE_BITS) - 1)); + + *dp++ = palette_lookup[p]; + } + + row_info->color_type = PNG_COLOR_TYPE_PALETTE; + row_info->channels = 1; + row_info->pixel_depth = row_info->bit_depth; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + } + + else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + quantize_lookup) + { + sp = row; + + for (i = 0; i < row_width; i++, sp++) + { + *sp = quantize_lookup[*sp]; + } + } + } +} +#endif /* PNG_READ_QUANTIZE_SUPPORTED */ + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_read_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_read_intrapixel"); + + if ( + (row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff); + *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff); + } + } + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp + 1) = (png_byte)(red & 0xff); + *(rp + 4) = (png_byte)((blue >> 8) & 0xff); + *(rp + 5) = (png_byte)(blue & 0xff); + } + } + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/contrib/libpng/pngrutil.c b/contrib/libpng/pngrutil.c new file mode 100644 index 0000000..4c3cd53 --- /dev/null +++ b/contrib/libpng/pngrutil.c @@ -0,0 +1,3616 @@ + +/* pngrutil.c - utilities to read a PNG file + * + * Last changed in libpng 1.5.1 [February 3, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file contains routines that are only called from within + * libpng itself during the course of reading an image. + */ + +#include "pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +#define png_strtod(p,a,b) strtod(a,b) + +png_uint_32 PNGAPI +png_get_uint_31(png_structp png_ptr, png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + + if (uval > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range"); + + return (uval); +} + +#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED) +/* The following is a variation on the above for use with the fixed + * point values used for gAMA and cHRM. Instead of png_error it + * issues a warning and returns (-1) - an invalid value because both + * gAMA and cHRM use *unsigned* integers for fixed point values. + */ +#define PNG_FIXED_ERROR (-1) + +static png_fixed_point /* PRIVATE */ +png_get_fixed_point(png_structp png_ptr, png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + + if (uval <= PNG_UINT_31_MAX) + return (png_fixed_point)uval; /* known to be in range */ + + /* The caller can turn off the warning by passing NULL. */ + if (png_ptr != NULL) + png_warning(png_ptr, "PNG fixed point integer out of range"); + + return PNG_FIXED_ERROR; +} +#endif + +#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED +/* NOTE: the read macros will obscure these definitions, so that if + * PNG_USE_READ_MACROS is set the library will not use them internally, + * but the APIs will still be available externally. + * + * The parentheses around "PNGAPI function_name" in the following three + * functions are necessary because they allow the macros to co-exist with + * these (unused but exported) functions. + */ + +/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ +png_uint_32 (PNGAPI +png_get_uint_32)(png_const_bytep buf) +{ + png_uint_32 uval = + ((png_uint_32)(*(buf )) << 24) + + ((png_uint_32)(*(buf + 1)) << 16) + + ((png_uint_32)(*(buf + 2)) << 8) + + ((png_uint_32)(*(buf + 3)) ) ; + + return uval; +} + +/* Grab a signed 32-bit integer from a buffer in big-endian format. The + * data is stored in the PNG file in two's complement format and there + * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore + * the following code does a two's complement to native conversion. + */ +png_int_32 (PNGAPI +png_get_int_32)(png_const_bytep buf) +{ + png_uint_32 uval = png_get_uint_32(buf); + if ((uval & 0x80000000L) == 0) /* non-negative */ + return uval; + + uval = (uval ^ 0xffffffffL) + 1; /* 2's complement: -x = ~x+1 */ + return -(png_int_32)uval; +} + +/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ +png_uint_16 (PNGAPI +png_get_uint_16)(png_const_bytep buf) +{ + /* ANSI-C requires an int value to accomodate at least 16 bits so this + * works and allows the compiler not to worry about possible narrowing + * on 32 bit systems. (Pre-ANSI systems did not make integers smaller + * than 16 bits either.) + */ + unsigned int val = + ((unsigned int)(*buf) << 8) + + ((unsigned int)(*(buf + 1))); + + return (png_uint_16)val; +} + +#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */ + +/* Read and check the PNG file signature */ +void /* PRIVATE */ +png_read_sig(png_structp png_ptr, png_infop info_ptr) +{ + png_size_t num_checked, num_to_check; + + /* Exit if the user application does not expect a signature. */ + if (png_ptr->sig_bytes >= 8) + return; + + num_checked = png_ptr->sig_bytes; + num_to_check = 8 - num_checked; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE; +#endif + + /* The signature must be serialized in a single I/O call. */ + png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); + png_ptr->sig_bytes = 8; + + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + { + if (num_checked < 4 && + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_error(png_ptr, "Not a PNG file"); + else + png_error(png_ptr, "PNG file corrupted by ASCII conversion"); + } + if (num_checked < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Read the chunk header (length + type name). + * Put the type name into png_ptr->chunk_name, and return the length. + */ +png_uint_32 /* PRIVATE */ +png_read_chunk_header(png_structp png_ptr) +{ + png_byte buf[8]; + png_uint_32 length; + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR; +#endif + + /* Read the length and the chunk name. + * This must be performed in a single I/O call. + */ + png_read_data(png_ptr, buf, 8); + length = png_get_uint_31(png_ptr, buf); + + /* Put the chunk name into png_ptr->chunk_name. */ + png_memcpy(png_ptr->chunk_name, buf + 4, 4); + + png_debug2(0, "Reading %s chunk, length = %u", + png_ptr->chunk_name, length); + + /* Reset the crc and run it over the chunk name. */ + png_reset_crc(png_ptr); + png_calculate_crc(png_ptr, png_ptr->chunk_name, 4); + + /* Check to see if chunk name is valid. */ + png_check_chunk_name(png_ptr, png_ptr->chunk_name); + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; +#endif + + return length; +} + +/* Read data, and (optionally) run it through the CRC. */ +void /* PRIVATE */ +png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length) +{ + if (png_ptr == NULL) + return; + + png_read_data(png_ptr, buf, length); + png_calculate_crc(png_ptr, buf, length); +} + +/* Optionally skip data and then check the CRC. Depending on whether we + * are reading a ancillary or critical chunk, and how the program has set + * things up, we may calculate the CRC on the data and print a message. + * Returns '1' if there was a CRC error, '0' otherwise. + */ +int /* PRIVATE */ +png_crc_finish(png_structp png_ptr, png_uint_32 skip) +{ + png_size_t i; + png_size_t istop = png_ptr->zbuf_size; + + for (i = (png_size_t)skip; i > istop; i -= istop) + { + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + } + + if (i) + { + png_crc_read(png_ptr, png_ptr->zbuf, i); + } + + if (png_crc_error(png_ptr)) + { + if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */ + !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) || + (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */ + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))) + { + png_chunk_warning(png_ptr, "CRC error"); + } + + else + { + png_chunk_benign_error(png_ptr, "CRC error"); + return (0); + } + + return (1); + } + + return (0); +} + +/* Compare the CRC stored in the PNG file with that calculated by libpng from + * the data it has read thus far. + */ +int /* PRIVATE */ +png_crc_error(png_structp png_ptr) +{ + png_byte crc_bytes[4]; + png_uint_32 crc; + int need_crc = 1; + + if (png_ptr->chunk_name[0] & 0x20) /* ancillary */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + + else /* critical */ + { + if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) + need_crc = 0; + } + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC; +#endif + + /* The chunk CRC must be serialized in a single I/O call. */ + png_read_data(png_ptr, crc_bytes, 4); + + if (need_crc) + { + crc = png_get_uint_32(crc_bytes); + return ((int)(crc != png_ptr->crc)); + } + + else + return (0); +} + +#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ + defined(PNG_READ_iCCP_SUPPORTED) +static png_size_t +png_inflate(png_structp png_ptr, png_bytep data, png_size_t size, + png_bytep output, png_size_t output_size) +{ + png_size_t count = 0; + + /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it can't + * even necessarily handle 65536 bytes) because the type uInt is "16 bits or + * more". Consequently it is necessary to chunk the input to zlib. This + * code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the maximum value + * that can be stored in a uInt.) It is possible to set ZLIB_IO_MAX to a + * lower value in pngpriv.h and this may sometimes have a performance + * advantage, because it forces access of the input data to be separated from + * at least some of the use by some period of time. + */ + png_ptr->zstream.next_in = data; + /* avail_in is set below from 'size' */ + png_ptr->zstream.avail_in = 0; + + while (1) + { + int ret, avail; + + /* The setting of 'avail_in' used to be outside the loop, by setting it + * inside it is possible to chunk the input to zlib and simply rely on + * zlib to advance the 'next_in' pointer. This allows arbitrary amounts o + * data to be passed through zlib at the unavoidable cost of requiring a + * window save (memcpy of up to 32768 output bytes) every ZLIB_IO_MAX + * input bytes. + */ + if (png_ptr->zstream.avail_in == 0 && size > 0) + { + if (size <= ZLIB_IO_MAX) + { + /* The value is less than ZLIB_IO_MAX so the cast is safe: */ + png_ptr->zstream.avail_in = (uInt)size; + size = 0; + } + + else + { + png_ptr->zstream.avail_in = ZLIB_IO_MAX; + size -= ZLIB_IO_MAX; + } + } + + /* Reset the output buffer each time round - we empty it + * after every inflate call. + */ + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = png_ptr->zbuf_size; + + ret = inflate(&png_ptr->zstream, Z_NO_FLUSH); + avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out; + + /* First copy/count any new output - but only if we didn't + * get an error code. + */ + if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0) + { + png_size_t space = avail; /* > 0, see above */ + + if (output != 0 && output_size > count) + { + png_size_t copy = output_size - count; + + if (space < copy) + copy = space; + + png_memcpy(output + count, png_ptr->zbuf, copy); + } + count += space; + } + + if (ret == Z_OK) + continue; + + /* Termination conditions - always reset the zstream, it + * must be left in inflateInit state. + */ + png_ptr->zstream.avail_in = 0; + inflateReset(&png_ptr->zstream); + + if (ret == Z_STREAM_END) + return count; /* NOTE: may be zero. */ + + /* Now handle the error codes - the API always returns 0 + * and the error message is dumped into the uncompressed + * buffer if available. + */ + { + PNG_CONST char *msg; +#ifdef PNG_CONSOLE_IO_SUPPORTED + char umsg[52]; +#endif + if (png_ptr->zstream.msg != 0) + msg = png_ptr->zstream.msg; + + else + { +#ifdef PNG_CONSOLE_IO_SUPPORTED + switch (ret) + { + case Z_BUF_ERROR: + msg = "Buffer error in compressed datastream in %s chunk"; + break; + + case Z_DATA_ERROR: + msg = "Data error in compressed datastream in %s chunk"; + break; + + default: + msg = "Incomplete compressed datastream in %s chunk"; + break; + } + + png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name); + msg = umsg; +#else + msg = "Damaged compressed datastream in chunk other than IDAT"; +#endif + } + + png_warning(png_ptr, msg); + } + + /* 0 means an error - notice that this code simply ignores + * zero length compressed chunks as a result. + */ + return 0; + } +} + +/* + * Decompress trailing data in a chunk. The assumption is that chunkdata + * points at an allocated area holding the contents of a chunk with a + * trailing compressed part. What we get back is an allocated area + * holding the original prefix part and an uncompressed version of the + * trailing part (the malloc area passed in is freed). + */ +void /* PRIVATE */ +png_decompress_chunk(png_structp png_ptr, int comp_type, + png_size_t chunklength, + png_size_t prefix_size, png_size_t *newlength) +{ + /* The caller should guarantee this */ + if (prefix_size > chunklength) + { + /* The recovery is to delete the chunk. */ + png_warning(png_ptr, "invalid chunklength"); + prefix_size = 0; /* To delete everything */ + } + + else if (comp_type == PNG_COMPRESSION_TYPE_BASE) + { + png_size_t expanded_size = png_inflate(png_ptr, + (png_bytep)(png_ptr->chunkdata + prefix_size), + chunklength - prefix_size, + 0, /*output*/ + 0); /*output size*/ + + /* Now check the limits on this chunk - if the limit fails the + * compressed data will be removed, the prefix will remain. + */ +#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + if (png_ptr->user_chunk_malloc_max && + (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1)) +#else +# ifdef PNG_USER_CHUNK_MALLOC_MAX + if ((PNG_USER_CHUNK_MALLOC_MAX > 0) && + prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1) +# endif +#endif + png_warning(png_ptr, "Exceeded size limit while expanding chunk"); + + /* If the size is zero either there was an error and a message + * has already been output (warning) or the size really is zero + * and we have nothing to do - the code will exit through the + * error case below. + */ +#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \ + defined(PNG_USER_CHUNK_MALLOC_MAX) + else if (expanded_size > 0) +#else + if (expanded_size > 0) +#endif + { + /* Success (maybe) - really uncompress the chunk. */ + png_size_t new_size = 0; + png_charp text = png_malloc_warn(png_ptr, + prefix_size + expanded_size + 1); + + if (text != NULL) + { + png_memcpy(text, png_ptr->chunkdata, prefix_size); + new_size = png_inflate(png_ptr, + (png_bytep)(png_ptr->chunkdata + prefix_size), + chunklength - prefix_size, + (png_bytep)(text + prefix_size), expanded_size); + text[prefix_size + expanded_size] = 0; /* just in case */ + + if (new_size == expanded_size) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = text; + *newlength = prefix_size + expanded_size; + return; /* The success return! */ + } + + png_warning(png_ptr, "png_inflate logic error"); + png_free(png_ptr, text); + } + + else + png_warning(png_ptr, "Not enough memory to decompress chunk"); + } + } + + else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ + { +#ifdef PNG_STDIO_SUPPORTED + char umsg[50]; + + png_snprintf(umsg, sizeof umsg, + "Unknown zTXt compression type %d", comp_type); + png_warning(png_ptr, umsg); +#else + png_warning(png_ptr, "Unknown zTXt compression type"); +#endif + + /* The recovery is to simply drop the data. */ + } + + /* Generic error return - leave the prefix, delete the compressed + * data, reallocate the chunkdata to remove the potentially large + * amount of compressed data. + */ + { + png_charp text = png_malloc_warn(png_ptr, prefix_size + 1); + + if (text != NULL) + { + if (prefix_size > 0) + png_memcpy(text, png_ptr->chunkdata, prefix_size); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = text; + + /* This is an extra zero in the 'uncompressed' part. */ + *(png_ptr->chunkdata + prefix_size) = 0x00; + } + /* Ignore a malloc error here - it is safe. */ + } + + *newlength = prefix_size; +} +#endif + +/* Read and check the IDHR chunk */ +void /* PRIVATE */ +png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[13]; + png_uint_32 width, height; + int bit_depth, color_type, compression_type, filter_type; + int interlace_type; + + png_debug(1, "in png_handle_IHDR"); + + if (png_ptr->mode & PNG_HAVE_IHDR) + png_error(png_ptr, "Out of place IHDR"); + + /* Check the length */ + if (length != 13) + png_error(png_ptr, "Invalid IHDR chunk"); + + png_ptr->mode |= PNG_HAVE_IHDR; + + png_crc_read(png_ptr, buf, 13); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_31(png_ptr, buf); + height = png_get_uint_31(png_ptr, buf + 4); + bit_depth = buf[8]; + color_type = buf[9]; + compression_type = buf[10]; + filter_type = buf[11]; + interlace_type = buf[12]; + + /* Set internal variables */ + png_ptr->width = width; + png_ptr->height = height; + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->interlaced = (png_byte)interlace_type; + png_ptr->color_type = (png_byte)color_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + + /* Find number of channels */ + switch (png_ptr->color_type) + { + default: /* invalid, png_set_IHDR calls png_error */ + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_PALETTE: + png_ptr->channels = 1; + break; + + case PNG_COLOR_TYPE_RGB: + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: + png_ptr->channels = 4; + break; + } + + /* Set up other useful info */ + png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * + png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width); + png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); + png_debug1(3, "channels = %d", png_ptr->channels); + png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes); + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); +} + +/* Read and check the palette */ +void /* PRIVATE */ +png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_color palette[PNG_MAX_PALETTE_LENGTH]; + int num, i; +#ifdef PNG_POINTER_INDEXING_SUPPORTED + png_colorp pal_ptr; +#endif + + png_debug(1, "in png_handle_PLTE"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before PLTE"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid PLTE after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + png_error(png_ptr, "Duplicate PLTE chunk"); + + png_ptr->mode |= PNG_HAVE_PLTE; + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring PLTE chunk in grayscale PNG"); + png_crc_finish(png_ptr, length); + return; + } + +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_crc_finish(png_ptr, length); + return; + } +#endif + + if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) + { + if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + png_warning(png_ptr, "Invalid palette chunk"); + png_crc_finish(png_ptr, length); + return; + } + + else + { + png_error(png_ptr, "Invalid palette chunk"); + } + } + + num = (int)length / 3; + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + pal_ptr->red = buf[0]; + pal_ptr->green = buf[1]; + pal_ptr->blue = buf[2]; + } +#else + for (i = 0; i < num; i++) + { + png_byte buf[3]; + + png_crc_read(png_ptr, buf, 3); + /* Don't depend upon png_color being any order */ + palette[i].red = buf[0]; + palette[i].green = buf[1]; + palette[i].blue = buf[2]; + } +#endif + + /* If we actually need the PLTE chunk (ie for a paletted image), we do + * whatever the normal CRC configuration tells us. However, if we + * have an RGB image, the PLTE can be considered ancillary, so + * we will act as though it is. + */ +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) +#endif + { + png_crc_finish(png_ptr, 0); + } + +#ifndef PNG_READ_OPT_PLTE_SUPPORTED + else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */ + { + /* If we don't want to use the data from an ancillary chunk, + * we have two options: an error abort, or a warning and we + * ignore the data in this chunk (which should be OK, since + * it's considered ancillary for a RGB or RGBA image). + */ + if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE)) + { + if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) + { + png_chunk_benign_error(png_ptr, "CRC error"); + } + + else + { + png_chunk_warning(png_ptr, "CRC error"); + return; + } + } + + /* Otherwise, we (optionally) emit a warning and use the chunk. */ + else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) + { + png_chunk_warning(png_ptr, "CRC error"); + } + } +#endif + + png_set_PLTE(png_ptr, info_ptr, palette, num); + +#ifdef PNG_READ_tRNS_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + if (png_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect tRNS chunk length"); + png_ptr->num_trans = (png_uint_16)num; + } + + if (info_ptr->num_trans > (png_uint_16)num) + { + png_warning(png_ptr, "Truncating incorrect info tRNS chunk length"); + info_ptr->num_trans = (png_uint_16)num; + } + } + } +#endif + +} + +void /* PRIVATE */ +png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_debug(1, "in png_handle_IEND"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT)) + { + png_error(png_ptr, "No image in file"); + } + + png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); + + if (length != 0) + { + png_warning(png_ptr, "Incorrect IEND chunk length"); + } + + png_crc_finish(png_ptr, length); + + PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */ +} + +#ifdef PNG_READ_gAMA_SUPPORTED +void /* PRIVATE */ +png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_fixed_point igamma; + png_byte buf[4]; + + png_debug(1, "in png_handle_gAMA"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before gAMA"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid gAMA after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place gAMA chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA) +#ifdef PNG_READ_sRGB_SUPPORTED + && !(info_ptr->valid & PNG_INFO_sRGB) +#endif + ) + { + png_warning(png_ptr, "Duplicate gAMA chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 4) + { + png_warning(png_ptr, "Incorrect gAMA chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 4); + + if (png_crc_finish(png_ptr, 0)) + return; + + igamma = png_get_fixed_point(NULL, buf); + + /* Check for zero gamma or an error. */ + if (igamma <= 0) + { + png_warning(png_ptr, + "Ignoring gAMA chunk with out of range gamma"); + + return; + } + +# ifdef PNG_READ_sRGB_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); + +# ifdef PNG_CONSOLE_IO_SUPPORTED + fprintf(stderr, "gamma = (%d/100000)", (int)igamma); +# endif + return; + } + } +# endif /* PNG_READ_sRGB_SUPPORTED */ + +# ifdef PNG_READ_GAMMA_SUPPORTED + /* Gamma correction on read is supported. */ + png_ptr->gamma = igamma; +# endif + /* And set the 'info' structure members. */ + png_set_gAMA_fixed(png_ptr, info_ptr, igamma); +} +#endif + +#ifdef PNG_READ_sBIT_SUPPORTED +void /* PRIVATE */ +png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[4]; + + png_debug(1, "in png_handle_sBIT"); + + buf[0] = buf[1] = buf[2] = buf[3] = 0; + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sBIT"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sBIT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + { + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sBIT chunk"); + } + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)) + { + png_warning(png_ptr, "Duplicate sBIT chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 3; + + else + truelen = (png_size_t)png_ptr->channels; + + if (length != truelen || length > 4) + { + png_warning(png_ptr, "Incorrect sBIT chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + + if (png_crc_finish(png_ptr, 0)) + return; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + { + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[1]; + png_ptr->sig_bit.blue = buf[2]; + png_ptr->sig_bit.alpha = buf[3]; + } + + else + { + png_ptr->sig_bit.gray = buf[0]; + png_ptr->sig_bit.red = buf[0]; + png_ptr->sig_bit.green = buf[0]; + png_ptr->sig_bit.blue = buf[0]; + png_ptr->sig_bit.alpha = buf[1]; + } + + png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); +} +#endif + +#ifdef PNG_READ_cHRM_SUPPORTED +void /* PRIVATE */ +png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[32]; + png_fixed_point x_white, y_white, x_red, y_red, x_green, y_green, x_blue, + y_blue; + + png_debug(1, "in png_handle_cHRM"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before cHRM"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid cHRM after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Missing PLTE before cHRM"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM) +# ifdef PNG_READ_sRGB_SUPPORTED + && !(info_ptr->valid & PNG_INFO_sRGB) +# endif + ) + { + png_warning(png_ptr, "Duplicate cHRM chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 32) + { + png_warning(png_ptr, "Incorrect cHRM chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 32); + + if (png_crc_finish(png_ptr, 0)) + return; + + x_white = png_get_fixed_point(NULL, buf); + y_white = png_get_fixed_point(NULL, buf + 4); + x_red = png_get_fixed_point(NULL, buf + 8); + y_red = png_get_fixed_point(NULL, buf + 12); + x_green = png_get_fixed_point(NULL, buf + 16); + y_green = png_get_fixed_point(NULL, buf + 20); + x_blue = png_get_fixed_point(NULL, buf + 24); + y_blue = png_get_fixed_point(NULL, buf + 28); + + if (x_white == PNG_FIXED_ERROR || + y_white == PNG_FIXED_ERROR || + x_red == PNG_FIXED_ERROR || + y_red == PNG_FIXED_ERROR || + x_green == PNG_FIXED_ERROR || + y_green == PNG_FIXED_ERROR || + x_blue == PNG_FIXED_ERROR || + y_blue == PNG_FIXED_ERROR) + { + png_warning(png_ptr, "Ignoring cHRM chunk with negative chromaticities"); + return; + } + +#ifdef PNG_READ_sRGB_SUPPORTED + if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB)) + { + if (PNG_OUT_OF_RANGE(x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + +#ifdef PNG_CONSOLE_IO_SUPPORTED + fprintf(stderr, "wx=%d, wy=%d, rx=%d, ry=%d\n", + x_white, y_white, x_red, y_red); + + fprintf(stderr, "gx=%d, gy=%d, bx=%d, by=%d\n", + x_green, y_green, x_blue, y_blue); +#endif /* PNG_CONSOLE_IO_SUPPORTED */ + } + return; + } +#endif /* PNG_READ_sRGB_SUPPORTED */ + + png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red, + x_green, y_green, x_blue, y_blue); +} +#endif + +#ifdef PNG_READ_sRGB_SUPPORTED +void /* PRIVATE */ +png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + int intent; + png_byte buf[1]; + + png_debug(1, "in png_handle_sRGB"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sRGB"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sRGB after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place sRGB chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)) + { + png_warning(png_ptr, "Duplicate sRGB chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 1) + { + png_warning(png_ptr, "Incorrect sRGB chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 1); + + if (png_crc_finish(png_ptr, 0)) + return; + + intent = buf[0]; + + /* Check for bad intent */ + if (intent >= PNG_sRGB_INTENT_LAST) + { + png_warning(png_ptr, "Unknown sRGB intent"); + return; + } + +#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)) + { + if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500L, 500)) + { + png_warning(png_ptr, + "Ignoring incorrect gAMA value when sRGB is also present"); +#ifdef PNG_CONSOLE_IO_SUPPORTED + fprintf(stderr, "incorrect gamma=(%d/100000)\n", info_ptr->gamma); +#endif + } + } +#endif /* PNG_READ_gAMA_SUPPORTED */ + +#ifdef PNG_READ_cHRM_SUPPORTED + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)) + if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_red, 64000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_green, 60000L, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_blue, 6000, 1000)) + { + png_warning(png_ptr, + "Ignoring incorrect cHRM value when sRGB is also present"); + } +#endif /* PNG_READ_cHRM_SUPPORTED */ + + png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent); +} +#endif /* PNG_READ_sRGB_SUPPORTED */ + +#ifdef PNG_READ_iCCP_SUPPORTED +void /* PRIVATE */ +png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_byte compression_type; + png_bytep pC; + png_charp profile; + png_uint_32 skip = 0; + png_uint_32 profile_size; + png_alloc_size_t profile_length; + png_size_t slength, prefix_length, data_length; + + png_debug(1, "in png_handle_iCCP"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iCCP"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid iCCP after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->mode & PNG_HAVE_PLTE) + /* Should be an error, but we can cope with it */ + png_warning(png_ptr, "Out of place iCCP chunk"); + + if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)) + { + png_warning(png_ptr, "Duplicate iCCP chunk"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iCCP chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (profile = png_ptr->chunkdata; *profile; profile++) + /* Empty loop to find end of name */ ; + + ++profile; + + /* There should be at least one zero (the compression type byte) + * following the separator, and we should be on it + */ + if (profile >= png_ptr->chunkdata + slength - 1) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Malformed iCCP chunk"); + return; + } + + /* Compression_type should always be zero */ + compression_type = *profile++; + + if (compression_type) + { + png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk"); + compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8 + wrote nonzero) */ + } + + prefix_length = profile - png_ptr->chunkdata; + png_decompress_chunk(png_ptr, compression_type, + slength, prefix_length, &data_length); + + profile_length = data_length - prefix_length; + + if (prefix_length > data_length || profile_length < 4) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "Profile size field missing from iCCP chunk"); + return; + } + + /* Check the profile_size recorded in the first 32 bits of the ICC profile */ + pC = (png_bytep)(png_ptr->chunkdata + prefix_length); + profile_size = ((*(pC )) << 24) | + ((*(pC + 1)) << 16) | + ((*(pC + 2)) << 8) | + ((*(pC + 3)) ); + + /* NOTE: the following guarantees that 'profile_length' fits into 32 bits, + * because profile_size is a 32 bit value. + */ + if (profile_size < profile_length) + profile_length = profile_size; + + /* And the following guarantees that profile_size == profile_length. */ + if (profile_size > profile_length) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +#ifdef PNG_STDIO_SUPPORTED + { + char umsg[80]; + + png_snprintf2(umsg, 80, + "Ignoring iCCP chunk with declared size = %u " + "and actual length = %u", + (unsigned int) profile_size, + (unsigned int) profile_length); + png_warning(png_ptr, umsg); + } +#else + png_warning(png_ptr, + "Ignoring iCCP chunk with uncompressed size mismatch"); +#endif + return; + } + + png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata, + compression_type, (png_bytep)png_ptr->chunkdata + prefix_length, + profile_size); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +} +#endif /* PNG_READ_iCCP_SUPPORTED */ + +#ifdef PNG_READ_sPLT_SUPPORTED +void /* PRIVATE */ +png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +/* Note: this does not properly handle chunks that are > 64K under DOS */ +{ + png_bytep entry_start; + png_sPLT_t new_palette; +#ifdef PNG_POINTER_INDEXING_SUPPORTED + png_sPLT_entryp pp; +#endif + png_uint_32 data_length; + int entry_size, i; + png_uint_32 skip = 0; + png_size_t slength; + png_uint_32 dl; + png_size_t max_dl; + + png_debug(1, "in png_handle_sPLT"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for sPLT"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sPLT"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sPLT after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "sPLT chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1); + + /* WARNING: this may break if size_t is less than 32 bits; it is assumed + * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a + * potential breakage point if the types in pngconf.h aren't exactly right. + */ + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; + entry_start++) + /* Empty loop to find end of name */ ; + + ++entry_start; + + /* A sample depth should follow the separator, and we should be on it */ + if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "malformed sPLT chunk"); + return; + } + + new_palette.depth = *entry_start++; + entry_size = (new_palette.depth == 8 ? 6 : 10); + /* This must fit in a png_uint_32 because it is derived from the original + * chunk data length (and use 'length', not 'slength' here for clarity - + * they are guaranteed to be the same, see the tests above.) + */ + data_length = length - (png_uint_32)(entry_start - + (png_bytep)png_ptr->chunkdata); + + /* Integrity-check the data length */ + if (data_length % entry_size) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "sPLT chunk has bad length"); + return; + } + + dl = (png_int_32)(data_length / entry_size); + max_dl = PNG_SIZE_MAX / png_sizeof(png_sPLT_entry); + + if (dl > max_dl) + { + png_warning(png_ptr, "sPLT chunk too long"); + return; + } + + new_palette.nentries = (png_int_32)(data_length / entry_size); + + new_palette.entries = (png_sPLT_entryp)png_malloc_warn( + png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry)); + + if (new_palette.entries == NULL) + { + png_warning(png_ptr, "sPLT chunk requires too much memory"); + return; + } + +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (i = 0; i < new_palette.nentries; i++) + { + pp = new_palette.entries + i; + + if (new_palette.depth == 8) + { + pp->red = *entry_start++; + pp->green = *entry_start++; + pp->blue = *entry_start++; + pp->alpha = *entry_start++; + } + + else + { + pp->red = png_get_uint_16(entry_start); entry_start += 2; + pp->green = png_get_uint_16(entry_start); entry_start += 2; + pp->blue = png_get_uint_16(entry_start); entry_start += 2; + pp->alpha = png_get_uint_16(entry_start); entry_start += 2; + } + + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#else + pp = new_palette.entries; + + for (i = 0; i < new_palette.nentries; i++) + { + + if (new_palette.depth == 8) + { + pp[i].red = *entry_start++; + pp[i].green = *entry_start++; + pp[i].blue = *entry_start++; + pp[i].alpha = *entry_start++; + } + + else + { + pp[i].red = png_get_uint_16(entry_start); entry_start += 2; + pp[i].green = png_get_uint_16(entry_start); entry_start += 2; + pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; + pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; + } + + pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + } +#endif + + /* Discard all chunk data except the name and stash that */ + new_palette.name = png_ptr->chunkdata; + + png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, new_palette.entries); +} +#endif /* PNG_READ_sPLT_SUPPORTED */ + +#ifdef PNG_READ_tRNS_SUPPORTED +void /* PRIVATE */ +png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_tRNS"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tRNS"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid tRNS after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + { + png_warning(png_ptr, "Duplicate tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + png_byte buf[2]; + + if (length != 2) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 2); + png_ptr->num_trans = 1; + png_ptr->trans_color.gray = png_get_uint_16(buf); + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_byte buf[6]; + + if (length != 6) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, (png_size_t)length); + png_ptr->num_trans = 1; + png_ptr->trans_color.red = png_get_uint_16(buf); + png_ptr->trans_color.green = png_get_uint_16(buf + 2); + png_ptr->trans_color.blue = png_get_uint_16(buf + 4); + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + /* Should be an error, but we can cope with it. */ + png_warning(png_ptr, "Missing PLTE before tRNS"); + } + + if (length > (png_uint_32)png_ptr->num_palette || + length > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect tRNS chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + if (length == 0) + { + png_warning(png_ptr, "Zero length tRNS chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, readbuf, (png_size_t)length); + png_ptr->num_trans = (png_uint_16)length; + } + + else + { + png_warning(png_ptr, "tRNS chunk not allowed with alpha channel"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_crc_finish(png_ptr, 0)) + { + png_ptr->num_trans = 0; + return; + } + + png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, + &(png_ptr->trans_color)); +} +#endif + +#ifdef PNG_READ_bKGD_SUPPORTED +void /* PRIVATE */ +png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t truelen; + png_byte buf[6]; + + png_debug(1, "in png_handle_bKGD"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before bKGD"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid bKGD after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + !(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before bKGD"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)) + { + png_warning(png_ptr, "Duplicate bKGD chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + truelen = 1; + + else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + truelen = 6; + + else + truelen = 2; + + if (length != truelen) + { + png_warning(png_ptr, "Incorrect bKGD chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, truelen); + + if (png_crc_finish(png_ptr, 0)) + return; + + /* We convert the index value into RGB components so that we can allow + * arbitrary RGB values for background when we have transparency, and + * so it is easy to determine the RGB values of the background color + * from the info_ptr struct. + */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_ptr->background.index = buf[0]; + + if (info_ptr && info_ptr->num_palette) + { + if (buf[0] >= info_ptr->num_palette) + { + png_warning(png_ptr, "Incorrect bKGD chunk index value"); + return; + } + + png_ptr->background.red = + (png_uint_16)png_ptr->palette[buf[0]].red; + + png_ptr->background.green = + (png_uint_16)png_ptr->palette[buf[0]].green; + + png_ptr->background.blue = + (png_uint_16)png_ptr->palette[buf[0]].blue; + } + } + + else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ + { + png_ptr->background.red = + png_ptr->background.green = + png_ptr->background.blue = + png_ptr->background.gray = png_get_uint_16(buf); + } + + else + { + png_ptr->background.red = png_get_uint_16(buf); + png_ptr->background.green = png_get_uint_16(buf + 2); + png_ptr->background.blue = png_get_uint_16(buf + 4); + } + + png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); +} +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +void /* PRIVATE */ +png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + unsigned int num, i; + png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_hIST"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before hIST"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid hIST after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (!(png_ptr->mode & PNG_HAVE_PLTE)) + { + png_warning(png_ptr, "Missing PLTE before hIST"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)) + { + png_warning(png_ptr, "Duplicate hIST chunk"); + png_crc_finish(png_ptr, length); + return; + } + + num = length / 2 ; + + if (num != (unsigned int)png_ptr->num_palette || num > + (unsigned int)PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, "Incorrect hIST chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + for (i = 0; i < num; i++) + { + png_byte buf[2]; + + png_crc_read(png_ptr, buf, 2); + readbuf[i] = png_get_uint_16(buf); + } + + if (png_crc_finish(png_ptr, 0)) + return; + + png_set_hIST(png_ptr, info_ptr, readbuf); +} +#endif + +#ifdef PNG_READ_pHYs_SUPPORTED +void /* PRIVATE */ +png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_uint_32 res_x, res_y; + int unit_type; + + png_debug(1, "in png_handle_pHYs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pHYs"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pHYs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)) + { + png_warning(png_ptr, "Duplicate pHYs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect pHYs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + + if (png_crc_finish(png_ptr, 0)) + return; + + res_x = png_get_uint_32(buf); + res_y = png_get_uint_32(buf + 4); + unit_type = buf[8]; + png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); +} +#endif + +#ifdef PNG_READ_oFFs_SUPPORTED +void /* PRIVATE */ +png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[9]; + png_int_32 offset_x, offset_y; + int unit_type; + + png_debug(1, "in png_handle_oFFs"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before oFFs"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid oFFs after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)) + { + png_warning(png_ptr, "Duplicate oFFs chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (length != 9) + { + png_warning(png_ptr, "Incorrect oFFs chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 9); + + if (png_crc_finish(png_ptr, 0)) + return; + + offset_x = png_get_int_32(buf); + offset_y = png_get_int_32(buf + 4); + unit_type = buf[8]; + png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); +} +#endif + +#ifdef PNG_READ_pCAL_SUPPORTED +/* Read the pCAL chunk (described in the PNG Extensions document) */ +void /* PRIVATE */ +png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_int_32 X0, X1; + png_byte type, nparams; + png_charp buf, units, endptr; + png_charpp params; + png_size_t slength; + int i; + + png_debug(1, "in png_handle_pCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before pCAL"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid pCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)) + { + png_warning(png_ptr, "Duplicate pCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)", + length + 1); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory for pCAL purpose"); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + png_debug(3, "Finding end of pCAL purpose string"); + for (buf = png_ptr->chunkdata; *buf; buf++) + /* Empty loop */ ; + + endptr = png_ptr->chunkdata + slength; + + /* We need to have at least 12 bytes after the purpose string + * in order to get the parameter information. + */ + if (endptr <= buf + 12) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_debug(3, "Reading pCAL X0, X1, type, nparams, and units"); + X0 = png_get_int_32((png_bytep)buf+1); + X1 = png_get_int_32((png_bytep)buf+5); + type = buf[9]; + nparams = buf[10]; + units = buf + 11; + + png_debug(3, "Checking pCAL equation type and number of parameters"); + /* Check that we have the right number of parameters for known + * equation types. + */ + if ((type == PNG_EQUATION_LINEAR && nparams != 2) || + (type == PNG_EQUATION_BASE_E && nparams != 3) || + (type == PNG_EQUATION_ARBITRARY && nparams != 3) || + (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) + { + png_warning(png_ptr, "Invalid pCAL parameters for equation type"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + else if (type >= PNG_EQUATION_LAST) + { + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + } + + for (buf = units; *buf; buf++) + /* Empty loop to move past the units string. */ ; + + png_debug(3, "Allocating pCAL parameters array"); + + params = (png_charpp)png_malloc_warn(png_ptr, + (png_size_t)(nparams * png_sizeof(png_charp))); + + if (params == NULL) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_warning(png_ptr, "No memory for pCAL params"); + return; + } + + /* Get pointers to the start of each parameter string. */ + for (i = 0; i < (int)nparams; i++) + { + buf++; /* Skip the null string terminator from previous parameter. */ + + png_debug1(3, "Reading pCAL parameter %d", i); + + for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++) + /* Empty loop to move past each parameter string */ ; + + /* Make sure we haven't run out of data yet */ + if (buf > endptr) + { + png_warning(png_ptr, "Invalid pCAL data"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, params); + return; + } + } + + png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams, + units, params); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, params); +} +#endif + +#ifdef PNG_READ_sCAL_SUPPORTED +/* Read the sCAL chunk */ +void /* PRIVATE */ +png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_size_t slength, i; + int state; + + png_debug(1, "in png_handle_sCAL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before sCAL"); + + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Invalid sCAL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL)) + { + png_warning(png_ptr, "Duplicate sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)", + length + 1); + + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "Out of memory while processing sCAL chunk"); + png_crc_finish(png_ptr, length); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */ + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + /* Validate the unit. */ + if (png_ptr->chunkdata[0] != 1 && png_ptr->chunkdata[0] != 2) + { + png_warning(png_ptr, "Invalid sCAL ignored: invalid unit"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + /* Validate the ASCII numbers, need two ASCII numbers separated by + * a '\0' and they need to fit exactly in the chunk data. + */ + i = 0; + state = 0; + + if (png_ptr->chunkdata[1] == 45 /* negative width */ || + !png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || + i >= slength || png_ptr->chunkdata[i++] != 0) + png_warning(png_ptr, "Invalid sCAL chunk ignored: bad width format"); + + else + { + png_size_t heighti = i; + + if (png_ptr->chunkdata[i] == 45 /* negative height */ || + !png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || + i != slength) + png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format"); + + else + /* This is the (only) success case. */ + png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], + png_ptr->chunkdata+1, png_ptr->chunkdata+heighti); + } + + /* Clean up - just free the temporarily allocated buffer. */ + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; +} +#endif + +#ifdef PNG_READ_tIME_SUPPORTED +void /* PRIVATE */ +png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_byte buf[7]; + png_time mod_time; + + png_debug(1, "in png_handle_tIME"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Out of place tIME chunk"); + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)) + { + png_warning(png_ptr, "Duplicate tIME chunk"); + png_crc_finish(png_ptr, length); + return; + } + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + + if (length != 7) + { + png_warning(png_ptr, "Incorrect tIME chunk length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, buf, 7); + + if (png_crc_finish(png_ptr, 0)) + return; + + mod_time.second = buf[6]; + mod_time.minute = buf[5]; + mod_time.hour = buf[4]; + mod_time.day = buf[3]; + mod_time.month = buf[2]; + mod_time.year = png_get_uint_16(buf); + + png_set_tIME(png_ptr, info_ptr, &mod_time); +} +#endif + +#ifdef PNG_READ_tEXt_SUPPORTED +/* Note: this does not properly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key; + png_charp text; + png_uint_32 skip = 0; + png_size_t slength; + int ret; + + png_debug(1, "in png_handle_tEXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for tEXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before tEXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "tEXt chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process text chunk"); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, skip)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + key = png_ptr->chunkdata; + + key[slength] = 0x00; + + for (text = key; *text; text++) + /* Empty loop to find end of key */ ; + + if (text != key + slength) + text++; + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + png_sizeof(png_text)); + + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process text chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr->key = key; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; + text_ptr->text = text; + text_ptr->text_length = png_strlen(text); + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + png_free(png_ptr, text_ptr); + + if (ret) + png_warning(png_ptr, "Insufficient memory to process text chunk"); +} +#endif + +#ifdef PNG_READ_zTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp text; + int comp_type; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_zTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for zTXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before zTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + * there is no hard and fast rule to tell us where to stop. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "zTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "Out of memory processing zTXt chunk"); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (text = png_ptr->chunkdata; *text; text++) + /* Empty loop */ ; + + /* zTXt must have some text after the chunkdataword */ + if (text >= png_ptr->chunkdata + slength - 2) + { + png_warning(png_ptr, "Truncated zTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + else + { + comp_type = *(++text); + + if (comp_type != PNG_TEXT_COMPRESSION_zTXt) + { + png_warning(png_ptr, "Unknown compression type in zTXt chunk"); + comp_type = PNG_TEXT_COMPRESSION_zTXt; + } + + text++; /* Skip the compression_method byte */ + } + + prefix_len = text - png_ptr->chunkdata; + + png_decompress_chunk(png_ptr, comp_type, + (png_size_t)length, prefix_len, &data_len); + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + png_sizeof(png_text)); + + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process zTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + text_ptr->compression = comp_type; + text_ptr->key = png_ptr->chunkdata; + text_ptr->lang = NULL; + text_ptr->lang_key = NULL; + text_ptr->itxt_length = 0; + text_ptr->text = png_ptr->chunkdata + prefix_len; + text_ptr->text_length = data_len; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + + if (ret) + png_error(png_ptr, "Insufficient memory to store zTXt chunk"); +} +#endif + +#ifdef PNG_READ_iTXt_SUPPORTED +/* Note: this does not correctly handle chunks that are > 64K under DOS */ +void /* PRIVATE */ +png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_textp text_ptr; + png_charp key, lang, text, lang_key; + int comp_flag; + int comp_type = 0; + int ret; + png_size_t slength, prefix_len, data_len; + + png_debug(1, "in png_handle_iTXt"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for iTXt"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + png_error(png_ptr, "Missing IHDR before iTXt"); + + if (png_ptr->mode & PNG_HAVE_IDAT) + png_ptr->mode |= PNG_AFTER_IDAT; + +#ifdef PNG_MAX_MALLOC_64K + /* We will no doubt have problems with chunks even half this size, but + * there is no hard and fast rule to tell us where to stop. + */ + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "iTXt chunk too large to fit in memory"); + png_crc_finish(png_ptr, length); + return; + } +#endif + + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1); + + if (png_ptr->chunkdata == NULL) + { + png_warning(png_ptr, "No memory to process iTXt chunk"); + return; + } + + slength = (png_size_t)length; + png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength); + + if (png_crc_finish(png_ptr, 0)) + { + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + png_ptr->chunkdata[slength] = 0x00; + + for (lang = png_ptr->chunkdata; *lang; lang++) + /* Empty loop */ ; + + lang++; /* Skip NUL separator */ + + /* iTXt must have a language tag (possibly empty), two compression bytes, + * translated keyword (possibly empty), and possibly some text after the + * keyword + */ + + if (lang >= png_ptr->chunkdata + slength - 3) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + else + { + comp_flag = *lang++; + comp_type = *lang++; + } + + for (lang_key = lang; *lang_key; lang_key++) + /* Empty loop */ ; + + lang_key++; /* Skip NUL separator */ + + if (lang_key >= png_ptr->chunkdata + slength) + { + png_warning(png_ptr, "Truncated iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + for (text = lang_key; *text; text++) + /* Empty loop */ ; + + text++; /* Skip NUL separator */ + + if (text >= png_ptr->chunkdata + slength) + { + png_warning(png_ptr, "Malformed iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + prefix_len = text - png_ptr->chunkdata; + + key=png_ptr->chunkdata; + + if (comp_flag) + png_decompress_chunk(png_ptr, comp_type, + (size_t)length, prefix_len, &data_len); + + else + data_len = png_strlen(png_ptr->chunkdata + prefix_len); + + text_ptr = (png_textp)png_malloc_warn(png_ptr, + png_sizeof(png_text)); + + if (text_ptr == NULL) + { + png_warning(png_ptr, "Not enough memory to process iTXt chunk"); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + return; + } + + text_ptr->compression = (int)comp_flag + 1; + text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key); + text_ptr->lang = png_ptr->chunkdata + (lang - key); + text_ptr->itxt_length = data_len; + text_ptr->text_length = 0; + text_ptr->key = png_ptr->chunkdata; + text_ptr->text = png_ptr->chunkdata + prefix_len; + + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); + + png_free(png_ptr, text_ptr); + png_free(png_ptr, png_ptr->chunkdata); + png_ptr->chunkdata = NULL; + + if (ret) + png_error(png_ptr, "Insufficient memory to store iTXt chunk"); +} +#endif + +/* This function is called when we haven't found a handler for a + * chunk. If there isn't a problem with the chunk itself (ie bad + * chunk name, CRC, or a critical chunk), the chunk is silently ignored + * -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which + * case it will be saved away to be written out later. + */ +void /* PRIVATE */ +png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +{ + png_uint_32 skip = 0; + + png_debug(1, "in png_handle_unknown"); + +#ifdef PNG_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_cache_max != 0) + { + if (png_ptr->user_chunk_cache_max == 1) + { + png_crc_finish(png_ptr, length); + return; + } + + if (--png_ptr->user_chunk_cache_max == 1) + { + png_warning(png_ptr, "No space in chunk cache for unknown chunk"); + png_crc_finish(png_ptr, length); + return; + } + } +#endif + + if (png_ptr->mode & PNG_HAVE_IDAT) + { + PNG_IDAT; + + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */ + png_ptr->mode |= PNG_AFTER_IDAT; + } + + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + && png_ptr->read_user_chunk_fn == NULL +#endif + ) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + || (png_ptr->read_user_chunk_fn != NULL) +#endif + ) + { +#ifdef PNG_MAX_MALLOC_64K + if (length > (png_uint_32)65535L) + { + png_warning(png_ptr, "unknown chunk too large to fit in memory"); + skip = length - (png_uint_32)65535L; + length = (png_uint_32)65535L; + } +#endif + + png_memcpy((png_charp)png_ptr->unknown_chunk.name, + (png_charp)png_ptr->chunk_name, + png_sizeof(png_ptr->unknown_chunk.name)); + + png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] + = '\0'; + + png_ptr->unknown_chunk.size = (png_size_t)length; + + if (length == 0) + png_ptr->unknown_chunk.data = NULL; + + else + { + png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length); + png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); + } + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + if (png_ptr->read_user_chunk_fn != NULL) + { + /* Callback to user unknown chunk handler */ + int ret; + + ret = (*(png_ptr->read_user_chunk_fn)) + (png_ptr, &png_ptr->unknown_chunk); + + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + + if (ret == 0) + { + if (!(png_ptr->chunk_name[0] & 0x20)) + { +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != + PNG_HANDLE_CHUNK_ALWAYS) +#endif + png_chunk_error(png_ptr, "unknown critical chunk"); + } + + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + } + } + + else +#endif + png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); + + png_free(png_ptr, png_ptr->unknown_chunk.data); + png_ptr->unknown_chunk.data = NULL; + } + + else +#endif + skip = length; + + png_crc_finish(png_ptr, skip); + +#ifndef PNG_READ_USER_CHUNKS_SUPPORTED + PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */ +#endif +} + +/* This function is called to verify that a chunk name is valid. + * This function can't have the "critical chunk check" incorporated + * into it, since in the future we will need to be able to call user + * functions to handle unknown critical chunks after we check that + * the chunk name itself is valid. + */ + +#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + +void /* PRIVATE */ +png_check_chunk_name(png_structp png_ptr, png_const_bytep chunk_name) +{ + png_debug(1, "in png_check_chunk_name"); + if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) || + isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3])) + { + png_chunk_error(png_ptr, "invalid chunk type"); + } +} + +/* Combines the row recently read in with the existing pixels in the + * row. This routine takes care of alpha and transparency if requested. + * This routine also handles the two methods of progressive display + * of interlaced images, depending on the mask value. + * The mask value describes which pixels are to be combined with + * the row. The pattern always repeats every 8 pixels, so just 8 + * bits are needed. A one indicates the pixel is to be combined, + * a zero indicates the pixel is to be skipped. This is in addition + * to any alpha or transparency value associated with the pixel. If + * you want all pixels to be combined, pass 0xff (255) in mask. + */ + +void /* PRIVATE */ +png_combine_row(png_structp png_ptr, png_bytep row, int mask) +{ + png_debug(1, "in png_combine_row"); + + if (mask == 0xff) + { + png_memcpy(row, png_ptr->row_buf + 1, + PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)); + } + + else + { + switch (png_ptr->row_info.pixel_depth) + { + case 1: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_inc, s_start, s_end; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 7; + s_inc = 1; + } + + else +#endif + { + s_start = 7; + s_end = 0; + s_inc = -1; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + int value; + + value = (*sp >> shift) & 0x01; + *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + + else + shift += s_inc; + + if (m == 1) + m = 0x80; + + else + m >>= 1; + } + break; + } + + case 2: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 6; + s_inc = 2; + } + + else +#endif + { + s_start = 6; + s_end = 0; + s_inc = -2; + } + + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0x03; + *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + + else + shift += s_inc; + + if (m == 1) + m = 0x80; + + else + m >>= 1; + } + break; + } + + case 4: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + int s_start, s_end, s_inc; + int m = 0x80; + int shift; + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + int value; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + { + s_start = 0; + s_end = 4; + s_inc = 4; + } + + else +#endif + { + s_start = 4; + s_end = 0; + s_inc = -4; + } + shift = s_start; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + value = (*sp >> shift) & 0xf; + *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); + *dp |= (png_byte)(value << shift); + } + + if (shift == s_end) + { + shift = s_start; + sp++; + dp++; + } + + else + shift += s_inc; + + if (m == 1) + m = 0x80; + + else + m >>= 1; + } + break; + } + + default: + { + png_bytep sp = png_ptr->row_buf + 1; + png_bytep dp = row; + png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3); + png_uint_32 i; + png_uint_32 row_width = png_ptr->width; + png_byte m = 0x80; + + for (i = 0; i < row_width; i++) + { + if (m & mask) + { + png_memcpy(dp, sp, pixel_bytes); + } + + sp += pixel_bytes; + dp += pixel_bytes; + + if (m == 1) + m = 0x80; + + else + m >>= 1; + } + break; + } + } + } +} + +#ifdef PNG_READ_INTERLACING_SUPPORTED +void /* PRIVATE */ +png_do_read_interlace(png_structp png_ptr) +{ + png_row_infop row_info = &(png_ptr->row_info); + png_bytep row = png_ptr->row_buf + 1; + int pass = png_ptr->pass; + png_uint_32 transformations = png_ptr->transformations; + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_read_interlace"); + if (row != NULL && row_info != NULL) + { + png_uint_32 final_width; + + final_width = row_info->width * png_pass_inc[pass]; + + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_byte v; + png_uint_32 i; + int j; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)((row_info->width + 7) & 0x07); + dshift = (int)((final_width + 7) & 0x07); + s_start = 7; + s_end = 0; + s_inc = -1; + } + + else +#endif + { + sshift = 7 - (int)((row_info->width + 7) & 0x07); + dshift = 7 - (int)((final_width + 7) & 0x07); + s_start = 0; + s_end = 7; + s_inc = 1; + } + + for (i = 0; i < row_info->width; i++) + { + v = (png_byte)((*sp >> sshift) & 0x01); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + + case 2: + { + png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + int sshift, dshift; + int s_start, s_end, s_inc; + int jstop = png_pass_inc[pass]; + png_uint_32 i; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 3) & 0x03) << 1); + dshift = (int)(((final_width + 3) & 0x03) << 1); + s_start = 6; + s_end = 0; + s_inc = -2; + } + + else +#endif + { + sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1); + dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1); + s_start = 0; + s_end = 6; + s_inc = 2; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v; + int j; + + v = (png_byte)((*sp >> sshift) & 0x03); + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + + case 4: + { + png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); + png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + int sshift, dshift; + int s_start, s_end, s_inc; + png_uint_32 i; + int jstop = png_pass_inc[pass]; + +#ifdef PNG_READ_PACKSWAP_SUPPORTED + if (transformations & PNG_PACKSWAP) + { + sshift = (int)(((row_info->width + 1) & 0x01) << 2); + dshift = (int)(((final_width + 1) & 0x01) << 2); + s_start = 4; + s_end = 0; + s_inc = -4; + } + + else +#endif + { + sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2); + dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2); + s_start = 0; + s_end = 4; + s_inc = 4; + } + + for (i = 0; i < row_info->width; i++) + { + png_byte v = (png_byte)((*sp >> sshift) & 0xf); + int j; + + for (j = 0; j < jstop; j++) + { + *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff); + *dp |= (png_byte)(v << dshift); + + if (dshift == s_end) + { + dshift = s_start; + dp--; + } + + else + dshift += s_inc; + } + + if (sshift == s_end) + { + sshift = s_start; + sp--; + } + + else + sshift += s_inc; + } + break; + } + default: + { + png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + + png_bytep sp = row + (png_size_t)(row_info->width - 1) + * pixel_bytes; + + png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + + int jstop = png_pass_inc[pass]; + png_uint_32 i; + + for (i = 0; i < row_info->width; i++) + { + png_byte v[8]; + int j; + + png_memcpy(v, sp, pixel_bytes); + + for (j = 0; j < jstop; j++) + { + png_memcpy(dp, v, pixel_bytes); + dp -= pixel_bytes; + } + + sp -= pixel_bytes; + } + break; + } + } + row_info->width = final_width; + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width); + } +#ifndef PNG_READ_PACKSWAP_SUPPORTED + PNG_UNUSED(transformations) /* Silence compiler warning */ +#endif +} +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + +void /* PRIVATE */ +png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row, + png_const_bytep prev_row, int filter) +{ + png_debug(1, "in png_read_filter_row"); + png_debug2(2, "row = %u, filter = %d", png_ptr->row_number, filter); + switch (filter) + { + case PNG_FILTER_VALUE_NONE: + break; + + case PNG_FILTER_VALUE_SUB: + { + png_size_t i; + png_size_t istop = row_info->rowbytes; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp = row + bpp; + png_bytep lp = row; + + for (i = bpp; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_UP: + { + png_size_t i; + png_size_t istop = row_info->rowbytes; + png_bytep rp = row; + png_const_bytep pp = prev_row; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + break; + } + case PNG_FILTER_VALUE_AVG: + { + png_size_t i; + png_bytep rp = row; + png_const_bytep pp = prev_row; + png_bytep lp = row; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_size_t istop = row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + + rp++; + } + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *lp++) / 2 ) & 0xff); + + rp++; + } + break; + } + case PNG_FILTER_VALUE_PAETH: + { + png_size_t i; + png_bytep rp = row; + png_const_bytep pp = prev_row; + png_bytep lp = row; + png_const_bytep cp = prev_row; + unsigned int bpp = (row_info->pixel_depth + 7) >> 3; + png_size_t istop=row_info->rowbytes - bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + + for (i = 0; i < istop; i++) /* Use leftover rp,pp */ + { + int a, b, c, pa, pb, pc, p; + + a = *lp++; + b = *pp++; + c = *cp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + /* + if (pa <= pb && pa <= pc) + p = a; + + else if (pb <= pc) + p = b; + + else + p = c; + */ + + p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; + + *rp = (png_byte)(((int)(*rp) + p) & 0xff); + rp++; + } + break; + } + default: + png_error(png_ptr, "Ignoring bad adaptive filter type"); + /*NOT REACHED */ + break; + } +} + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED +void /* PRIVATE */ +png_read_finish_row(png_structp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + png_debug(1, "in png_read_finish_row"); + png_ptr->row_number++; + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + do + { + png_ptr->pass++; + + if (png_ptr->pass >= 7) + break; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + } + + else /* if (png_ptr->transformations & PNG_INTERLACE) */ + break; /* libpng deinterlacing sees every row */ + + } while (png_ptr->num_rows == 0 || png_ptr->iwidth == 0); + + if (png_ptr->pass < 7) + return; + } +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) + { + PNG_IDAT; + char extra; + int ret; + + png_ptr->zstream.next_out = (Byte *)&extra; + png_ptr->zstream.avail_out = (uInt)1; + + for (;;) + { + if (!(png_ptr->zstream.avail_in)) + { + while (!png_ptr->idat_size) + { + png_crc_finish(png_ptr, 0); + png_ptr->idat_size = png_read_chunk_header(png_ptr); + if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) + png_error(png_ptr, "Not enough image data"); + } + + png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_in = png_ptr->zbuf; + + if (png_ptr->zbuf_size > png_ptr->idat_size) + png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; + + png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); + png_ptr->idat_size -= png_ptr->zstream.avail_in; + } + + ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); + + if (ret == Z_STREAM_END) + { + if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in || + png_ptr->idat_size) + png_warning(png_ptr, "Extra compressed data"); + + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + if (ret != Z_OK) + png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : + "Decompression Error"); + + if (!(png_ptr->zstream.avail_out)) + { + png_warning(png_ptr, "Extra compressed data"); + png_ptr->mode |= PNG_AFTER_IDAT; + png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; + break; + } + + } + png_ptr->zstream.avail_out = 0; + } + + if (png_ptr->idat_size || png_ptr->zstream.avail_in) + png_warning(png_ptr, "Extra compression data"); + + inflateReset(&png_ptr->zstream); + + png_ptr->mode |= PNG_AFTER_IDAT; +} +#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +void /* PRIVATE */ +png_read_start_row(png_structp png_ptr) +{ +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int max_pixel_depth; + png_size_t row_bytes; + + png_debug(1, "in png_read_start_row"); + png_ptr->zstream.avail_in = 0; + png_init_read_transformations(png_ptr); +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + } + + else +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + } + + max_pixel_depth = png_ptr->pixel_depth; + +#ifdef PNG_READ_PACK_SUPPORTED + if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) + max_pixel_depth = 8; +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + if (png_ptr->num_trans) + max_pixel_depth = 32; + + else + max_pixel_depth = 24; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth < 8) + max_pixel_depth = 8; + + if (png_ptr->num_trans) + max_pixel_depth *= 2; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (png_ptr->num_trans) + { + max_pixel_depth *= 4; + max_pixel_depth /= 3; + } + } + } +#endif + +#ifdef PNG_READ_FILLER_SUPPORTED + if (png_ptr->transformations & (PNG_FILLER)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + max_pixel_depth = 32; + + else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + { + if (max_pixel_depth <= 8) + max_pixel_depth = 16; + + else + max_pixel_depth = 32; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + if (max_pixel_depth <= 32) + max_pixel_depth = 32; + + else + max_pixel_depth = 64; + } + } +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + if (png_ptr->transformations & PNG_GRAY_TO_RGB) + { + if ( +#ifdef PNG_READ_EXPAND_SUPPORTED + (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) || +#endif +#ifdef PNG_READ_FILLER_SUPPORTED + (png_ptr->transformations & (PNG_FILLER)) || +#endif + png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (max_pixel_depth <= 16) + max_pixel_depth = 32; + + else + max_pixel_depth = 64; + } + + else + { + if (max_pixel_depth <= 8) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 32; + + else + max_pixel_depth = 24; + } + + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + max_pixel_depth = 64; + + else + max_pixel_depth = 48; + } + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \ +defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) + if (png_ptr->transformations & PNG_USER_TRANSFORM) + { + int user_pixel_depth = png_ptr->user_transform_depth* + png_ptr->user_transform_channels; + + if (user_pixel_depth > max_pixel_depth) + max_pixel_depth=user_pixel_depth; + } +#endif + + /* Align the width on the next larger 8 pixels. Mainly used + * for interlacing + */ + row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7)); + /* Calculate the maximum bytes needed, adding a byte and a pixel + * for safety's sake + */ + row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) + + 1 + ((max_pixel_depth + 7) >> 3); + +#ifdef PNG_MAX_MALLOC_64K + if (row_bytes > (png_uint_32)65536L) + png_error(png_ptr, "This image requires a row greater than 64KB"); +#endif + + if (row_bytes + 48 > png_ptr->old_big_row_buf_size) + { + png_free(png_ptr, png_ptr->big_row_buf); + + if (png_ptr->interlaced) + png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, + row_bytes + 48); + + else + png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, + row_bytes + 48); + + png_ptr->old_big_row_buf_size = row_bytes + 48; + +#ifdef PNG_ALIGNED_MEMORY_SUPPORTED + /* Use 16-byte aligned memory for row_buf with at least 16 bytes + * of padding before and after row_buf. + */ + png_ptr->row_buf = png_ptr->big_row_buf + 32 - + (((png_alloc_size_t)png_ptr->big_row_buf + 15) & 0x0F); + + png_ptr->old_big_row_buf_size = row_bytes + 48; +#else + /* Use 32 bytes of padding before and 16 bytes after row_buf. */ + png_ptr->row_buf = png_ptr->big_row_buf + 32; +#endif + png_ptr->old_big_row_buf_size = row_bytes + 48; + } + +#ifdef PNG_MAX_MALLOC_64K + if (png_ptr->rowbytes > 65535) + png_error(png_ptr, "This image requires a row greater than 64KB"); + +#endif + if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1)) + png_error(png_ptr, "Row has too many bytes to allocate in memory"); + + if (png_ptr->rowbytes + 1 > png_ptr->old_prev_row_size) + { + png_free(png_ptr, png_ptr->prev_row); + + png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1); + + png_ptr->old_prev_row_size = png_ptr->rowbytes + 1; + } + + png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + + png_debug1(3, "width = %u,", png_ptr->width); + png_debug1(3, "height = %u,", png_ptr->height); + png_debug1(3, "iwidth = %u,", png_ptr->iwidth); + png_debug1(3, "num_rows = %u,", png_ptr->num_rows); + png_debug1(3, "rowbytes = %lu,", (unsigned long)png_ptr->rowbytes); + png_debug1(3, "irowbytes = %lu", + (unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1); + + png_ptr->flags |= PNG_FLAG_ROW_INIT; +} +#endif /* PNG_READ_SUPPORTED */ diff --git a/contrib/libpng/pngset.c b/contrib/libpng/pngset.c new file mode 100644 index 0000000..2cfcf33 --- /dev/null +++ b/contrib/libpng/pngset.c @@ -0,0 +1,1225 @@ + +/* pngset.c - storage of image information into info struct + * + * Last changed in libpng 1.5.1 [February 3, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * The functions here are used during reads to store data from the file + * into the info struct, and during writes to store application data + * into the info struct for writing into the file. This abstracts the + * info struct and allows us to change the structure in the future. + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#ifdef PNG_bKGD_SUPPORTED +void PNGAPI +png_set_bKGD(png_structp png_ptr, png_infop info_ptr, + png_const_color_16p background) +{ + png_debug1(1, "in %s storage function", "bKGD"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16)); + info_ptr->valid |= PNG_INFO_bKGD; +} +#endif + +#ifdef PNG_cHRM_SUPPORTED +void PNGFAPI +png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, + png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, + png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y) +{ + png_debug1(1, "in %s storage function", "cHRM fixed"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + +# ifdef PNG_CHECK_cHRM_SUPPORTED + if (png_check_cHRM_fixed(png_ptr, + white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y)) +# endif + { + info_ptr->x_white = white_x; + info_ptr->y_white = white_y; + info_ptr->x_red = red_x; + info_ptr->y_red = red_y; + info_ptr->x_green = green_x; + info_ptr->y_green = green_y; + info_ptr->x_blue = blue_x; + info_ptr->y_blue = blue_y; + info_ptr->valid |= PNG_INFO_cHRM; + } +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_cHRM(png_structp png_ptr, png_infop info_ptr, + double white_x, double white_y, double red_x, double red_y, + double green_x, double green_y, double blue_x, double blue_y) +{ + png_set_cHRM_fixed(png_ptr, info_ptr, + png_fixed(png_ptr, white_x, "cHRM White X"), + png_fixed(png_ptr, white_y, "cHRM White Y"), + png_fixed(png_ptr, red_x, "cHRM Red X"), + png_fixed(png_ptr, red_y, "cHRM Red Y"), + png_fixed(png_ptr, green_x, "cHRM Green X"), + png_fixed(png_ptr, green_y, "cHRM Green Y"), + png_fixed(png_ptr, blue_x, "cHRM Blue X"), + png_fixed(png_ptr, blue_y, "cHRM Blue Y")); +} +# endif /* PNG_FLOATING_POINT_SUPPORTED */ + +#endif /* PNG_cHRM_SUPPORTED */ + +#ifdef PNG_gAMA_SUPPORTED +void PNGFAPI +png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point + file_gamma) +{ + png_debug1(1, "in %s storage function", "gAMA"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Previously these values were limited, however they must be + * wrong, therefore storing them (and setting PNG_INFO_gAMA) + * must be wrong too. + */ + if (file_gamma > (png_fixed_point)PNG_UINT_31_MAX) + png_warning(png_ptr, "Gamma too large, ignored"); + + else if (file_gamma <= 0) + png_warning(png_ptr, "Negative or zero gamma ignored"); + + else + { + info_ptr->gamma = file_gamma; + info_ptr->valid |= PNG_INFO_gAMA; + } +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) +{ + png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma, + "png_set_gAMA")); +} +# endif +#endif + +#ifdef PNG_hIST_SUPPORTED +void PNGAPI +png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_uint_16p hist) +{ + int i; + + png_debug1(1, "in %s storage function", "hIST"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->num_palette == 0 || info_ptr->num_palette + > PNG_MAX_PALETTE_LENGTH) + { + png_warning(png_ptr, + "Invalid palette size, hIST allocation skipped"); + + return; + } + + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); + + /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in + * version 1.2.1 + */ + png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, + PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16)); + + if (png_ptr->hist == NULL) + { + png_warning(png_ptr, "Insufficient memory for hIST chunk data"); + return; + } + + for (i = 0; i < info_ptr->num_palette; i++) + png_ptr->hist[i] = hist[i]; + + info_ptr->hist = png_ptr->hist; + info_ptr->valid |= PNG_INFO_hIST; + info_ptr->free_me |= PNG_FREE_HIST; +} +#endif + +void PNGAPI +png_set_IHDR(png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, + int color_type, int interlace_type, int compression_type, + int filter_type) +{ + png_debug1(1, "in %s storage function", "IHDR"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->width = width; + info_ptr->height = height; + info_ptr->bit_depth = (png_byte)bit_depth; + info_ptr->color_type = (png_byte)color_type; + info_ptr->compression_type = (png_byte)compression_type; + info_ptr->filter_type = (png_byte)filter_type; + info_ptr->interlace_type = (png_byte)interlace_type; + + png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, + info_ptr->compression_type, info_ptr->filter_type); + + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + info_ptr->channels = 1; + + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_ptr->channels = 3; + + else + info_ptr->channels = 1; + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + info_ptr->channels++; + + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + /* Check for potential overflow */ + if (width > + (PNG_UINT_32_MAX >> 3) /* 8-byte RRGGBBAA pixels */ + - 48 /* bigrowbuf hack */ + - 1 /* filter byte */ + - 7*8 /* rounding of width to multiple of 8 pixels */ + - 8) /* extra max_pixel_depth pad */ + info_ptr->rowbytes = 0; + else + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); +} + +#ifdef PNG_oFFs_SUPPORTED +void PNGAPI +png_set_oFFs(png_structp png_ptr, png_infop info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "oFFs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_offset = offset_x; + info_ptr->y_offset = offset_y; + info_ptr->offset_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_oFFs; +} +#endif + +#ifdef PNG_pCAL_SUPPORTED +void PNGAPI +png_set_pCAL(png_structp png_ptr, png_infop info_ptr, + png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, + int nparams, png_const_charp units, png_charpp params) +{ + png_size_t length; + int i; + + png_debug1(1, "in %s storage function", "pCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + length = png_strlen(purpose) + 1; + png_debug1(3, "allocating purpose for info (%lu bytes)", + (unsigned long)length); + + /* TODO: validate format of calibration name and unit name */ + + /* Check that the type matches the specification. */ + if (type < 0 || type > 3) + png_error(png_ptr, "Invalid pCAL equation type"); + + /* Validate params[nparams] */ + for (i=0; ipcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); + + if (info_ptr->pcal_purpose == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL purpose"); + return; + } + + png_memcpy(info_ptr->pcal_purpose, purpose, length); + + png_debug(3, "storing X0, X1, type, and nparams in info"); + info_ptr->pcal_X0 = X0; + info_ptr->pcal_X1 = X1; + info_ptr->pcal_type = (png_byte)type; + info_ptr->pcal_nparams = (png_byte)nparams; + + length = png_strlen(units) + 1; + png_debug1(3, "allocating units for info (%lu bytes)", + (unsigned long)length); + + info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); + + if (info_ptr->pcal_units == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL units"); + return; + } + + png_memcpy(info_ptr->pcal_units, units, length); + + info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, + (png_size_t)((nparams + 1) * png_sizeof(png_charp))); + + if (info_ptr->pcal_params == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL params"); + return; + } + + png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp)); + + for (i = 0; i < nparams; i++) + { + length = png_strlen(params[i]) + 1; + png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, + (unsigned long)length); + + info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + + if (info_ptr->pcal_params[i] == NULL) + { + png_warning(png_ptr, "Insufficient memory for pCAL parameter"); + return; + } + + png_memcpy(info_ptr->pcal_params[i], params[i], length); + } + + info_ptr->valid |= PNG_INFO_pCAL; + info_ptr->free_me |= PNG_FREE_PCAL; +} +#endif + +#ifdef PNG_sCAL_SUPPORTED +void PNGAPI +png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, + int unit, png_const_charp swidth, png_const_charp sheight) +{ + png_size_t lengthw = 0, lengthh = 0; + + png_debug1(1, "in %s storage function", "sCAL"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Double check the unit (should never get here with an invalid + * unit unless this is an API call.) + */ + if (unit != 1 && unit != 2) + png_error(png_ptr, "Invalid sCAL unit"); + + if (swidth == NULL || (lengthw = png_strlen(swidth)) <= 0 || + swidth[0] == 45 /*'-'*/ || !png_check_fp_string(swidth, lengthw)) + png_error(png_ptr, "Invalid sCAL width"); + + if (sheight == NULL || (lengthh = png_strlen(sheight)) <= 0 || + sheight[0] == 45 /*'-'*/ || !png_check_fp_string(sheight, lengthh)) + png_error(png_ptr, "Invalid sCAL height"); + + info_ptr->scal_unit = (png_byte)unit; + + ++lengthw; + + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw); + + info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, lengthw); + + if (info_ptr->scal_s_width == NULL) + { + png_warning(png_ptr, "Memory allocation failed while processing sCAL"); + return; + } + + png_memcpy(info_ptr->scal_s_width, swidth, lengthw); + + ++lengthh; + + png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh); + + info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, lengthh); + + if (info_ptr->scal_s_height == NULL) + { + png_free (png_ptr, info_ptr->scal_s_width); + info_ptr->scal_s_width = NULL; + + png_warning(png_ptr, "Memory allocation failed while processing sCAL"); + return; + } + + png_memcpy(info_ptr->scal_s_height, sheight, lengthh); + + info_ptr->valid |= PNG_INFO_sCAL; + info_ptr->free_me |= PNG_FREE_SCAL; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width, + double height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + /* Check the arguments. */ + if (width <= 0) + png_warning(png_ptr, "Invalid sCAL width ignored"); + + else if (height <= 0) + png_warning(png_ptr, "Invalid sCAL height ignored"); + + else + { + /* Convert 'width' and 'height' to ASCII. */ + char swidth[PNG_sCAL_MAX_DIGITS+1]; + char sheight[PNG_sCAL_MAX_DIGITS+1]; + + png_ascii_from_fp(png_ptr, swidth, sizeof swidth, width, + PNG_sCAL_PRECISION); + png_ascii_from_fp(png_ptr, sheight, sizeof sheight, height, + PNG_sCAL_PRECISION); + + png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); + } +} +# endif + +# ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit, + png_fixed_point width, png_fixed_point height) +{ + png_debug1(1, "in %s storage function", "sCAL"); + + /* Check the arguments. */ + if (width <= 0) + png_warning(png_ptr, "Invalid sCAL width ignored"); + + else if (height <= 0) + png_warning(png_ptr, "Invalid sCAL height ignored"); + + else + { + /* Convert 'width' and 'height' to ASCII. */ + char swidth[PNG_sCAL_MAX_DIGITS+1]; + char sheight[PNG_sCAL_MAX_DIGITS+1]; + + png_ascii_from_fixed(png_ptr, swidth, sizeof swidth, width); + png_ascii_from_fixed(png_ptr, sheight, sizeof sheight, height); + + png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight); + } +} +# endif +#endif + +#ifdef PNG_pHYs_SUPPORTED +void PNGAPI +png_set_pHYs(png_structp png_ptr, png_infop info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type) +{ + png_debug1(1, "in %s storage function", "pHYs"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->x_pixels_per_unit = res_x; + info_ptr->y_pixels_per_unit = res_y; + info_ptr->phys_unit_type = (png_byte)unit_type; + info_ptr->valid |= PNG_INFO_pHYs; +} +#endif + +void PNGAPI +png_set_PLTE(png_structp png_ptr, png_infop info_ptr, + png_const_colorp palette, int num_palette) +{ + + png_debug1(1, "in %s storage function", "PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) + { + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Invalid palette length"); + + else + { + png_warning(png_ptr, "Invalid palette length"); + return; + } + } + + /* It may not actually be necessary to set png_ptr->palette here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); + + /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead + * of num_palette entries, in case of an invalid PNG file that has + * too-large sample values. + */ + png_ptr->palette = (png_colorp)png_calloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)); + + png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color)); + info_ptr->palette = png_ptr->palette; + info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; + + info_ptr->free_me |= PNG_FREE_PLTE; + + info_ptr->valid |= PNG_INFO_PLTE; +} + +#ifdef PNG_sBIT_SUPPORTED +void PNGAPI +png_set_sBIT(png_structp png_ptr, png_infop info_ptr, + png_const_color_8p sig_bit) +{ + png_debug1(1, "in %s storage function", "sBIT"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8)); + info_ptr->valid |= PNG_INFO_sBIT; +} +#endif + +#ifdef PNG_sRGB_SUPPORTED +void PNGAPI +png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int srgb_intent) +{ + png_debug1(1, "in %s storage function", "sRGB"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->srgb_intent = (png_byte)srgb_intent; + info_ptr->valid |= PNG_INFO_sRGB; +} + +void PNGAPI +png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, + int srgb_intent) +{ + png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + +# ifdef PNG_gAMA_SUPPORTED + png_set_gAMA_fixed(png_ptr, info_ptr, 45455L); +# endif + +# ifdef PNG_cHRM_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + /* color x y */ + /* white */ 31270L, 32900L, + /* red */ 64000L, 33000L, + /* green */ 30000L, 60000L, + /* blue */ 15000L, 6000L + ); +# endif /* cHRM */ +} +#endif /* sRGB */ + + +#ifdef PNG_iCCP_SUPPORTED +void PNGAPI +png_set_iCCP(png_structp png_ptr, png_infop info_ptr, + png_const_charp name, int compression_type, + png_const_bytep profile, png_uint_32 proflen) +{ + png_charp new_iccp_name; + png_bytep new_iccp_profile; + png_uint_32 length; + + png_debug1(1, "in %s storage function", "iCCP"); + + if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) + return; + + length = png_strlen(name)+1; + new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length); + + if (new_iccp_name == NULL) + { + png_warning(png_ptr, "Insufficient memory to process iCCP chunk"); + return; + } + + png_memcpy(new_iccp_name, name, length); + new_iccp_profile = (png_bytep)png_malloc_warn(png_ptr, proflen); + + if (new_iccp_profile == NULL) + { + png_free (png_ptr, new_iccp_name); + png_warning(png_ptr, + "Insufficient memory to process iCCP profile"); + return; + } + + png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); + + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); + + info_ptr->iccp_proflen = proflen; + info_ptr->iccp_name = new_iccp_name; + info_ptr->iccp_profile = new_iccp_profile; + /* Compression is always zero but is here so the API and info structure + * does not have to change if we introduce multiple compression types + */ + info_ptr->iccp_compression = (png_byte)compression_type; + info_ptr->free_me |= PNG_FREE_ICCP; + info_ptr->valid |= PNG_INFO_iCCP; +} +#endif + +#ifdef PNG_TEXT_SUPPORTED +void PNGAPI +png_set_text(png_structp png_ptr, png_infop info_ptr, png_const_textp text_ptr, + int num_text) +{ + int ret; + ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); + + if (ret) + png_error(png_ptr, "Insufficient memory to store text"); +} + +int /* PRIVATE */ +png_set_text_2(png_structp png_ptr, png_infop info_ptr, + png_const_textp text_ptr, int num_text) +{ + int i; + + png_debug1(1, "in %s storage function", ((png_ptr == NULL || + png_ptr->chunk_name[0] == '\0') ? + "text" : (png_const_charp)png_ptr->chunk_name)); + + if (png_ptr == NULL || info_ptr == NULL || num_text == 0) + return(0); + + /* Make sure we have enough space in the "text" array in info_struct + * to hold all of the incoming text_ptr objects. + */ + if (info_ptr->num_text + num_text > info_ptr->max_text) + { + if (info_ptr->text != NULL) + { + png_textp old_text; + int old_max; + + old_max = info_ptr->max_text; + info_ptr->max_text = info_ptr->num_text + num_text + 8; + old_text = info_ptr->text; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_size_t)(info_ptr->max_text * png_sizeof(png_text))); + + if (info_ptr->text == NULL) + { + png_free(png_ptr, old_text); + return(1); + } + + png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * + png_sizeof(png_text))); + png_free(png_ptr, old_text); + } + + else + { + info_ptr->max_text = num_text + 8; + info_ptr->num_text = 0; + info_ptr->text = (png_textp)png_malloc_warn(png_ptr, + (png_size_t)(info_ptr->max_text * png_sizeof(png_text))); + if (info_ptr->text == NULL) + return(1); + info_ptr->free_me |= PNG_FREE_TEXT; + } + + png_debug1(3, "allocated %d entries for info_ptr->text", + info_ptr->max_text); + } + for (i = 0; i < num_text; i++) + { + png_size_t text_length, key_len; + png_size_t lang_len, lang_key_len; + png_textp textp = &(info_ptr->text[info_ptr->num_text]); + + if (text_ptr[i].key == NULL) + continue; + + if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE || + text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST) + { + png_warning(png_ptr, "text compression mode is out of range"); + continue; + } + + key_len = png_strlen(text_ptr[i].key); + + if (text_ptr[i].compression <= 0) + { + lang_len = 0; + lang_key_len = 0; + } + + else +# ifdef PNG_iTXt_SUPPORTED + { + /* Set iTXt data */ + + if (text_ptr[i].lang != NULL) + lang_len = png_strlen(text_ptr[i].lang); + + else + lang_len = 0; + + if (text_ptr[i].lang_key != NULL) + lang_key_len = png_strlen(text_ptr[i].lang_key); + + else + lang_key_len = 0; + } +# else /* PNG_iTXt_SUPPORTED */ + { + png_warning(png_ptr, "iTXt chunk not supported"); + continue; + } +# endif + + if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') + { + text_length = 0; +# ifdef PNG_iTXt_SUPPORTED + if (text_ptr[i].compression > 0) + textp->compression = PNG_ITXT_COMPRESSION_NONE; + + else +# endif + textp->compression = PNG_TEXT_COMPRESSION_NONE; + } + + else + { + text_length = png_strlen(text_ptr[i].text); + textp->compression = text_ptr[i].compression; + } + + textp->key = (png_charp)png_malloc_warn(png_ptr, + (png_size_t) + (key_len + text_length + lang_len + lang_key_len + 4)); + + if (textp->key == NULL) + return(1); + + png_debug2(2, "Allocated %lu bytes at %p in png_set_text", + (unsigned long)(png_uint_32) + (key_len + lang_len + lang_key_len + text_length + 4), + textp->key); + + png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len)); + *(textp->key + key_len) = '\0'; + + if (text_ptr[i].compression > 0) + { + textp->lang = textp->key + key_len + 1; + png_memcpy(textp->lang, text_ptr[i].lang, lang_len); + *(textp->lang + lang_len) = '\0'; + textp->lang_key = textp->lang + lang_len + 1; + png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); + *(textp->lang_key + lang_key_len) = '\0'; + textp->text = textp->lang_key + lang_key_len + 1; + } + + else + { + textp->lang=NULL; + textp->lang_key=NULL; + textp->text = textp->key + key_len + 1; + } + + if (text_length) + png_memcpy(textp->text, text_ptr[i].text, + (png_size_t)(text_length)); + + *(textp->text + text_length) = '\0'; + +# ifdef PNG_iTXt_SUPPORTED + if (textp->compression > 0) + { + textp->text_length = 0; + textp->itxt_length = text_length; + } + + else +# endif + { + textp->text_length = text_length; + textp->itxt_length = 0; + } + + info_ptr->num_text++; + png_debug1(3, "transferred text chunk %d", info_ptr->num_text); + } + return(0); +} +#endif + +#ifdef PNG_tIME_SUPPORTED +void PNGAPI +png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time) +{ + png_debug1(1, "in %s storage function", "tIME"); + + if (png_ptr == NULL || info_ptr == NULL || + (png_ptr->mode & PNG_WROTE_tIME)) + return; + + png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time)); + info_ptr->valid |= PNG_INFO_tIME; +} +#endif + +#ifdef PNG_tRNS_SUPPORTED +void PNGAPI +png_set_tRNS(png_structp png_ptr, png_infop info_ptr, + png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color) +{ + png_debug1(1, "in %s storage function", "tRNS"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (trans_alpha != NULL) + { + /* It may not actually be necessary to set png_ptr->trans_alpha here; + * we do it for backward compatibility with the way the png_handle_tRNS + * function used to do the allocation. + */ + + png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); + + /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ + png_ptr->trans_alpha = info_ptr->trans_alpha = + (png_bytep)png_malloc(png_ptr, (png_size_t)PNG_MAX_PALETTE_LENGTH); + + if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) + png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + } + + if (trans_color != NULL) + { + int sample_max = (1 << info_ptr->bit_depth); + + if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_color->gray > sample_max) || + (info_ptr->color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max))) + png_warning(png_ptr, + "tRNS chunk has out-of-range samples for bit_depth"); + + png_memcpy(&(info_ptr->trans_color), trans_color, + png_sizeof(png_color_16)); + + if (num_trans == 0) + num_trans = 1; + } + + info_ptr->num_trans = (png_uint_16)num_trans; + + if (num_trans != 0) + { + info_ptr->valid |= PNG_INFO_tRNS; + info_ptr->free_me |= PNG_FREE_TRNS; + } +} +#endif + +#ifdef PNG_sPLT_SUPPORTED +void PNGAPI +png_set_sPLT(png_structp png_ptr, + png_infop info_ptr, png_const_sPLT_tp entries, int nentries) +/* + * entries - array of png_sPLT_t structures + * to be added to the list of palettes + * in the info structure. + * + * nentries - number of palette structures to be + * added. + */ +{ + png_sPLT_tp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL) + return; + + np = (png_sPLT_tp)png_malloc_warn(png_ptr, + (info_ptr->splt_palettes_num + nentries) * + (png_size_t)png_sizeof(png_sPLT_t)); + + if (np == NULL) + { + png_warning(png_ptr, "No memory for sPLT palettes"); + return; + } + + png_memcpy(np, info_ptr->splt_palettes, + info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t)); + + png_free(png_ptr, info_ptr->splt_palettes); + info_ptr->splt_palettes=NULL; + + for (i = 0; i < nentries; i++) + { + png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; + png_const_sPLT_tp from = entries + i; + png_uint_32 length; + + length = png_strlen(from->name) + 1; + to->name = (png_charp)png_malloc_warn(png_ptr, (png_size_t)length); + + if (to->name == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + continue; + } + + png_memcpy(to->name, from->name, length); + to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, + (png_size_t)(from->nentries * png_sizeof(png_sPLT_entry))); + + if (to->entries == NULL) + { + png_warning(png_ptr, + "Out of memory while processing sPLT chunk"); + png_free(png_ptr, to->name); + to->name = NULL; + continue; + } + + png_memcpy(to->entries, from->entries, + from->nentries * png_sizeof(png_sPLT_entry)); + + to->nentries = from->nentries; + to->depth = from->depth; + } + + info_ptr->splt_palettes = np; + info_ptr->splt_palettes_num += nentries; + info_ptr->valid |= PNG_INFO_sPLT; + info_ptr->free_me |= PNG_FREE_SPLT; +} +#endif /* PNG_sPLT_SUPPORTED */ + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +void PNGAPI +png_set_unknown_chunks(png_structp png_ptr, + png_infop info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) +{ + png_unknown_chunkp np; + int i; + + if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) + return; + + np = (png_unknown_chunkp)png_malloc_warn(png_ptr, + (png_size_t)(info_ptr->unknown_chunks_num + num_unknowns) * + png_sizeof(png_unknown_chunk)); + + if (np == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk"); + return; + } + + png_memcpy(np, info_ptr->unknown_chunks, + (png_size_t)info_ptr->unknown_chunks_num * + png_sizeof(png_unknown_chunk)); + + png_free(png_ptr, info_ptr->unknown_chunks); + info_ptr->unknown_chunks = NULL; + + for (i = 0; i < num_unknowns; i++) + { + png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; + png_const_unknown_chunkp from = unknowns + i; + + png_memcpy(to->name, from->name, png_sizeof(from->name)); + to->name[png_sizeof(to->name)-1] = '\0'; + to->size = from->size; + + /* Note our location in the read or write sequence */ + to->location = (png_byte)(png_ptr->mode & 0xff); + + if (from->size == 0) + to->data=NULL; + + else + { + to->data = (png_bytep)png_malloc_warn(png_ptr, + (png_size_t)from->size); + + if (to->data == NULL) + { + png_warning(png_ptr, + "Out of memory while processing unknown chunk"); + to->size = 0; + } + + else + png_memcpy(to->data, from->data, from->size); + } + } + + info_ptr->unknown_chunks = np; + info_ptr->unknown_chunks_num += num_unknowns; + info_ptr->free_me |= PNG_FREE_UNKN; +} + +void PNGAPI +png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, + int chunk, int location) +{ + if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < + info_ptr->unknown_chunks_num) + info_ptr->unknown_chunks[chunk].location = (png_byte)location; +} +#endif + + +#ifdef PNG_MNG_FEATURES_SUPPORTED +png_uint_32 PNGAPI +png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) +{ + png_debug(1, "in png_permit_mng_features"); + + if (png_ptr == NULL) + return (png_uint_32)0; + + png_ptr->mng_features_permitted = + (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); + + return (png_uint_32)png_ptr->mng_features_permitted; +} +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED +void PNGAPI +png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_const_bytep + chunk_list, int num_chunks) +{ + png_bytep new_list, p; + int i, old_num_chunks; + if (png_ptr == NULL) + return; + + if (num_chunks == 0) + { + if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE) + png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; + + if (keep == PNG_HANDLE_CHUNK_ALWAYS) + png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; + + else + png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; + + return; + } + + if (chunk_list == NULL) + return; + + old_num_chunks = png_ptr->num_chunk_list; + new_list=(png_bytep)png_malloc(png_ptr, + (png_size_t)(5*(num_chunks + old_num_chunks))); + + if (png_ptr->chunk_list != NULL) + { + png_memcpy(new_list, png_ptr->chunk_list, + (png_size_t)(5*old_num_chunks)); + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->chunk_list=NULL; + } + + png_memcpy(new_list + 5*old_num_chunks, chunk_list, + (png_size_t)(5*num_chunks)); + + for (p = new_list + 5*old_num_chunks + 4, i = 0; inum_chunk_list = old_num_chunks + num_chunks; + png_ptr->chunk_list = new_list; + png_ptr->free_me |= PNG_FREE_LIST; +} +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +void PNGAPI +png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, + png_user_chunk_ptr read_user_chunk_fn) +{ + png_debug(1, "in png_set_read_user_chunk_fn"); + + if (png_ptr == NULL) + return; + + png_ptr->read_user_chunk_fn = read_user_chunk_fn; + png_ptr->user_chunk_ptr = user_chunk_ptr; +} +#endif + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) +{ + png_debug1(1, "in %s storage function", "rows"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) + png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); + + info_ptr->row_pointers = row_pointers; + + if (row_pointers) + info_ptr->valid |= PNG_INFO_IDAT; +} +#endif + +void PNGAPI +png_set_compression_buffer_size(png_structp png_ptr, png_size_t size) +{ + if (png_ptr == NULL) + return; + + png_free(png_ptr, png_ptr->zbuf); + + if (size > ZLIB_IO_MAX) + { + png_warning(png_ptr, "Attempt to set buffer size beyond max ignored"); + png_ptr->zbuf_size = ZLIB_IO_MAX; + size = ZLIB_IO_MAX; /* must fit */ + } + + else + png_ptr->zbuf_size = (uInt)size; + + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); + + /* The following ensures a relatively safe failure if this gets called while + * the buffer is actually in use. + */ + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = 0; + png_ptr->zstream.avail_in = 0; +} + +void PNGAPI +png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) +{ + if (png_ptr && info_ptr) + info_ptr->valid &= ~mask; +} + + + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED +/* This function was added to libpng 1.2.6 */ +void PNGAPI +png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max, + png_uint_32 user_height_max) +{ + /* Images with dimensions larger than these limits will be + * rejected by png_set_IHDR(). To accept any PNG datastream + * regardless of dimensions, set both limits to 0x7ffffffL. + */ + if (png_ptr == NULL) + return; + + png_ptr->user_width_max = user_width_max; + png_ptr->user_height_max = user_height_max; +} + +/* This function was added to libpng 1.4.0 */ +void PNGAPI +png_set_chunk_cache_max (png_structp png_ptr, + png_uint_32 user_chunk_cache_max) +{ + if (png_ptr) + png_ptr->user_chunk_cache_max = user_chunk_cache_max; +} + +/* This function was added to libpng 1.4.1 */ +void PNGAPI +png_set_chunk_malloc_max (png_structp png_ptr, + png_alloc_size_t user_chunk_malloc_max) +{ + if (png_ptr) + png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; +} +#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ + + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED +void PNGAPI +png_set_benign_errors(png_structp png_ptr, int allowed) +{ + png_debug(1, "in png_set_benign_errors"); + + if (allowed) + png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; + + else + png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN; +} +#endif /* PNG_BENIGN_ERRORS_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/contrib/libpng/pngstruct.h b/contrib/libpng/pngstruct.h new file mode 100644 index 0000000..8d781fa --- /dev/null +++ b/contrib/libpng/pngstruct.h @@ -0,0 +1,308 @@ + +/* pngstruct.h - header file for PNG reference library + * + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* The structure that holds the information to read and write PNG files. + * The only people who need to care about what is inside of this are the + * people who will be modifying the library for their own special needs. + * It should NOT be accessed directly by an application. + */ + +#ifndef PNGSTRUCT_H +#define PNGSTRUCT_H +/* zlib.h defines the structure z_stream, an instance of which is included + * in this structure and is required for decompressing the LZ compressed + * data in PNG files. + */ +#include "zlib.h" + +struct png_struct_def +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf png_jmpbuf; /* used in png_error */ + png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */ +#endif + png_error_ptr error_fn; /* function for printing errors and aborting */ + png_error_ptr warning_fn; /* function for printing warnings */ + png_voidp error_ptr; /* user supplied struct for error functions */ + png_rw_ptr write_data_fn; /* function for writing output data */ + png_rw_ptr read_data_fn; /* function for reading input data */ + png_voidp io_ptr; /* ptr to application struct for I/O functions */ + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr write_user_transform_fn; /* user write transform */ +#endif + +/* These were added in libpng-1.0.2 */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + png_voidp user_transform_ptr; /* user supplied struct for user transform */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ +#endif +#endif + + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations; /* which transformations to perform */ + + z_stream zstream; /* pointer to decompression structure (below) */ + png_bytep zbuf; /* buffer for zlib */ + uInt zbuf_size; /* size of zbuf (typically 65536) */ + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ + + png_uint_32 width; /* width of image in pixels */ + png_uint_32 height; /* height of image in pixels */ + png_uint_32 num_rows; /* number of rows in current pass */ + png_uint_32 usr_width; /* width of row at start of write */ + png_size_t rowbytes; /* size of row in bytes */ + png_uint_32 iwidth; /* width of current interlaced row in pixels */ + png_uint_32 row_number; /* current row in interlace pass */ + png_bytep prev_row; /* buffer to save previous (unfiltered) row */ + png_bytep row_buf; /* buffer to save current (unfiltered) row */ + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ + png_row_info row_info; /* used for transformation routines */ + + png_uint_32 idat_size; /* current IDAT size for read */ + png_uint_32 crc; /* current chunk CRC value */ + png_colorp palette; /* palette from the input file */ + png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_16 num_trans; /* number of transparency values */ + png_byte chunk_name[5]; /* null-terminated name of current chunk */ + png_byte compression; /* file compression type (always 0) */ + png_byte filter; /* file filter type (always 0) */ + png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ + png_byte pass; /* current interlace pass (0 - 6) */ + png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ + png_byte color_type; /* color type of file */ + png_byte bit_depth; /* bit depth of file */ + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte pixel_depth; /* number of bits per pixel */ + png_byte channels; /* number of channels in file */ + png_byte usr_channels; /* channels at start of write */ + png_byte sig_bytes; /* magic bytes read/written from start of file */ + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif + +#ifdef PNG_bKGD_SUPPORTED + png_byte background_gamma_type; + png_fixed_point background_gamma; + png_color_16 background; /* background color in screen gamma space */ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_color_16 background_1; /* background normalized to gamma 1.0 */ +#endif +#endif /* PNG_bKGD_SUPPORTED */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_flush_ptr output_flush_fn; /* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */ + png_fixed_point gamma; /* file gamma value */ + png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_bytep gamma_to_1; /* converts from file to 1.0 */ + png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ + png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + png_color_8 shift; /* shift for significant bit tranformation */ +#endif + +#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ + || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) + png_bytep trans_alpha; /* alpha values for paletted files */ + png_color_16 trans_color; /* transparent color for non-paletted files */ +#endif + + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED + png_progressive_info_ptr info_fn; /* called after header data fully read */ + png_progressive_row_ptr row_fn; /* called after a prog. row is decoded */ + png_progressive_end_ptr end_fn; /* called after image is complete */ + png_bytep save_buffer_ptr; /* current location in save_buffer */ + png_bytep save_buffer; /* buffer for previously read data */ + png_bytep current_buffer_ptr; /* current location in current_buffer */ + png_bytep current_buffer; /* buffer for recently used data */ + png_uint_32 push_length; /* size of current input chunk */ + png_uint_32 skip_length; /* bytes to skip in input data */ + png_size_t save_buffer_size; /* amount of data now in save_buffer */ + png_size_t save_buffer_max; /* total size of save_buffer */ + png_size_t buffer_size; /* total amount of available input data */ + png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ + int cur_palette; /* current push library palette index */ + +# ifdef PNG_TEXT_SUPPORTED + png_size_t current_text_size; /* current size of text input data */ + png_size_t current_text_left; /* how much text left to read in input */ + png_charp current_text; /* current text chunk buffer */ + png_charp current_text_ptr; /* current location in current_text */ +# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ + +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ + +#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) +/* For the Borland special 64K segment handler */ + png_bytepp offset_table_ptr; + png_bytep offset_table; + png_uint_16 offset_table_number; + png_uint_16 offset_table_count; + png_uint_16 offset_table_count_free; +#endif + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_bytep palette_lookup; /* lookup table for quantizing */ + png_bytep quantize_index; /* index translation for palette files */ +#endif + +#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED) + png_uint_16p hist; /* histogram */ +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ + png_bytep prev_filters; /* filter type(s) of previous row(s) */ + png_uint_16p filter_weights; /* weight(s) for previous line(s) */ + png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ + png_uint_16p filter_costs; /* relative filter calculation cost */ + png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_charp time_buffer; /* String to hold RFC 1123 time text */ +#endif + +/* New members added in libpng-1.0.6 */ + + png_uint_32 free_me; /* flags items libpng is responsible for freeing */ + +#ifdef PNG_USER_CHUNKS_SUPPORTED + png_voidp user_chunk_ptr; + png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ +#endif + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + int num_chunk_list; + png_bytep chunk_list; +#endif + +/* New members added in libpng-1.0.3 */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_byte rgb_to_gray_status; + /* These were changed from png_byte in libpng-1.0.6 */ + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + png_uint_16 rgb_to_gray_blue_coeff; +#endif + +/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ +#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ + defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ + defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) +/* Changed from png_byte to png_uint_32 at version 1.2.0 */ + png_uint_32 mng_features_permitted; +#endif + +/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_byte filter_type; +#endif + +/* New members added in libpng-1.2.0 */ + +/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +#ifdef PNG_USER_MEM_SUPPORTED + png_voidp mem_ptr; /* user supplied struct for mem functions */ + png_malloc_ptr malloc_fn; /* function for allocating memory */ + png_free_ptr free_fn; /* function for freeing memory */ +#endif + +/* New member added in libpng-1.0.13 and 1.2.0 */ + png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + +#ifdef PNG_READ_QUANTIZE_SUPPORTED +/* The following three members were added at version 1.0.14 and 1.2.4 */ + png_bytep quantize_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is + in the palette */ + png_bytep palette_to_index; /* which original index points to this + palette color */ +#endif + +/* New members added in libpng-1.0.16 and 1.2.6 */ + png_byte compression_type; + +#ifdef PNG_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; + png_uint_32 user_height_max; + + /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown + * chunks that can be stored (0 means unlimited). + */ + png_uint_32 user_chunk_cache_max; + + /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk + * can occupy when decompressed. 0 means unlimited. + */ + png_alloc_size_t user_chunk_malloc_max; +#endif + +/* New member added in libpng-1.0.25 and 1.2.17 */ +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + /* Storage for unknown chunk that the library doesn't recognize. */ + png_unknown_chunk unknown_chunk; +#endif + +/* New members added in libpng-1.2.26 */ + png_size_t old_big_row_buf_size; + png_size_t old_prev_row_size; + +/* New member added in libpng-1.2.30 */ + png_charp chunkdata; /* buffer for reading chunk data */ + +#ifdef PNG_IO_STATE_SUPPORTED +/* New member added in libpng-1.4.0 */ + png_uint_32 io_state; +#endif +}; +#endif /* PNGSTRUCT_H */ diff --git a/contrib/libpng/pngtest.c b/contrib/libpng/pngtest.c new file mode 100644 index 0000000..cbb7eb2 --- /dev/null +++ b/contrib/libpng/pngtest.c @@ -0,0 +1,1787 @@ + +/* pngtest.c - a simple test program to test libpng + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This program reads in a PNG image, writes it out again, and then + * compares the two files. If the files are identical, this shows that + * the basic chunk handling, filtering, and (de)compression code is working + * properly. It does not currently test all of the transforms, although + * it probably should. + * + * The program will report "FAIL" in certain legitimate cases: + * 1) when the compression level or filter selection method is changed. + * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. + * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks + * exist in the input file. + * 4) others not listed here... + * In these cases, it is best to check with another tool such as "pngcheck" + * to see what the differences between the two files are. + * + * If a filename is given on the command-line, then this file is used + * for the input, rather than the default "pngtest.png". This allows + * testing a wide variety of files easily. You can also test a number + * of files at once by typing "pngtest -m file1.png file2.png ..." + */ + +#include "zlib.h" +#include "png.h" +/* Copied from pngpriv.h but only used in error messages below. */ +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif +# include +# include +# include +# define FCLOSE(file) fclose(file) + +#ifndef PNG_STDIO_SUPPORTED +typedef FILE * png_FILE_p; +#endif + +/* Makes pngtest verbose so we can find problems. */ +#ifndef PNG_DEBUG +# define PNG_DEBUG 0 +#endif + +#if PNG_DEBUG > 1 +# define pngtest_debug(m) ((void)fprintf(stderr, m "\n")) +# define pngtest_debug1(m,p1) ((void)fprintf(stderr, m "\n", p1)) +# define pngtest_debug2(m,p1,p2) ((void)fprintf(stderr, m "\n", p1, p2)) +#else +# define pngtest_debug(m) ((void)0) +# define pngtest_debug1(m,p1) ((void)0) +# define pngtest_debug2(m,p1,p2) ((void)0) +#endif + +#if !PNG_DEBUG +# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ +#endif + +/* The code uses memcmp and memcpy on large objects (typically row pointers) so + * it is necessary to do soemthing special on certain architectures, note that + * the actual support for this was effectively removed in 1.4, so only the + * memory remains in this program: + */ +#define CVT_PTR(ptr) (ptr) +#define CVT_PTR_NOCHECK(ptr) (ptr) +#define png_memcmp memcmp +#define png_memcpy memcpy +#define png_memset memset + +/* Turn on CPU timing +#define PNGTEST_TIMING +*/ + +#ifndef PNG_FLOATING_POINT_SUPPORTED +#undef PNGTEST_TIMING +#endif + +#ifdef PNGTEST_TIMING +static float t_start, t_stop, t_decode, t_encode, t_misc; +#include +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +#define PNG_tIME_STRING_LENGTH 29 +static int tIME_chunk_present = 0; +static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; +#endif + +static int verbose = 0; + +int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); + +#ifdef __TURBOC__ +#include +#endif + +/* Defined so I can write to a file on gui/windowing platforms */ +/* #define STDERR stderr */ +#define STDERR stdout /* For DOS */ + +/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) png_ptr->jmpbuf +#endif + +/* Example of using row callbacks to make a simple progress meter */ +static int status_pass = 1; +static int status_dots_requested = 0; +static int status_dots = 1; + +void PNGCBAPI +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void PNGCBAPI +read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX) + return; + + if (status_pass != pass) + { + fprintf(stdout, "\n Pass %d: ", pass); + status_pass = pass; + status_dots = 31; + } + + status_dots--; + + if (status_dots == 0) + { + fprintf(stdout, "\n "); + status_dots=30; + } + + fprintf(stdout, "r"); +} + +void PNGCBAPI +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); +void PNGCBAPI +write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) +{ + if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) + return; + + fprintf(stdout, "w"); +} + + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely examine the row filters. We set this to 256 rather than + * 5 in case illegal filter values are present.) + */ +static png_uint_32 filters_used[256]; +void PNGCBAPI +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void PNGCBAPI +count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + if (png_ptr != NULL && row_info != NULL) + ++filters_used[*(data - 1)]; +} +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely count the zero samples) + */ + +static png_uint_32 zero_samples; + +void PNGCBAPI +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); +void PNGCBAPI +count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) +{ + png_bytep dp = data; + if (png_ptr == NULL) + return; + + /* Contents of row_info: + * png_uint_32 width width of row + * png_uint_32 rowbytes number of bytes in row + * png_byte color_type color type of pixels + * png_byte bit_depth bit depth of samples + * png_byte channels number of channels (1-4) + * png_byte pixel_depth bits per pixel (depth*channels) + */ + + /* Counts the number of zero samples (or zero pixels if color_type is 3 */ + + if (row_info->color_type == 0 || row_info->color_type == 3) + { + int pos = 0; + png_uint_32 n, nstop; + + for (n = 0, nstop=row_info->width; nbit_depth == 1) + { + if (((*dp << pos++ ) & 0x80) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 2) + { + if (((*dp << (pos+=2)) & 0xc0) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 4) + { + if (((*dp << (pos+=4)) & 0xf0) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 8) + if (*dp++ == 0) + zero_samples++; + + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + dp+=2; + } + } + } + else /* Other color types */ + { + png_uint_32 n, nstop; + int channel; + int color_channels = row_info->channels; + if (row_info->color_type > 3)color_channels--; + + for (n = 0, nstop=row_info->width; nbit_depth == 8) + if (*dp++ == 0) + zero_samples++; + + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + + dp+=2; + } + } + if (row_info->color_type > 3) + { + dp++; + if (row_info->bit_depth == 16) + dp++; + } + } + } +} +#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ + +static int wrote_question = 0; + +#ifndef PNG_STDIO_SUPPORTED +/* START of code to validate stdio-free compilation */ +/* These copies of the default read/write functions come from pngrio.c and + * pngwio.c. They allow "don't include stdio" testing of the library. + * This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ + +#ifdef PNG_IO_STATE_SUPPORTED +void +pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, + png_uint_32 io_op); +void +pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, + png_uint_32 io_op) +{ + png_uint_32 io_state = png_get_io_state(png_ptr); + int err = 0; + + /* Check if the current operation (reading / writing) is as expected. */ + if ((io_state & PNG_IO_MASK_OP) != io_op) + png_error(png_ptr, "Incorrect operation in I/O state"); + + /* Check if the buffer size specific to the current location + * (file signature / header / data / crc) is as expected. + */ + switch (io_state & PNG_IO_MASK_LOC) + { + case PNG_IO_SIGNATURE: + if (data_length > 8) + err = 1; + break; + case PNG_IO_CHUNK_HDR: + if (data_length != 8) + err = 1; + break; + case PNG_IO_CHUNK_DATA: + break; /* no restrictions here */ + case PNG_IO_CHUNK_CRC: + if (data_length != 4) + err = 1; + break; + default: + err = 1; /* uninitialized */ + } + if (err) + png_error(png_ptr, "Bad I/O state or buffer size"); +} +#endif + +#ifndef USE_FAR_KEYWORD +static void PNGCBAPI +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check = 0; + png_voidp io_ptr; + + /* fread() returns 0 on error, so it is OK to store this in a png_size_t + * instead of an int, which is what fread() actually returns. + */ + io_ptr = png_get_io_ptr(png_ptr); + if (io_ptr != NULL) + { + check = fread(data, 1, length, (png_FILE_p)io_ptr); + } + + if (check != length) + { + png_error(png_ptr, "Read Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_READING); +#endif +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGCBAPI +pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + png_byte *n_data; + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + n_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_get_io_ptr(png_ptr)); + if ((png_bytep)n_data == data) + { + check = fread(n_data, 1, length, io_ptr); + } + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t read, remaining, err; + check = 0; + remaining = length; + + do + { + read = MIN(NEAR_BUF_SIZE, remaining); + err = fread(buf, 1, 1, io_ptr); + png_memcpy(data, buf, read); /* Copy far buffer to near buffer */ + if (err != read) + break; + else + check += err; + data += read; + remaining -= read; + } + while (remaining != 0); + } + + if (check != length) + png_error(png_ptr, "Read Error"); + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_READING); +#endif +} +#endif /* USE_FAR_KEYWORD */ + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +static void PNGCBAPI +pngtest_flush(png_structp png_ptr) +{ + /* Do nothing; fflush() is said to be just a waste of energy. */ + PNG_UNUSED(png_ptr) /* Stifle compiler warning */ +} +#endif + +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +static void PNGCBAPI +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr)); + + if (check != length) + { + png_error(png_ptr, "Write Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); +#endif +} +#else +/* This is the model-independent version. Since the standard I/O library + can't handle far buffers in the medium and small models, we have to copy + the data. +*/ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +static void PNGCBAPI +pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_get_io_ptr(png_ptr)); + + if ((png_bytep)near_data == data) + { + check = fwrite(near_data, 1, length, io_ptr); + } + + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ + err = fwrite(buf, 1, written, io_ptr); + if (err != written) + break; + else + check += err; + data += written; + remaining -= written; + } + while (remaining != 0); + } + + if (check != length) + { + png_error(png_ptr, "Write Error"); + } + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); +#endif +} +#endif /* USE_FAR_KEYWORD */ + +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +static void PNGCBAPI +pngtest_warning(png_structp png_ptr, png_const_charp message) +{ + PNG_CONST char *name = "UNKNOWN (ERROR!)"; + char *test; + test = png_get_error_ptr(png_ptr); + + if (test == NULL) + fprintf(STDERR, "%s: libpng warning: %s\n", name, message); + + else + fprintf(STDERR, "%s: libpng warning: %s\n", test, message); +} + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void PNGCBAPI +pngtest_error(png_structp png_ptr, png_const_charp message) +{ + pngtest_warning(png_ptr, message); + /* We can return because png_error calls the default handler, which is + * actually OK in this case. + */ +} +#endif /* !PNG_STDIO_SUPPORTED */ +/* END of code to validate stdio-free compilation */ + +/* START of code to validate memory allocation and deallocation */ +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more then 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * This piece of code can be compiled to validate max 64K allocations + * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. + */ +typedef struct memory_information +{ + png_alloc_size_t size; + png_voidp pointer; + struct memory_information FAR *next; +} memory_information; +typedef memory_information FAR *memory_infop; + +static memory_infop pinformation = NULL; +static int current_allocation = 0; +static int maximum_allocation = 0; +static int total_allocation = 0; +static int num_allocations = 0; + +png_voidp PNGCBAPI png_debug_malloc PNGARG((png_structp png_ptr, + png_alloc_size_t size)); +void PNGCBAPI png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); + +png_voidp +PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) +{ + + /* png_malloc has already tested for NULL; png_create_struct calls + * png_debug_malloc directly, with png_ptr == NULL which is OK + */ + + if (size == 0) + return (NULL); + + /* This calls the library allocator twice, once to get the requested + buffer and once to get a new free list entry. */ + { + /* Disable malloc_fn and free_fn */ + memory_infop pinfo; + png_set_mem_fn(png_ptr, NULL, NULL, NULL); + pinfo = (memory_infop)png_malloc(png_ptr, + png_sizeof(*pinfo)); + pinfo->size = size; + current_allocation += size; + total_allocation += size; + num_allocations ++; + + if (current_allocation > maximum_allocation) + maximum_allocation = current_allocation; + + pinfo->pointer = png_malloc(png_ptr, size); + /* Restore malloc_fn and free_fn */ + + png_set_mem_fn(png_ptr, + NULL, png_debug_malloc, png_debug_free); + + if (size != 0 && pinfo->pointer == NULL) + { + current_allocation -= size; + total_allocation -= size; + png_error(png_ptr, + "out of memory in pngtest->png_debug_malloc"); + } + + pinfo->next = pinformation; + pinformation = pinfo; + /* Make sure the caller isn't assuming zeroed memory. */ + png_memset(pinfo->pointer, 0xdd, pinfo->size); + + if (verbose) + printf("png_malloc %lu bytes at %p\n", (unsigned long)size, + pinfo->pointer); + + return (png_voidp)(pinfo->pointer); + } +} + +/* Free a pointer. It is removed from the list at the same time. */ +void PNGCBAPI +png_debug_free(png_structp png_ptr, png_voidp ptr) +{ + if (png_ptr == NULL) + fprintf(STDERR, "NULL pointer to png_debug_free.\n"); + + if (ptr == 0) + { +#if 0 /* This happens all the time. */ + fprintf(STDERR, "WARNING: freeing NULL pointer\n"); +#endif + return; + } + + /* Unlink the element from the list. */ + { + memory_infop FAR *ppinfo = &pinformation; + + for (;;) + { + memory_infop pinfo = *ppinfo; + + if (pinfo->pointer == ptr) + { + *ppinfo = pinfo->next; + current_allocation -= pinfo->size; + if (current_allocation < 0) + fprintf(STDERR, "Duplicate free of memory\n"); + /* We must free the list element too, but first kill + the memory that is to be freed. */ + png_memset(ptr, 0x55, pinfo->size); + png_free_default(png_ptr, pinfo); + pinfo = NULL; + break; + } + + if (pinfo->next == NULL) + { + fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); + break; + } + + ppinfo = &pinfo->next; + } + } + + /* Finally free the data. */ + if (verbose) + printf("Freeing %p\n", ptr); + + png_free_default(png_ptr, ptr); + ptr = NULL; +} +#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ +/* END of code to test memory allocation/deallocation */ + + +/* Demonstration of user chunk support of the sTER and vpAg chunks */ +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + +/* (sTER is a public chunk not yet known by libpng. vpAg is a private +chunk used in ImageMagick to store "virtual page" size). */ + +static png_uint_32 user_chunk_data[4]; + + /* 0: sTER mode + 1 + * 1: vpAg width + * 2: vpAg height + * 3: vpAg units + */ + +static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr, + png_unknown_chunkp chunk) +{ + png_uint_32 + *my_user_chunk_data; + + /* Return one of the following: + * return (-n); chunk had an error + * return (0); did not recognize + * return (n); success + * + * The unknown chunk structure contains the chunk data: + * png_byte name[5]; + * png_byte *data; + * png_size_t size; + * + * Note that libpng has already taken care of the CRC handling. + */ + + if (chunk->name[0] == 115 && chunk->name[1] == 84 && /* s T */ + chunk->name[2] == 69 && chunk->name[3] == 82) /* E R */ + { + /* Found sTER chunk */ + if (chunk->size != 1) + return (-1); /* Error return */ + + if (chunk->data[0] != 0 && chunk->data[0] != 1) + return (-1); /* Invalid mode */ + + my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); + my_user_chunk_data[0]=chunk->data[0]+1; + return (1); + } + + if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */ + chunk->name[2] != 65 || chunk->name[3] != 103) /* A g */ + return (0); /* Did not recognize */ + + /* Found ImageMagick vpAg chunk */ + + if (chunk->size != 9) + return (-1); /* Error return */ + + my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); + + my_user_chunk_data[1]=png_get_uint_31(png_ptr, chunk->data); + my_user_chunk_data[2]=png_get_uint_31(png_ptr, chunk->data + 4); + my_user_chunk_data[3]=(png_uint_32)chunk->data[8]; + + return (1); + +} +#endif +/* END of code to demonstrate user chunk support */ + +/* Test one file */ +int +test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) +{ + static png_FILE_p fpin; + static png_FILE_p fpout; /* "static" prevents setjmp corruption */ + png_structp read_ptr; + png_infop read_info_ptr, end_info_ptr; +#ifdef PNG_WRITE_SUPPORTED + png_structp write_ptr; + png_infop write_info_ptr; + png_infop write_end_info_ptr; +#else + png_structp write_ptr = NULL; + png_infop write_info_ptr = NULL; + png_infop write_end_info_ptr = NULL; +#endif + png_bytep row_buf; + png_uint_32 y; + png_uint_32 width, height; + int num_pass, pass; + int bit_depth, color_type; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf png_jmpbuf; +#endif +#endif + + char inbuf[256], outbuf[256]; + + row_buf = NULL; + + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find input file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "wb")) == NULL) + { + fprintf(STDERR, "Could not open output file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + pngtest_debug("Allocating read and write structures"); +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + read_ptr = + png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + read_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif +#ifndef PNG_STDIO_SUPPORTED + png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + user_chunk_data[0] = 0; + user_chunk_data[1] = 0; + user_chunk_data[2] = 0; + user_chunk_data[3] = 0; + png_set_read_user_chunk_fn(read_ptr, user_chunk_data, + read_user_chunk_callback); + +#endif +#ifdef PNG_WRITE_SUPPORTED +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + write_ptr = + png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + write_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif +#ifndef PNG_STDIO_SUPPORTED + png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, + pngtest_warning); +#endif +#endif + pngtest_debug("Allocating read_info, write_info and end_info structures"); + read_info_ptr = png_create_info_struct(read_ptr); + end_info_ptr = png_create_info_struct(read_ptr); +#ifdef PNG_WRITE_SUPPORTED + write_info_ptr = png_create_info_struct(write_ptr); + write_end_info_ptr = png_create_info_struct(write_ptr); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + pngtest_debug("Setting jmpbuf for read struct"); +#ifdef USE_FAR_KEYWORD + if (setjmp(png_jmpbuf)) +#else + if (setjmp(png_jmpbuf(read_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); + png_free(read_ptr, row_buf); + row_buf = NULL; + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(read_ptr), png_jmpbuf, png_sizeof(jmp_buf)); +#endif + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Setting jmpbuf for write struct"); +#ifdef USE_FAR_KEYWORD + + if (setjmp(png_jmpbuf)) +#else + if (setjmp(png_jmpbuf(write_ptr))) +#endif + { + fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + FCLOSE(fpin); + FCLOSE(fpout); + return (1); + } + +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(write_ptr), png_jmpbuf, png_sizeof(jmp_buf)); +#endif +#endif +#endif + + pngtest_debug("Initializing input and output streams"); +#ifdef PNG_STDIO_SUPPORTED + png_init_io(read_ptr, fpin); +# ifdef PNG_WRITE_SUPPORTED + png_init_io(write_ptr, fpout); +# endif +#else + png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); +# ifdef PNG_WRITE_SUPPORTED + png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, +# ifdef PNG_WRITE_FLUSH_SUPPORTED + pngtest_flush); +# else + NULL); +# endif +# endif +#endif + + if (status_dots_requested == 1) + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, write_row_callback); +#endif + png_set_read_status_fn(read_ptr, read_row_callback); + } + + else + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, NULL); +#endif + png_set_read_status_fn(read_ptr, NULL); + } + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + { + int i; + + for (i = 0; i<256; i++) + filters_used[i] = 0; + + png_set_read_user_transform_fn(read_ptr, count_filters); + } +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + zero_samples = 0; + png_set_write_user_transform_fn(write_ptr, count_zero_samples); +#endif + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_HANDLE_CHUNK_ALWAYS +# define PNG_HANDLE_CHUNK_ALWAYS 3 +# endif + png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, + NULL, 0); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +# ifndef PNG_HANDLE_CHUNK_IF_SAFE +# define PNG_HANDLE_CHUNK_IF_SAFE 2 +# endif + png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, + NULL, 0); +#endif + + pngtest_debug("Reading info struct"); + png_read_info(read_ptr, read_info_ptr); + + pngtest_debug("Transferring info struct"); + { + int interlace_type, compression_type, filter_type; + + if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, + &color_type, &interlace_type, &compression_type, &filter_type)) + { + png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + color_type, interlace_type, compression_type, filter_type); +#else + color_type, PNG_INTERLACE_NONE, compression_type, filter_type); +#endif + } + } +#ifdef PNG_FIXED_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + + if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, + &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + png_fixed_point gamma; + + if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); + } +#endif +#else /* Use floating point versions */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + + if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y)) + { + png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + double gamma; + + if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) + png_set_gAMA(write_ptr, write_info_ptr, gamma); + } +#endif +#endif /* Floating point */ +#endif /* Fixed point */ +#ifdef PNG_iCCP_SUPPORTED + { + png_charp name; + png_bytep profile; + png_uint_32 proflen; + int compression_type; + + if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, + &profile, &proflen)) + { + png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, + profile, proflen); + } + } +#endif +#ifdef PNG_sRGB_SUPPORTED + { + int intent; + + if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) + png_set_sRGB(write_ptr, write_info_ptr, intent); + } +#endif + { + png_colorp palette; + int num_palette; + + if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) + png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); + } +#ifdef PNG_bKGD_SUPPORTED + { + png_color_16p background; + + if (png_get_bKGD(read_ptr, read_info_ptr, &background)) + { + png_set_bKGD(write_ptr, write_info_ptr, background); + } + } +#endif +#ifdef PNG_hIST_SUPPORTED + { + png_uint_16p hist; + + if (png_get_hIST(read_ptr, read_info_ptr, &hist)) + png_set_hIST(write_ptr, write_info_ptr, hist); + } +#endif +#ifdef PNG_oFFs_SUPPORTED + { + png_int_32 offset_x, offset_y; + int unit_type; + + if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y, + &unit_type)) + { + png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); + } + } +#endif +#ifdef PNG_pCAL_SUPPORTED + { + png_charp purpose, units; + png_charpp params; + png_int_32 X0, X1; + int type, nparams; + + if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, + &nparams, &units, ¶ms)) + { + png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, + nparams, units, params); + } + } +#endif +#ifdef PNG_pHYs_SUPPORTED + { + png_uint_32 res_x, res_y; + int unit_type; + + if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) + png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); + } +#endif +#ifdef PNG_sBIT_SUPPORTED + { + png_color_8p sig_bit; + + if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) + png_set_sBIT(write_ptr, write_info_ptr, sig_bit); + } +#endif +#ifdef PNG_sCAL_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + { + int unit; + double scal_width, scal_height; + + if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); + } + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + { + int unit; + png_charp scal_width, scal_height; + + if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height)) + { + png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, + scal_height); + } + } +#endif +#endif +#endif +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); + } + } +#endif +#ifdef PNG_tIME_SUPPORTED + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, read_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_info_ptr, mod_time); +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* We have to use png_memcpy instead of "=" because the string + * pointed to by png_convert_to_rfc1123() gets free'ed before + * we use it. + */ + png_memcpy(tIME_string, + png_convert_to_rfc1123(read_ptr, mod_time), + png_sizeof(tIME_string)); + + tIME_string[png_sizeof(tIME_string) - 1] = '\0'; + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#ifdef PNG_tRNS_SUPPORTED + { + png_bytep trans_alpha; + int num_trans; + png_color_16p trans_color; + + if (png_get_tRNS(read_ptr, read_info_ptr, &trans_alpha, &num_trans, + &trans_color)) + { + int sample_max = (1 << bit_depth); + /* libpng doesn't reject a tRNS chunk with out-of-range samples */ + if (!((color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_color->gray > sample_max) || + (color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max)))) + png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans, + trans_color); + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr, + &unknowns); + + if (num_unknowns) + { + int i; + png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, + num_unknowns); + /* Copy the locations from the read_info_ptr. The automatically + * generated locations in write_info_ptr are wrong because we + * haven't written anything yet. + */ + for (i = 0; i < num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, + unknowns[i].location); + } + } +#endif + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Writing info struct"); + +/* If we wanted, we could write info in two steps: + * png_write_info_before_PLTE(write_ptr, write_info_ptr); + */ + png_write_info(write_ptr, write_info_ptr); + +#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED + if (user_chunk_data[0] != 0) + { + png_byte png_sTER[5] = {115, 84, 69, 82, '\0'}; + + unsigned char + ster_chunk_data[1]; + + if (verbose) + fprintf(STDERR, "\n stereo mode = %lu\n", + (unsigned long)(user_chunk_data[0] - 1)); + + ster_chunk_data[0]=(unsigned char)(user_chunk_data[0] - 1); + png_write_chunk(write_ptr, png_sTER, ster_chunk_data, 1); + } + + if (user_chunk_data[1] != 0 || user_chunk_data[2] != 0) + { + png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; + + unsigned char + vpag_chunk_data[9]; + + if (verbose) + fprintf(STDERR, " vpAg = %lu x %lu, units = %lu\n", + (unsigned long)user_chunk_data[1], + (unsigned long)user_chunk_data[2], + (unsigned long)user_chunk_data[3]); + + png_save_uint_32(vpag_chunk_data, user_chunk_data[1]); + png_save_uint_32(vpag_chunk_data + 4, user_chunk_data[2]); + vpag_chunk_data[8] = (unsigned char)(user_chunk_data[3] & 0xff); + png_write_chunk(write_ptr, png_vpAg, vpag_chunk_data, 9); + } + +#endif +#endif + +#ifdef SINGLE_ROWBUF_ALLOC + pngtest_debug("Allocating row buffer..."); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug1("\t0x%08lx", (unsigned long)row_buf); +#endif /* SINGLE_ROWBUF_ALLOC */ + pngtest_debug("Writing row data"); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) + num_pass = png_set_interlace_handling(read_ptr); +# ifdef PNG_WRITE_SUPPORTED + png_set_interlace_handling(write_ptr); +# endif +#else + num_pass = 1; +#endif + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; +#endif + for (pass = 0; pass < num_pass; pass++) + { + pngtest_debug1("Writing row data for pass %d", pass); + for (y = 0; y < height; y++) + { +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); + row_buf = (png_bytep)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug2("\t0x%08lx (%u bytes)", (unsigned long)row_buf, + png_get_rowbytes(read_ptr, read_info_ptr)); + +#endif /* !SINGLE_ROWBUF_ALLOC */ + png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1); + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_decode += (t_stop - t_start); + t_start = t_stop; +#endif + png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_encode += (t_stop - t_start); + t_start = t_stop; +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* !SINGLE_ROWBUF_ALLOC */ + } + } + +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); +#endif + + pngtest_debug("Reading and writing end_info data"); + + png_read_end(read_ptr, end_info_ptr); +#ifdef PNG_TEXT_SUPPORTED + { + png_textp text_ptr; + int num_text; + + if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text); + } + } +#endif +#ifdef PNG_tIME_SUPPORTED + { + png_timep mod_time; + + if (png_get_tIME(read_ptr, end_info_ptr, &mod_time)) + { + png_set_tIME(write_ptr, write_end_info_ptr, mod_time); +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* We have to use png_memcpy instead of "=" because the string + pointed to by png_convert_to_rfc1123() gets free'ed before + we use it */ + png_memcpy(tIME_string, + png_convert_to_rfc1123(read_ptr, mod_time), + png_sizeof(tIME_string)); + + tIME_string[png_sizeof(tIME_string) - 1] = '\0'; + tIME_chunk_present++; +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunkp unknowns; + int num_unknowns = png_get_unknown_chunks(read_ptr, end_info_ptr, + &unknowns); + + if (num_unknowns) + { + int i; + png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, + num_unknowns); + /* Copy the locations from the read_info_ptr. The automatically + * generated locations in write_end_info_ptr are wrong because we + * haven't written the end_info yet. + */ + for (i = 0; i < num_unknowns; i++) + png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i, + unknowns[i].location); + } + } +#endif +#ifdef PNG_WRITE_SUPPORTED + png_write_end(write_ptr, write_end_info_ptr); +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED + if (verbose) + { + png_uint_32 iwidth, iheight; + iwidth = png_get_image_width(write_ptr, write_info_ptr); + iheight = png_get_image_height(write_ptr, write_info_ptr); + fprintf(STDERR, "\n Image width = %lu, height = %lu\n", + (unsigned long)iwidth, (unsigned long)iheight); + } +#endif + + pngtest_debug("Destroying data structs"); +#ifdef SINGLE_ROWBUF_ALLOC + pngtest_debug("destroying row_buf for read_ptr"); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* SINGLE_ROWBUF_ALLOC */ + pngtest_debug("destroying read_ptr, read_info_ptr, end_info_ptr"); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("destroying write_end_info_ptr"); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + pngtest_debug("destroying write_ptr, write_info_ptr"); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + pngtest_debug("Destruction complete."); + + FCLOSE(fpin); + FCLOSE(fpout); + + pngtest_debug("Opening files for comparison"); + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", inname); + return (1); + } + + if ((fpout = fopen(outname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", outname); + FCLOSE(fpin); + return (1); + } + + for (;;) + { + png_size_t num_in, num_out; + + num_in = fread(inbuf, 1, 1, fpin); + num_out = fread(outbuf, 1, 1, fpout); + + if (num_in != num_out) + { + fprintf(STDERR, "\nFiles %s and %s are of a different size\n", + inname, outname); + + if (wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + + if (!num_in) + break; + + if (png_memcmp(inbuf, outbuf, num_in)) + { + fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); + + if (wrote_question == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT chunk size (%d bytes),", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + "\n filtering heuristic (libpng default), compression"); + fprintf(STDERR, + " level (zlib default),\n and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + FCLOSE(fpin); + FCLOSE(fpout); + return (0); + } + } + + FCLOSE(fpin); + FCLOSE(fpout); + + return (0); +} + +/* Input and output filenames */ +#ifdef RISCOS +static PNG_CONST char *inname = "pngtest/png"; +static PNG_CONST char *outname = "pngout/png"; +#else +static PNG_CONST char *inname = "pngtest.png"; +static PNG_CONST char *outname = "pngout.png"; +#endif + +int +main(int argc, char *argv[]) +{ + int multiple = 0; + int ierror = 0; + + fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); + fprintf(STDERR, "%s", png_get_copyright(NULL)); + /* Show the version of libpng used in building the library */ + fprintf(STDERR, " library (%lu):%s", + (unsigned long)png_access_version_number(), + png_get_header_version(NULL)); + + /* Show the version of libpng used in building the application */ + fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, + PNG_HEADER_VERSION_STRING); + + /* Do some consistency checking on the memory allocation settings, I'm + * not sure this matters, but it is nice to know, the first of these + * tests should be impossible because of the way the macros are set + * in pngconf.h + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); +#endif + /* I think the following can happen. */ +#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); +#endif + + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) + { + fprintf(STDERR, + "Warning: versions are different between png.h and png.c\n"); + fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); + ++ierror; + } + + if (argc > 1) + { + if (strcmp(argv[1], "-m") == 0) + { + multiple = 1; + status_dots_requested = 0; + } + + else if (strcmp(argv[1], "-mv") == 0 || + strcmp(argv[1], "-vm") == 0 ) + { + multiple = 1; + verbose = 1; + status_dots_requested = 1; + } + + else if (strcmp(argv[1], "-v") == 0) + { + verbose = 1; + status_dots_requested = 1; + inname = argv[2]; + } + + else + { + inname = argv[1]; + status_dots_requested = 0; + } + } + + if (!multiple && argc == 3 + verbose) + outname = argv[2 + verbose]; + + if ((!multiple && argc > 3 + verbose) || (multiple && argc < 2)) + { + fprintf(STDERR, + "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", + argv[0], argv[0]); + fprintf(STDERR, + " reads/writes one PNG file (without -m) or multiple files (-m)\n"); + fprintf(STDERR, + " with -m %s is used as a temporary file\n", outname); + exit(1); + } + + if (multiple) + { + int i; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + for (i=2; isize, + (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + + else + { + int i; + for (i = 0; i<3; ++i) + { + int kerror; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + if (i == 1) + status_dots_requested = 1; + + else if (verbose == 0) + status_dots_requested = 0; + + if (i == 0 || verbose == 1 || ierror != 0) + fprintf(STDERR, "\n Testing %s:", inname); + + kerror = test_one_file(inname, outname); + + if (kerror == 0) + { + if (verbose == 1 || i == 2) + { +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + int k; +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + fprintf(STDERR, "\n PASS (%lu zero samples)\n", + (unsigned long)zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + for (k = 0; k<256; k++) + if (filters_used[k]) + fprintf(STDERR, " Filter %d was used %lu times\n", + k, (unsigned long)filters_used[k]); +#endif +#ifdef PNG_TIME_RFC1123_SUPPORTED + if (tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n", tIME_string); +#endif /* PNG_TIME_RFC1123_SUPPORTED */ + } + } + + else + { + if (verbose == 0 && i != 2) + fprintf(STDERR, "\n Testing %s:", inname); + + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation - allocation_now); + + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + + while (pinfo != NULL) + { + fprintf(STDERR, " %lu bytes at %x\n", + (unsigned long)pinfo->size, (unsigned int)pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; + fprintf(STDERR, " CPU time used = %.3f seconds", + (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " (decoding %.3f,\n", + t_decode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " encoding %.3f ,", + t_encode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " other %.3f seconds)\n\n", + t_misc/(float)CLOCKS_PER_SEC); +#endif + + if (ierror == 0) + fprintf(STDERR, " libpng passes test\n"); + + else + fprintf(STDERR, " libpng FAILS test\n"); + + return (int)(ierror != 0); +} + +/* Generate a compiler error if there is an old png.h in the search path. */ +typedef png_libpng_version_1_5_1 Your_png_h_is_not_version_1_5_1; diff --git a/contrib/libpng/pngtest.png b/contrib/libpng/pngtest.png new file mode 100644 index 0000000..cdf10da Binary files /dev/null and b/contrib/libpng/pngtest.png differ diff --git a/contrib/libpng/pngtrans.c b/contrib/libpng/pngtrans.c new file mode 100644 index 0000000..137f555 --- /dev/null +++ b/contrib/libpng/pngtrans.c @@ -0,0 +1,723 @@ + +/* pngtrans.c - transforms the data in a row (used by both readers and writers) + * + * Last changed in libpng 1.5.1 [February 3, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Turn on BGR-to-RGB mapping */ +void PNGAPI +png_set_bgr(png_structp png_ptr) +{ + png_debug(1, "in png_set_bgr"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_BGR; +} +#endif + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Turn on 16 bit byte swapping */ +void PNGAPI +png_set_swap(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth == 16) + png_ptr->transformations |= PNG_SWAP_BYTES; +} +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) +/* Turn on pixel packing */ +void PNGAPI +png_set_packing(png_structp png_ptr) +{ + png_debug(1, "in png_set_packing"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth < 8) + { + png_ptr->transformations |= PNG_PACK; + png_ptr->usr_bit_depth = 8; + } +} +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +/* Turn on packed pixel swapping */ +void PNGAPI +png_set_packswap(png_structp png_ptr) +{ + png_debug(1, "in png_set_packswap"); + + if (png_ptr == NULL) + return; + + if (png_ptr->bit_depth < 8) + png_ptr->transformations |= PNG_PACKSWAP; +} +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) +void PNGAPI +png_set_shift(png_structp png_ptr, png_const_color_8p true_bits) +{ + png_debug(1, "in png_set_shift"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SHIFT; + png_ptr->shift = *true_bits; +} +#endif + +#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ + defined(PNG_WRITE_INTERLACING_SUPPORTED) +int PNGAPI +png_set_interlace_handling(png_structp png_ptr) +{ + png_debug(1, "in png_set_interlace handling"); + + if (png_ptr && png_ptr->interlaced) + { + png_ptr->transformations |= PNG_INTERLACE; + return (7); + } + + return (1); +} +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) +/* Add a filler byte on read, or remove a filler or alpha byte on write. + * The filler type has changed in v0.95 to allow future 2-byte fillers + * for 48-bit input data, as well as to avoid problems with some compilers + * that don't like bytes as parameters. + */ +void PNGAPI +png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_filler"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_FILLER; + png_ptr->filler = (png_uint_16)filler; + + if (filler_loc == PNG_FILLER_AFTER) + png_ptr->flags |= PNG_FLAG_FILLER_AFTER; + + else + png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; + + /* This should probably go in the "do_read_filler" routine. + * I attempted to do that in libpng-1.0.1a but that caused problems + * so I restored it in libpng-1.0.2a + */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + { + png_ptr->usr_channels = 4; + } + + /* Also I added this in libpng-1.0.2a (what happens when we expand + * a less-than-8-bit grayscale to GA?) */ + + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8) + { + png_ptr->usr_channels = 2; + } +} + +/* Added to libpng-1.2.7 */ +void PNGAPI +png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc) +{ + png_debug(1, "in png_set_add_alpha"); + + if (png_ptr == NULL) + return; + + png_set_filler(png_ptr, filler, filler_loc); + png_ptr->transformations |= PNG_ADD_ALPHA; +} + +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) +void PNGAPI +png_set_swap_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_swap_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SWAP_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ + defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) +void PNGAPI +png_set_invert_alpha(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_alpha"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_INVERT_ALPHA; +} +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) +void PNGAPI +png_set_invert_mono(png_structp png_ptr) +{ + png_debug(1, "in png_set_invert_mono"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_INVERT_MONO; +} + +/* Invert monochrome grayscale data */ +void /* PRIVATE */ +png_do_invert(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_invert"); + + /* This test removed from libpng version 1.0.13 and 1.2.0: + * if (row_info->bit_depth == 1 && + */ + if (row_info->color_type == PNG_COLOR_TYPE_GRAY) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(~(*rp)); + rp++; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 8) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i += 2) + { + *rp = (png_byte)(~(*rp)); + rp += 2; + } + } + +#ifdef PNG_16BIT_SUPPORTED + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + row_info->bit_depth == 16) + { + png_bytep rp = row; + png_size_t i; + png_size_t istop = row_info->rowbytes; + + for (i = 0; i < istop; i += 4) + { + *rp = (png_byte)(~(*rp)); + *(rp + 1) = (png_byte)(~(*(rp + 1))); + rp += 4; + } + } +#endif +} +#endif + +#ifdef PNG_16BIT_SUPPORTED +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) +/* Swaps byte order on 16 bit depth images */ +void /* PRIVATE */ +png_do_swap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_swap"); + + if (row_info->bit_depth == 16) + { + png_bytep rp = row; + png_uint_32 i; + png_uint_32 istop= row_info->width * row_info->channels; + + for (i = 0; i < istop; i++, rp += 2) + { + png_byte t = *rp; + *rp = *(rp + 1); + *(rp + 1) = t; + } + } +} +#endif +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) +static PNG_CONST png_byte onebppswaptable[256] = { + 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, + 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, + 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, + 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, + 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, + 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, + 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, + 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, + 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, + 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, + 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, + 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, + 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, + 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, + 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, + 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, + 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, + 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, + 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, + 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, + 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, + 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, + 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, + 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, + 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, + 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, + 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, + 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, + 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, + 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, + 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, + 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF +}; + +static PNG_CONST png_byte twobppswaptable[256] = { + 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, + 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, + 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, + 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4, + 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8, + 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8, + 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC, + 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC, + 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1, + 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1, + 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5, + 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5, + 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9, + 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9, + 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD, + 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD, + 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2, + 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2, + 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6, + 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6, + 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA, + 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA, + 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE, + 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE, + 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3, + 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3, + 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7, + 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7, + 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB, + 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB, + 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF, + 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF +}; + +static PNG_CONST png_byte fourbppswaptable[256] = { + 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, + 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, + 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, + 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1, + 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, + 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2, + 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, + 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3, + 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, + 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4, + 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, + 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5, + 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, + 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6, + 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, + 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7, + 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, + 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8, + 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, + 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9, + 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A, + 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA, + 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B, + 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB, + 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C, + 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC, + 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D, + 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD, + 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E, + 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE, + 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F, + 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF +}; + +/* Swaps pixel packing order within bytes */ +void /* PRIVATE */ +png_do_packswap(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_packswap"); + + if (row_info->bit_depth < 8) + { + png_bytep rp; + png_const_bytep end, table; + + end = row + row_info->rowbytes; + + if (row_info->bit_depth == 1) + table = onebppswaptable; + + else if (row_info->bit_depth == 2) + table = twobppswaptable; + + else if (row_info->bit_depth == 4) + table = fourbppswaptable; + + else + return; + + for (rp = row; rp < end; rp++) + *rp = table[*rp]; + } +} +#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */ + +#if defined(PNG_WRITE_FILLER_SUPPORTED) || \ + defined(PNG_READ_STRIP_ALPHA_SUPPORTED) +/* Remove filler or alpha byte(s) */ +void /* PRIVATE */ +png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) +{ + png_debug(1, "in png_do_strip_filler"); + + { + png_bytep sp = row; + png_bytep dp = row; + png_uint_32 row_width = row_info->width; + png_uint_32 i; + + if ((row_info->color_type == PNG_COLOR_TYPE_RGB || + (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && + (flags & PNG_FLAG_STRIP_ALPHA))) && + row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + /* This converts from RGBX or RGBA to RGB */ + if (flags & PNG_FLAG_FILLER_AFTER) + { + dp += 3; sp += 4; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp++; + } + } + + /* This converts from XRGB or ARGB to RGB */ + else + { + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + row_info->pixel_depth = 24; + row_info->rowbytes = row_width * 3; + } + + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */ + sp += 8; dp += 6; + for (i = 1; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + + else + { + /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */ + for (i = 0; i < row_width; i++) + { + /* This could be (although png_memcpy is probably slower): + png_memcpy(dp, sp, 6); + sp += 8; + dp += 6; + */ + + sp += 2; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + + row_info->pixel_depth = 48; + row_info->rowbytes = row_width * 6; + } + row_info->channels = 3; + } + + else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY || + (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && + (flags & PNG_FLAG_STRIP_ALPHA))) && + row_info->channels == 2) + { + if (row_info->bit_depth == 8) + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from GX or GA to G */ + for (i = 0; i < row_width; i++) + { + *dp++ = *sp++; + sp++; + } + } + + else + { + /* This converts from XG or AG to G */ + for (i = 0; i < row_width; i++) + { + sp++; + *dp++ = *sp++; + } + } + + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; + } + + else /* if (row_info->bit_depth == 16) */ + { + if (flags & PNG_FLAG_FILLER_AFTER) + { + /* This converts from GGXX or GGAA to GG */ + sp += 4; dp += 2; + for (i = 1; i < row_width; i++) + { + *dp++ = *sp++; + *dp++ = *sp++; + sp += 2; + } + } + + else + { + /* This converts from XXGG or AAGG to GG */ + for (i = 0; i < row_width; i++) + { + sp += 2; + *dp++ = *sp++; + *dp++ = *sp++; + } + } + + row_info->pixel_depth = 16; + row_info->rowbytes = row_width * 2; + } + row_info->channels = 1; + } + + if (flags & PNG_FLAG_STRIP_ALPHA) + row_info->color_type = (png_byte)(row_info->color_type & + ~PNG_COLOR_MASK_ALPHA); + } +} +#endif + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) +/* Swaps red and blue bytes within a pixel */ +void /* PRIVATE */ +png_do_bgr(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_bgr"); + + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 3) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 4) + { + png_byte save = *rp; + *rp = *(rp + 2); + *(rp + 2) = save; + } + } + } + +#ifdef PNG_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 6) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + png_bytep rp; + png_uint_32 i; + + for (i = 0, rp = row; i < row_width; i++, rp += 8) + { + png_byte save = *rp; + *rp = *(rp + 4); + *(rp + 4) = save; + save = *(rp + 1); + *(rp + 1) = *(rp + 5); + *(rp + 5) = save; + } + } + } +#endif + } +} +#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */ + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ + defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +void PNGAPI +png_set_user_transform_info(png_structp png_ptr, png_voidp + user_transform_ptr, int user_transform_depth, int user_transform_channels) +{ + png_debug(1, "in png_set_user_transform_info"); + + if (png_ptr == NULL) + return; + png_ptr->user_transform_ptr = user_transform_ptr; + png_ptr->user_transform_depth = (png_byte)user_transform_depth; + png_ptr->user_transform_channels = (png_byte)user_transform_channels; +} +#endif + +/* This function returns a pointer to the user_transform_ptr associated with + * the user transform functions. The application should free any memory + * associated with this pointer before png_write_destroy and png_read_destroy + * are called. + */ +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED +png_voidp PNGAPI +png_get_user_transform_ptr(png_const_structp png_ptr) +{ + if (png_ptr == NULL) + return (NULL); + + return ((png_voidp)png_ptr->user_transform_ptr); +} +#endif + +png_uint_32 PNGAPI +png_get_current_row_number(png_const_structp png_ptr) +{ + if (png_ptr != NULL) + return png_ptr->row_number; + return PNG_UINT_32_MAX; /* help the app not to fail silently */ +} + +png_byte PNGAPI +png_get_current_pass_number(png_const_structp png_ptr) +{ + if (png_ptr != NULL) + return png_ptr->pass; + return 8; /* invalid */ +} +#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED || + PNG_WRITE_USER_TRANSFORM_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/contrib/libpng/pngvalid.c b/contrib/libpng/pngvalid.c new file mode 100644 index 0000000..faebe4b --- /dev/null +++ b/contrib/libpng/pngvalid.c @@ -0,0 +1,6658 @@ + +/* pngvalid.c - validate libpng by constructing then reading png files. + * + * Last changed in libpng 1.5.1 [February 3, 2011] + * Copyright (c) 2011 Glenn Randers-Pehrson + * Written by John Cunningham Bowler + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * NOTES: + * This is a C program that is intended to be linked against libpng. It + * generates bitmaps internally, stores them as PNG files (using the + * sequential write code) then reads them back (using the sequential + * read code) and validates that the result has the correct data. + * + * The program can be modified and extended to test the correctness of + * transformations performed by libpng. + */ + +#include "png.h" +#if PNG_LIBPNG_VER < 10500 +/* This delibarately lacks the PNG_CONST. */ +typedef png_byte *png_const_bytep; + +/* This is copied from 1.5.1 png.h: */ +#define PNG_INTERLACE_ADAM7_PASSES 7 +#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7) +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) +#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ + (((yIn)<>(((7-(off))-(pass))<<2)) & 0xFU) | \ + ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U)) +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +/* These are needed too for the defualt build: */ +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#endif + +#include "zlib.h" /* For crc32 */ + +#include /* For floating point constants */ +#include /* For malloc */ +#include /* For memcpy, memset */ +#include /* For floor */ + +/* Unused formal parameter errors are removed using the following macro which is + * expected to have no bad effects on performance. + */ +#ifndef UNUSED +# if defined(__GNUC__) || defined(_MSC_VER) +# define UNUSED(param) (void)param; +# else +# define UNUSED(param) +# endif +#endif + +/***************************** EXCEPTION HANDLING *****************************/ +#include "contrib/visupng/cexcept.h" +struct png_store; +define_exception_type(struct png_store*); + +/* The following are macros to reduce typing everywhere where the well known + * name 'the_exception_context' must be defined. + */ +#define anon_context(ps) struct exception_context *the_exception_context = \ + &(ps)->exception_context +#define context(ps,fault) anon_context(ps); png_store *fault + +/******************************* UTILITIES ************************************/ +/* Error handling is particularly problematic in production code - error + * handlers often themselves have bugs which lead to programs that detect + * minor errors crashing. The following functions deal with one very + * common class of errors in error handlers - attempting to format error or + * warning messages into buffers that are too small. + */ +static size_t safecat(char *buffer, size_t bufsize, size_t pos, + PNG_CONST char *cat) +{ + while (pos < bufsize && cat != NULL && *cat != 0) + buffer[pos++] = *cat++; + + if (pos >= bufsize) + pos = bufsize-1; + + buffer[pos] = 0; + return pos; +} + +static size_t safecatn(char *buffer, size_t bufsize, size_t pos, int n) +{ + char number[64]; + sprintf(number, "%d", n); + return safecat(buffer, bufsize, pos, number); +} + +static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d, + int precision) +{ + char number[64]; + sprintf(number, "%.*f", precision, d); + return safecat(buffer, bufsize, pos, number); +} + +static PNG_CONST char invalid[] = "invalid"; +static PNG_CONST char sep[] = ": "; + +/* NOTE: this is indexed by ln2(bit_depth)! */ +static PNG_CONST char *bit_depths[8] = +{ + "1", "2", "4", "8", "16", invalid, invalid, invalid +}; + +static PNG_CONST char *colour_types[8] = +{ + "greyscale", invalid, "truecolour", "indexed-colour", + "greyscale with alpha", invalid, "truecolour with alpha", invalid +}; + +/* To get log-bit-depth from bit depth, returns 0 to 7 (7 on error). */ +static unsigned int +log2depth(png_byte bit_depth) +{ + switch (bit_depth) + { + case 1: + return 0; + + case 2: + return 1; + + case 4: + return 2; + + case 8: + return 3; + + case 16: + return 4; + + default: + return 7; + } +} + +/* A numeric ID based on PNG file characteristics. The 'do_interlace' field + * simply records whether pngvalid did the interlace itself or whether it + * was done by libpng. Width and height must be less than 256. + */ +#define FILEID(col, depth, interlace, width, height, do_interlace) \ + ((png_uint_32)((col) + ((depth)<<3) + ((interlace)<<8) + \ + (((do_interlace)!=0)<<15) + ((width)<<16) + ((height)<<24))) + +#define COL_FROM_ID(id) ((png_byte)((id)& 0x7U)) +#define DEPTH_FROM_ID(id) ((png_byte)(((id) >> 3) & 0x1fU)) +#define INTERLACE_FROM_ID(id) ((int)(((id) >> 8) & 0x3)) +#define DO_INTERLACE_FROM_ID(id) ((int)(((id)>>15) & 1)) +#define WIDTH_FROM_ID(id) (((id)>>16) & 0xff) +#define HEIGHT_FROM_ID(id) (((id)>>24) & 0xff) + +/* Utility to construct a standard name for a standard image. */ +static size_t +standard_name(char *buffer, size_t bufsize, size_t pos, png_byte colour_type, + int log_bit_depth, int interlace_type, png_uint_32 w, png_uint_32 h, + int do_interlace) +{ + pos = safecat(buffer, bufsize, pos, colour_types[colour_type]); + pos = safecat(buffer, bufsize, pos, " "); + pos = safecat(buffer, bufsize, pos, bit_depths[log_bit_depth]); + pos = safecat(buffer, bufsize, pos, " bit "); + + if (interlace_type != PNG_INTERLACE_NONE) + pos = safecat(buffer, bufsize, pos, "interlaced"); + if (do_interlace) + pos = safecat(buffer, bufsize, pos, "(pngvalid)"); + else + pos = safecat(buffer, bufsize, pos, "(libpng)"); + if (w > 0 || h > 0) + { + pos = safecat(buffer, bufsize, pos, " "); + pos = safecatn(buffer, bufsize, pos, w); + pos = safecat(buffer, bufsize, pos, "x"); + pos = safecatn(buffer, bufsize, pos, h); + } + + return pos; +} + +static size_t +standard_name_from_id(char *buffer, size_t bufsize, size_t pos, png_uint_32 id) +{ + return standard_name(buffer, bufsize, pos, COL_FROM_ID(id), + log2depth(DEPTH_FROM_ID(id)), INTERLACE_FROM_ID(id), + WIDTH_FROM_ID(id), HEIGHT_FROM_ID(id), DO_INTERLACE_FROM_ID(id)); +} + +/* Convenience API and defines to list valid formats. Note that 16 bit read and + * write support is required to do 16 bit read tests (we must be able to make a + * 16 bit image to test!) + */ +#ifdef PNG_WRITE_16BIT_SUPPORTED +# define WRITE_BDHI 4 +# ifdef PNG_READ_16BIT_SUPPORTED +# define READ_BDHI 4 +# define DO_16BIT +# endif +#else +# define WRITE_BDHI 3 +#endif +#ifndef DO_16BIT +# define READ_BDHI 3 +#endif + +static int +next_format(png_bytep colour_type, png_bytep bit_depth) +{ + if (*bit_depth == 0) + { + *colour_type = 0, *bit_depth = 1; + return 1; + } + + *bit_depth = (png_byte)(*bit_depth << 1); + + /* Palette images are restricted to 8 bit depth */ + if (*bit_depth <= 8 +# ifdef DO_16BIT + || (*colour_type != 3 && *bit_depth <= 16) +# endif + ) + return 1; + + /* Move to the next color type, or return 0 at the end. */ + switch (*colour_type) + { + case 0: + *colour_type = 2; + *bit_depth = 8; + return 1; + + case 2: + *colour_type = 3; + *bit_depth = 1; + return 1; + + case 3: + *colour_type = 4; + *bit_depth = 8; + return 1; + + case 4: + *colour_type = 6; + *bit_depth = 8; + return 1; + + default: + return 0; + } +} + +static unsigned int +sample(png_const_bytep row, png_byte colour_type, png_byte bit_depth, + png_uint_32 x, unsigned int sample_index) +{ + png_uint_32 bit_index, result; + + /* Find a sample index for the desired sample: */ + x *= bit_depth; + bit_index = x; + + if ((colour_type & 1) == 0) /* !palette */ + { + if (colour_type & 2) + bit_index *= 3; + + if (colour_type & 4) + bit_index += x; /* Alpha channel */ + + if (colour_type & (2+4)) + bit_index += sample_index * bit_depth; /* Multiple channels: select one */ + } + + /* Return the sample from the row as an integer. */ + row += bit_index >> 3; + result = *row; + + if (bit_depth == 8) + return result; + + else if (bit_depth > 8) + return (result << 8) + *++row; + + /* Less than 8 bits per sample. */ + bit_index &= 7; + return (result >> (8-bit_index-bit_depth)) & ((1U<> 3] & ~destMask; + unsigned int sourceByte = fromBuffer[fromIndex >> 3]; + + /* Don't rely on << or >> supporting '0' here, just in case: */ + fromIndex &= 7; + if (fromIndex > 0) sourceByte <<= fromIndex; + if ((toIndex & 7) > 0) sourceByte >>= toIndex & 7; + + toBuffer[toIndex >> 3] = (png_byte)(destByte | (sourceByte & destMask)); + } + else /* One or more bytes */ + memmove(toBuffer+(toIndex>>3), fromBuffer+(fromIndex>>3), pixelSize>>3); +} + +/* Compare pixels - they are assumed to start at the first byte in the + * given buffers. + */ +static int +pixel_cmp(png_const_bytep pa, png_const_bytep pb, png_uint_32 bit_width) +{ + if (memcmp(pa, pb, bit_width>>3) == 0) + { + png_uint_32 p; + + if ((bit_width & 7) == 0) return 0; + + /* Ok, any differences? */ + p = pa[bit_width >> 3]; + p ^= pb[bit_width >> 3]; + + if (p == 0) return 0; + + /* There are, but they may not be significant, remove the bits + * after the end (the low order bits in PNG.) + */ + bit_width &= 7; + p >>= 8-bit_width; + + if (p == 0) return 0; + } + + return 1; /* Different */ +} + +/*************************** BASIC PNG FILE WRITING ***************************/ +/* A png_store takes data from the sequential writer or provides data + * to the sequential reader. It can also store the result of a PNG + * write for later retrieval. + */ +#define STORE_BUFFER_SIZE 500 /* arbitrary */ +typedef struct png_store_buffer +{ + struct png_store_buffer* prev; /* NOTE: stored in reverse order */ + png_byte buffer[STORE_BUFFER_SIZE]; +} png_store_buffer; + +#define FILE_NAME_SIZE 64 + +typedef struct png_store_file +{ + struct png_store_file* next; /* as many as you like... */ + char name[FILE_NAME_SIZE]; + png_uint_32 id; /* must be correct (see FILEID) */ + png_size_t datacount; /* In this (the last) buffer */ + png_store_buffer data; /* Last buffer in file */ +} png_store_file; + +/* The following is a pool of memory allocated by a single libpng read or write + * operation. + */ +typedef struct store_pool +{ + struct png_store *store; /* Back pointer */ + struct store_memory *list; /* List of allocated memory */ + png_byte mark[4]; /* Before and after data */ + + /* Statistics for this run. */ + png_alloc_size_t max; /* Maximum single allocation */ + png_alloc_size_t current; /* Current allocation */ + png_alloc_size_t limit; /* Highest current allocation */ + png_alloc_size_t total; /* Total allocation */ + + /* Overall statistics (retained across successive runs). */ + png_alloc_size_t max_max; + png_alloc_size_t max_limit; + png_alloc_size_t max_total; +} store_pool; + +typedef struct png_store +{ + /* For cexcept.h exception handling - simply store one of these; + * the context is a self pointer but it may point to a different + * png_store (in fact it never does in this program.) + */ + struct exception_context + exception_context; + + unsigned int verbose :1; + unsigned int treat_warnings_as_errors :1; + unsigned int expect_error :1; + unsigned int expect_warning :1; + unsigned int saw_warning :1; + unsigned int speed :1; + unsigned int progressive :1; /* use progressive read */ + unsigned int validated :1; /* used as a temporary flag */ + int nerrors; + int nwarnings; + char test[128]; /* Name of test */ + char error[256]; + + /* Read fields */ + png_structp pread; /* Used to read a saved file */ + png_infop piread; + png_store_file* current; /* Set when reading */ + png_store_buffer* next; /* Set when reading */ + png_size_t readpos; /* Position in *next */ + png_byte* image; /* Buffer for reading interlaced images */ + size_t cb_image; /* Size of this buffer */ + store_pool read_memory_pool; + + /* Write fields */ + png_store_file* saved; + png_structp pwrite; /* Used when writing a new file */ + png_infop piwrite; + png_size_t writepos; /* Position in .new */ + char wname[FILE_NAME_SIZE]; + png_store_buffer new; /* The end of the new PNG file being written. */ + store_pool write_memory_pool; +} png_store; + +/* Initialization and cleanup */ +static void +store_pool_mark(png_byte *mark) +{ + /* Generate a new mark. This uses a boring repeatable algorithm and it is + * implemented here so that it gives the same set of numbers on every + * architecture. It's a linear congruential generator (Knuth or Sedgewick + * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and + * Hill, "The Art of Electronics". + */ + static png_uint_32 u0 = 0x12345678, u1 = 1; + + /* There are thirty three bits, the next bit in the sequence is bit-33 XOR + * bit-20. The top 1 bit is in u1, the bottom 32 are in u0. + */ + int i; + for (i=0; i<4; ++i) + { + /* First generate 8 new bits then shift them in at the end. */ + png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff; + u1 <<= 8; + u1 |= u0 >> 24; + u0 <<= 8; + u0 |= u; + *mark++ = (png_byte)u; + } +} + +/* Use this for random 32 bit values, this function makes sure the result is + * non-zero. + */ +static png_uint_32 +random_32(void) +{ + + for(;;) + { + png_byte mark[4]; + png_uint_32 result; + + store_pool_mark(mark); + result = png_get_uint_32(mark); + + if (result != 0) + return result; + } +} + +static void +store_pool_init(png_store *ps, store_pool *pool) +{ + memset(pool, 0, sizeof *pool); + + pool->store = ps; + pool->list = NULL; + pool->max = pool->current = pool->limit = pool->total = 0; + pool->max_max = pool->max_limit = pool->max_total = 0; + store_pool_mark(pool->mark); +} + +static void +store_init(png_store* ps) +{ + memset(ps, 0, sizeof *ps); + init_exception_context(&ps->exception_context); + store_pool_init(ps, &ps->read_memory_pool); + store_pool_init(ps, &ps->write_memory_pool); + ps->verbose = 0; + ps->treat_warnings_as_errors = 0; + ps->expect_error = 0; + ps->expect_warning = 0; + ps->saw_warning = 0; + ps->speed = 0; + ps->progressive = 0; + ps->validated = 0; + ps->nerrors = ps->nwarnings = 0; + ps->pread = NULL; + ps->piread = NULL; + ps->saved = ps->current = NULL; + ps->next = NULL; + ps->readpos = 0; + ps->image = NULL; + ps->cb_image = 0; + ps->pwrite = NULL; + ps->piwrite = NULL; + ps->writepos = 0; + ps->new.prev = NULL; +} + +/* This somewhat odd function is used when reading an image to ensure that the + * buffer is big enough - this is why a png_structp is available. + */ +static void +store_ensure_image(png_store *ps, png_structp pp, size_t cb) +{ + if (ps->cb_image < cb) + { + if (ps->image != NULL) + { + free(ps->image-1); + ps->cb_image = 0; + } + + /* The buffer is deliberately mis-aligned. */ + ps->image = malloc(cb+1); + if (ps->image == NULL) + png_error(pp, "OOM allocating image buffer"); + + ++(ps->image); + ps->cb_image = cb; + } + + /* And, for error checking, the whole buffer is set to '1' - this + * matches what happens with the 'size' test images on write and also + * matches the unused bits in the test rows. + */ + memset(ps->image, 0xff, cb); +} + +static void +store_freebuffer(png_store_buffer* psb) +{ + if (psb->prev) + { + store_freebuffer(psb->prev); + free(psb->prev); + psb->prev = NULL; + } +} + +static void +store_freenew(png_store *ps) +{ + store_freebuffer(&ps->new); + ps->writepos = 0; +} + +static void +store_storenew(png_store *ps) +{ + png_store_buffer *pb; + + if (ps->writepos != STORE_BUFFER_SIZE) + png_error(ps->pwrite, "invalid store call"); + + pb = malloc(sizeof *pb); + + if (pb == NULL) + png_error(ps->pwrite, "store new: OOM"); + + *pb = ps->new; + ps->new.prev = pb; + ps->writepos = 0; +} + +static void +store_freefile(png_store_file **ppf) +{ + if (*ppf != NULL) + { + store_freefile(&(*ppf)->next); + + store_freebuffer(&(*ppf)->data); + (*ppf)->datacount = 0; + free(*ppf); + *ppf = NULL; + } +} + +/* Main interface to file storeage, after writing a new PNG file (see the API + * below) call store_storefile to store the result with the given name and id. + */ +static void +store_storefile(png_store *ps, png_uint_32 id) +{ + png_store_file *pf = malloc(sizeof *pf); + if (pf == NULL) + png_error(ps->pwrite, "storefile: OOM"); + safecat(pf->name, sizeof pf->name, 0, ps->wname); + pf->id = id; + pf->data = ps->new; + pf->datacount = ps->writepos; + ps->new.prev = NULL; + ps->writepos = 0; + + /* And save it. */ + pf->next = ps->saved; + ps->saved = pf; +} + +/* Generate an error message (in the given buffer) */ +static size_t +store_message(png_store *ps, png_structp pp, char *buffer, size_t bufsize, + size_t pos, PNG_CONST char *msg) +{ + if (pp != NULL && pp == ps->pread) + { + /* Reading a file */ + pos = safecat(buffer, bufsize, pos, "read: "); + + if (ps->current != NULL) + { + pos = safecat(buffer, bufsize, pos, ps->current->name); + pos = safecat(buffer, bufsize, pos, sep); + } + } + + else if (pp != NULL && pp == ps->pwrite) + { + /* Writing a file */ + pos = safecat(buffer, bufsize, pos, "write: "); + pos = safecat(buffer, bufsize, pos, ps->wname); + pos = safecat(buffer, bufsize, pos, sep); + } + + else + { + /* Neither reading nor writing (or a memory error in struct delete) */ + pos = safecat(buffer, bufsize, pos, "pngvalid: "); + } + + if (ps->test[0] != 0) + { + pos = safecat(buffer, bufsize, pos, ps->test); + pos = safecat(buffer, bufsize, pos, sep); + } + pos = safecat(buffer, bufsize, pos, msg); + return pos; +} + +/* Log an error or warning - the relevant count is always incremented. */ +static void +store_log(png_store* ps, png_structp pp, png_const_charp message, int is_error) +{ + /* The warning is copied to the error buffer if there are no errors and it is + * the first warning. The error is copied to the error buffer if it is the + * first error (overwriting any prior warnings). + */ + if (is_error ? (ps->nerrors)++ == 0 : + (ps->nwarnings)++ == 0 && ps->nerrors == 0) + store_message(ps, pp, ps->error, sizeof ps->error, 0, message); + + if (ps->verbose) + { + char buffer[256]; + size_t pos; + + if (is_error) + pos = safecat(buffer, sizeof buffer, 0, "error: "); + else + pos = safecat(buffer, sizeof buffer, 0, "warning: "); + + store_message(ps, pp, buffer, sizeof buffer, pos, message); + fputs(buffer, stderr); + fputc('\n', stderr); + } +} + +/* Functions to use as PNG callbacks. */ +static void +store_error(png_structp pp, png_const_charp message) /* PNG_NORETURN */ +{ + png_store *ps = png_get_error_ptr(pp); + + if (!ps->expect_error) + store_log(ps, pp, message, 1 /* error */); + + /* And finally throw an exception. */ + { + struct exception_context *the_exception_context = &ps->exception_context; + Throw ps; + } +} + +static void +store_warning(png_structp pp, png_const_charp message) +{ + png_store *ps = png_get_error_ptr(pp); + + if (!ps->expect_warning) + store_log(ps, pp, message, 0 /* warning */); + else + ps->saw_warning = 1; +} + +static void +store_write(png_structp pp, png_bytep pb, png_size_t st) +{ + png_store *ps = png_get_io_ptr(pp); + + if (ps->pwrite != pp) + png_error(pp, "store state damaged"); + + while (st > 0) + { + size_t cb; + + if (ps->writepos >= STORE_BUFFER_SIZE) + store_storenew(ps); + + cb = st; + + if (cb > STORE_BUFFER_SIZE - ps->writepos) + cb = STORE_BUFFER_SIZE - ps->writepos; + + memcpy(ps->new.buffer + ps->writepos, pb, cb); + pb += cb; + st -= cb; + ps->writepos += cb; + } +} + +static void +store_flush(png_structp pp) +{ + UNUSED(pp) /*DOES NOTHING*/ +} + +static size_t +store_read_buffer_size(png_store *ps) +{ + /* Return the bytes available for read in the current buffer. */ + if (ps->next != &ps->current->data) + return STORE_BUFFER_SIZE; + + return ps->current->datacount; +} + +/* Return total bytes available for read. */ +static size_t +store_read_buffer_avail(png_store *ps) +{ + if (ps->current != NULL && ps->next != NULL) + { + png_store_buffer *next = &ps->current->data; + size_t cbAvail = ps->current->datacount; + + while (next != ps->next && next != NULL) + { + next = next->prev; + cbAvail += STORE_BUFFER_SIZE; + } + + if (next != ps->next) + png_error(ps->pread, "buffer read error"); + + if (cbAvail > ps->readpos) + return cbAvail - ps->readpos; + } + + return 0; +} + +static int +store_read_buffer_next(png_store *ps) +{ + png_store_buffer *pbOld = ps->next; + png_store_buffer *pbNew = &ps->current->data; + if (pbOld != pbNew) + { + while (pbNew != NULL && pbNew->prev != pbOld) + pbNew = pbNew->prev; + + if (pbNew != NULL) + { + ps->next = pbNew; + ps->readpos = 0; + return 1; + } + + png_error(ps->pread, "buffer lost"); + } + + return 0; /* EOF or error */ +} + +/* Need separate implementation and callback to allow use of the same code + * during progressive read, where the io_ptr is set internally by libpng. + */ +static void +store_read_imp(png_store *ps, png_bytep pb, png_size_t st) +{ + if (ps->current == NULL || ps->next == NULL) + png_error(ps->pread, "store state damaged"); + + while (st > 0) + { + size_t cbAvail = store_read_buffer_size(ps) - ps->readpos; + + if (cbAvail > 0) + { + if (cbAvail > st) cbAvail = st; + memcpy(pb, ps->next->buffer + ps->readpos, cbAvail); + st -= cbAvail; + pb += cbAvail; + ps->readpos += cbAvail; + } + + else if (!store_read_buffer_next(ps)) + png_error(ps->pread, "read beyond end of file"); + } +} + +static void +store_read(png_structp pp, png_bytep pb, png_size_t st) +{ + png_store *ps = png_get_io_ptr(pp); + + if (ps == NULL || ps->pread != pp) + png_error(pp, "bad store read call"); + + store_read_imp(ps, pb, st); +} + +static void +store_progressive_read(png_store *ps, png_structp pp, png_infop pi) +{ + /* Notice that a call to store_read will cause this function to fail because + * readpos will be set. + */ + if (ps->pread != pp || ps->current == NULL || ps->next == NULL) + png_error(pp, "store state damaged (progressive)"); + + do + { + if (ps->readpos != 0) + png_error(pp, "store_read called during progressive read"); + + png_process_data(pp, pi, ps->next->buffer, store_read_buffer_size(ps)); + } + while (store_read_buffer_next(ps)); +} + +/***************************** MEMORY MANAGEMENT*** ***************************/ +/* A store_memory is simply the header for an allocated block of memory. The + * pointer returned to libpng is just after the end of the header block, the + * allocated memory is followed by a second copy of the 'mark'. + */ +typedef struct store_memory +{ + store_pool *pool; /* Originating pool */ + struct store_memory *next; /* Singly linked list */ + png_alloc_size_t size; /* Size of memory allocated */ + png_byte mark[4]; /* ID marker */ +} store_memory; + +/* Handle a fatal error in memory allocation. This calls png_error if the + * libpng struct is non-NULL, else it outputs a message and returns. This means + * that a memory problem while libpng is running will abort (png_error) the + * handling of particular file while one in cleanup (after the destroy of the + * struct has returned) will simply keep going and free (or attempt to free) + * all the memory. + */ +static void +store_pool_error(png_store *ps, png_structp pp, PNG_CONST char *msg) +{ + if (pp != NULL) + png_error(pp, msg); + + /* Else we have to do it ourselves. png_error eventually calls store_log, + * above. store_log accepts a NULL png_structp - it just changes what gets + * output by store_message. + */ + store_log(ps, pp, msg, 1 /* error */); +} + +static void +store_memory_free(png_structp pp, store_pool *pool, store_memory *memory) +{ + /* Note that pp may be NULL (see store_pool_delete below), the caller has + * found 'memory' in pool->list *and* unlinked this entry, so this is a valid + * pointer (for sure), but the contents may have been trashed. + */ + if (memory->pool != pool) + store_pool_error(pool->store, pp, "memory corrupted (pool)"); + + else if (memcmp(memory->mark, pool->mark, sizeof memory->mark) != 0) + store_pool_error(pool->store, pp, "memory corrupted (start)"); + + /* It should be safe to read the size field now. */ + else + { + png_alloc_size_t cb = memory->size; + + if (cb > pool->max) + store_pool_error(pool->store, pp, "memory corrupted (size)"); + + else if (memcmp((png_bytep)(memory+1)+cb, pool->mark, sizeof pool->mark) + != 0) + store_pool_error(pool->store, pp, "memory corrupted (end)"); + + /* Finally give the library a chance to find problems too: */ + else + { + pool->current -= cb; + free(memory); + } + } +} + +static void +store_pool_delete(png_store *ps, store_pool *pool) +{ + if (pool->list != NULL) + { + fprintf(stderr, "%s: %s %s: memory lost (list follows):\n", ps->test, + pool == &ps->read_memory_pool ? "read" : "write", + pool == &ps->read_memory_pool ? (ps->current != NULL ? + ps->current->name : "unknown file") : ps->wname); + ++ps->nerrors; + + do + { + store_memory *next = pool->list; + pool->list = next->next; + next->next = NULL; + + fprintf(stderr, "\t%lu bytes @ %p\n", + (unsigned long)next->size, next+1); + /* The NULL means this will always return, even if the memory is + * corrupted. + */ + store_memory_free(NULL, pool, next); + } + while (pool->list != NULL); + } + + /* And reset the other fields too for the next time. */ + if (pool->max > pool->max_max) pool->max_max = pool->max; + pool->max = 0; + if (pool->current != 0) /* unexpected internal error */ + fprintf(stderr, "%s: %s %s: memory counter mismatch (internal error)\n", + ps->test, pool == &ps->read_memory_pool ? "read" : "write", + pool == &ps->read_memory_pool ? (ps->current != NULL ? + ps->current->name : "unknown file") : ps->wname); + pool->current = 0; + + if (pool->limit > pool->max_limit) + pool->max_limit = pool->limit; + + pool->limit = 0; + + if (pool->total > pool->max_total) + pool->max_total = pool->total; + + pool->total = 0; + + /* Get a new mark too. */ + store_pool_mark(pool->mark); +} + +/* The memory callbacks: */ +static png_voidp +store_malloc(png_structp pp, png_alloc_size_t cb) +{ + store_pool *pool = png_get_mem_ptr(pp); + store_memory *new = malloc(cb + (sizeof *new) + (sizeof pool->mark)); + + if (new != NULL) + { + if (cb > pool->max) + pool->max = cb; + + pool->current += cb; + + if (pool->current > pool->limit) + pool->limit = pool->current; + + pool->total += cb; + + new->size = cb; + memcpy(new->mark, pool->mark, sizeof new->mark); + memcpy((png_byte*)(new+1) + cb, pool->mark, sizeof pool->mark); + new->pool = pool; + new->next = pool->list; + pool->list = new; + ++new; + } + + else + store_pool_error(pool->store, pp, "out of memory"); + + return new; +} + +static void +store_free(png_structp pp, png_voidp memory) +{ + store_pool *pool = png_get_mem_ptr(pp); + store_memory *this = memory, **test; + + /* First check that this 'memory' really is valid memory - it must be in the + * pool list. If it is, use the shared memory_free function to free it. + */ + --this; + for (test = &pool->list; *test != this; test = &(*test)->next) + { + if (*test == NULL) + { + store_pool_error(pool->store, pp, "bad pointer to free"); + return; + } + } + + /* Unlink this entry, *test == this. */ + *test = this->next; + this->next = NULL; + store_memory_free(pp, pool, this); +} + +/* Setup functions. */ +/* Cleanup when aborting a write or after storing the new file. */ +static void +store_write_reset(png_store *ps) +{ + if (ps->pwrite != NULL) + { + anon_context(ps); + + Try + png_destroy_write_struct(&ps->pwrite, &ps->piwrite); + + Catch_anonymous + { + /* memory corruption: continue. */ + } + + ps->pwrite = NULL; + ps->piwrite = NULL; + } + + /* And make sure that all the memory has been freed - this will output + * spurious errors in the case of memory corruption above, but this is safe. + */ + store_pool_delete(ps, &ps->write_memory_pool); + + store_freenew(ps); +} + +/* The following is the main write function, it returns a png_struct and, + * optionally, a png_info suitable for writiing a new PNG file. Use + * store_storefile above to record this file after it has been written. The + * returned libpng structures as destroyed by store_write_reset above. + */ +static png_structp +set_store_for_write(png_store *ps, png_infopp ppi, + PNG_CONST char * volatile name) +{ + anon_context(ps); + + Try + { + if (ps->pwrite != NULL) + png_error(ps->pwrite, "write store already in use"); + + store_write_reset(ps); + safecat(ps->wname, sizeof ps->wname, 0, name); + + /* Don't do the slow memory checks if doing a speed test. */ + if (ps->speed) + ps->pwrite = png_create_write_struct(PNG_LIBPNG_VER_STRING, + ps, store_error, store_warning); + + else + ps->pwrite = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, + ps, store_error, store_warning, &ps->write_memory_pool, + store_malloc, store_free); + + png_set_write_fn(ps->pwrite, ps, store_write, store_flush); + + if (ppi != NULL) + *ppi = ps->piwrite = png_create_info_struct(ps->pwrite); + } + + Catch_anonymous + return NULL; + + return ps->pwrite; +} + +/* Cleanup when finished reading (either due to error or in the success case). + */ +static void +store_read_reset(png_store *ps) +{ + if (ps->pread != NULL) + { + anon_context(ps); + + Try + png_destroy_read_struct(&ps->pread, &ps->piread, NULL); + + Catch_anonymous + { + /* error already output: continue */ + } + + ps->pread = NULL; + ps->piread = NULL; + } + + /* Always do this to be safe. */ + store_pool_delete(ps, &ps->read_memory_pool); + + ps->current = NULL; + ps->next = NULL; + ps->readpos = 0; + ps->validated = 0; +} + +static void +store_read_set(png_store *ps, png_uint_32 id) +{ + png_store_file *pf = ps->saved; + + while (pf != NULL) + { + if (pf->id == id) + { + ps->current = pf; + ps->next = NULL; + store_read_buffer_next(ps); + return; + } + + pf = pf->next; + } + + { + size_t pos; + char msg[FILE_NAME_SIZE+64]; + + pos = standard_name_from_id(msg, sizeof msg, 0, id); + pos = safecat(msg, sizeof msg, pos, ": file not found"); + png_error(ps->pread, msg); + } +} + +/* The main interface for reading a saved file - pass the id number of the file + * to retrieve. Ids must be unique or the earlier file will be hidden. The API + * returns a png_struct and, optionally, a png_info. Both of these will be + * destroyed by store_read_reset above. + */ +static png_structp +set_store_for_read(png_store *ps, png_infopp ppi, png_uint_32 id, + PNG_CONST char *name) +{ + /* Set the name for png_error */ + safecat(ps->test, sizeof ps->test, 0, name); + + if (ps->pread != NULL) + png_error(ps->pread, "read store already in use"); + + store_read_reset(ps); + + /* Both the create APIs can return NULL if used in their default mode + * (because there is no other way of handling an error because the jmp_buf + * by default is stored in png_struct and that has not been allocated!) + * However, given that store_error works correctly in these circumstances + * we don't ever expect NULL in this program. + */ + if (ps->speed) + ps->pread = png_create_read_struct(PNG_LIBPNG_VER_STRING, ps, + store_error, store_warning); + + else + ps->pread = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, ps, + store_error, store_warning, &ps->read_memory_pool, store_malloc, + store_free); + + if (ps->pread == NULL) + { + struct exception_context *the_exception_context = &ps->exception_context; + + store_log(ps, NULL, "png_create_read_struct returned NULL (unexpected)", + 1 /*error*/); + + Throw ps; + } + + store_read_set(ps, id); + + if (ppi != NULL) + *ppi = ps->piread = png_create_info_struct(ps->pread); + + return ps->pread; +} + +/* The overall cleanup of a store simply calls the above then removes all the + * saved files. This does not delete the store itself. + */ +static void +store_delete(png_store *ps) +{ + store_write_reset(ps); + store_read_reset(ps); + store_freefile(&ps->saved); + + if (ps->image != NULL) + { + free(ps->image-1); + ps->image = NULL; + ps->cb_image = 0; + } +} + +/*********************** PNG FILE MODIFICATION ON READ ************************/ +/* Files may be modified on read. The following structure contains a complete + * png_store together with extra members to handle modification and a special + * read callback for libpng. To use this the 'modifications' field must be set + * to a list of png_modification structures that actually perform the + * modification, otherwise a png_modifier is functionally equivalent to a + * png_store. There is a special read function, set_modifier_for_read, which + * replaces set_store_for_read. + */ +typedef struct png_modifier +{ + png_store this; /* I am a png_store */ + struct png_modification *modifications; /* Changes to make */ + + enum modifier_state + { + modifier_start, /* Initial value */ + modifier_signature, /* Have a signature */ + modifier_IHDR /* Have an IHDR */ + } state; /* My state */ + + /* Information from IHDR: */ + png_byte bit_depth; /* From IHDR */ + png_byte colour_type; /* From IHDR */ + + /* While handling PLTE, IDAT and IEND these chunks may be pended to allow + * other chunks to be inserted. + */ + png_uint_32 pending_len; + png_uint_32 pending_chunk; + + /* Test values */ + double *gammas; + unsigned int ngammas; + + /* Lowest sbit to test (libpng fails for sbit < 8) */ + png_byte sbitlow; + + /* Error control - these are the limits on errors accepted by the gamma tests + * below. + */ + double maxout8; /* Maximum output value error */ + double maxabs8; /* Absolute sample error 0..1 */ + double maxpc8; /* Percentage sample error 0..100% */ + double maxout16; /* Maximum output value error */ + double maxabs16; /* Absolute sample error 0..1 */ + double maxpc16; /* Percentage sample error 0..100% */ + + /* Logged 8 and 16 bit errors ('output' values): */ + double error_gray_2; + double error_gray_4; + double error_gray_8; + double error_gray_16; + double error_color_8; + double error_color_16; + + /* Flags: */ + /* Whether or not to interlace. */ + int interlace_type :9; /* int, but must store '1' */ + + /* Run the standard tests? */ + unsigned int test_standard :1; + + /* Run the odd-sized image and interlace read/write tests? */ + unsigned int test_size :1; + + /* Run tests on reading with a combiniation of transforms, */ + unsigned int test_transform :1; + + /* When to use the use_input_precision option: */ + unsigned int use_input_precision :1; + unsigned int use_input_precision_sbit :1; + unsigned int use_input_precision_16to8 :1; + + /* Which gamma tests to run: */ + unsigned int test_gamma_threshold :1; + unsigned int test_gamma_transform :1; /* main tests */ + unsigned int test_gamma_sbit :1; + unsigned int test_gamma_strip16 :1; + + unsigned int log :1; /* Log max error */ + + /* Buffer information, the buffer size limits the size of the chunks that can + * be modified - they must fit (including header and CRC) into the buffer! + */ + size_t flush; /* Count of bytes to flush */ + size_t buffer_count; /* Bytes in buffer */ + size_t buffer_position; /* Position in buffer */ + png_byte buffer[1024]; +} png_modifier; + +static double abserr(png_modifier *pm, png_byte bit_depth) +{ + return bit_depth == 16 ? pm->maxabs16 : pm->maxabs8; +} + +static double pcerr(png_modifier *pm, png_byte bit_depth) +{ + return (bit_depth == 16 ? pm->maxpc16 : pm->maxpc8) * .01; +} + +static double outerr(png_modifier *pm, png_byte bit_depth) +{ + /* There is a serious error in the 2 and 4 bit grayscale transform because + * the gamma table value (8 bits) is simply shifted, not rounded, so the + * error in 4 bit greyscale gamma is up to the value below. This is a hack + * to allow pngvalid to succeed: + */ + if (bit_depth == 2) + return .73182-.5; + + if (bit_depth == 4) + return .90644-.5; + + if (bit_depth == 16) + return pm->maxout16; + + return pm->maxout8; +} + +/* This returns true if the test should be stopped now because it has already + * failed and it is running silently. + */ +static int fail(png_modifier *pm) +{ + return !pm->log && !pm->this.verbose && (pm->this.nerrors > 0 || + (pm->this.treat_warnings_as_errors && pm->this.nwarnings > 0)); +} + +static void +modifier_init(png_modifier *pm) +{ + memset(pm, 0, sizeof *pm); + store_init(&pm->this); + pm->modifications = NULL; + pm->state = modifier_start; + pm->sbitlow = 1U; + pm->maxout8 = pm->maxpc8 = pm->maxabs8 = 0; + pm->maxout16 = pm->maxpc16 = pm->maxabs16 = 0; + pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0; + pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0; + pm->interlace_type = PNG_INTERLACE_NONE; + pm->test_standard = 0; + pm->test_size = 0; + pm->test_transform = 0; + pm->use_input_precision = 0; + pm->use_input_precision_sbit = 0; + pm->use_input_precision_16to8 = 0; + pm->test_gamma_threshold = 0; + pm->test_gamma_transform = 0; + pm->test_gamma_sbit = 0; + pm->test_gamma_strip16 = 0; + pm->log = 0; + + /* Rely on the memset for all the other fields - there are no pointers */ +} + +/* One modification structure must be provided for each chunk to be modified (in + * fact more than one can be provided if multiple separate changes are desired + * for a single chunk.) Modifications include adding a new chunk when a + * suitable chunk does not exist. + * + * The caller of modify_fn will reset the CRC of the chunk and record 'modified' + * or 'added' as appropriate if the modify_fn returns 1 (true). If the + * modify_fn is NULL the chunk is simply removed. + */ +typedef struct png_modification +{ + struct png_modification *next; + png_uint_32 chunk; + + /* If the following is NULL all matching chunks will be removed: */ + int (*modify_fn)(struct png_modifier *pm, + struct png_modification *me, int add); + + /* If the following is set to PLTE, IDAT or IEND and the chunk has not been + * found and modified (and there is a modify_fn) the modify_fn will be called + * to add the chunk before the relevant chunk. + */ + png_uint_32 add; + unsigned int modified :1; /* Chunk was modified */ + unsigned int added :1; /* Chunk was added */ + unsigned int removed :1; /* Chunk was removed */ +} png_modification; + +static void modification_reset(png_modification *pmm) +{ + if (pmm != NULL) + { + pmm->modified = 0; + pmm->added = 0; + pmm->removed = 0; + modification_reset(pmm->next); + } +} + +static void +modification_init(png_modification *pmm) +{ + memset(pmm, 0, sizeof *pmm); + pmm->next = NULL; + pmm->chunk = 0; + pmm->modify_fn = NULL; + pmm->add = 0; + modification_reset(pmm); +} + +static void +modifier_reset(png_modifier *pm) +{ + store_read_reset(&pm->this); + pm->modifications = NULL; + pm->state = modifier_start; + pm->bit_depth = pm->colour_type = 0; + pm->pending_len = pm->pending_chunk = 0; + pm->flush = pm->buffer_count = pm->buffer_position = 0; +} + +/* Convenience macros. */ +#define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d)) +#define CHUNK_IHDR CHUNK(73,72,68,82) +#define CHUNK_PLTE CHUNK(80,76,84,69) +#define CHUNK_IDAT CHUNK(73,68,65,84) +#define CHUNK_IEND CHUNK(73,69,78,68) +#define CHUNK_cHRM CHUNK(99,72,82,77) +#define CHUNK_gAMA CHUNK(103,65,77,65) +#define CHUNK_sBIT CHUNK(115,66,73,84) +#define CHUNK_sRGB CHUNK(115,82,71,66) + +/* The guts of modification are performed during a read. */ +static void +modifier_crc(png_bytep buffer) +{ + /* Recalculate the chunk CRC - a complete chunk must be in + * the buffer, at the start. + */ + uInt datalen = png_get_uint_32(buffer); + png_save_uint_32(buffer+datalen+8, crc32(0L, buffer+4, datalen+4)); +} + +static void +modifier_setbuffer(png_modifier *pm) +{ + modifier_crc(pm->buffer); + pm->buffer_count = png_get_uint_32(pm->buffer)+12; + pm->buffer_position = 0; +} + +/* Separate the callback into the actual implementation (which is passed the + * png_modifier explicitly) and the callback, which gets the modifier from the + * png_struct. + */ +static void +modifier_read_imp(png_modifier *pm, png_bytep pb, png_size_t st) +{ + while (st > 0) + { + size_t cb; + png_uint_32 len, chunk; + png_modification *mod; + + if (pm->buffer_position >= pm->buffer_count) switch (pm->state) + { + static png_byte sign[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; + case modifier_start: + store_read_imp(&pm->this, pm->buffer, 8); /* size of signature. */ + pm->buffer_count = 8; + pm->buffer_position = 0; + + if (memcmp(pm->buffer, sign, 8) != 0) + png_error(pm->this.pread, "invalid PNG file signature"); + pm->state = modifier_signature; + break; + + case modifier_signature: + store_read_imp(&pm->this, pm->buffer, 13+12); /* size of IHDR */ + pm->buffer_count = 13+12; + pm->buffer_position = 0; + + if (png_get_uint_32(pm->buffer) != 13 || + png_get_uint_32(pm->buffer+4) != CHUNK_IHDR) + png_error(pm->this.pread, "invalid IHDR"); + + /* Check the list of modifiers for modifications to the IHDR. */ + mod = pm->modifications; + while (mod != NULL) + { + if (mod->chunk == CHUNK_IHDR && mod->modify_fn && + (*mod->modify_fn)(pm, mod, 0)) + { + mod->modified = 1; + modifier_setbuffer(pm); + } + + /* Ignore removal or add if IHDR! */ + mod = mod->next; + } + + /* Cache information from the IHDR (the modified one.) */ + pm->bit_depth = pm->buffer[8+8]; + pm->colour_type = pm->buffer[8+8+1]; + + pm->state = modifier_IHDR; + pm->flush = 0; + break; + + case modifier_IHDR: + default: + /* Read a new chunk and process it until we see PLTE, IDAT or + * IEND. 'flush' indicates that there is still some data to + * output from the preceding chunk. + */ + if ((cb = pm->flush) > 0) + { + if (cb > st) cb = st; + pm->flush -= cb; + store_read_imp(&pm->this, pb, cb); + pb += cb; + st -= cb; + if (st <= 0) return; + } + + /* No more bytes to flush, read a header, or handle a pending + * chunk. + */ + if (pm->pending_chunk != 0) + { + png_save_uint_32(pm->buffer, pm->pending_len); + png_save_uint_32(pm->buffer+4, pm->pending_chunk); + pm->pending_len = 0; + pm->pending_chunk = 0; + } + else + store_read_imp(&pm->this, pm->buffer, 8); + + pm->buffer_count = 8; + pm->buffer_position = 0; + + /* Check for something to modify or a terminator chunk. */ + len = png_get_uint_32(pm->buffer); + chunk = png_get_uint_32(pm->buffer+4); + + /* Terminators first, they may have to be delayed for added + * chunks + */ + if (chunk == CHUNK_PLTE || chunk == CHUNK_IDAT || + chunk == CHUNK_IEND) + { + mod = pm->modifications; + + while (mod != NULL) + { + if ((mod->add == chunk || + (mod->add == CHUNK_PLTE && chunk == CHUNK_IDAT)) && + mod->modify_fn != NULL && !mod->modified && !mod->added) + { + /* Regardless of what the modify function does do not run + * this again. + */ + mod->added = 1; + + if ((*mod->modify_fn)(pm, mod, 1 /*add*/)) + { + /* Reset the CRC on a new chunk */ + if (pm->buffer_count > 0) + modifier_setbuffer(pm); + + else + { + pm->buffer_position = 0; + mod->removed = 1; + } + + /* The buffer has been filled with something (we assume) + * so output this. Pend the current chunk. + */ + pm->pending_len = len; + pm->pending_chunk = chunk; + break; /* out of while */ + } + } + + mod = mod->next; + } + + /* Don't do any further processing if the buffer was modified - + * otherwise the code will end up modifying a chunk that was + * just added. + */ + if (mod != NULL) + break; /* out of switch */ + } + + /* If we get to here then this chunk may need to be modified. To + * do this it must be less than 1024 bytes in total size, otherwise + * it just gets flushed. + */ + if (len+12 <= sizeof pm->buffer) + { + store_read_imp(&pm->this, pm->buffer+pm->buffer_count, + len+12-pm->buffer_count); + pm->buffer_count = len+12; + + /* Check for a modification, else leave it be. */ + mod = pm->modifications; + while (mod != NULL) + { + if (mod->chunk == chunk) + { + if (mod->modify_fn == NULL) + { + /* Remove this chunk */ + pm->buffer_count = pm->buffer_position = 0; + mod->removed = 1; + break; /* Terminate the while loop */ + } + + else if ((*mod->modify_fn)(pm, mod, 0)) + { + mod->modified = 1; + /* The chunk may have been removed: */ + if (pm->buffer_count == 0) + { + pm->buffer_position = 0; + break; + } + modifier_setbuffer(pm); + } + } + + mod = mod->next; + } + } + + else + pm->flush = len+12 - pm->buffer_count; /* data + crc */ + + /* Take the data from the buffer (if there is any). */ + break; + } + + /* Here to read from the modifier buffer (not directly from + * the store, as in the flush case above.) + */ + cb = pm->buffer_count - pm->buffer_position; + + if (cb > st) + cb = st; + + memcpy(pb, pm->buffer + pm->buffer_position, cb); + st -= cb; + pb += cb; + pm->buffer_position += cb; + } +} + +/* The callback: */ +static void +modifier_read(png_structp pp, png_bytep pb, png_size_t st) +{ + png_modifier *pm = png_get_io_ptr(pp); + + if (pm == NULL || pm->this.pread != pp) + png_error(pp, "bad modifier_read call"); + + modifier_read_imp(pm, pb, st); +} + +/* Like store_progressive_read but the data is getting changed as we go so we + * need a local buffer. + */ +static void +modifier_progressive_read(png_modifier *pm, png_structp pp, png_infop pi) +{ + if (pm->this.pread != pp || pm->this.current == NULL || + pm->this.next == NULL) + png_error(pp, "store state damaged (progressive)"); + + /* This is another Horowitz and Hill random noise generator. In this case + * the aim is to stress the progressive reader with truely horrible variable + * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers + * is generated. We could probably just count from 1 to 32767 and get as + * good a result. + */ + for (;;) + { + static png_uint_32 noise = 1; + png_size_t cb, cbAvail; + png_byte buffer[512]; + + /* Generate 15 more bits of stuff: */ + noise = (noise << 9) | ((noise ^ (noise >> (9-5))) & 0x1ff); + cb = noise & 0x1ff; + + /* Check that this number of bytes are available (in the current buffer.) + * (This doesn't quite work - the modifier might delete a chunk; unlikely + * but possible, it doesn't happen at present because the modifier only + * adds chunks to standard images.) + */ + cbAvail = store_read_buffer_avail(&pm->this); + if (pm->buffer_count > pm->buffer_position) + cbAvail += pm->buffer_count - pm->buffer_position; + + if (cb > cbAvail) + { + /* Check for EOF: */ + if (cbAvail == 0) + break; + + cb = cbAvail; + } + + modifier_read_imp(pm, buffer, cb); + png_process_data(pp, pi, buffer, cb); + } + + /* Check the invariants at the end (if this fails it's a problem in this + * file!) + */ + if (pm->buffer_count > pm->buffer_position || + pm->this.next != &pm->this.current->data || + pm->this.readpos < pm->this.current->datacount) + png_error(pp, "progressive read implementation error"); +} + +/* Set up a modifier. */ +static png_structp +set_modifier_for_read(png_modifier *pm, png_infopp ppi, png_uint_32 id, + PNG_CONST char *name) +{ + /* Do this first so that the modifier fields are cleared even if an error + * happens allocating the png_struct. No allocation is done here so no + * cleanup is required. + */ + pm->state = modifier_start; + pm->bit_depth = 0; + pm->colour_type = 255; + + pm->pending_len = 0; + pm->pending_chunk = 0; + pm->flush = 0; + pm->buffer_count = 0; + pm->buffer_position = 0; + + return set_store_for_read(&pm->this, ppi, id, name); +} + +/***************************** STANDARD PNG FILES *****************************/ +/* Standard files - write and save standard files. */ +/* There are two basic forms of standard images. Those which attempt to have + * all the possible pixel values (not possible for 16bpp images, but a range of + * values are produced) and those which have a range of image sizes. The former + * are used for testing transforms, in particular gamma correction and bit + * reduction and increase. The latter are reserved for testing the behavior of + * libpng with respect to 'odd' image sizes - particularly small images where + * rows become 1 byte and interlace passes disappear. + * + * The first, most useful, set are the 'transform' images, the second set of + * small images are the 'size' images. + * + * The transform files are constructed with rows which fit into a 1024 byte row + * buffer. This makes allocation easier below. Further regardless of the file + * format every row has 128 pixels (giving 1024 bytes for 64bpp formats). + * + * Files are stored with no gAMA or sBIT chunks, with a PLTE only when needed + * and with an ID derived from the colour type, bit depth and interlace type + * as above (FILEID). The width (128) and height (variable) are not stored in + * the FILEID - instead the fields are set to 0, indicating a transform file. + * + * The size files ar constructed with rows a maximum of 128 bytes wide, allowing + * a maximum width of 16 pixels (for the 64bpp case.) They also have a maximum + * height of 16 rows. The width and height are stored in the FILEID and, being + * non-zero, indicate a size file. + */ + +/* The number of passes is related to the interlace type. There wass no libpng + * API to determine this prior to 1.5, so we need an inquiry function: + */ +static int +npasses_from_interlace_type(png_structp pp, int interlace_type) +{ + switch (interlace_type) + { + default: + png_error(pp, "invalid interlace type"); + + case PNG_INTERLACE_NONE: + return 1; + + case PNG_INTERLACE_ADAM7: + return PNG_INTERLACE_ADAM7_PASSES; + } +} + +static unsigned int +bit_size(png_structp pp, png_byte colour_type, png_byte bit_depth) +{ + switch (colour_type) + { + case 0: return bit_depth; + + case 2: return 3*bit_depth; + + case 3: return bit_depth; + + case 4: return 2*bit_depth; + + case 6: return 4*bit_depth; + + default: png_error(pp, "invalid color type"); + } +} + +#define TRANSFORM_WIDTH 128U +#define TRANSFORM_ROWMAX (TRANSFORM_WIDTH*8U) +#define SIZE_ROWMAX (16*8U) /* 16 pixels, max 8 bytes each - 128 bytes */ +#define STANDARD_ROWMAX TRANSFORM_ROWMAX /* The larger of the two */ + +/* So the maximum image sizes are as follows. A 'transform' image may require + * more than 65535 bytes. The size images are a maximum of 2046 bytes. + */ +#define TRANSFORM_IMAGEMAX (TRANSFORM_ROWMAX * (png_uint_32)2048) +#define SIZE_IMAGEMAX (SIZE_ROWMAX * 16U) + +static size_t +transform_rowsize(png_structp pp, png_byte colour_type, png_byte bit_depth) +{ + return (TRANSFORM_WIDTH * bit_size(pp, colour_type, bit_depth)) / 8; +} + +/* transform_width(pp, colour_type, bit_depth) current returns the same number + * every time, so just use a macro: + */ +#define transform_width(pp, colour_type, bit_depth) TRANSFORM_WIDTH + +static png_uint_32 +transform_height(png_structp pp, png_byte colour_type, png_byte bit_depth) +{ + switch (bit_size(pp, colour_type, bit_depth)) + { + case 1: + case 2: + case 4: + return 1; /* Total of 128 pixels */ + + case 8: + return 2; /* Total of 256 pixels/bytes */ + + case 16: + return 512; /* Total of 65536 pixels */ + + case 24: + case 32: + return 512; /* 65536 pixels */ + + case 48: + case 64: + return 2048;/* 4 x 65536 pixels. */ + + default: + return 0; /* Error, will be caught later */ + } +} + +/* The following can only be defined here, now we have the definitions + * of the transform image sizes. + */ +static png_uint_32 +standard_width(png_structp pp, png_uint_32 id) +{ + png_uint_32 width = WIDTH_FROM_ID(id); + UNUSED(pp) + + if (width == 0) + width = transform_width(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); + + return width; +} + +static png_uint_32 +standard_height(png_structp pp, png_uint_32 id) +{ + png_uint_32 height = HEIGHT_FROM_ID(id); + + if (height == 0) + height = transform_height(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); + + return height; +} + +static png_uint_32 +standard_rowsize(png_structp pp, png_uint_32 id) +{ + png_uint_32 width = standard_width(pp, id); + + /* This won't overflow: */ + width *= bit_size(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); + return (width + 7) / 8; +} + +static void +transform_row(png_structp pp, png_byte buffer[TRANSFORM_ROWMAX], + png_byte colour_type, png_byte bit_depth, png_uint_32 y) +{ + png_uint_32 v = y << 7; + png_uint_32 i = 0; + + switch (bit_size(pp, colour_type, bit_depth)) + { + case 1: + while (i<128/8) buffer[i] = v & 0xff, v += 17, ++i; + return; + + case 2: + while (i<128/4) buffer[i] = v & 0xff, v += 33, ++i; + return; + + case 4: + while (i<128/2) buffer[i] = v & 0xff, v += 65, ++i; + return; + + case 8: + /* 256 bytes total, 128 bytes in each row set as follows: */ + while (i<128) buffer[i] = v & 0xff, ++v, ++i; + return; + + case 16: + /* Generate all 65536 pixel values in order, which includes the 8 bit + * GA case as well as the 16 bit G case. + */ + while (i<128) + buffer[2*i] = (v>>8) & 0xff, buffer[2*i+1] = v & 0xff, ++v, ++i; + + return; + + case 24: + /* 65535 pixels, but rotate the values. */ + while (i<128) + { + /* Three bytes per pixel, r, g, b, make b by r^g */ + buffer[3*i+0] = (v >> 8) & 0xff; + buffer[3*i+1] = v & 0xff; + buffer[3*i+2] = ((v >> 8) ^ v) & 0xff; + ++v; + ++i; + } + + return; + + case 32: + /* 65535 pixels, r, g, b, a; just replicate */ + while (i<128) + { + buffer[4*i+0] = (v >> 8) & 0xff; + buffer[4*i+1] = v & 0xff; + buffer[4*i+2] = (v >> 8) & 0xff; + buffer[4*i+3] = v & 0xff; + ++v; + ++i; + } + + return; + + case 48: + /* y is maximum 2047, giving 4x65536 pixels, make 'r' increase by 1 at + * each pixel, g increase by 257 (0x101) and 'b' by 0x1111: + */ + while (i<128) + { + png_uint_32 t = v++; + buffer[6*i+0] = (t >> 8) & 0xff; + buffer[6*i+1] = t & 0xff; + t *= 257; + buffer[6*i+2] = (t >> 8) & 0xff; + buffer[6*i+3] = t & 0xff; + t *= 17; + buffer[6*i+4] = (t >> 8) & 0xff; + buffer[6*i+5] = t & 0xff; + ++i; + } + + return; + + case 64: + /* As above in the 32 bit case. */ + while (i<128) + { + png_uint_32 t = v++; + buffer[8*i+0] = (t >> 8) & 0xff; + buffer[8*i+1] = t & 0xff; + buffer[8*i+4] = (t >> 8) & 0xff; + buffer[8*i+5] = t & 0xff; + t *= 257; + buffer[8*i+2] = (t >> 8) & 0xff; + buffer[8*i+3] = t & 0xff; + buffer[8*i+6] = (t >> 8) & 0xff; + buffer[8*i+7] = t & 0xff; + ++i; + } + return; + + default: + break; + } + + png_error(pp, "internal error"); +} + +/* This is just to do the right cast - could be changed to a function to check + * 'bd' but there isn't much point. + */ +#define DEPTH(bd) ((png_byte)(1U << (bd))) + +/* Make a standardized image given a an image colour type, bit depth and + * interlace type. The standard images have a very restricted range of + * rows and heights and are used for testing transforms rather than image + * layout details. See make_size_images below for a way to make images + * that test odd sizes along with the libpng interlace handling. + */ +static void +make_transform_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, + png_byte PNG_CONST bit_depth, int interlace_type, png_const_charp name) +{ + context(ps, fault); + + Try + { + png_infop pi; + png_structp pp = set_store_for_write(ps, &pi, name); + png_uint_32 h; + + /* In the event of a problem return control to the Catch statement below + * to do the clean up - it is not possible to 'return' directly from a Try + * block. + */ + if (pp == NULL) + Throw ps; + + h = transform_height(pp, colour_type, bit_depth); + + png_set_IHDR(pp, pi, transform_width(pp, colour_type, bit_depth), h, + bit_depth, colour_type, interlace_type, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + if (colour_type == 3) /* palette */ + { + unsigned int i = 0; + png_color pal[256]; + + do + pal[i].red = pal[i].green = pal[i].blue = (png_byte)i; + while(++i < 256U); + + png_set_PLTE(pp, pi, pal, 256); + } + + png_write_info(pp, pi); + + if (png_get_rowbytes(pp, pi) != + transform_rowsize(pp, colour_type, bit_depth)) + png_error(pp, "row size incorrect"); + + else + { + /* Somewhat confusingly this must be called *after* png_write_info + * because if it is called before, the information in *pp has not been + * updated to reflect the interlaced image. + */ + int npasses = png_set_interlace_handling(pp); + int pass; + + if (npasses != npasses_from_interlace_type(pp, interlace_type)) + png_error(pp, "write: png_set_interlace_handling failed"); + + for (pass=0; passtest, sizeof ps->test, 0, "make standard images"); + + /* Arguments are colour_type, low bit depth, high bit depth + */ + make_standard(ps, 0, 0, WRITE_BDHI); + make_standard(ps, 2, 3, WRITE_BDHI); + make_standard(ps, 3, 0, 3 /*palette: max 8 bits*/); + make_standard(ps, 4, 3, WRITE_BDHI); + make_standard(ps, 6, 3, WRITE_BDHI); +} + +/* The following two routines use the PNG interlace support macros from + * png.h to interlace or deinterlace rows. + */ +static void +interlace_row(png_bytep buffer, png_const_bytep imageRow, + unsigned int pixel_size, png_uint_32 w, int pass) +{ + png_uint_32 xin, xout, xstep; + + /* Note that this can, trivially, be optimized to a memcpy on pass 7, the + * code is presented this way to make it easier to understand. In practice + * consult the code in the libpng source to see other ways of doing this. + */ + xin = PNG_PASS_START_COL(pass); + xstep = 1U<= 8) + *buffer++ = (png_byte)y++, bit_width -= 8; + + /* There may be up to 7 remaining bits, these go in the most significant + * bits of the byte. + */ + if (bit_width > 0) + { + png_uint_32 mask = (1U<<(8-bit_width))-1; + *buffer = (png_byte)((*buffer & mask) | (y & ~mask)); + } +} + +static void +make_size_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, + png_byte PNG_CONST bit_depth, int PNG_CONST interlace_type, + png_uint_32 PNG_CONST w, png_uint_32 PNG_CONST h, + int PNG_CONST do_interlace) +{ + context(ps, fault); + + Try + { + png_infop pi; + png_structp pp; + unsigned int pixel_size; + + /* Make a name and get an appropriate id for the store: */ + char name[FILE_NAME_SIZE]; + PNG_CONST png_uint_32 id = FILEID(colour_type, bit_depth, interlace_type, + w, h, do_interlace); + + standard_name_from_id(name, sizeof name, 0, id); + pp = set_store_for_write(ps, &pi, name); + + /* In the event of a problem return control to the Catch statement below + * to do the clean up - it is not possible to 'return' directly from a Try + * block. + */ + if (pp == NULL) + Throw ps; + + png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + /* Same palette as make_transform_image - I don' think there is any + * benefit from using a different one (JB 20101211) + */ + if (colour_type == 3) /* palette */ + { + unsigned int i = 0; + png_color pal[256]; + + do + pal[i].red = pal[i].green = pal[i].blue = (png_byte)i; + while(++i < 256U); + + png_set_PLTE(pp, pi, pal, 256); + } + + png_write_info(pp, pi); + + /* Calculate the bit size, divide by 8 to get the byte size - this won't + * overflow because we know the w values are all small enough even for + * a system where 'unsigned int' is only 16 bits. + */ + pixel_size = bit_size(pp, colour_type, bit_depth); + if (png_get_rowbytes(pp, pi) != ((w * pixel_size) + 7) / 8) + png_error(pp, "row size incorrect"); + + else + { + int npasses = npasses_from_interlace_type(pp, interlace_type); + png_uint_32 y; + int pass; + png_byte image[16][SIZE_ROWMAX]; + + /* To help consistent error detection make the parts of this buffer + * that aren't set below all '1': + */ + memset(image, 0xff, sizeof image); + + if (!do_interlace && npasses != png_set_interlace_handling(pp)) + png_error(pp, "write: png_set_interlace_handling failed"); + + /* Prepare the whole image first to avoid making it 7 times: */ + for (y=0; y 0) + { + /* Set to all 1's for error detection (libpng tends to + * set unset things to 0). + */ + memset(tempRow, 0xff, sizeof tempRow); + interlace_row(tempRow, row, pixel_size, w, pass); + row = tempRow; + } + else + continue; + } + + /* Only get to here if the row has some pixels in it. */ + png_write_row(pp, row); + } + } + } + + png_write_end(pp, pi); + + /* And store this under the appropriate id, then clean up. */ + store_storefile(ps, id); + + store_write_reset(ps); + } + + Catch(fault) + { + /* Use the png_store returned by the exception. This may help the compiler + * because 'ps' is not used in this branch of the setjmp. Note that fault + * and ps will always be the same value. + */ + store_write_reset(fault); + } +} + +static void +make_size(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, int bdlo, + int PNG_CONST bdhi) +{ + for (; bdlo <= bdhi; ++bdlo) + { + png_uint_32 width; + + for (width = 1; width <= 16; ++width) + { + png_uint_32 height; + + for (height = 1; height <= 16; ++height) + { + /* The four combinations of DIY interlace and interlace or not - + * no interlace + DIY should be identical to no interlace with + * libpng doing it. + */ + make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE, + width, height, 0); + make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE, + width, height, 1); + make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7, + width, height, 0); + make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7, + width, height, 1); + } + } + } +} + +static void +make_size_images(png_store *ps) +{ + /* This is in case of errors. */ + safecat(ps->test, sizeof ps->test, 0, "make size images"); + + /* Arguments are colour_type, low bit depth, high bit depth + */ + make_size(ps, 0, 0, WRITE_BDHI); + make_size(ps, 2, 3, WRITE_BDHI); + make_size(ps, 3, 0, 3 /*palette: max 8 bits*/); + make_size(ps, 4, 3, WRITE_BDHI); + make_size(ps, 6, 3, WRITE_BDHI); +} + +/* Return a row based on image id and 'y' for checking: */ +static void +standard_row(png_structp pp, png_byte std[STANDARD_ROWMAX], png_uint_32 id, + png_uint_32 y) +{ + if (WIDTH_FROM_ID(id) == 0) + transform_row(pp, std, COL_FROM_ID(id), DEPTH_FROM_ID(id), y); + else + size_row(std, WIDTH_FROM_ID(id) * bit_size(pp, COL_FROM_ID(id), + DEPTH_FROM_ID(id)), y); +} + +/* Tests - individual test cases */ +/* Like 'make_standard' but errors are deliberately introduced into the calls + * to ensure that they get detected - it should not be possible to write an + * invalid image with libpng! + */ +static void +sBIT0_error_fn(png_structp pp, png_infop pi) +{ + /* 0 is invalid... */ + png_color_8 bad; + bad.red = bad.green = bad.blue = bad.gray = bad.alpha = 0; + png_set_sBIT(pp, pi, &bad); +} + +static void +sBIT_error_fn(png_structp pp, png_infop pi) +{ + png_byte bit_depth; + png_color_8 bad; + + if (png_get_color_type(pp, pi) == PNG_COLOR_TYPE_PALETTE) + bit_depth = 8; + + else + bit_depth = png_get_bit_depth(pp, pi); + + /* Now we know the bit depth we can easily generate an invalid sBIT entry */ + bad.red = bad.green = bad.blue = bad.gray = bad.alpha = + (png_byte)(bit_depth+1); + png_set_sBIT(pp, pi, &bad); +} + +static PNG_CONST struct +{ + void (*fn)(png_structp, png_infop); + PNG_CONST char *msg; + unsigned int warning :1; /* the error is a warning... */ +} error_test[] = + { + { sBIT0_error_fn, "sBIT(0): failed to detect error", 1 }, + { sBIT_error_fn, "sBIT(too big): failed to detect error", 1 }, + }; + +static void +make_error(png_store* volatile ps, png_byte PNG_CONST colour_type, + png_byte bit_depth, int interlace_type, int test, png_const_charp name) +{ + context(ps, fault); + + Try + { + png_structp pp; + png_infop pi; + + pp = set_store_for_write(ps, &pi, name); + + if (pp == NULL) + Throw ps; + + png_set_IHDR(pp, pi, transform_width(pp, colour_type, bit_depth), + transform_height(pp, colour_type, bit_depth), bit_depth, colour_type, + interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + if (colour_type == 3) /* palette */ + { + unsigned int i = 0; + png_color pal[256]; + + do + pal[i].red = pal[i].green = pal[i].blue = (png_byte)i; + while(++i < 256U); + + png_set_PLTE(pp, pi, pal, 256); + } + + /* Time for a few errors, these are in various optional chunks, the + * standard tests test the standard chunks pretty well. + */ +# define exception__prev exception_prev_1 +# define exception__env exception_env_1 + Try + { + /* Expect this to throw: */ + ps->expect_error = !error_test[test].warning; + ps->expect_warning = error_test[test].warning; + ps->saw_warning = 0; + error_test[test].fn(pp, pi); + + /* Normally the error is only detected here: */ + png_write_info(pp, pi); + + /* And handle the case where it was only a warning: */ + if (ps->expect_warning && ps->saw_warning) + Throw ps; + + /* If we get here there is a problem, we have success - no error or + * no warning - when we shouldn't have success. Log an error. + */ + store_log(ps, pp, error_test[test].msg, 1 /*error*/); + } + + Catch (fault) + ps = fault; /* expected exit, make sure ps is not clobbered */ +#undef exception__prev +#undef exception__env + + /* And clear these flags */ + ps->expect_error = 0; + ps->expect_warning = 0; + + /* Now write the whole image, just to make sure that the detected, or + * undetected, errro has not created problems inside libpng. + */ + if (png_get_rowbytes(pp, pi) != + transform_rowsize(pp, colour_type, bit_depth)) + png_error(pp, "row size incorrect"); + + else + { + png_uint_32 h = transform_height(pp, colour_type, bit_depth); + int npasses = png_set_interlace_handling(pp); + int pass; + + if (npasses != npasses_from_interlace_type(pp, interlace_type)) + png_error(pp, "write: png_set_interlace_handling failed"); + + for (pass=0; passthis, colour_type, DEPTH(bdlo), interlace_type, + test, name); + + if (fail(pm)) + return 0; + } + } + } + + return 1; /* keep going */ +} + +static void +perform_error_test(png_modifier *pm) +{ + /* Need to do this here because we just write in this test. */ + safecat(pm->this.test, sizeof pm->this.test, 0, "error test"); + + if (!make_errors(pm, 0, 0, WRITE_BDHI)) + return; + + if (!make_errors(pm, 2, 3, WRITE_BDHI)) + return; + + if (!make_errors(pm, 3, 0, 3)) + return; + + if (!make_errors(pm, 4, 3, WRITE_BDHI)) + return; + + if (!make_errors(pm, 6, 3, WRITE_BDHI)) + return; +} + +/* Because we want to use the same code in both the progressive reader and the + * sequential reader it is necessary to deal with the fact that the progressive + * reader callbacks only have one parameter (png_get_progressive_ptr()), so this + * must contain all the test parameters and all the local variables directly + * accessible to the sequential reader implementation. + * + * The technique adopted is to reinvent part of what Dijkstra termed a + * 'display'; an array of pointers to the stack frames of enclosing functions so + * that a nested function definition can access the local (C auto) variables of + * the functions that contain its definition. In fact C provides the first + * pointer (the local variables - the stack frame pointer) and the last (the + * global variables - the BCPL global vector typically implemented as global + * addresses), this code requires one more pointer to make the display - the + * local variables (and function call parameters) of the function that actually + * invokes either the progressive or sequential reader. + * + * Perhaps confusingly this technique is confounded with classes - the + * 'standard_display' defined here is sub-classed as the 'gamma_display' below. + * A gamma_display is a standard_display, taking advantage of the ANSI-C + * requirement that the pointer to the first member of a structure must be the + * same as the pointer to the structure. This allows us to reuse standard_ + * functions in the gamma test code; something that could not be done with + * nested funtions! + */ +typedef struct standard_palette_entry /* pngvalid format palette! */ +{ + png_byte red; + png_byte green; + png_byte blue; + png_byte alpha; +} standard_palette[256]; + +typedef struct standard_display +{ + png_store* ps; /* Test parameters (passed to the function) */ + png_byte colour_type; + png_byte bit_depth; + png_byte red_sBIT; /* Input data sBIT values. */ + png_byte green_sBIT; + png_byte blue_sBIT; + png_byte alpha_sBIT; + int interlace_type; + png_uint_32 id; /* Calculated file ID */ + png_uint_32 w; /* Width of image */ + png_uint_32 h; /* Height of image */ + int npasses; /* Number of interlaced passes */ + png_uint_32 pixel_size; /* Width of one pixel in bits */ + png_uint_32 bit_width; /* Width of output row in bits */ + size_t cbRow; /* Bytes in a row of the output image */ + int do_interlace; /* Do interlacing internally */ + int is_transparent; /* Transparecy information was present. */ + struct + { + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + } transparent; /* The transparent color, if set. */ + standard_palette + palette; +} standard_display; + +static void +standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id, + int do_interlace) +{ + dp->ps = ps; + dp->colour_type = COL_FROM_ID(id); + dp->bit_depth = DEPTH_FROM_ID(id); + dp->alpha_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = + dp->bit_depth; + dp->interlace_type = INTERLACE_FROM_ID(id); + dp->id = id; + /* All the rest are filled in after the read_info: */ + dp->w = 0; + dp->h = 0; + dp->npasses = 0; + dp->pixel_size = 0; + dp->bit_width = 0; + dp->cbRow = 0; + dp->do_interlace = do_interlace; + dp->is_transparent = 0; + /* Preset the transparent color to black: */ + memset(&dp->transparent, 0, sizeof dp->transparent); + /* Preset the palette to full intensity/opaque througout: */ + memset(dp->palette, 0xff, sizeof dp->palette); + +} + +/* Call this only if the colour type is 3 - PNG_COLOR_TYPE_PALETTE - otherwise + * it will png_error out. The API returns true if tRNS information was + * present. + */ +static int +standard_palette_init(standard_palette palette, png_structp pp, png_infop pi) +{ + png_colorp pal; + png_bytep trans_alpha; + int num; + + pal = 0; + num = -1; + if (png_get_PLTE(pp, pi, &pal, &num) & PNG_INFO_PLTE) + { + int i; + + for (i=0; i 256) + png_error(pp, "validate: unexpected png_get_tRNS (palette) result"); + + for (i=0; ibit_depth) + png_error(pp, "validate: bit depth changed"); + + if (png_get_color_type(pp, pi) != dp->colour_type) + png_error(pp, "validate: color type changed"); + + if (png_get_filter_type(pp, pi) != PNG_FILTER_TYPE_BASE) + png_error(pp, "validate: filter type changed"); + + if (png_get_interlace_type(pp, pi) != dp->interlace_type) + png_error(pp, "validate: interlacing changed"); + + if (png_get_compression_type(pp, pi) != PNG_COMPRESSION_TYPE_BASE) + png_error(pp, "validate: compression type changed"); + + dp->w = png_get_image_width(pp, pi); + + if (dp->w != standard_width(pp, dp->id)) + png_error(pp, "validate: image width changed"); + + dp->h = png_get_image_height(pp, pi); + + if (dp->h != standard_height(pp, dp->id)) + png_error(pp, "validate: image height changed"); + + /* Record (but don't check at present) the input sBIT according to the colour + * type information. + */ + { + png_color_8p sBIT = 0; + + if (png_get_sBIT(pp, pi, &sBIT) & PNG_INFO_sBIT) + { + int sBIT_invalid = 0; + + if (sBIT == 0) + png_error(pp, "validate: unexpected png_get_sBIT result"); + + if (dp->colour_type & PNG_COLOR_MASK_COLOR) + { + if (sBIT->red == 0 || sBIT->red > dp->bit_depth) + sBIT_invalid = 1; + else + dp->red_sBIT = sBIT->red; + + if (sBIT->green == 0 || sBIT->green > dp->bit_depth) + sBIT_invalid = 1; + else + dp->green_sBIT = sBIT->green; + + if (sBIT->blue == 0 || sBIT->blue > dp->bit_depth) + sBIT_invalid = 1; + else + dp->blue_sBIT = sBIT->blue; + } + + else /* !COLOR */ + { + if (sBIT->gray == 0 || sBIT->gray > dp->bit_depth) + sBIT_invalid = 1; + else + dp->blue_sBIT = dp->green_sBIT = dp->red_sBIT = sBIT->gray; + } + + /* All 8 bits in tRNS for a palette image are significant - see the + * spec. + */ + if (dp->colour_type & PNG_COLOR_MASK_ALPHA) + { + if (sBIT->alpha == 0 || sBIT->alpha > dp->bit_depth) + sBIT_invalid = 1; + else + dp->alpha_sBIT = sBIT->alpha; + } + + if (sBIT_invalid) + png_error(pp, "validate: sBIT value out of range"); + } + } + + /* Important: this is validating the value *before* any transforms have been + * put in place. It doesn't matter for the standard tests, where there are + * no transforms, but it does for other tests where rowbytes may change after + * png_read_update_info. + */ + if (png_get_rowbytes(pp, pi) != standard_rowsize(pp, dp->id)) + png_error(pp, "validate: row size changed"); + + /* The palette is never read for non-palette images, even though it is valid + * - this could be changed. + */ + if (dp->colour_type == 3) /* palette */ + { + int i; + + dp->is_transparent = standard_palette_init(dp->palette, pp, pi); + + /* And validate the result. */ + for (i=0; i<256; ++i) + if (dp->palette[i].red != i || dp->palette[i].green != i || + dp->palette[i].blue != i) + png_error(pp, "validate: color type 3 PLTE chunk changed"); + } + + /* In any case always check for a tranparent color: */ + { + png_color_16p trans_color = 0; + + if (png_get_tRNS(pp, pi, 0, 0, &trans_color) & PNG_INFO_tRNS) + { + if (trans_color == 0) + png_error(pp, "validate: unexpected png_get_tRNS (color) result"); + + switch (dp->colour_type) + { + case 0: + dp->transparent.red = dp->transparent.green = dp->transparent.blue = + trans_color->gray; + dp->is_transparent = 1; + break; + + case 2: + dp->transparent.red = trans_color->red; + dp->transparent.green = trans_color->green; + dp->transparent.blue = trans_color->blue; + dp->is_transparent = 1; + break; + + case 3: + /* Not expected because it should result in the array case + * above. + */ + png_error(pp, "validate: unexpected png_get_tRNS result"); + break; + + default: + png_error(pp, "validate: invalid tRNS chunk with alpha image"); + } + } + } + + /* Read the number of passes - expected to match the value used when + * creating the image (interlaced or not). This has the side effect of + * turning on interlace handling (if do_interlace is not set.) + */ + dp->npasses = npasses_from_interlace_type(pp, dp->interlace_type); + if (!dp->do_interlace && dp->npasses != png_set_interlace_handling(pp)) + png_error(pp, "validate: file changed interlace type"); + + /* Caller calls png_read_update_info or png_start_read_image now, then calls + * part2. + */ +} + +/* This must be called *after* the png_read_update_info call to get the correct + * 'rowbytes' value, otherwise png_get_rowbytes will refer to the untransformed + * image. + */ +static void +standard_info_part2(standard_display *dp, png_structp pp, png_infop pi, + int nImages) +{ + /* Record cbRow now that it can be found. */ + dp->pixel_size = bit_size(pp, png_get_color_type(pp, pi), + png_get_bit_depth(pp, pi)); + dp->bit_width = png_get_image_width(pp, pi) * dp->pixel_size; + dp->cbRow = png_get_rowbytes(pp, pi); + + /* Validate the rowbytes here again. */ + if (dp->cbRow != (dp->bit_width+7)/8) + png_error(pp, "bad png_get_rowbytes calculation"); + + /* Then ensure there is enough space for the output image(s). */ + store_ensure_image(dp->ps, pp, nImages * dp->cbRow * dp->h); +} + +static void +standard_info_imp(standard_display *dp, png_structp pp, png_infop pi, + int nImages) +{ + /* Note that the validation routine has the side effect of turning on + * interlace handling in the subsequent code. + */ + standard_info_part1(dp, pp, pi); + + /* And the info callback has to call this (or png_read_update_info - see + * below in the png_modifier code for that variant. + */ + png_start_read_image(pp); + + /* Validate the height, width and rowbytes plus ensure that sufficient buffer + * exists for decoding the image. + */ + standard_info_part2(dp, pp, pi, nImages); +} + +static void +standard_info(png_structp pp, png_infop pi) +{ + standard_display *dp = png_get_progressive_ptr(pp); + + /* Call with nImages==1 because the progressive reader can only produce one + * image. + */ + standard_info_imp(dp, pp, pi, 1 /*only one image*/); +} + +static void +progressive_row(png_structp pp, png_bytep new_row, png_uint_32 y, int pass) +{ + PNG_CONST standard_display *dp = png_get_progressive_ptr(pp); + + /* When handling interlacing some rows will be absent in each pass, the + * callback still gets called, but with a NULL pointer. This is checked + * in the 'else' clause below. We need our own 'cbRow', but we can't call + * png_get_rowbytes because we got no info structure. + */ + if (new_row != NULL) + { + png_bytep row; + + /* In the case where the reader doesn't do the interlace it gives + * us the y in the sub-image: + */ + if (dp->do_interlace && dp->interlace_type == PNG_INTERLACE_ADAM7) + y = PNG_ROW_FROM_PASS_ROW(y, pass); + + /* Validate this just in case. */ + if (y >= dp->h) + png_error(pp, "invalid y to progressive row callback"); + + row = dp->ps->image + y * dp->cbRow; + + /* Combine the new row into the old: */ + if (dp->do_interlace) + { + if (dp->interlace_type == PNG_INTERLACE_ADAM7) + deinterlace_row(row, new_row, dp->pixel_size, dp->w, pass); + else + memcpy(row, new_row, dp->cbRow); + } + else + png_progressive_combine_row(pp, row, new_row); + } else if (dp->interlace_type == PNG_INTERLACE_ADAM7 && + PNG_ROW_IN_INTERLACE_PASS(y, pass) && + PNG_PASS_COLS(dp->w, pass) > 0) + png_error(pp, "missing row in progressive de-interlacing"); +} + +static void +sequential_row(standard_display *dp, png_structp pp, png_infop pi, + PNG_CONST png_bytep pImage, PNG_CONST png_bytep pDisplay) +{ + PNG_CONST int npasses = dp->npasses; + PNG_CONST int do_interlace = dp->do_interlace && + dp->interlace_type == PNG_INTERLACE_ADAM7; + PNG_CONST png_uint_32 height = standard_height(pp, dp->id); + PNG_CONST png_uint_32 width = standard_width(pp, dp->id); + PNG_CONST size_t cbRow = dp->cbRow; + int pass; + + for (pass=0; pass 0 && PNG_ROW_IN_INTERLACE_PASS(y, pass)) + { + /* Read the row into a pair of temporary buffers, then do the + * merge here into the output rows. + */ + png_byte row[STANDARD_ROWMAX], display[STANDARD_ROWMAX]; + + /* The following aids (to some extent) error detection - we can + * see where png_read_row wrote. Use opposite values in row and + * display to make this easier. + */ + memset(row, 0xff, sizeof row); + memset(display, 0, sizeof display); + + png_read_row(pp, row, display); + + if (pRow1 != NULL) + deinterlace_row(pRow1, row, dp->pixel_size, dp->w, pass); + + if (pRow2 != NULL) + deinterlace_row(pRow2, display, dp->pixel_size, dp->w, pass); + } + } + else + png_read_row(pp, pRow1, pRow2); + + if (pRow1 != NULL) + pRow1 += cbRow; + + if (pRow2 != NULL) + pRow2 += cbRow; + } + } + + /* And finish the read operation (only really necessary if the caller wants + * to find additional data in png_info from chunks after the last IDAT.) + */ + png_read_end(pp, pi); +} + +static void +standard_row_validate(standard_display *dp, png_structp pp, png_const_bytep row, + png_const_bytep display, png_uint_32 y) +{ + png_byte std[STANDARD_ROWMAX]; + + memset(std, 0xff, sizeof std); + standard_row(pp, std, dp->id, y); + + /* At the end both the 'row' and 'display' arrays should end up identical. + * In earlier passes 'row' will be partially filled in, with only the pixels + * that have been read so far, but 'display' will have those pixels + * replicated to fill the unread pixels while reading an interlaced image. + * The side effect inside the libpng sequential reader is that the 'row' + * array retains the correct values for unwritten pixels within the row + * bytes, while the 'display' array gets bits off the end of the image (in + * the last byte) trashed. Unfortunately in the progressive reader the + * row bytes are always trashed, so we always do a pixel_cmp here even though + * a memcmp of all cbRow bytes will succeed for the sequential reader. + */ + if (row != NULL && pixel_cmp(std, row, dp->bit_width) != 0) + { + char msg[64]; + sprintf(msg, "PNG image row %d changed", y); + png_error(pp, msg); + } + + /* In this case use pixel_cmp because we need to compare a partial + * byte at the end of the row if the row is not an exact multiple + * of 8 bits wide. + */ + if (display != NULL && pixel_cmp(std, display, dp->bit_width) != 0) + { + char msg[64]; + sprintf(msg, "display row %d changed", y); + png_error(pp, msg); + } +} + +static void +standard_image_validate(standard_display *dp, png_structp pp, + png_const_bytep pImage, png_const_bytep pDisplay) +{ + png_uint_32 y; + + for (y=0; yh; ++y) + { + standard_row_validate(dp, pp, pImage, pDisplay, y); + + if (pImage != NULL) + pImage += dp->cbRow; + + if (pDisplay != NULL) + pDisplay += dp->cbRow; + } + + /* This avoids false positives if the validation code is never called! */ + dp->ps->validated = 1; +} + +static void +standard_end(png_structp pp, png_infop pi) +{ + standard_display *dp = png_get_progressive_ptr(pp); + + UNUSED(pi) + + /* Validate the image - progressive reading only produces one variant for + * interlaced images. + */ + standard_image_validate(dp, pp, dp->ps->image, NULL); +} + +/* A single test run checking the standard image to ensure it is not damaged. */ +static void +standard_test(png_store* PNG_CONST psIn, png_uint_32 PNG_CONST id, + int do_interlace) +{ + standard_display d; + context(psIn, fault); + + /* Set up the display (stack frame) variables from the arguments to the + * function and initialize the locals that are filled in later. + */ + standard_display_init(&d, psIn, id, do_interlace); + + /* Everything is protected by a Try/Catch. The functions called also + * typically have local Try/Catch blocks. + */ + Try + { + png_structp pp; + png_infop pi; + + /* Get a png_struct for reading the image. This will throw an error if it + * fails, so we don't need to check the result. + */ + pp = set_store_for_read(d.ps, &pi, d.id, + d.do_interlace ? (d.ps->progressive ? + "pngvalid progressive deinterlacer" : + "pngvalid sequential deinterlacer") : (d.ps->progressive ? + "progressive reader" : "sequential reader")); + + /* Introduce the correct read function. */ + if (d.ps->progressive) + { + png_set_progressive_read_fn(pp, &d, standard_info, progressive_row, + standard_end); + + /* Now feed data into the reader until we reach the end: */ + store_progressive_read(d.ps, pp, pi); + } + else + { + /* Note that this takes the store, not the display. */ + png_set_read_fn(pp, d.ps, store_read); + + /* Check the header values: */ + png_read_info(pp, pi); + + /* The code tests both versions of the images that the sequential + * reader can produce. + */ + standard_info_imp(&d, pp, pi, 2 /*images*/); + + /* Need the total bytes in the image below; we can't get to this point + * unless the PNG file values have been checked against the expected + * values. + */ + { + PNG_CONST png_bytep pImage = d.ps->image; + PNG_CONST png_bytep pDisplay = pImage + d.cbRow * d.h; + + sequential_row(&d, pp, pi, pImage, pDisplay); + + /* After the last pass loop over the rows again to check that the + * image is correct. + */ + standard_image_validate(&d, pp, pImage, pDisplay); + } + } + + /* Check for validation. */ + if (!d.ps->validated) + png_error(pp, "image read failed silently"); + + /* Successful completion. */ + } + + Catch(fault) + d.ps = fault; /* make sure this hasn't been clobbered. */ + + /* In either case clean up the store. */ + store_read_reset(d.ps); +} + +static int +test_standard(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, + int bdlo, int PNG_CONST bdhi) +{ + for (; bdlo <= bdhi; ++bdlo) + { + int interlace_type; + + for (interlace_type = PNG_INTERLACE_NONE; + interlace_type < PNG_INTERLACE_LAST; ++interlace_type) + { + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + interlace_type, 0, 0, 0), 0/*do_interlace*/); + + if (fail(pm)) + return 0; + } + } + + return 1; /* keep going */ +} + +static void +perform_standard_test(png_modifier *pm) +{ + /* Test each colour type over the valid range of bit depths (expressed as + * log2(bit_depth) in turn, stop as soon as any error is detected. + */ + if (!test_standard(pm, 0, 0, READ_BDHI)) + return; + + if (!test_standard(pm, 2, 3, READ_BDHI)) + return; + + if (!test_standard(pm, 3, 0, 3)) + return; + + if (!test_standard(pm, 4, 3, READ_BDHI)) + return; + + if (!test_standard(pm, 6, 3, READ_BDHI)) + return; +} + + +/********************************** SIZE TESTS ********************************/ +static int +test_size(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, + int bdlo, int PNG_CONST bdhi) +{ + /* Run the tests on each combination. + * + * NOTE: on my 32 bit x86 each of the following blocks takes + * a total of 3.5 seconds if done across every combo of bit depth + * width and height. This is a waste of time in practice, hence the + * hinc and winc stuff: + */ + static PNG_CONST png_byte hinc[] = {1, 3, 11, 1, 5}; + static PNG_CONST png_byte winc[] = {1, 9, 5, 7, 1}; + for (; bdlo <= bdhi; ++bdlo) + { + png_uint_32 h, w; + + for (h=1; h<=16; h+=hinc[bdlo]) for (w=1; w<=16; w+=winc[bdlo]) + { + /* First test all the 'size' images against the sequential + * reader using libpng to deinterlace (where required.) This + * validates the write side of libpng. There are four possibilities + * to validate. + */ + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + PNG_INTERLACE_NONE, w, h, 0), 0/*do_interlace*/); + + if (fail(pm)) + return 0; + + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + PNG_INTERLACE_NONE, w, h, 1), 0/*do_interlace*/); + + if (fail(pm)) + return 0; + + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + PNG_INTERLACE_ADAM7, w, h, 0), 0/*do_interlace*/); + + if (fail(pm)) + return 0; + + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + PNG_INTERLACE_ADAM7, w, h, 1), 0/*do_interlace*/); + + if (fail(pm)) + return 0; + + /* Now validate the interlaced read side - do_interlace true, + * in the progressive case this does actually make a difference + * to the code used in the non-interlaced case too. + */ + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + PNG_INTERLACE_NONE, w, h, 0), 1/*do_interlace*/); + + if (fail(pm)) + return 0; + + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + PNG_INTERLACE_ADAM7, w, h, 0), 1/*do_interlace*/); + + if (fail(pm)) + return 0; + } + } + + return 1; /* keep going */ +} + +static void +perform_size_test(png_modifier *pm) +{ + /* Test each colour type over the valid range of bit depths (expressed as + * log2(bit_depth) in turn, stop as soon as any error is detected. + */ + if (!test_size(pm, 0, 0, READ_BDHI)) + return; + + if (!test_size(pm, 2, 3, READ_BDHI)) + return; + + /* For the moment don't do the palette test - it's a waste of time when + * compared to the greyscale test. + */ +#if 0 + if (!test_size(pm, 3, 0, 3)) + return; +#endif + + if (!test_size(pm, 4, 3, READ_BDHI)) + return; + + if (!test_size(pm, 6, 3, READ_BDHI)) + return; +} + + +/******************************* TRANSFORM TESTS ******************************/ +/* A set of tests to validate libpng image transforms. The possibilities here + * are legion because the transforms can be combined in a combinatorial + * fashion. To deal with this some measure of restraint is required, otherwise + * the tests would take forever. + */ +typedef struct image_pixel +{ + /* A local (pngvalid) representation of a PNG pixel, in all its + * various forms. + */ + unsigned int red, green, blue, alpha; /* For non-palette images. */ + unsigned int palette_index; /* For a palette image. */ + png_byte colour_type; /* As in the spec. */ + png_byte bit_depth; /* Defines bit size in row */ + png_byte sample_depth; /* Scale of samples */ + int have_tRNS; /* tRNS chunk may need processing */ + + /* For checking the code calculates double precision floating point values + * along with an error value, accumulated from the transforms. Because an + * sBIT setting allows larger error bounds (indeed, by the spec, apparently + * up to just less than +/-1 in the scaled value) the *lowest* sBIT for each + * channel is stored. This sBIT value is folded in to the stored error value + * at the end of the application of the transforms to the pixel. + */ + double redf, greenf, bluef, alphaf; + double rede, greene, bluee, alphae; + png_byte red_sBIT, green_sBIT, blue_sBIT, alpha_sBIT; +} image_pixel; + +/* Shared utility function, see below. */ +static void +image_pixel_setf(image_pixel *this, unsigned int max) +{ + this->redf = this->red / (double)max; + this->greenf = this->green / (double)max; + this->bluef = this->blue / (double)max; + this->alphaf = this->alpha / (double)max; + + if (this->red < max) + this->rede = this->redf * DBL_EPSILON; + else + this->rede = 0; + if (this->green < max) + this->greene = this->greenf * DBL_EPSILON; + else + this->greene = 0; + if (this->blue < max) + this->bluee = this->bluef * DBL_EPSILON; + else + this->bluee = 0; + if (this->alpha < max) + this->alphae = this->alphaf * DBL_EPSILON; + else + this->alphae = 0; +} + +/* Initialize the structure for the next pixel - call this before doing any + * transforms and call it for each pixel since all the fields may need to be + * reset. + */ +static void +image_pixel_init(image_pixel *this, png_const_bytep row, png_byte colour_type, + png_byte bit_depth, png_uint_32 x, standard_palette palette) +{ + PNG_CONST png_byte sample_depth = (png_byte)(colour_type == + PNG_COLOR_TYPE_PALETTE ? 8 : bit_depth); + PNG_CONST unsigned int max = (1U<palette_index = this->red = this->green = this->blue = + sample(row, colour_type, bit_depth, x, 0); + this->alpha = max; + this->red_sBIT = this->green_sBIT = this->blue_sBIT = this->alpha_sBIT = + sample_depth; + + /* Then override as appropriate: */ + if (colour_type == 3) /* palette */ + { + /* This permits the caller to default to the sample value. */ + if (palette != 0) + { + PNG_CONST unsigned int i = this->palette_index; + + this->red = palette[i].red; + this->green = palette[i].green; + this->blue = palette[i].blue; + this->alpha = palette[i].alpha; + } + } + + else /* not palette */ + { + unsigned int i = 0; + + if (colour_type & 2) + { + this->green = sample(row, colour_type, bit_depth, x, 1); + this->blue = sample(row, colour_type, bit_depth, x, 2); + i = 2; + } + if (colour_type & 4) + this->alpha = sample(row, colour_type, bit_depth, x, ++i); + } + + /* Calculate the scaled values, these are simply the values divided by + * 'max' and the error is initialized to the double precision epsilon value + * from the header file. + */ + image_pixel_setf(this, max); + + /* Store the input information for use in the transforms - these will + * modify the information. + */ + this->colour_type = colour_type; + this->bit_depth = bit_depth; + this->sample_depth = sample_depth; + this->have_tRNS = 0; +} + +/* Convert a palette image to an rgb image. This necessarily converts the tRNS + * chunk at the same time, because the tRNS will be in palette form. + */ +static void +image_pixel_convert_PLTE(image_pixel *this, const standard_display *display) +{ + if (this->colour_type == PNG_COLOR_TYPE_PALETTE) + { + PNG_CONST unsigned int i = this->palette_index; + + this->bit_depth = this->sample_depth; + this->red = display->palette[i].red; + this->green = display->palette[i].green; + this->blue = display->palette[i].blue; + this->red_sBIT = display->red_sBIT; + this->green_sBIT = display->green_sBIT; + this->blue_sBIT = display->blue_sBIT; + + if (this->have_tRNS) + { + this->alpha = display->palette[i].alpha; + this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; + this->have_tRNS = 0; + } + else + { + this->alpha = 255; + this->colour_type = PNG_COLOR_TYPE_RGB; + } + this->alpha_sBIT = 8; + + /* And regenerate the scaled values and all the errors, which are now set + * back to the initial values. + */ + image_pixel_setf(this, 255); + } +} + +/* Add an alpha channel, this will glom in the tRNS information because tRNS is + * not valid in an alpha image. The bit depth will invariably be set to at + * least 8. Palette images will be converted to alpha (using the above API). + */ +static void +image_pixel_add_alpha(image_pixel *this, const standard_display *display) +{ + if (this->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(this, display); + + if ((this->colour_type & PNG_COLOR_MASK_ALPHA) == 0) + { + if (this->colour_type == PNG_COLOR_TYPE_GRAY) + { + if (this->bit_depth < 8) + this->bit_depth = 8; + + if (this->have_tRNS) + { + this->have_tRNS = 0; + + /* Check the input, original, channel value here against the + * original tRNS gray chunk valie. + */ + if (this->red == display->transparent.red) + this->alphaf = 0; + else + this->alphaf = 1; + } + else + this->alphaf = 1; + + this->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; + } + + else if (this->colour_type == PNG_COLOR_TYPE_RGB) + { + if (this->have_tRNS) + { + this->have_tRNS = 0; + + /* Again, check the exact input values, not the current transformed + * value! + */ + if (this->red == display->transparent.red && + this->green == display->transparent.green && + this->blue == display->transparent.blue) + this->alphaf = 0; + else + this->alphaf = 1; + + this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; + } + } + + /* The error in the alpha is zero and the sBIT value comes from the + * original sBIT data (actually it will always be the original bit depth). + */ + this->alphae = 0; + this->alpha_sBIT = display->alpha_sBIT; + } +} + +struct transform_display; +typedef struct image_transform +{ + /* The name of this transform: a string. */ + PNG_CONST char *name; + + /* Each transform can be disabled from the command line: */ + int enable; + + /* The global list of transforms; read only. */ + struct image_transform *PNG_CONST list; + + /* The global count of the number of times this transform has been set on an + * image. + */ + unsigned int global_use; + + /* The local count of the number of times this transform has been set. */ + unsigned int local_use; + + /* The next transform in the list, each transform must call its own next + * transform after it has processed the pixel successfully. + */ + PNG_CONST struct image_transform *next; + + /* A single transform for the image, expressed as a series of function + * callbacks and some space for values. + * + * First a callback to set the transform on the current png_read_struct: + */ + void (*set)(PNG_CONST struct image_transform *this, + struct transform_display *that, png_structp pp, png_infop pi); + + /* Then a transform that takes an input pixel in one PNG format or another + * and modifies it by a pngvalid implementation of the transform (thus + * duplicating the libpng intent without, we hope, duplicating the bugs + * in the libpng implementation!) The png_structp is solely to allow error + * reporting via png_error and png_warning. + */ + void (*mod)(PNG_CONST struct image_transform *this, image_pixel *that, + png_structp pp, PNG_CONST struct transform_display *display); + + /* Add this transform to the list and return true if the transform is + * meaningful for this colour type and bit depth - if false then the + * transform should have no effect on the image so there's not a lot of + * point running it. + */ + int (*add)(struct image_transform *this, + PNG_CONST struct image_transform **that, png_byte colour_type, + png_byte bit_depth); +} image_transform; + +typedef struct transform_display +{ + standard_display this; + + /* Parameters */ + png_modifier* pm; + PNG_CONST image_transform* transform_list; + + /* Local variables */ + png_byte output_colour_type; + png_byte output_bit_depth; +} transform_display; + +/* Two functions to end the list: */ +static void +image_transform_set_end(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + UNUSED(this) + UNUSED(that) + UNUSED(pp) + UNUSED(pi) +} + +/* At the end of the list recalculate the output image pixel value from the + * double precision values set up by the preceding 'mod' calls: + */ +static unsigned int +sample_scale(double sample_value, unsigned int scale) +{ + sample_value = floor(sample_value * scale + .5); + + /* Return NaN as 0: */ + if (!(sample_value > 0)) + sample_value = 0; + else if (sample_value > scale) + sample_value = scale; + + return (unsigned int)sample_value; +} + +static void +image_transform_mod_end(PNG_CONST image_transform *this, image_pixel *that, + png_structp pp, PNG_CONST transform_display *display) +{ + PNG_CONST unsigned int scale = (1U<sample_depth)-1; + + UNUSED(this) + UNUSED(pp) + UNUSED(display) + + /* At the end recalculate the digitized red green and blue values according + * to the current sample_depth of the pixel. + * + * The sample value is simply scaled to the maximum, checking for over + * and underflow (which can both happen for some image transforms, + * including simple size scaling, though libpng doesn't do that at present. + */ + that->red = sample_scale(that->redf, scale); + + /* The error value is increased, at the end, according to the lowest sBIT + * value seen. Common sense tells us that the intermediate integer + * representations are no more accurate than +/- 0.5 in the integral values, + * the sBIT allows the implementation to be worse than this. In addition the + * PNG specification actually permits any error within the range (-1..+1), + * but that is ignored here. Instead the final digitized value is compared, + * below to the digitized value of the error limits - this has the net effect + * of allowing (almost) +/-1 in the output value. It's difficult to see how + * any algorithm that digitizes intermediate results can be more accurate. + */ + that->rede += 1./(2*((1U<red_sBIT)-1)); + + if (that->colour_type & PNG_COLOR_MASK_COLOR) + { + that->green = sample_scale(that->greenf, scale); + that->blue = sample_scale(that->bluef, scale); + that->greene += 1./(2*((1U<green_sBIT)-1)); + that->bluee += 1./(2*((1U<blue_sBIT)-1)); + } + else + { + that->blue = that->green = that->red; + that->bluef = that->greenf = that->redf; + that->bluee = that->greene = that->rede; + } + + if ((that->colour_type & PNG_COLOR_MASK_ALPHA) || + that->colour_type == PNG_COLOR_TYPE_PALETTE) + { + that->alpha = sample_scale(that->alphaf, scale); + that->alphae += 1./(2*((1U<alpha_sBIT)-1)); + } + else + { + that->alpha = scale; /* opaque */ + that->alpha = 1; /* Override this. */ + that->alphae = 0; /* It's exact ;-) */ + } +} + +/* Static 'end' structure: */ +static image_transform image_transform_end = +{ + "(end)", /* name */ + 1, /* enable */ + 0, /* list */ + 0, /* global_use */ + 0, /* local_use */ + 0, /* next */ + image_transform_set_end, + image_transform_mod_end, + 0 /* never called, I want it to crash if it is! */ +}; + +/* Reader callbacks and implementations, where they differ from the standard + * ones. + */ +static void +transform_display_init(transform_display *dp, png_modifier *pm, png_uint_32 id, + PNG_CONST image_transform *transform_list) +{ + /* Standard fields */ + standard_display_init(&dp->this, &pm->this, id, 0/*do_interlace*/); + + /* Parameter fields */ + dp->pm = pm; + dp->transform_list = transform_list; + + /* Local variable fields */ + dp->output_colour_type = 255; /* invalid */ + dp->output_bit_depth = 255; /* invalid */ +} + +static void +transform_info_imp(transform_display *dp, png_structp pp, png_infop pi) +{ + /* Reuse the standard stuff as appropriate. */ + standard_info_part1(&dp->this, pp, pi); + + /* Now set the list of transforms. */ + dp->transform_list->set(dp->transform_list, dp, pp, pi); + + /* Update the info structure for these transforms: */ + png_read_update_info(pp, pi); + + /* And get the output information into the standard_display */ + standard_info_part2(&dp->this, pp, pi, 1/*images*/); + + /* Plus the extra stuff we need for the transform tests: */ + dp->output_colour_type = png_get_color_type(pp, pi); + dp->output_bit_depth = png_get_bit_depth(pp, pi); + + /* Validate the combination of colour type and bit depth that we are getting + * out of libpng; the semantics of something not in the PNG spec are, at + * best, unclear. + */ + switch (dp->output_colour_type) + { + case PNG_COLOR_TYPE_PALETTE: + if (dp->output_bit_depth > 8) goto error; + /*FALL THROUGH*/ + case PNG_COLOR_TYPE_GRAY: + if (dp->output_bit_depth == 1 || dp->output_bit_depth == 2 || + dp->output_bit_depth == 4) + break; + /*FALL THROUGH*/ + default: + if (dp->output_bit_depth == 8 || dp->output_bit_depth == 16) + break; + /*FALL THROUGH*/ + error: + { + char message[128]; + size_t pos; + + pos = safecat(message, sizeof message, 0, + "invalid final bit depth: colour type("); + pos = safecatn(message, sizeof message, pos, dp->output_colour_type); + pos = safecat(message, sizeof message, pos, ") with bit depth: "); + pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); + + png_error(pp, message); + } + } + + /* Use a test pixel to check that the output agrees with what we expect - + * this avoids running the whole test if the output is unexpected. + */ + { + image_pixel test_pixel; + + memset(&test_pixel, 0, sizeof test_pixel); + test_pixel.colour_type = dp->this.colour_type; /* input */ + test_pixel.bit_depth = dp->this.bit_depth; + if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE) + test_pixel.sample_depth = 8; + else + test_pixel.sample_depth = test_pixel.bit_depth; + /* Don't need sBIT here */ + test_pixel.have_tRNS = dp->this.is_transparent; + + dp->transform_list->mod(dp->transform_list, &test_pixel, pp, dp); + + if (test_pixel.colour_type != dp->output_colour_type) + { + char message[128]; + size_t pos = safecat(message, sizeof message, 0, "colour type "); + + pos = safecatn(message, sizeof message, pos, dp->output_colour_type); + pos = safecat(message, sizeof message, pos, " expected "); + pos = safecatn(message, sizeof message, pos, test_pixel.colour_type); + + png_error(pp, message); + } + + if (test_pixel.bit_depth != dp->output_bit_depth) + { + char message[128]; + size_t pos = safecat(message, sizeof message, 0, "bit depth "); + + pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); + pos = safecat(message, sizeof message, pos, " expected "); + pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth); + + png_error(pp, message); + } + + /* If both bit depth and colour type are correct check the sample depth. + * I believe these are both internal errors. + */ + if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE) + { + if (test_pixel.sample_depth != 8) /* oops - internal error! */ + png_error(pp, "pngvalid: internal: palette sample depth not 8"); + } + else if (test_pixel.sample_depth != dp->output_bit_depth) + { + char message[128]; + size_t pos = safecat(message, sizeof message, 0, + "internal: sample depth "); + + pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); + pos = safecat(message, sizeof message, pos, " expected "); + pos = safecatn(message, sizeof message, pos, test_pixel.sample_depth); + + png_error(pp, message); + } + } +} + +static void +transform_info(png_structp pp, png_infop pi) +{ + transform_info_imp(png_get_progressive_ptr(pp), pp, pi); +} + +static void +transform_range_check(png_structp pp, unsigned int r, unsigned int g, + unsigned int b, unsigned int a, unsigned int in_digitized, double in, + unsigned int out, png_byte sample_depth, double err, PNG_CONST char *name) +{ + /* Compare the scaled, digitzed, values of our local calculation (in+-err) + * with the digitized values libpng produced; 'sample_depth' is the actual + * digitization depth of the libpng output colors (the bit depth except for + * palette images where it is always 8.) + */ + unsigned int max = (1U<= in_min && out <= in_max)) + { + char message[256]; + size_t pos; + + pos = safecat(message, sizeof message, 0, name); + pos = safecat(message, sizeof message, pos, " output value error: rgba("); + pos = safecatn(message, sizeof message, pos, r); + pos = safecat(message, sizeof message, pos, ","); + pos = safecatn(message, sizeof message, pos, g); + pos = safecat(message, sizeof message, pos, ","); + pos = safecatn(message, sizeof message, pos, b); + pos = safecat(message, sizeof message, pos, ","); + pos = safecatn(message, sizeof message, pos, a); + pos = safecat(message, sizeof message, pos, "): "); + pos = safecatn(message, sizeof message, pos, out); + pos = safecat(message, sizeof message, pos, " expected: "); + pos = safecatn(message, sizeof message, pos, in_digitized); + pos = safecat(message, sizeof message, pos, " ("); + pos = safecatd(message, sizeof message, pos, (in-err)*max, 3); + pos = safecat(message, sizeof message, pos, ".."); + pos = safecatd(message, sizeof message, pos, (in+err)*max, 3); + pos = safecat(message, sizeof message, pos, ")"); + + png_error(pp, message); + } +} + +static void +transform_image_validate(transform_display *dp, png_structp pp, png_infop pi, + png_const_bytep pRow) +{ + /* Constants for the loop below: */ + PNG_CONST png_byte in_ct = dp->this.colour_type; + PNG_CONST png_byte in_bd = dp->this.bit_depth; + PNG_CONST png_uint_32 w = dp->this.w; + PNG_CONST png_uint_32 h = dp->this.h; + PNG_CONST size_t cbRow = dp->this.cbRow; + PNG_CONST png_byte out_ct = dp->output_colour_type; + PNG_CONST png_byte out_bd = dp->output_bit_depth; + PNG_CONST png_byte sample_depth = (png_byte)(out_ct == + PNG_COLOR_TYPE_PALETTE ? 8 : out_bd); + PNG_CONST png_byte red_sBIT = dp->this.red_sBIT; + PNG_CONST png_byte green_sBIT = dp->this.green_sBIT; + PNG_CONST png_byte blue_sBIT = dp->this.blue_sBIT; + PNG_CONST png_byte alpha_sBIT = dp->this.alpha_sBIT; + PNG_CONST int have_tRNS = dp->this.is_transparent; + + standard_palette out_palette; + png_uint_32 y; + + UNUSED(pi) + + /* Read the palette corresponding to the output if the output colour type + * indicates a palette, othewise set out_palette to garbage. + */ + if (out_ct == PNG_COLOR_TYPE_PALETTE) + (void)standard_palette_init(out_palette, pp, pi); + else + memset(out_palette, 0x5e, sizeof out_palette); + + for (y=0; ythis.palette); + + in_pixel.red_sBIT = red_sBIT; + in_pixel.green_sBIT = green_sBIT; + in_pixel.blue_sBIT = blue_sBIT; + in_pixel.alpha_sBIT = alpha_sBIT; + in_pixel.have_tRNS = have_tRNS; + + /* For error detection, below. */ + r = in_pixel.red; + g = in_pixel.green; + b = in_pixel.blue; + a = in_pixel.alpha; + + dp->transform_list->mod(dp->transform_list, &in_pixel, pp, dp); + + /* Read the output pixel and compare it to what we got, we don't + * use the error field here, so no need to update sBIT. + */ + image_pixel_init(&out_pixel, pRow, out_ct, out_bd, x, out_palette); + + /* We don't expect changes to the index here even if the bit depth is + * changed. + */ + if (in_ct == PNG_COLOR_TYPE_PALETTE && + out_ct == PNG_COLOR_TYPE_PALETTE) + { + if (in_pixel.palette_index != out_pixel.palette_index) + png_error(pp, "unexpected transformed palette index"); + } + + /* Check the colours for palette images too - in fact the palette could + * be separately verified itself in most cases. + */ + if (in_pixel.red != out_pixel.red) + transform_range_check(pp, r, g, b, a, in_pixel.red, in_pixel.redf, + out_pixel.red, sample_depth, in_pixel.rede, "red/gray"); + + if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 && + in_pixel.green != out_pixel.green) + transform_range_check(pp, r, g, b, a, in_pixel.green, + in_pixel.greenf, out_pixel.green, sample_depth, in_pixel.greene, + "green"); + + if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 && + in_pixel.blue != out_pixel.blue) + transform_range_check(pp, r, g, b, a, in_pixel.blue, in_pixel.bluef, + out_pixel.blue, sample_depth, in_pixel.bluee, "blue"); + + if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0 && + in_pixel.alpha != out_pixel.alpha) + transform_range_check(pp, r, g, b, a, in_pixel.alpha, + in_pixel.alphaf, out_pixel.alpha, sample_depth, in_pixel.alphae, + "alpha"); + } /* pixel (x) loop */ + } /* row (y) loop */ + + /* Record that something was actually checked to avoid a false positive. */ + dp->this.ps->validated = 1; +} + +static void +transform_end(png_structp pp, png_infop pi) +{ + transform_display *dp = png_get_progressive_ptr(pp); + + transform_image_validate(dp, pp, pi, dp->this.ps->image); +} + +/* A single test run. */ +static void +transform_test(png_modifier *pmIn, PNG_CONST png_uint_32 idIn, + PNG_CONST image_transform* transform_listIn, PNG_CONST char *name) +{ + transform_display d; + context(&pmIn->this, fault); + + transform_display_init(&d, pmIn, idIn, transform_listIn); + + Try + { + png_structp pp; + png_infop pi; + + /* Get a png_struct for writing the image. */ + pp = set_modifier_for_read(d.pm, &pi, d.this.id, name); + +# if 0 + /* Logging (debugging only) */ + { + char buffer[256]; + + (void)store_message(&d.pm->this, pp, buffer, sizeof buffer, 0, + "running test"); + + fprintf(stderr, "%s\n", buffer); + } +# endif + + /* Introduce the correct read function. */ + if (d.pm->this.progressive) + { + /* Share the row function with the standard implementation. */ + png_set_progressive_read_fn(pp, &d, transform_info, progressive_row, + transform_end); + + /* Now feed data into the reader until we reach the end: */ + modifier_progressive_read(d.pm, pp, pi); + } + else + { + /* modifier_read expects a png_modifier* */ + png_set_read_fn(pp, d.pm, modifier_read); + + /* Check the header values: */ + png_read_info(pp, pi); + + /* Process the 'info' requirements. Only one image is generated */ + transform_info_imp(&d, pp, pi); + + sequential_row(&d.this, pp, pi, NULL, d.this.ps->image); + + transform_image_validate(&d, pp, pi, d.this.ps->image); + } + + modifier_reset(d.pm); + } + + Catch(fault) + modifier_reset((png_modifier*)fault); +} + +/* The transforms: */ +#define ITSTRUCT(name) image_transform_##name +#define IT(name,prev)\ +static image_transform ITSTRUCT(name) =\ +{\ + #name,\ + 1, /*enable*/\ + &ITSTRUCT(prev), /*list*/\ + 0, /*global_use*/\ + 0, /*local_use*/\ + 0, /*next*/\ + image_transform_png_set_##name##_set,\ + image_transform_png_set_##name##_mod,\ + image_transform_png_set_##name##_add\ +} + +/* To save code: */ +static int +image_transform_default_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(colour_type) + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return 1; +} + +/* png_set_palette_to_rgb */ +static void +image_transform_png_set_palette_to_rgb_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_palette_to_rgb(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_palette_to_rgb_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + if (that->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(that, &display->this); + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_palette_to_rgb_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return colour_type == PNG_COLOR_TYPE_PALETTE; +} + +IT(palette_to_rgb, end); + + +/* png_set_tRNS_to_alpha */ +static void +image_transform_png_set_tRNS_to_alpha_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_tRNS_to_alpha(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_tRNS_to_alpha_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + /* LIBPNG BUG: this always forces palette images to RGB. */ + if (that->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(that, &display->this); + + /* This effectively does an 'expand' only if there is some transparency to + * covert to an alpha channel. + */ + if (that->have_tRNS) + image_pixel_add_alpha(that, &display->this); + + /* LIBPNG BUG: otherwise libpng still expands to 8 bits! */ + else + { + if (that->bit_depth < 8) + that->bit_depth =8; + if (that->sample_depth < 8) + that->sample_depth = 8; + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_tRNS_to_alpha_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + /* We don't know yet whether there will be a tRNS chunk, but we know that + * this transformation should do nothing if there already is an alpha + * channel. + */ + return (colour_type & PNG_COLOR_MASK_ALPHA) == 0; +} + +IT(tRNS_to_alpha,palette_to_rgb); + +/* png_set_gray_to_rgb */ +static void +image_transform_png_set_gray_to_rgb_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_gray_to_rgb(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_gray_to_rgb_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + /* NOTE: we can actually pend the tRNS processing at this point because we + * can correctly recognize the original pixel value even though we have + * mapped the one gray channel to the three RGB ones, but in fact libpng + * doesn't do this, so we don't either. + */ + if ((that->colour_type & PNG_COLOR_MASK_COLOR) == 0 && that->have_tRNS) + image_pixel_add_alpha(that, &display->this); + + /* Simply expand the bit depth and alter the colour type as required. */ + if (that->colour_type == PNG_COLOR_TYPE_GRAY) + { + /* RGB images have a bit depth at least equal to '8' */ + if (that->bit_depth < 8) + that->sample_depth = that->bit_depth = 8; + + /* And just changing the colour type works here because the green and blue + * channels are being maintained in lock-step with the red/gray: + */ + that->colour_type = PNG_COLOR_TYPE_RGB; + } + + else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) + that->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_gray_to_rgb_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return (colour_type & PNG_COLOR_MASK_COLOR) == 0; +} + +IT(gray_to_rgb,tRNS_to_alpha); + +/* png_set_expand */ +static void +image_transform_png_set_expand_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_expand(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_expand_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + /* The general expand case depends on what the colour type is: */ + if (that->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(that, &display->this); + else if (that->bit_depth < 8) /* grayscale */ + that->sample_depth = that->bit_depth = 8; + + if (that->have_tRNS) + image_pixel_add_alpha(that, &display->this); + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_expand_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + /* 'expand' should do nothing for RGBA or GA input - no tRNS and the bit + * depth is at least 8 already. + */ + return (colour_type & PNG_COLOR_MASK_ALPHA) == 0; +} + +IT(expand,gray_to_rgb); + +/* png_set_expand_gray_1_2_4_to_8 + * LIBPNG BUG: this just does an 'expand' + */ +static void +image_transform_png_set_expand_gray_1_2_4_to_8_set( + PNG_CONST image_transform *this, transform_display *that, png_structp pp, + png_infop pi) +{ + png_set_expand_gray_1_2_4_to_8(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_expand_gray_1_2_4_to_8_mod( + PNG_CONST image_transform *this, image_pixel *that, png_structp pp, + PNG_CONST transform_display *display) +{ + image_transform_png_set_expand_mod(this, that, pp, display); +} + +static int +image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + return image_transform_png_set_expand_add(this, that, colour_type, + bit_depth); +} + +IT(expand_gray_1_2_4_to_8, expand); + +/* png_set_strip_16 */ +static void +image_transform_png_set_strip_16_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_strip_16(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_strip_16_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + if (that->bit_depth == 16) + { + that->sample_depth = that->bit_depth = 8; + if (that->red_sBIT > 8) that->red_sBIT = 8; + if (that->green_sBIT > 8) that->green_sBIT = 8; + if (that->blue_sBIT > 8) that->blue_sBIT = 8; + if (that->alpha_sBIT > 8) that->alpha_sBIT = 8; + +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED + /* The strip 16 algoirithm drops the low 8 bits rather than calculating + * 1/257, so we need to adjust the permitted errors appropriately: + */ + { + PNG_CONST double d = (255-128.5)/65535; + that->rede += d; + that->greene += d; + that->bluee += d; + that->alphae += d; + } +# endif + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_strip_16_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(colour_type) + + this->next = *that; + *that = this; + + return bit_depth > 8; +} + +IT(strip_16, expand_gray_1_2_4_to_8); + +/* png_set_strip_alpha */ +static void +image_transform_png_set_strip_alpha_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_strip_alpha(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_strip_alpha_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) + that->colour_type = PNG_COLOR_TYPE_GRAY; + else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) + that->colour_type = PNG_COLOR_TYPE_RGB; + + that->have_tRNS = 0; + that->alphaf = 1; + that->alphae = 0; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_strip_alpha_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return (colour_type & PNG_COLOR_MASK_ALPHA) != 0; +} + +IT(strip_alpha,strip_16); + +/* png_set_rgb_to_gray(png_structp, int err_action, double red, double green) + * png_set_rgb_to_gray_fixed(png_structp, int err_action, png_fixed_point red, + * png_fixed_point green) + * png_get_rgb_to_gray_status + * + * At present the APIs are simply tested using the 16.16 fixed point conversion + * values known to be used inside libpng: + * + * red: 6968 + * green: 23434 + * blue: 2366 + * + * NOTE: this currently ignores the gamma because no gamma is being set, the + * tests on gamma need to happen in the gamma test set. + */ +static void +image_transform_png_set_rgb_to_gray_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + PNG_CONST int error_action = 1; /* no error, no defines in png.h */ + +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_rgb_to_gray(pp, error_action, -1, -1); +# else + png_set_rgb_to_gray_fixed(pp, error_action, -1, -1); +# endif + + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + if ((that->colour_type & PNG_COLOR_MASK_COLOR) != 0) + { + if (that->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(that, &display->this); + + /* Image now has RGB channels... */ + that->bluef = that->greenf = that->redf = (that->redf * 6968 + + that->greenf * 23434 + that->bluef * 2366) / 32768; + that->bluee = that->greene = that->rede = (that->rede * 6968 + + that->greene * 23434 + that->bluee * 2366) / 32768 * + (1 + DBL_EPSILON * 6); + + /* The sBIT is the minium of the three colour channel sBITs. */ + if (that->red_sBIT > that->green_sBIT) + that->red_sBIT = that->green_sBIT; + if (that->red_sBIT > that->blue_sBIT) + that->red_sBIT = that->blue_sBIT; + that->blue_sBIT = that->green_sBIT = that->red_sBIT; + + /* And zap the colour bit in the type: */ + if (that->colour_type == PNG_COLOR_TYPE_RGB) + that->colour_type = PNG_COLOR_TYPE_GRAY; + else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) + that->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_rgb_to_gray_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return (colour_type & PNG_COLOR_MASK_COLOR) != 0; +} + +IT(rgb_to_gray,strip_alpha); + +/* png_set_background(png_structp, png_const_color_16p background_color, + * int background_gamma_code, int need_expand, double background_gamma) + * png_set_background_fixed(png_structp, png_const_color_16p background_color, + * int background_gamma_code, int need_expand, + * png_fixed_point background_gamma) + * + * As with rgb_to_gray this ignores the gamma. +*/ +static void +image_transform_png_set_background_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_color_16 back; + + /* Since we don't know the output bit depth at this point we must use the + * input values and ask libpng to expand the chunk as required. + */ + back.index = 255; /* Should not be used */ + back.gray = back.blue = back.green = back.red = + (png_uint_16)((1U << that->this.bit_depth) >> 1); + +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 1, 0); +# else + png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 1, 0); +# endif + + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_background_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + /* Check for tRNS first: */ + if (that->have_tRNS && that->colour_type != PNG_COLOR_TYPE_PALETTE) + image_pixel_add_alpha(that, &display->this); + + /* This is only necessary if the alpha value is less than 1. */ + if (that->alphaf < 1) + { + /* Repeat the calculation above and scale the result: */ + unsigned int tmp = (1U << display->this.bit_depth); + double component = (tmp >> 1)/(double)(tmp-1); + + /* Now we do the background calculation without any gamma correction. */ + if (that->alphaf <= 0) + { + that->bluef = that->greenf = that->redf = component; + that->bluee = that->greene = that->rede = component * DBL_EPSILON; + that->blue_sBIT = that->green_sBIT = that->red_sBIT = that->bit_depth; + } + + else + { + component *= 1-that->alphaf; + that->redf = that->redf * that->alphaf + component; + that->rede = that->rede * that->alphaf + that->redf * 3 * DBL_EPSILON; + that->greenf = that->greenf * that->alphaf + component; + that->greene = that->greene * that->alphaf + that->greenf * 3 * + DBL_EPSILON; + that->bluef = that->bluef * that->alphaf + component; + that->bluee = that->bluee * that->alphaf + that->bluef * 3 * + DBL_EPSILON; + } + + /* Remove the alpha type and set the alpha. */ + that->alphaf = 1; + that->alphae = 0; + + if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) + that->colour_type = PNG_COLOR_TYPE_RGB; + else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) + that->colour_type = PNG_COLOR_TYPE_GRAY; + } + + this->next->mod(this->next, that, pp, display); +} + +#define image_transform_png_set_background_add image_transform_default_add + +IT(background,rgb_to_gray); + +static image_transform *PNG_CONST image_transform_first = &ITSTRUCT(background); + +static void +transform_enable(PNG_CONST char *name) +{ + /* Everything starts out enabled, so if we see an 'enable' disabled + * everything else the first time round. + */ + static int all_disabled = 0; + int found_it = 0; + image_transform *list = image_transform_first; + + while (list != &image_transform_end) + { + if (strcmp(list->name, name) == 0) + { + list->enable = 1; + found_it = 1; + } + else if (!all_disabled) + list->enable = 0; + + list = list->list; + } + + all_disabled = 1; + + if (!found_it) + { + fprintf(stderr, "pngvalid: --transform-enable=%s: unknown transform\n", + name); + exit(1); + } +} + +static void +transform_disable(PNG_CONST char *name) +{ + image_transform *list = image_transform_first; + + while (list != &image_transform_end) + { + if (strcmp(list->name, name) == 0) + { + list->enable = 0; + return; + } + + list = list->list; + } + + fprintf(stderr, "pngvalid: --transform-disable=%s: unknown transform\n", + name); + exit(1); +} + +static void +image_transform_reset_count(void) +{ + image_transform *next = image_transform_first; + int count = 0; + + while (next != &image_transform_end) + { + next->local_use = 0; + next->next = 0; + next = next->list; + ++count; + } + + /* This can only happen if we every have more than 32 transforms (excluding + * the end) in the list. + */ + if (count > 32) abort(); +} + +static int +image_transform_test_counter(png_uint_32 counter, unsigned int max) +{ + /* Test the list to see if there is any point contining, given a current + * counter and a 'max' value. + */ + image_transform *next = image_transform_first; + + while (next != &image_transform_end) + { + /* For max 0 or 1 continue until the counter overflows: */ + counter >>= 1; + + /* Continue if any entry hasn't reacked the max. */ + if (max > 1 && next->local_use < max) + return 1; + next = next->list; + } + + return max <= 1 && counter == 0; +} + +static png_uint_32 +image_transform_add(PNG_CONST image_transform **this, unsigned int max, + png_uint_32 counter, char *name, size_t sizeof_name, size_t *pos, + png_byte colour_type, png_byte bit_depth) +{ + for (;;) /* until we manage to add something */ + { + png_uint_32 mask; + image_transform *list; + + /* Find the next counter value, if the counter is zero this is the start + * of the list. This routine always returns the current counter (not the + * next) so it returns 0 at the end and expects 0 at the beginning. + */ + if (counter == 0) /* first time */ + { + image_transform_reset_count(); + if (max <= 1) + counter = 1; + else + counter = random_32(); + } + else /* advance the counter */ + { + switch (max) + { + case 0: ++counter; break; + case 1: counter <<= 1; break; + default: counter = random_32(); break; + } + } + + /* Now add all these items, if possible */ + *this = &image_transform_end; + list = image_transform_first; + mask = 1; + + /* Go through the whole list adding anything that the counter selects: */ + while (list != &image_transform_end) + { + if ((counter & mask) != 0 && list->enable && + (max == 0 || list->local_use < max)) + { + /* Candidate to add: */ + if (list->add(list, this, colour_type, bit_depth) || max == 0) + { + /* Added, so add to the name too. */ + *pos = safecat(name, sizeof_name, *pos, " +"); + *pos = safecat(name, sizeof_name, *pos, list->name); + } + + else + { + /* Not useful and max>0, so remvoe it from *this: */ + *this = list->next; + list->next = 0; + + /* And, since we know it isn't useful, stop it being added again + * in this run: + */ + list->local_use = max; + } + } + + mask <<= 1; + list = list->list; + } + + /* Now if anything was added we have something to do. */ + if (*this != &image_transform_end) + return counter; + + /* Nothing added, but was there anything in there to add? */ + if (!image_transform_test_counter(counter, max)) + return 0; + } +} + +#ifdef THIS_IS_THE_PROFORMA +static void +image_transform_png_set_@_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_@(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_@_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_@_add(image_transform *this, + PNG_CONST image_transform **that, char *name, size_t sizeof_name, + size_t *pos, png_byte colour_type, png_byte bit_depth) +{ + this->next = *that; + *that = this; + + *pos = safecat(name, sizeof_name, *pos, " +@"); + + return 1; +} + +IT(@); +#endif + +/* png_set_quantize(png_structp, png_colorp palette, int num_palette, + * int maximum_colors, png_const_uint_16p histogram, int full_quantize) + * + * Very difficult to validate this! + */ +/*NOTE: TBD NYI */ + +/* The data layout transforms are handled by swapping our own channel data, + * necessarily these need to happen at the end of the transform list because the + * semantic of the channels changes after these are executed. Some of these, + * like set_shift and set_packing, can't be done at present because they change + * the layout of the data at the sub-sample level so sample() won't get the + * right answer. + */ +/* png_set_invert_alpha */ +/*NOTE: TBD NYI */ + +/* png_set_bgr */ +/*NOTE: TBD NYI */ + +/* png_set_swap_alpha */ +/*NOTE: TBD NYI */ + +/* png_set_swap */ +/*NOTE: TBD NYI */ + +/* png_set_filler, (png_structp png_ptr, png_uint_32 filler, int flags)); */ +/*NOTE: TBD NYI */ + +/* png_set_add_alpha, (png_structp png_ptr, png_uint_32 filler, int flags)); */ +/*NOTE: TBD NYI */ + +/* png_set_packing */ +/*NOTE: TBD NYI */ + +/* png_set_packswap */ +/*NOTE: TBD NYI */ + +/* png_set_invert_mono */ +/*NOTE: TBD NYI */ + +/* png_set_shift(png_structp, png_const_color_8p true_bits) */ +/*NOTE: TBD NYI */ + +static int +test_transform(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, + int bdlo, int PNG_CONST bdhi, png_uint_32 max) +{ + for (; bdlo <= bdhi; ++bdlo) + { + PNG_CONST png_byte bit_depth = DEPTH(bdlo); + png_uint_32 counter = 0; + size_t base_pos; + char name[64]; + + base_pos = safecat(name, sizeof name, 0, "transform:"); + + for (;;) + { + size_t pos = base_pos; + PNG_CONST image_transform *list = 0; + + counter = image_transform_add(&list, max, counter, name, sizeof name, + &pos, colour_type, bit_depth); + + if (counter == 0) + break; + + /* The command line can change this to checking interlaced images. */ + transform_test(pm, FILEID(colour_type, bit_depth, pm->interlace_type, + 0, 0, 0), list, name); + + if (fail(pm)) + return 0; + } + } + + return 1; /* keep going */ +} + +static void +perform_transform_test(png_modifier *pm) +{ + /* Test each colour type over the valid range of bit depths (expressed as + * log2(bit_depth) in turn, stop as soon as any error is detected. + */ + if (!test_transform(pm, 0, 0, READ_BDHI, 1)) + return; + + if (!test_transform(pm, 2, 3, READ_BDHI, 1)) + return; + + if (!test_transform(pm, 3, 0, 3, 1)) + return; + + if (!test_transform(pm, 4, 3, READ_BDHI, 1)) + return; + + if (!test_transform(pm, 6, 3, READ_BDHI, 1)) + return; +} + + +/********************************* GAMMA TESTS ********************************/ +/* Gamma test images. */ +typedef struct gamma_modification +{ + png_modification this; + png_fixed_point gamma; +} gamma_modification; + +static int +gamma_modify(png_modifier *pm, png_modification *me, int add) +{ + UNUSED(add) + /* This simply dumps the given gamma value into the buffer. */ + png_save_uint_32(pm->buffer, 4); + png_save_uint_32(pm->buffer+4, CHUNK_gAMA); + png_save_uint_32(pm->buffer+8, ((gamma_modification*)me)->gamma); + return 1; +} + +static void +gamma_modification_init(gamma_modification *me, png_modifier *pm, double gammad) +{ + double g; + + modification_init(&me->this); + me->this.chunk = CHUNK_gAMA; + me->this.modify_fn = gamma_modify; + me->this.add = CHUNK_PLTE; + g = floor(gammad * 100000 + .5); + me->gamma = (png_fixed_point)g; + me->this.next = pm->modifications; + pm->modifications = &me->this; +} + +typedef struct srgb_modification +{ + png_modification this; + png_byte intent; +} srgb_modification; + +static int +srgb_modify(png_modifier *pm, png_modification *me, int add) +{ + UNUSED(add) + /* As above, ignore add and just make a new chunk */ + png_save_uint_32(pm->buffer, 1); + png_save_uint_32(pm->buffer+4, CHUNK_sRGB); + pm->buffer[8] = ((srgb_modification*)me)->intent; + return 1; +} + +static void +srgb_modification_init(srgb_modification *me, png_modifier *pm, png_byte intent) +{ + modification_init(&me->this); + me->this.chunk = CHUNK_sBIT; + + if (intent <= 3) /* if valid, else *delete* sRGB chunks */ + { + me->this.modify_fn = srgb_modify; + me->this.add = CHUNK_PLTE; + me->intent = intent; + } + + else + { + me->this.modify_fn = 0; + me->this.add = 0; + me->intent = 0; + } + + me->this.next = pm->modifications; + pm->modifications = &me->this; +} + +typedef struct sbit_modification +{ + png_modification this; + png_byte sbit; +} sbit_modification; + +static int +sbit_modify(png_modifier *pm, png_modification *me, int add) +{ + png_byte sbit = ((sbit_modification*)me)->sbit; + if (pm->bit_depth > sbit) + { + int cb = 0; + switch (pm->colour_type) + { + case 0: + cb = 1; + break; + + case 2: + case 3: + cb = 3; + break; + + case 4: + cb = 2; + break; + + case 6: + cb = 4; + break; + + default: + png_error(pm->this.pread, + "unexpected colour type in sBIT modification"); + } + + png_save_uint_32(pm->buffer, cb); + png_save_uint_32(pm->buffer+4, CHUNK_sBIT); + + while (cb > 0) + (pm->buffer+8)[--cb] = sbit; + + return 1; + } + else if (!add) + { + /* Remove the sBIT chunk */ + pm->buffer_count = pm->buffer_position = 0; + return 1; + } + else + return 0; /* do nothing */ +} + +static void +sbit_modification_init(sbit_modification *me, png_modifier *pm, png_byte sbit) +{ + modification_init(&me->this); + me->this.chunk = CHUNK_sBIT; + me->this.modify_fn = sbit_modify; + me->this.add = CHUNK_PLTE; + me->sbit = sbit; + me->this.next = pm->modifications; + pm->modifications = &me->this; +} + +/* Reader callbacks and implementations, where they differ from the standard + * ones. + */ +typedef struct gamma_display +{ + standard_display this; + + /* Parameters */ + png_modifier* pm; + double file_gamma; + double screen_gamma; + png_byte sbit; + int threshold_test; + PNG_CONST char* name; + int speed; + int use_input_precision; + int strip16; + + /* Local variables */ + double maxerrout; + double maxerrpc; + double maxerrabs; +} gamma_display; + +static void +gamma_display_init(gamma_display *dp, png_modifier *pm, png_uint_32 id, + double file_gamma, double screen_gamma, png_byte sbit, int threshold_test, + int speed, int use_input_precision, int strip16) +{ + /* Standard fields */ + standard_display_init(&dp->this, &pm->this, id, 0/*do_interlace*/); + + /* Parameter fields */ + dp->pm = pm; + dp->file_gamma = file_gamma; + dp->screen_gamma = screen_gamma; + dp->sbit = sbit; + dp->threshold_test = threshold_test; + dp->speed = speed; + dp->use_input_precision = use_input_precision; + dp->strip16 = strip16; + + /* Local variable fields */ + dp->maxerrout = dp->maxerrpc = dp->maxerrabs = 0; +} + +static void +gamma_info_imp(gamma_display *dp, png_structp pp, png_infop pi) +{ + /* Reuse the standard stuff as appropriate. */ + standard_info_part1(&dp->this, pp, pi); + + /* If requested strip 16 to 8 bits - this is handled automagically below + * because the output bit depth is read from the library. Note that there + * are interactions with sBIT but, internally, libpng makes sbit at most + * PNG_MAX_GAMMA_8 when doing the following. + */ + if (dp->strip16) +# ifdef PNG_READ_16_TO_8_SUPPORTED + png_set_strip_16(pp); +# else + png_error(pp, "strip16 (16 to 8 bit conversion) not supported"); +# endif + + png_read_update_info(pp, pi); + + /* Now we may get a different cbRow: */ + standard_info_part2(&dp->this, pp, pi, 1 /*images*/); +} + +static void +gamma_info(png_structp pp, png_infop pi) +{ + gamma_info_imp(png_get_progressive_ptr(pp), pp, pi); +} + +static void +gamma_image_validate(gamma_display *dp, png_structp pp, png_infop pi, + png_const_bytep pRow) +{ + /* Get some constants derived from the input and output file formats: */ + PNG_CONST png_byte sbit = dp->sbit; + PNG_CONST double file_gamma = dp->file_gamma; + PNG_CONST double screen_gamma = dp->screen_gamma; + PNG_CONST int use_input_precision = dp->use_input_precision; + PNG_CONST int speed = dp->speed; + PNG_CONST png_byte in_ct = dp->this.colour_type; + PNG_CONST png_byte in_bd = dp->this.bit_depth; + PNG_CONST png_uint_32 w = dp->this.w; + PNG_CONST png_uint_32 h = dp->this.h; + PNG_CONST size_t cbRow = dp->this.cbRow; + PNG_CONST png_byte out_ct = png_get_color_type(pp, pi); + PNG_CONST png_byte out_bd = png_get_bit_depth(pp, pi); + PNG_CONST unsigned int outmax = (1U<pm, out_bd); + PNG_CONST double maxout = outerr(dp->pm, out_bd); + PNG_CONST double maxpc = pcerr(dp->pm, out_bd); + + /* There are three sources of error, firstly the quantization in the + * file encoding, determined by sbit and/or the file depth, secondly + * the output (screen) gamma and thirdly the output file encoding. + * + * Since this API receives the screen and file gamma in double + * precision it is possible to calculate an exact answer given an input + * pixel value. Therefore we assume that the *input* value is exact - + * sample/maxsample - calculate the corresponding gamma corrected + * output to the limits of double precision arithmetic and compare with + * what libpng returns. + * + * Since the library must quantize the output to 8 or 16 bits there is + * a fundamental limit on the accuracy of the output of +/-.5 - this + * quantization limit is included in addition to the other limits + * specified by the paramaters to the API. (Effectively, add .5 + * everywhere.) + * + * The behavior of the 'sbit' paramter is defined by section 12.5 + * (sample depth scaling) of the PNG spec. That section forces the + * decoder to assume that the PNG values have been scaled if sBIT is + * present: + * + * png-sample = floor( input-sample * (max-out/max-in) + .5); + * + * This means that only a subset of the possible PNG values should + * appear in the input. However, the spec allows the encoder to use a + * variety of approximations to the above and doesn't require any + * restriction of the values produced. + * + * Nevertheless the spec requires that the upper 'sBIT' bits of the + * value stored in a PNG file be the original sample bits. + * Consequently the code below simply scales the top sbit bits by + * (1<= + PNG_GAMMA_THRESHOLD && !dp->threshold_test && !speed && in_ct != 3) || + in_bd != out_bd; + + PNG_CONST unsigned int samples_per_pixel = (out_ct & 2U) ? 3U : 1U; + + PNG_CONST double gamma_correction = 1/(file_gamma*screen_gamma);/* Overall */ + + double maxerrout = 0, maxerrabs = 0, maxerrpc = 0; + png_uint_32 y; + + for (y=0; y> (in_bd-sbit); + + double i, input_sample, encoded_sample, output; + double encoded_error, error; + double es_lo, es_hi; + + /* First check on the 'perfect' result obtained from the + * digitized input value, id, and compare this against the + * actual digitized result, 'od'. 'i' is the input result + * in the range 0..1: + * + * NOTE: sBIT should be taken into account here but isn't, + * as described above. + */ + i = isbit; i /= (1U< maxerrout) + maxerrout = encoded_error; + + if (encoded_error < .5+maxout) + continue; + + /* There may be an error, so calculate the actual sample + * values - unencoded light intensity values. Note that + * in practice these are not unencoded because they + * include a 'viewing correction' to decrease or + * (normally) increase the perceptual contrast of the + * image. There's nothing we can do about this - we don't + * know what it is - so assume the unencoded value is + * perceptually linear. + */ + input_sample = pow(i, 1/file_gamma); /* In range 0..1 */ + output = od; + output /= outmax; + output = pow(output, screen_gamma); + + /* Now we have the numbers for real errors, both absolute + * values as as a percentage of the correct value (output): + */ + error = fabs(input_sample-output); + + if (error > maxerrabs) + maxerrabs = error; + + /* The following is an attempt to ignore the tendency of + * quantization to dominate the percentage errors for low + * output sample values: + */ + if (input_sample*maxpc > .5+maxabs) + { + double percentage_error = error/input_sample; + if (percentage_error > maxerrpc) maxerrpc = percentage_error; + } + + /* Now calculate the digitization limits for + * 'encoded_sample' using the 'max' values. Note that + * maxout is in the encoded space but maxpc and maxabs are + * in linear light space. + * + * First find the maximum error in linear light space, + * range 0..1: + */ + { + double tmp = input_sample * maxpc; + if (tmp < maxabs) tmp = maxabs; + + /* Low bound - the minimum of the three: */ + es_lo = encoded_sample - maxout; + + if (es_lo > 0 && input_sample-tmp > 0) + { + double low_value = outmax * pow(input_sample-tmp, + 1/screen_gamma); + if (low_value < es_lo) es_lo = low_value; + } + + else + es_lo = 0; + + es_hi = encoded_sample + maxout; + + if (es_hi < outmax && input_sample+tmp < 1) + { + double high_value = outmax * pow(input_sample+tmp, + 1/screen_gamma); + if (high_value > es_hi) es_hi = high_value; + } + + else + es_hi = outmax; + } + + /* The primary test is that the final encoded value + * returned by the library should be between the two limits + * (inclusive) that were calculated above. At this point + * quantization of the output must be taken into account. + */ + if (od+.5 < es_lo || od-.5 > es_hi) + { + /* There has been an error in processing. */ + double is_lo, is_hi; + + if (use_input_precision) + { + /* Ok, something is wrong - this actually happens in + * current libpng sbit processing. Assume that the + * input value (id, adjusted for sbit) can be + * anywhere between value-.5 and value+.5 - quite a + * large range if sbit is low. + */ + double tmp = (isbit - .5)/((1U< 0) + { + is_lo = outmax * pow(tmp, gamma_correction) - maxout; + if (is_lo < 0) is_lo = 0; + } + + else + is_lo = 0; + + tmp = (isbit + .5)/((1U< outmax) is_hi = outmax; + } + + else + is_hi = outmax; + + if (!(od+.5 < is_lo || od-.5 > is_hi)) + continue; + } + else + is_lo = es_lo, is_hi = es_hi; + + { + char msg[256]; + + sprintf(msg, + "error: %.3f; %u{%u;%u} -> %u not %.2f (%.1f-%.1f)", + od-encoded_sample, id, sbit, isbit, od, + encoded_sample, is_lo, is_hi); + + png_warning(pp, msg); + } + } + } + } + + else if (!speed && memcmp(std, pRow, cbRow) != 0) + { + char msg[64]; + + /* No transform is expected on the threshold tests. */ + sprintf(msg, "gamma: below threshold row %d changed", y); + + png_error(pp, msg); + } + } /* row (y) loop */ + + dp->maxerrout = maxerrout; + dp->maxerrabs = maxerrabs; + dp->maxerrpc = maxerrpc; + dp->this.ps->validated = 1; +} + +static void +gamma_end(png_structp pp, png_infop pi) +{ + gamma_display *dp = png_get_progressive_ptr(pp); + + gamma_image_validate(dp, pp, pi, dp->this.ps->image); +} + +/* A single test run checking a gamma transformation. + * + * maxabs: maximum absolute error as a fraction + * maxout: maximum output error in the output units + * maxpc: maximum percentage error (as a percentage) + */ +static void +gamma_test(png_modifier *pmIn, PNG_CONST png_byte colour_typeIn, + PNG_CONST png_byte bit_depthIn, PNG_CONST int interlace_typeIn, + PNG_CONST double file_gammaIn, PNG_CONST double screen_gammaIn, + PNG_CONST png_byte sbitIn, PNG_CONST int threshold_testIn, + PNG_CONST char *name, PNG_CONST int speedIn, + PNG_CONST int use_input_precisionIn, PNG_CONST int strip16In) +{ + gamma_display d; + context(&pmIn->this, fault); + + gamma_display_init(&d, pmIn, FILEID(colour_typeIn, bit_depthIn, + interlace_typeIn, 0, 0, 0), file_gammaIn, screen_gammaIn, sbitIn, + threshold_testIn, speedIn, use_input_precisionIn, strip16In); + + Try + { + png_structp pp; + png_infop pi; + gamma_modification gamma_mod; + srgb_modification srgb_mod; + sbit_modification sbit_mod; + + /* Make an appropriate modifier to set the PNG file gamma to the + * given gamma value and the sBIT chunk to the given precision. + */ + d.pm->modifications = NULL; + gamma_modification_init(&gamma_mod, d.pm, d.file_gamma); + srgb_modification_init(&srgb_mod, d.pm, 127 /*delete*/); + sbit_modification_init(&sbit_mod, d.pm, d.sbit); + + modification_reset(d.pm->modifications); + + /* Get a png_struct for writing the image. */ + pp = set_modifier_for_read(d.pm, &pi, d.this.id, name); + + /* Set up gamma processing. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_gamma(pp, d.screen_gamma, d.file_gamma); +#else + { + png_fixed_point s = floor(d.screen_gamma*100000+.5); + png_fixed_point f = floor(d.file_gamma*100000+.5); + png_set_gamma_fixed(pp, s, f); + } +#endif + + /* Introduce the correct read function. */ + if (d.pm->this.progressive) + { + /* Share the row function with the standard implementation. */ + png_set_progressive_read_fn(pp, &d, gamma_info, progressive_row, + gamma_end); + + /* Now feed data into the reader until we reach the end: */ + modifier_progressive_read(d.pm, pp, pi); + } + else + { + /* modifier_read expects a png_modifier* */ + png_set_read_fn(pp, d.pm, modifier_read); + + /* Check the header values: */ + png_read_info(pp, pi); + + /* Process the 'info' requirements. Only one image is generated */ + gamma_info_imp(&d, pp, pi); + + sequential_row(&d.this, pp, pi, NULL, d.this.ps->image); + + gamma_image_validate(&d, pp, pi, d.this.ps->image); + } + + modifier_reset(d.pm); + + if (d.pm->log && !d.threshold_test && !d.speed) + fprintf(stderr, "%d bit %s %s: max error %f (%.2g, %2g%%)\n", + d.this.bit_depth, colour_types[d.this.colour_type], d.name, + d.maxerrout, d.maxerrabs, 100*d.maxerrpc); + + /* Log the summary values too. */ + if (d.this.colour_type == 0 || d.this.colour_type == 4) + { + switch (d.this.bit_depth) + { + case 1: + break; + + case 2: + if (d.maxerrout > d.pm->error_gray_2) + d.pm->error_gray_2 = d.maxerrout; + + break; + + case 4: + if (d.maxerrout > d.pm->error_gray_4) + d.pm->error_gray_4 = d.maxerrout; + + break; + + case 8: + if (d.maxerrout > d.pm->error_gray_8) + d.pm->error_gray_8 = d.maxerrout; + + break; + + case 16: + if (d.maxerrout > d.pm->error_gray_16) + d.pm->error_gray_16 = d.maxerrout; + + break; + + default: + png_error(pp, "bad bit depth (internal: 1)"); + } + } + + else if (d.this.colour_type == 2 || d.this.colour_type == 6) + { + switch (d.this.bit_depth) + { + case 8: + + if (d.maxerrout > d.pm->error_color_8) + d.pm->error_color_8 = d.maxerrout; + + break; + + case 16: + + if (d.maxerrout > d.pm->error_color_16) + d.pm->error_color_16 = d.maxerrout; + + break; + + default: + png_error(pp, "bad bit depth (internal: 2)"); + } + } + } + + Catch(fault) + modifier_reset((png_modifier*)fault); +} + +static void gamma_threshold_test(png_modifier *pm, png_byte colour_type, + png_byte bit_depth, int interlace_type, double file_gamma, + double screen_gamma) +{ + size_t pos = 0; + char name[64]; + pos = safecat(name, sizeof name, pos, "threshold "); + pos = safecatd(name, sizeof name, pos, file_gamma, 3); + pos = safecat(name, sizeof name, pos, "/"); + pos = safecatd(name, sizeof name, pos, screen_gamma, 3); + + (void)gamma_test(pm, colour_type, bit_depth, interlace_type, file_gamma, + screen_gamma, bit_depth, 1, name, 0 /*speed*/, 0 /*no input precision*/, + 0 /*no strip16*/); +} + +static void +perform_gamma_threshold_tests(png_modifier *pm) +{ + png_byte colour_type = 0; + png_byte bit_depth = 0; + + while (next_format(&colour_type, &bit_depth)) + { + double test_gamma = 1.0; + while (test_gamma >= .4) + { + /* There's little point testing the interlacing vs non-interlacing, + * but this can be set from the command line. + */ + gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type, + test_gamma, 1/test_gamma); + test_gamma *= .95; + } + + /* And a special test for sRGB */ + gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type, + .45455, 2.2); + + if (fail(pm)) + return; + } +} + +static void gamma_transform_test(png_modifier *pm, + PNG_CONST png_byte colour_type, PNG_CONST png_byte bit_depth, + PNG_CONST int interlace_type, PNG_CONST double file_gamma, + PNG_CONST double screen_gamma, PNG_CONST png_byte sbit, PNG_CONST int speed, + PNG_CONST int use_input_precision, PNG_CONST int strip16) +{ + size_t pos = 0; + char name[64]; + + if (sbit != bit_depth) + { + pos = safecat(name, sizeof name, pos, "sbit("); + pos = safecatn(name, sizeof name, pos, sbit); + pos = safecat(name, sizeof name, pos, ") "); + } + + else + pos = safecat(name, sizeof name, pos, "gamma "); + + if (strip16) + pos = safecat(name, sizeof name, pos, "16to8 "); + + pos = safecatd(name, sizeof name, pos, file_gamma, 3); + pos = safecat(name, sizeof name, pos, "->"); + pos = safecatd(name, sizeof name, pos, screen_gamma, 3); + + gamma_test(pm, colour_type, bit_depth, interlace_type, file_gamma, + screen_gamma, sbit, 0, name, speed, use_input_precision, strip16); +} + +static void perform_gamma_transform_tests(png_modifier *pm, int speed) +{ + png_byte colour_type = 0; + png_byte bit_depth = 0; + + /* Ignore palette images - the gamma correction happens on the palette entry, + * haven't got the tests for this yet. + */ + while (next_format(&colour_type, &bit_depth)) if (colour_type != 3) + { + unsigned int i, j; + + for (i=0; ingammas; ++i) for (j=0; jngammas; ++j) if (i != j) + { + gamma_transform_test(pm, colour_type, bit_depth, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], bit_depth, speed, + pm->use_input_precision, 0 /*do not strip16*/); + + if (fail(pm)) + return; + } + } +} + +static void perform_gamma_sbit_tests(png_modifier *pm, int speed) +{ + png_byte sbit; + + /* The only interesting cases are colour and grayscale, alpha is ignored here + * for overall speed. Only bit depths 8 and 16 are tested. + */ + for (sbit=pm->sbitlow; sbit<(1<ngammas; ++i) + { + for (j=0; jngammas; ++j) + { + if (i != j) + { + if (sbit < 8) + { + gamma_transform_test(pm, 0, 8, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], sbit, speed, + pm->use_input_precision_sbit, 0 /*strip16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 2, 8, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], sbit, speed, + pm->use_input_precision_sbit, 0 /*strip16*/); + + if (fail(pm)) + return; + } + +#ifdef DO_16BIT + gamma_transform_test(pm, 0, 16, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], sbit, speed, + pm->use_input_precision_sbit, 0 /*strip16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 2, 16, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], sbit, speed, + pm->use_input_precision_sbit, 0 /*strip16*/); + + if (fail(pm)) + return; +#endif + } + } + } + } +} + +/* Note that this requires a 16 bit source image but produces 8 bit output, so + * we only need the 16bit write support. + */ +#ifdef PNG_READ_16_TO_8_SUPPORTED +static void perform_gamma_strip16_tests(png_modifier *pm, int speed) +{ +# ifndef PNG_MAX_GAMMA_8 +# define PNG_MAX_GAMMA_8 11 +# endif + /* Include the alpha cases here. Note that sbit matches the internal value + * used by the library - otherwise we will get spurious errors from the + * internal sbit style approximation. + * + * The threshold test is here because otherwise the 16 to 8 conversion will + * proceed *without* gamma correction, and the tests above will fail (but not + * by much) - this could be fixed, it only appears with the -g option. + */ + unsigned int i, j; + for (i=0; ingammas; ++i) + { + for (j=0; jngammas; ++j) + { + if (i != j && + fabs(pm->gammas[j]/pm->gammas[i]-1) >= PNG_GAMMA_THRESHOLD) + { + gamma_transform_test(pm, 0, 16, pm->interlace_type, 1/pm->gammas[i], + pm->gammas[j], PNG_MAX_GAMMA_8, speed, + pm->use_input_precision_16to8, 1 /*strip16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 2, 16, pm->interlace_type, 1/pm->gammas[i], + pm->gammas[j], PNG_MAX_GAMMA_8, speed, + pm->use_input_precision_16to8, 1 /*strip16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 4, 16, pm->interlace_type, 1/pm->gammas[i], + pm->gammas[j], PNG_MAX_GAMMA_8, speed, + pm->use_input_precision_16to8, 1 /*strip16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 6, 16, pm->interlace_type, 1/pm->gammas[i], + pm->gammas[j], PNG_MAX_GAMMA_8, speed, + pm->use_input_precision_16to8, 1 /*strip16*/); + + if (fail(pm)) + return; + } + } + } +} +#endif /* 16 to 8 bit conversion */ + +static void +perform_gamma_test(png_modifier *pm, int speed, int summary) +{ + /* First some arbitrary no-transform tests: */ + if (!speed && pm->test_gamma_threshold) + { + perform_gamma_threshold_tests(pm); + + if (fail(pm)) + return; + } + + /* Now some real transforms. */ + if (pm->test_gamma_transform) + { + perform_gamma_transform_tests(pm, speed); + + if (summary) + { + printf("Gamma correction error summary\n\n"); + printf("The printed value is the maximum error in the pixel values\n"); + printf("calculated by the libpng gamma correction code. The error\n"); + printf("is calculated as the difference between the output pixel\n"); + printf("value (always an integer) and the ideal value from the\n"); + printf("libpng specification (typically not an integer).\n\n"); + + printf("Expect this value to be less than .5 for 8 bit formats,\n"); + printf("less than 1 for formats with fewer than 8 bits and a small\n"); + printf("number (typically less than 5) for the 16 bit formats.\n"); + printf("For performance reasons the value for 16 bit formats\n"); + printf("increases when the image file includes an sBIT chunk.\n\n"); + + printf(" 2 bit gray: %.5f\n", pm->error_gray_2); + printf(" 4 bit gray: %.5f\n", pm->error_gray_4); + printf(" 8 bit gray: %.5f\n", pm->error_gray_8); + printf(" 8 bit color: %.5f\n", pm->error_color_8); +#ifdef DO_16BIT + printf(" 16 bit gray: %.5f\n", pm->error_gray_16); + printf(" 16 bit color: %.5f\n", pm->error_color_16); +#endif + } + } + + /* The sbit tests produce much larger errors: */ + if (pm->test_gamma_sbit) + { + pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = + pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0; + perform_gamma_sbit_tests(pm, speed); + + if (summary) + { + printf("Gamma correction with sBIT:\n"); + + if (pm->sbitlow < 8U) + { + printf(" 2 bit gray: %.5f\n", pm->error_gray_2); + printf(" 4 bit gray: %.5f\n", pm->error_gray_4); + printf(" 8 bit gray: %.5f\n", pm->error_gray_8); + printf(" 8 bit color: %.5f\n", pm->error_color_8); + } + + #ifdef DO_16BIT + printf(" 16 bit gray: %.5f\n", pm->error_gray_16); + printf(" 16 bit color: %.5f\n", pm->error_color_16); + #endif + } + } + +#ifdef PNG_READ_16_TO_8_SUPPORTED + if (pm->test_gamma_strip16) + { + /* The 16 to 8 bit strip operations: */ + pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = + pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0; + perform_gamma_strip16_tests(pm, speed); + + if (summary) + { + printf("Gamma correction with 16 to 8 bit reduction:\n"); + printf(" 16 bit gray: %.5f\n", pm->error_gray_16); + printf(" 16 bit color: %.5f\n", pm->error_color_16); + } + } +#endif +} + +/* INTERLACE MACRO VALIDATION */ +/* This is copied verbatim from the specification, it is simply the pass + * number in which each pixel in each 8x8 tile appears. The array must + * be indexed adam7[y][x] and notice that the pass numbers are based at + * 1, not 0 - the base libpng uses. + */ +static PNG_CONST +png_byte adam7[8][8] = +{ + { 1,6,4,6,2,6,4,6 }, + { 7,7,7,7,7,7,7,7 }, + { 5,6,5,6,5,6,5,6 }, + { 7,7,7,7,7,7,7,7 }, + { 3,6,4,6,3,6,4,6 }, + { 7,7,7,7,7,7,7,7 }, + { 5,6,5,6,5,6,5,6 }, + { 7,7,7,7,7,7,7,7 } +}; + +/* This routine validates all the interlace support macros in png.h for + * a variety of valid PNG widths and heights. It uses a number of similarly + * named internal routines that feed off the above array. + */ +static png_uint_32 +png_pass_start_row(int pass) +{ + int x, y; + ++pass; + for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) + return y; + return 0xf; +} + +static png_uint_32 +png_pass_start_col(int pass) +{ + int x, y; + ++pass; + for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) + return x; + return 0xf; +} + +static int +png_pass_row_shift(int pass) +{ + int x, y, base=(-1), inc=8; + ++pass; + for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) + { + if (base == (-1)) + base = y; + else if (base == y) + {} + else if (inc == y-base) + base=y; + else if (inc == 8) + inc = y-base, base=y; + else if (inc != y-base) + return 0xff; /* error - more than one 'inc' value! */ + } + + if (base == (-1)) return 0xfe; /* error - no row in pass! */ + + /* The shift is always 1, 2 or 3 - no pass has all the rows! */ + switch (inc) + { +case 2: return 1; +case 4: return 2; +case 8: return 3; +default: break; + } + + /* error - unrecognized 'inc' */ + return (inc << 8) + 0xfd; +} + +static int +png_pass_col_shift(int pass) +{ + int x, y, base=(-1), inc=8; + ++pass; + for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) + { + if (base == (-1)) + base = x; + else if (base == x) + {} + else if (inc == x-base) + base=x; + else if (inc == 8) + inc = x-base, base=x; + else if (inc != x-base) + return 0xff; /* error - more than one 'inc' value! */ + } + + if (base == (-1)) return 0xfe; /* error - no row in pass! */ + + /* The shift is always 1, 2 or 3 - no pass has all the rows! */ + switch (inc) + { +case 1: return 0; /* pass 7 has all the columns */ +case 2: return 1; +case 4: return 2; +case 8: return 3; +default: break; + } + + /* error - unrecognized 'inc' */ + return (inc << 8) + 0xfd; +} + +static png_uint_32 +png_row_from_pass_row(png_uint_32 yIn, int pass) +{ + /* By examination of the array: */ + switch (pass) + { +case 0: return yIn * 8; +case 1: return yIn * 8; +case 2: return yIn * 8 + 4; +case 3: return yIn * 4; +case 4: return yIn * 4 + 2; +case 5: return yIn * 2; +case 6: return yIn * 2 + 1; +default: break; + } + + return 0xff; /* bad pass number */ +} + +static png_uint_32 +png_col_from_pass_col(png_uint_32 xIn, int pass) +{ + /* By examination of the array: */ + switch (pass) + { +case 0: return xIn * 8; +case 1: return xIn * 8 + 4; +case 2: return xIn * 4; +case 3: return xIn * 4 + 2; +case 4: return xIn * 2; +case 5: return xIn * 2 + 1; +case 6: return xIn; +default: break; + } + + return 0xff; /* bad pass number */ +} + +static int +png_row_in_interlace_pass(png_uint_32 y, int pass) +{ + /* Is row 'y' in pass 'pass'? */ + int x; + y &= 7; + ++pass; + for (x=0; x<8; ++x) if (adam7[y][x] == pass) + return 1; + + return 0; +} + +static int +png_col_in_interlace_pass(png_uint_32 x, int pass) +{ + /* Is column 'x' in pass 'pass'? */ + int y; + x &= 7; + ++pass; + for (y=0; y<8; ++y) if (adam7[y][x] == pass) + return 1; + + return 0; +} + +static png_uint_32 +png_pass_rows(png_uint_32 height, int pass) +{ + png_uint_32 tiles = height>>3; + png_uint_32 rows = 0; + unsigned int x, y; + + height &= 7; + ++pass; + for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) + { + rows += tiles; + if (y < height) ++rows; + break; /* i.e. break the 'x', column, loop. */ + } + + return rows; +} + +static png_uint_32 +png_pass_cols(png_uint_32 width, int pass) +{ + png_uint_32 tiles = width>>3; + png_uint_32 cols = 0; + unsigned int x, y; + + width &= 7; + ++pass; + for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) + { + cols += tiles; + if (x < width) ++cols; + break; /* i.e. break the 'y', row, loop. */ + } + + return cols; +} + +static void +perform_interlace_macro_validation(void) +{ + /* The macros to validate, first those that depend only on pass: + * + * PNG_PASS_START_ROW(pass) + * PNG_PASS_START_COL(pass) + * PNG_PASS_ROW_SHIFT(pass) + * PNG_PASS_COL_SHIFT(pass) + */ + int pass; + + for (pass=0; pass<7; ++pass) + { + png_uint_32 m, f, v; + + m = PNG_PASS_START_ROW(pass); + f = png_pass_start_row(pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_START_ROW(%d) = %u != %x\n", pass, m, f); + exit(1); + } + + m = PNG_PASS_START_COL(pass); + f = png_pass_start_col(pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_START_COL(%d) = %u != %x\n", pass, m, f); + exit(1); + } + + m = PNG_PASS_ROW_SHIFT(pass); + f = png_pass_row_shift(pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_ROW_SHIFT(%d) = %u != %x\n", pass, m, f); + exit(1); + } + + m = PNG_PASS_COL_SHIFT(pass); + f = png_pass_col_shift(pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_COL_SHIFT(%d) = %u != %x\n", pass, m, f); + exit(1); + } + + /* Macros that depend on the image or sub-image height too: + * + * PNG_PASS_ROWS(height, pass) + * PNG_PASS_COLS(width, pass) + * PNG_ROW_FROM_PASS_ROW(yIn, pass) + * PNG_COL_FROM_PASS_COL(xIn, pass) + * PNG_ROW_IN_INTERLACE_PASS(y, pass) + * PNG_COL_IN_INTERLACE_PASS(x, pass) + */ + for (v=0;;) + { + /* First the base 0 stuff: */ + m = PNG_ROW_FROM_PASS_ROW(v, pass); + f = png_row_from_pass_row(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_ROW_FROM_PASS_ROW(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(1); + } + + m = PNG_COL_FROM_PASS_COL(v, pass); + f = png_col_from_pass_col(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_COL_FROM_PASS_COL(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(1); + } + + m = PNG_ROW_IN_INTERLACE_PASS(v, pass); + f = png_row_in_interlace_pass(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_ROW_IN_INTERLACE_PASS(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(1); + } + + m = PNG_COL_IN_INTERLACE_PASS(v, pass); + f = png_col_in_interlace_pass(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_COL_IN_INTERLACE_PASS(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(1); + } + + /* Then the base 1 stuff: */ + ++v; + m = PNG_PASS_ROWS(v, pass); + f = png_pass_rows(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_ROWS(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(1); + } + + m = PNG_PASS_COLS(v, pass); + f = png_pass_cols(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_COLS(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(1); + } + + /* Move to the next v - the stepping algorithm starts skipping + * values above 1024. + */ + if (v > 1024) + { + if (v == PNG_UINT_31_MAX) + break; + + v = (v << 1) ^ v; + if (v >= PNG_UINT_31_MAX) + v = PNG_UINT_31_MAX-1; + } + } + } +} + +/* main program */ +int main(int argc, PNG_CONST char **argv) +{ + volatile int summary = 1; /* Print the error summary at the end */ + + /* Create the given output file on success: */ + PNG_CONST char *volatile touch = NULL; + + /* This is an array of standard gamma values (believe it or not I've seen + * every one of these mentioned somewhere.) + * + * In the following list the most useful values are first! + */ + static double + gammas[]={2.2, 1.0, 2.2/1.45, 1.8, 1.5, 2.4, 2.5, 2.62, 2.9}; + + png_modifier pm; + context(&pm.this, fault); + + modifier_init(&pm); + + /* Preallocate the image buffer, because we know how big it needs to be, + * note that, for testing purposes, it is deliberately mis-aligned. + */ + pm.this.image = malloc(2*TRANSFORM_IMAGEMAX+1); + + if (pm.this.image != NULL) + { + /* Ignore OOM at this point - the 'ensure' routine above will allocate + * the array appropriately. + */ + ++(pm.this.image); + pm.this.cb_image = 2*TRANSFORM_IMAGEMAX; + } + + /* Default to error on warning: */ + pm.this.treat_warnings_as_errors = 1; + + /* Store the test gammas */ + pm.gammas = gammas; + pm.ngammas = 0; /* default to off */ + pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */ + pm.use_input_precision_16to8 = 1U; /* Because of the way libpng does it */ + + /* Some default values (set the behavior for 'make check' here). + * These values simply control the maximum error permitted in the gamma + * transformations. The practial limits for human perception are described + * below (the setting for maxpc16), however for 8 bit encodings it isn't + * possible to meet the accepted capabilities of human vision - i.e. 8 bit + * images can never be good enough, regardless of encoding. + */ + pm.maxout8 = .1; /* Arithmetic error in *encoded* value */ + pm.maxabs8 = .00005; /* 1/20000 */ + pm.maxpc8 = .499; /* I.e., .499% fractional error */ + pm.maxout16 = .499; /* Error in *encoded* value */ + pm.maxabs16 = .00005;/* 1/20000 */ + + /* NOTE: this is a reasonable perceptual limit. We assume that humans can + * perceive light level differences of 1% over a 100:1 range, so we need to + * maintain 1 in 10000 accuracy (in linear light space), which is what the + * following guarantees. It also allows significantly higher errors at + * higher 16 bit values, which is important for performance. The actual + * maximum 16 bit error is about +/-1.9 in the fixed point implementation but + * this is only allowed for values >38149 by the following: + */ + pm.maxpc16 = .005; /* I.e., 1/200% - 1/20000 */ + + /* Now parse the command line options. */ + while (--argc >= 1) + { + if (strcmp(*++argv, "-v") == 0) + pm.this.verbose = 1; + + else if (strcmp(*argv, "-l") == 0) + pm.log = 1; + + else if (strcmp(*argv, "-q") == 0) + summary = pm.this.verbose = pm.log = 0; + + else if (strcmp(*argv, "-w") == 0) + pm.this.treat_warnings_as_errors = 0; + + else if (strcmp(*argv, "--speed") == 0) + pm.this.speed = 1, pm.ngammas = (sizeof gammas)/(sizeof gammas[0]), + pm.test_standard = 0; + + else if (strcmp(*argv, "--size") == 0) + pm.test_size = 1; + + else if (strcmp(*argv, "--nosize") == 0) + pm.test_size = 0; + + else if (strcmp(*argv, "--standard") == 0) + pm.test_standard = 1; + + else if (strcmp(*argv, "--nostandard") == 0) + pm.test_standard = 0; + + else if (strcmp(*argv, "--transform") == 0) + pm.test_transform = 1; + + else if (strcmp(*argv, "--notransform") == 0) + pm.test_transform = 0; + + else if (strncmp(*argv, "--transform-disable=", + sizeof "--transform-disable") == 0) + { + pm.test_transform = 1; + transform_disable(*argv + sizeof "--transform-disable"); + } + + else if (strncmp(*argv, "--transform-enable=", + sizeof "--transform-enable") == 0) + { + pm.test_transform = 1; + transform_enable(*argv + sizeof "--transform-enable"); + } + + else if (strcmp(*argv, "--gamma") == 0) + { + /* Just do two gamma tests here (2.2 and linear) for speed: */ + pm.ngammas = 2U; + pm.test_gamma_threshold = 1; + pm.test_gamma_transform = 1; + pm.test_gamma_sbit = 1; + pm.test_gamma_strip16 = 1; + } + + else if (strcmp(*argv, "--nogamma") == 0) + pm.ngammas = 0; + + else if (strcmp(*argv, "--gamma-threshold") == 0) + pm.ngammas = 2U, pm.test_gamma_threshold = 1; + + else if (strcmp(*argv, "--nogamma-threshold") == 0) + pm.test_gamma_threshold = 0; + + else if (strcmp(*argv, "--gamma-transform") == 0) + pm.ngammas = 2U, pm.test_gamma_transform = 1; + + else if (strcmp(*argv, "--nogamma-transform") == 0) + pm.test_gamma_transform = 0; + + else if (strcmp(*argv, "--gamma-sbit") == 0) + pm.ngammas = 2U, pm.test_gamma_sbit = 1; + + else if (strcmp(*argv, "--nogamma-sbit") == 0) + pm.test_gamma_sbit = 0; + + else if (strcmp(*argv, "--gamma-16-to-8") == 0) + pm.ngammas = 2U, pm.test_gamma_strip16 = 1; + + else if (strcmp(*argv, "--nogamma-16-to-8") == 0) + pm.test_gamma_strip16 = 0; + + else if (strcmp(*argv, "--all-gammas") == 0) + pm.ngammas = (sizeof gammas)/(sizeof gammas[0]); + + else if (strcmp(*argv, "--progressive-read") == 0) + pm.this.progressive = 1; + + else if (strcmp(*argv, "--interlace") == 0) + pm.interlace_type = PNG_INTERLACE_ADAM7; + + else if (argc >= 1 && strcmp(*argv, "--sbitlow") == 0) + --argc, pm.sbitlow = (png_byte)atoi(*++argv); + + else if (argc >= 1 && strcmp(*argv, "--touch") == 0) + --argc, touch = *++argv; + + else if (argc >= 1 && strncmp(*argv, "--max", 4) == 0) + { + --argc; + + if (strcmp(4+*argv, "abs8") == 0) + pm.maxabs8 = atof(*++argv); + + else if (strcmp(4+*argv, "abs16") == 0) + pm.maxabs16 = atof(*++argv); + + else if (strcmp(4+*argv, "out8") == 0) + pm.maxout8 = atof(*++argv); + + else if (strcmp(4+*argv, "out16") == 0) + pm.maxout16 = atof(*++argv); + + else if (strcmp(4+*argv, "pc8") == 0) + pm.maxpc8 = atof(*++argv); + + else if (strcmp(4+*argv, "pc16") == 0) + pm.maxpc16 = atof(*++argv); + + else + { + fprintf(stderr, "pngvalid: %s: unknown 'max' option\n", *argv); + exit(1); + } + } + + else + { + fprintf(stderr, "pngvalid: %s: unknown argument\n", *argv); + exit(1); + } + } + + /* If pngvalid is run with no arguments default to a reasonable set of the + * tests. + */ + if (pm.test_standard == 0 && pm.test_size == 0 && pm.test_transform == 0 && + pm.ngammas == 0) + { + pm.test_standard = 1; + pm.test_size = 1; + pm.test_transform = 1; + pm.ngammas = 3U; + } + + if (pm.ngammas > 0 && + pm.test_gamma_threshold == 0 && pm.test_gamma_transform == 0 && + pm.test_gamma_sbit == 0 && pm.test_gamma_strip16 == 0) + { + pm.test_gamma_threshold = 1; + pm.test_gamma_transform = 1; + pm.test_gamma_sbit = 1; + pm.test_gamma_strip16 = 1; + } + + else if (pm.ngammas == 0) + { + /* Nothing to test so turn everything off: */ + pm.test_gamma_threshold = 0; + pm.test_gamma_transform = 0; + pm.test_gamma_sbit = 0; + pm.test_gamma_strip16 = 0; + } + + Try + { + /* Make useful base images */ + make_transform_images(&pm.this); + + /* Perform the standard and gamma tests. */ + if (pm.test_standard) + { + perform_interlace_macro_validation(); + perform_standard_test(&pm); + perform_error_test(&pm); + } + + /* Various oddly sized images: */ + if (pm.test_size) + { + make_size_images(&pm.this); + perform_size_test(&pm); + } + + /* Combinatorial transforms: */ + if (pm.test_transform) + perform_transform_test(&pm); + + if (pm.ngammas > 0) + perform_gamma_test(&pm, pm.this.speed != 0, + summary && !pm.this.speed); + } + + Catch(fault) + { + fprintf(stderr, "pngvalid: test aborted (probably failed in cleanup)\n"); + if (!pm.this.verbose) + { + if (pm.this.error[0] != 0) + fprintf(stderr, "pngvalid: first error: %s\n", pm.this.error); + + fprintf(stderr, "pngvalid: run with -v to see what happened\n"); + } + exit(1); + } + + if (summary && !pm.this.speed) + { + printf("Results using %s point arithmetic %s\n", +#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || PNG_LIBPNG_VER < 10500 + "floating", +#else + "fixed", +#endif + (pm.this.nerrors || (pm.this.treat_warnings_as_errors && + pm.this.nwarnings)) ? "(errors)" : (pm.this.nwarnings ? + "(warnings)" : "(no errors or warnings)") + ); + printf("Allocated memory statistics (in bytes):\n" + "\tread %lu maximum single, %lu peak, %lu total\n" + "\twrite %lu maximum single, %lu peak, %lu total\n", + (unsigned long)pm.this.read_memory_pool.max_max, + (unsigned long)pm.this.read_memory_pool.max_limit, + (unsigned long)pm.this.read_memory_pool.max_total, + (unsigned long)pm.this.write_memory_pool.max_max, + (unsigned long)pm.this.write_memory_pool.max_limit, + (unsigned long)pm.this.write_memory_pool.max_total); + } + + /* Do this here to provoke memory corruption errors in memory not directly + * allocated by libpng - not a complete test, but better than nothing. + */ + store_delete(&pm.this); + + /* Error exit if there are any errors, and maybe if there are any + * warnings. + */ + if (pm.this.nerrors || (pm.this.treat_warnings_as_errors && + pm.this.nwarnings)) + { + if (!pm.this.verbose) + fprintf(stderr, "pngvalid: %s\n", pm.this.error); + + fprintf(stderr, "pngvalid: %d errors, %d warnings\n", pm.this.nerrors, + pm.this.nwarnings); + + exit(1); + } + + /* Success case. */ + if (touch != NULL) + { + FILE *fsuccess = fopen(touch, "wt"); + + if (fsuccess != NULL) + { + int error = 0; + fprintf(fsuccess, "PNG validation succeeded\n"); + fflush(fsuccess); + error = ferror(fsuccess); + + if (fclose(fsuccess) || error) + { + fprintf(stderr, "%s: write failed\n", touch); + exit(1); + } + } + } + + return 0; +} diff --git a/contrib/libpng/pngwio.c b/contrib/libpng/pngwio.c new file mode 100644 index 0000000..95ffb34 --- /dev/null +++ b/contrib/libpng/pngwio.c @@ -0,0 +1,254 @@ + +/* pngwio.c - functions for data output + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This file provides a location for all output. Users who need + * special handling are expected to write functions that have the same + * arguments as these and perform similar functions, but that possibly + * use different output methods. Note that you shouldn't change these + * functions, but rather write replacement functions and then change + * them at run time with png_set_write_fn(...). + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +/* Write the data to whatever output you are using. The default routine + * writes to a file pointer. Note that this routine sometimes gets called + * with very small lengths, so you should implement some kind of simple + * buffering if you are using unbuffered writes. This should never be asked + * to write more than 64K on a 16 bit machine. + */ + +void /* PRIVATE */ +png_write_data(png_structp png_ptr, png_const_bytep data, png_size_t length) +{ + /* NOTE: write_data_fn must not change the buffer! */ + if (png_ptr->write_data_fn != NULL ) + (*(png_ptr->write_data_fn))(png_ptr, (png_bytep)data, length); + + else + png_error(png_ptr, "Call to NULL write function"); +} + +#ifdef PNG_STDIO_SUPPORTED +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +#ifndef USE_FAR_KEYWORD +void PNGCBAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_size_t check; + + if (png_ptr == NULL) + return; + + check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); + + if (check != length) + png_error(png_ptr, "Write Error"); +} +#else +/* This is the model-independent version. Since the standard I/O library + * can't handle far buffers in the medium and small models, we have to copy + * the data. + */ + +#define NEAR_BUF_SIZE 1024 +#define MIN(a,b) (a <= b ? a : b) + +void PNGCBAPI +png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_uint_32 check; + png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + + /* Check if data really is near. If so, use usual code. */ + near_data = (png_byte *)CVT_PTR_NOCHECK(data); + io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); + + if ((png_bytep)near_data == data) + { + check = fwrite(near_data, 1, length, io_ptr); + } + + else + { + png_byte buf[NEAR_BUF_SIZE]; + png_size_t written, remaining, err; + check = 0; + remaining = length; + + do + { + written = MIN(NEAR_BUF_SIZE, remaining); + png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ + err = fwrite(buf, 1, written, io_ptr); + + if (err != written) + break; + + else + check += err; + + data += written; + remaining -= written; + } + while (remaining != 0); + } + + if (check != length) + png_error(png_ptr, "Write Error"); +} + +#endif +#endif + +/* This function is called to output any data pending writing (normally + * to disk). After png_flush is called, there should be no data pending + * writing in any buffers. + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +void /* PRIVATE */ +png_flush(png_structp png_ptr) +{ + if (png_ptr->output_flush_fn != NULL) + (*(png_ptr->output_flush_fn))(png_ptr); +} + +# ifdef PNG_STDIO_SUPPORTED +void PNGCBAPI +png_default_flush(png_structp png_ptr) +{ + png_FILE_p io_ptr; + + if (png_ptr == NULL) + return; + + io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr)); + fflush(io_ptr); +} +# endif +#endif + +/* This function allows the application to supply new output functions for + * libpng if standard C streams aren't being used. + * + * This function takes as its arguments: + * png_ptr - pointer to a png output data structure + * io_ptr - pointer to user supplied structure containing info about + * the output functions. May be NULL. + * write_data_fn - pointer to a new output function that takes as its + * arguments a pointer to a png_struct, a pointer to + * data to be written, and a 32-bit unsigned int that is + * the number of bytes to be written. The new write + * function should call png_error(png_ptr, "Error msg") + * to exit and output any fatal error messages. May be + * NULL, in which case libpng's default function will + * be used. + * flush_data_fn - pointer to a new flush function that takes as its + * arguments a pointer to a png_struct. After a call to + * the flush function, there should be no data in any buffers + * or pending transmission. If the output method doesn't do + * any buffering of output, a function prototype must still be + * supplied although it doesn't have to do anything. If + * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile + * time, output_flush_fn will be ignored, although it must be + * supplied for compatibility. May be NULL, in which case + * libpng's default function will be used, if + * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not + * a good idea if io_ptr does not point to a standard + * *FILE structure. + */ +void PNGAPI +png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, + png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->io_ptr = io_ptr; + +#ifdef PNG_STDIO_SUPPORTED + if (write_data_fn != NULL) + png_ptr->write_data_fn = write_data_fn; + + else + png_ptr->write_data_fn = png_default_write_data; +#else + png_ptr->write_data_fn = write_data_fn; +#endif + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_STDIO_SUPPORTED + + if (output_flush_fn != NULL) + png_ptr->output_flush_fn = output_flush_fn; + + else + png_ptr->output_flush_fn = png_default_flush; + +# else + png_ptr->output_flush_fn = output_flush_fn; +# endif +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + + /* It is an error to read while writing a png file */ + if (png_ptr->read_data_fn != NULL) + { + png_ptr->read_data_fn = NULL; + + png_warning(png_ptr, + "Can't set both read_data_fn and write_data_fn in the" + " same structure"); + } +} + +#ifdef USE_FAR_KEYWORD +# ifdef _MSC_VER +void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + FP_OFF(near_ptr) = FP_OFF(ptr); + far_ptr = (void FAR *)near_ptr; + + if (check != 0) + if (FP_SEG(ptr) != FP_SEG(far_ptr)) + png_error(png_ptr, "segment lost in conversion"); + + return(near_ptr); +} +# else +void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check) +{ + void *near_ptr; + void FAR *far_ptr; + near_ptr = (void FAR *)ptr; + far_ptr = (void FAR *)near_ptr; + + if (check != 0) + if (far_ptr != ptr) + png_error(png_ptr, "segment lost in conversion"); + + return(near_ptr); +} +# endif +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/contrib/libpng/pngwrite.c b/contrib/libpng/pngwrite.c new file mode 100644 index 0000000..d90f449 --- /dev/null +++ b/contrib/libpng/pngwrite.c @@ -0,0 +1,1605 @@ + +/* pngwrite.c - general routines to write a PNG file + * + * Last changed in libpng 1.5.1 [February 3, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +/* Writes all the PNG information. This is the suggested way to use the + * library. If you have a new chunk to add, make a function to write it, + * and put it in the correct location here. If you want the chunk written + * after the image data, put it in png_write_end(). I strongly encourage + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing + * the chunk, as that will keep the code from breaking if you want to just + * write a plain PNG file. If you have long comments, I suggest writing + * them in png_write_end(), and compressing them. + */ +void PNGAPI +png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_info_before_PLTE"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + { + /* Write PNG signature */ + png_write_sig(png_ptr); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \ + (png_ptr->mng_features_permitted)) + { + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); + png_ptr->mng_features_permitted = 0; + } +#endif + + /* Write IHDR information. */ + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + info_ptr->interlace_type); +#else + 0); +#endif + /* The rest of these check to see if the valid field has the appropriate + * flag set, and if it does, writes the chunk. + */ +#ifdef PNG_WRITE_gAMA_SUPPORTED + if (info_ptr->valid & PNG_INFO_gAMA) + png_write_gAMA_fixed(png_ptr, info_ptr->gamma); +#endif +#ifdef PNG_WRITE_sRGB_SUPPORTED + if (info_ptr->valid & PNG_INFO_sRGB) + png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED + if (info_ptr->valid & PNG_INFO_iCCP) + png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, + (png_charp)info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); +#endif +#ifdef PNG_WRITE_sBIT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sBIT) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif +#ifdef PNG_WRITE_cHRM_SUPPORTED + if (info_ptr->valid & PNG_INFO_cHRM) + png_write_cHRM_fixed(png_ptr, + info_ptr->x_white, info_ptr->y_white, + info_ptr->x_red, info_ptr->y_red, + info_ptr->x_green, info_ptr->y_green, + info_ptr->x_blue, info_ptr->y_blue); +#endif + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && !(up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + if (up->size == 0) + png_warning(png_ptr, "Writing zero-length unknown chunk"); + + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; + } +} + +void PNGAPI +png_write_info(png_structp png_ptr, png_infop info_ptr) +{ +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) + int i; +#endif + + png_debug(1, "in png_write_info"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + png_write_info_before_PLTE(png_ptr, info_ptr); + + if (info_ptr->valid & PNG_INFO_PLTE) + png_write_PLTE(png_ptr, info_ptr->palette, + (png_uint_32)info_ptr->num_palette); + + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_error(png_ptr, "Valid palette required for paletted images"); + +#ifdef PNG_WRITE_tRNS_SUPPORTED + if (info_ptr->valid & PNG_INFO_tRNS) + { +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel (in tRNS) */ + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + int j; + for (j = 0; j<(int)info_ptr->num_trans; j++) + info_ptr->trans_alpha[j] = + (png_byte)(255 - info_ptr->trans_alpha[j]); + } +#endif + png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), + info_ptr->num_trans, info_ptr->color_type); + } +#endif +#ifdef PNG_WRITE_bKGD_SUPPORTED + if (info_ptr->valid & PNG_INFO_bKGD) + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED + if (info_ptr->valid & PNG_INFO_hIST) + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED + if (info_ptr->valid & PNG_INFO_oFFs) + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, + info_ptr->offset_unit_type); +#endif + +#ifdef PNG_WRITE_pCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_pCAL) + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, + info_ptr->pcal_units, info_ptr->pcal_params); +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED + if (info_ptr->valid & PNG_INFO_sCAL) + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, + info_ptr->scal_s_width, info_ptr->scal_s_height); +#endif /* sCAL */ + +#ifdef PNG_WRITE_pHYs_SUPPORTED + if (info_ptr->valid & PNG_INFO_pHYs) + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); +#endif /* pHYs */ + +#ifdef PNG_WRITE_tIME_SUPPORTED + if (info_ptr->valid & PNG_INFO_tIME) + { + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + png_ptr->mode |= PNG_WROTE_tIME; + } +#endif /* tIME */ + +#ifdef PNG_WRITE_sPLT_SUPPORTED + if (info_ptr->valid & PNG_INFO_sPLT) + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); +#endif /* sPLT */ + +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Check to see if we need to write text chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing header text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + + /* If we want a compressed text chunk */ + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, + 0); + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; +#else + /* Can't get here */ + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + } + } +#endif /* tEXt */ + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_HAVE_PLTE) && + !(up->location & PNG_HAVE_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif +} + +/* Writes the end of the PNG file. If you don't want to write comments or + * time information, you can pass NULL for info. If you already wrote these + * in png_write_info(), do not write them again here. If you have long + * comments, I suggest writing them here, and compressing them. + */ +void PNGAPI +png_write_end(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_write_end"); + + if (png_ptr == NULL) + return; + + if (!(png_ptr->mode & PNG_HAVE_IDAT)) + png_error(png_ptr, "No IDATs written into file"); + + /* See if user wants us to write information chunks */ + if (info_ptr != NULL) + { +#ifdef PNG_WRITE_TEXT_SUPPORTED + int i; /* local index variable */ +#endif +#ifdef PNG_WRITE_tIME_SUPPORTED + /* Check to see if user has supplied a time chunk */ + if ((info_ptr->valid & PNG_INFO_tIME) && + !(png_ptr->mode & PNG_WROTE_tIME)) + png_write_tIME(png_ptr, &(info_ptr->mod_time)); + +#endif +#ifdef PNG_WRITE_TEXT_SUPPORTED + /* Loop through comment chunks */ + for (i = 0; i < info_ptr->num_text; i++) + { + png_debug2(2, "Writing trailer text chunk %d, type %d", i, + info_ptr->text[i].compression); + /* An internationalized chunk? */ + if (info_ptr->text[i].compression > 0) + { +#ifdef PNG_WRITE_iTXt_SUPPORTED + /* Write international chunk */ + png_write_iTXt(png_ptr, + info_ptr->text[i].compression, + info_ptr->text[i].key, + info_ptr->text[i].lang, + info_ptr->text[i].lang_key, + info_ptr->text[i].text); +#else + png_warning(png_ptr, "Unable to write international text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) + { +#ifdef PNG_WRITE_zTXt_SUPPORTED + /* Write compressed chunk */ + png_write_zTXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0, + info_ptr->text[i].compression); +#else + png_warning(png_ptr, "Unable to write compressed text"); +#endif + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; + } + + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) + { +#ifdef PNG_WRITE_tEXt_SUPPORTED + /* Write uncompressed chunk */ + png_write_tEXt(png_ptr, info_ptr->text[i].key, + info_ptr->text[i].text, 0); +#else + png_warning(png_ptr, "Unable to write uncompressed text"); +#endif + + /* Mark this chunk as written */ + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + if (info_ptr->unknown_chunks_num) + { + png_unknown_chunk *up; + + png_debug(5, "writing extra chunks"); + + for (up = info_ptr->unknown_chunks; + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; + up++) + { + int keep = png_handle_as_unknown(png_ptr, up->name); + if (keep != PNG_HANDLE_CHUNK_NEVER && + up->location && (up->location & PNG_AFTER_IDAT) && + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) + { + png_write_chunk(png_ptr, up->name, up->data, up->size); + } + } + } +#endif + } + + png_ptr->mode |= PNG_AFTER_IDAT; + + /* Write end of PNG file */ + png_write_IEND(png_ptr); + /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, + * and restored again in libpng-1.2.30, may cause some applications that + * do not set png_ptr->output_flush_fn to crash. If your application + * experiences a problem, please try building libpng with + * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to + * png-mng-implement at lists.sf.net . + */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED +# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED + png_flush(png_ptr); +# endif +#endif +} + +#ifdef PNG_CONVERT_tIME_SUPPORTED +/* "tm" structure is not supported on WindowsCE */ +void PNGAPI +png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm FAR * ttime) +{ + png_debug(1, "in png_convert_from_struct_tm"); + + ptime->year = (png_uint_16)(1900 + ttime->tm_year); + ptime->month = (png_byte)(ttime->tm_mon + 1); + ptime->day = (png_byte)ttime->tm_mday; + ptime->hour = (png_byte)ttime->tm_hour; + ptime->minute = (png_byte)ttime->tm_min; + ptime->second = (png_byte)ttime->tm_sec; +} + +void PNGAPI +png_convert_from_time_t(png_timep ptime, time_t ttime) +{ + struct tm *tbuf; + + png_debug(1, "in png_convert_from_time_t"); + + tbuf = gmtime(&ttime); + png_convert_from_struct_tm(ptime, tbuf); +} +#endif + +/* Initialize png_ptr structure, and allocate any memory needed */ +PNG_FUNCTION(png_structp,PNGAPI +png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) +{ +#ifdef PNG_USER_MEM_SUPPORTED + return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, + warn_fn, NULL, NULL, NULL)); +} + +/* Alternate initialize png_ptr structure, and allocate any memory needed */ +static void png_reset_filter_heuristics(png_structp png_ptr); /* forward decl */ + +PNG_FUNCTION(png_structp,PNGAPI +png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +{ +#endif /* PNG_USER_MEM_SUPPORTED */ + volatile int png_cleanup_needed = 0; +#ifdef PNG_SETJMP_SUPPORTED + volatile +#endif + png_structp png_ptr; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf png_jmpbuf; +#endif +#endif + int i; + + png_debug(1, "in png_create_write_struct"); + +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); +#else + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); +#endif /* PNG_USER_MEM_SUPPORTED */ + if (png_ptr == NULL) + return (NULL); + + /* Added at libpng-1.2.6 */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_ptr->user_width_max = PNG_USER_WIDTH_MAX; + png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; +#endif + +#ifdef PNG_SETJMP_SUPPORTED +/* Applications that neglect to set up their own setjmp() and then + encounter a png_error() will longjmp here. Since the jmpbuf is + then meaningless we abort instead of returning. */ +#ifdef USE_FAR_KEYWORD + if (setjmp(png_jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */ +#endif +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), png_jmpbuf, png_sizeof(jmp_buf)); +#endif + PNG_ABORT(); +#endif + +#ifdef PNG_USER_MEM_SUPPORTED + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); +#endif /* PNG_USER_MEM_SUPPORTED */ + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); + + if (user_png_ver) + { + i = 0; + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#ifdef PNG_CONSOLE_IO_SUPPORTED + char msg[80]; + + if (user_png_ver) + { + png_snprintf2(msg, 80, + "Application built with libpng-%.20s" + " but running with %.20s", + user_png_ver, + png_libpng_ver); + png_warning(png_ptr, msg); + } +#else + png_warning(png_ptr, + "Incompatible libpng version in application and library"); +#endif +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + png_cleanup_needed = 1; + } + } + + /* Initialize zbuf - compression buffer */ + png_ptr->zbuf_size = PNG_ZBUF_SIZE; + + if (!png_cleanup_needed) + { + png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, + png_ptr->zbuf_size); + if (png_ptr->zbuf == NULL) + png_cleanup_needed = 1; + } + + if (png_cleanup_needed) + { + /* Clean up PNG structure and deallocate any memory. */ + png_free(png_ptr, png_ptr->zbuf); + png_ptr->zbuf = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, + (png_free_ptr)free_fn, (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + return (NULL); + } + + png_set_write_fn(png_ptr, NULL, NULL, NULL); + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + png_reset_filter_heuristics(png_ptr); +#endif + + return (png_ptr); +} + + +/* Write a few rows of image data. If the image is interlaced, + * either you will have to write the 7 sub images, or, if you + * have called png_set_interlace_handling(), you will have to + * "write" the image seven times. + */ +void PNGAPI +png_write_rows(png_structp png_ptr, png_bytepp row, + png_uint_32 num_rows) +{ + png_uint_32 i; /* row counter */ + png_bytepp rp; /* row pointer */ + + png_debug(1, "in png_write_rows"); + + if (png_ptr == NULL) + return; + + /* Loop through the rows */ + for (i = 0, rp = row; i < num_rows; i++, rp++) + { + png_write_row(png_ptr, *rp); + } +} + +/* Write the image. You only need to call this function once, even + * if you are writing an interlaced image. + */ +void PNGAPI +png_write_image(png_structp png_ptr, png_bytepp image) +{ + png_uint_32 i; /* row index */ + int pass, num_pass; /* pass variables */ + png_bytepp rp; /* points to current row */ + + if (png_ptr == NULL) + return; + + png_debug(1, "in png_write_image"); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Initialize interlace handling. If image is not interlaced, + * this will set pass to 1 + */ + num_pass = png_set_interlace_handling(png_ptr); +#else + num_pass = 1; +#endif + /* Loop through passes */ + for (pass = 0; pass < num_pass; pass++) + { + /* Loop through image */ + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) + { + png_write_row(png_ptr, *rp); + } + } +} + +/* Called by user to write a row of image data */ +void PNGAPI +png_write_row(png_structp png_ptr, png_const_bytep row) +{ + if (png_ptr == NULL) + return; + + png_debug2(1, "in png_write_row (row %u, pass %d)", + png_ptr->row_number, png_ptr->pass); + + /* Initialize transformations and other stuff if first time */ + if (png_ptr->row_number == 0 && png_ptr->pass == 0) + { + /* Make sure we wrote the header info */ + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) + png_error(png_ptr, + "png_write_info was never called before png_write_row"); + + /* Check for transforms that have been set but were defined out */ +#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) + if (png_ptr->transformations & PNG_INVERT_MONO) + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) + if (png_ptr->transformations & PNG_FILLER) + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined"); +#endif +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ + defined(PNG_READ_PACKSWAP_SUPPORTED) + if (png_ptr->transformations & PNG_PACKSWAP) + png_warning(png_ptr, + "PNG_WRITE_PACKSWAP_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) + if (png_ptr->transformations & PNG_PACK) + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) + if (png_ptr->transformations & PNG_SHIFT) + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) + if (png_ptr->transformations & PNG_BGR) + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined"); +#endif + +#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined"); +#endif + + png_write_start_row(png_ptr); + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced and not interested in row, return */ + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) + { + switch (png_ptr->pass) + { + case 0: + if (png_ptr->row_number & 0x07) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 1: + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 2: + if ((png_ptr->row_number & 0x07) != 4) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 3: + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 4: + if ((png_ptr->row_number & 0x03) != 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 5: + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) + { + png_write_finish_row(png_ptr); + return; + } + break; + + case 6: + if (!(png_ptr->row_number & 0x01)) + { + png_write_finish_row(png_ptr); + return; + } + break; + + default: /* error: ignore it */ + break; + } + } +#endif + + /* Set up row info for transformations */ + png_ptr->row_info.color_type = png_ptr->color_type; + png_ptr->row_info.width = png_ptr->usr_width; + png_ptr->row_info.channels = png_ptr->usr_channels; + png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * + png_ptr->row_info.channels); + + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, + png_ptr->row_info.width); + + png_debug1(3, "row_info->color_type = %d", png_ptr->row_info.color_type); + png_debug1(3, "row_info->width = %u", png_ptr->row_info.width); + png_debug1(3, "row_info->channels = %d", png_ptr->row_info.channels); + png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth); + png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth); + png_debug1(3, "row_info->rowbytes = %lu", + (unsigned long)png_ptr->row_info.rowbytes); + + /* Copy user's row into buffer, leaving room for filter byte. */ + png_memcpy(png_ptr->row_buf + 1, row, png_ptr->row_info.rowbytes); + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Handle interlacing */ + if (png_ptr->interlaced && png_ptr->pass < 6 && + (png_ptr->transformations & PNG_INTERLACE)) + { + png_do_write_interlace(&(png_ptr->row_info), + png_ptr->row_buf + 1, png_ptr->pass); + /* This should always get caught above, but still ... */ + if (!(png_ptr->row_info.width)) + { + png_write_finish_row(png_ptr); + return; + } + } +#endif + + /* Handle other transformations */ + if (png_ptr->transformations) + png_do_write_transformations(png_ptr); + +#ifdef PNG_MNG_FEATURES_SUPPORTED + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) + { + /* Intrapixel differencing */ + png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); + } +#endif + + /* Find a filter if necessary, filter the row and write it out. */ + png_write_find_filter(png_ptr, &(png_ptr->row_info)); + + if (png_ptr->write_row_fn != NULL) + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); +} + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +/* Set the automatic flush interval or 0 to turn flushing off */ +void PNGAPI +png_set_flush(png_structp png_ptr, int nrows) +{ + png_debug(1, "in png_set_flush"); + + if (png_ptr == NULL) + return; + + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); +} + +/* Flush the current output buffers now */ +void PNGAPI +png_write_flush(png_structp png_ptr) +{ + int wrote_IDAT; + + png_debug(1, "in png_write_flush"); + + if (png_ptr == NULL) + return; + + /* We have already written out all of the data */ + if (png_ptr->row_number >= png_ptr->num_rows) + return; + + do + { + int ret; + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); + wrote_IDAT = 0; + + /* Check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + + if (!(png_ptr->zstream.avail_out)) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + wrote_IDAT = 1; + } + } while (wrote_IDAT == 1); + + /* If there is any data left to be output, write it into a new IDAT */ + if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, + png_ptr->zbuf_size - png_ptr->zstream.avail_out); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + png_ptr->flush_rows = 0; + png_flush(png_ptr); +} +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ + +/* Free all memory used by the write */ +void PNGAPI +png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) +{ + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn = NULL; + png_voidp mem_ptr = NULL; +#endif + + png_debug(1, "in png_destroy_write_struct"); + + if (png_ptr_ptr != NULL) + { + png_ptr = *png_ptr_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; +#endif + } + +#ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr != NULL) + { + free_fn = png_ptr->free_fn; + mem_ptr = png_ptr->mem_ptr; + } +#endif + + if (info_ptr_ptr != NULL) + info_ptr = *info_ptr_ptr; + + if (info_ptr != NULL) + { + if (png_ptr != NULL) + { + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + if (png_ptr->num_chunk_list) + { + png_free(png_ptr, png_ptr->chunk_list); + png_ptr->num_chunk_list = 0; + } +#endif + } + +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)info_ptr); +#endif + *info_ptr_ptr = NULL; + } + + if (png_ptr != NULL) + { + png_write_destroy(png_ptr); +#ifdef PNG_USER_MEM_SUPPORTED + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, + (png_voidp)mem_ptr); +#else + png_destroy_struct((png_voidp)png_ptr); +#endif + *png_ptr_ptr = NULL; + } +} + + +/* Free any memory used in png_ptr struct (old method) */ +void /* PRIVATE */ +png_write_destroy(png_structp png_ptr) +{ +#ifdef PNG_SETJMP_SUPPORTED + jmp_buf tmp_jmp; /* Save jump buffer */ +#endif + png_error_ptr error_fn; + png_error_ptr warning_fn; + png_voidp error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_free_ptr free_fn; +#endif + + png_debug(1, "in png_write_destroy"); + + /* Free any memory zlib uses */ + deflateEnd(&png_ptr->zstream); + + /* Free our memory. png_free checks NULL for us. */ + png_free(png_ptr, png_ptr->zbuf); + png_free(png_ptr, png_ptr->row_buf); +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_free(png_ptr, png_ptr->prev_row); + png_free(png_ptr, png_ptr->sub_row); + png_free(png_ptr, png_ptr->up_row); + png_free(png_ptr, png_ptr->avg_row); + png_free(png_ptr, png_ptr->paeth_row); +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED + png_free(png_ptr, png_ptr->time_buffer); +#endif + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* Use this to save a little code space, it doesn't free the filter_costs */ + png_reset_filter_heuristics(png_ptr); + png_free(png_ptr, png_ptr->filter_costs); + png_free(png_ptr, png_ptr->inv_filter_costs); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + /* Reset structure */ + png_memcpy(tmp_jmp, png_ptr->png_jmpbuf, png_sizeof(jmp_buf)); +#endif + + error_fn = png_ptr->error_fn; + warning_fn = png_ptr->warning_fn; + error_ptr = png_ptr->error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + free_fn = png_ptr->free_fn; +#endif + + png_memset(png_ptr, 0, png_sizeof(png_struct)); + + png_ptr->error_fn = error_fn; + png_ptr->warning_fn = warning_fn; + png_ptr->error_ptr = error_ptr; +#ifdef PNG_USER_MEM_SUPPORTED + png_ptr->free_fn = free_fn; +#endif + +#ifdef PNG_SETJMP_SUPPORTED + png_memcpy(png_ptr->png_jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); +#endif +} + +/* Allow the application to select one or more row filters to use. */ +void PNGAPI +png_set_filter(png_structp png_ptr, int method, int filters) +{ + png_debug(1, "in png_set_filter"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_MNG_FEATURES_SUPPORTED + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + (method == PNG_INTRAPIXEL_DIFFERENCING)) + method = PNG_FILTER_TYPE_BASE; + +#endif + if (method == PNG_FILTER_TYPE_BASE) + { + switch (filters & (PNG_ALL_FILTERS | 0x07)) + { +#ifdef PNG_WRITE_FILTER_SUPPORTED + case 5: + case 6: + case 7: png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + case PNG_FILTER_VALUE_NONE: + png_ptr->do_filter = PNG_FILTER_NONE; break; + +#ifdef PNG_WRITE_FILTER_SUPPORTED + case PNG_FILTER_VALUE_SUB: + png_ptr->do_filter = PNG_FILTER_SUB; break; + + case PNG_FILTER_VALUE_UP: + png_ptr->do_filter = PNG_FILTER_UP; break; + + case PNG_FILTER_VALUE_AVG: + png_ptr->do_filter = PNG_FILTER_AVG; break; + + case PNG_FILTER_VALUE_PAETH: + png_ptr->do_filter = PNG_FILTER_PAETH; break; + + default: + png_ptr->do_filter = (png_byte)filters; break; +#else + default: + png_warning(png_ptr, "Unknown row filter for method 0"); +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + } + + /* If we have allocated the row_buf, this means we have already started + * with the image and we should have allocated all of the filter buffers + * that have been selected. If prev_row isn't already allocated, then + * it is too late to start using the filters that need it, since we + * will be missing the data in the previous row. If an application + * wants to start and stop using particular filters during compression, + * it should start out with all of the filters, and then add and + * remove them after the start of compression. + */ + if (png_ptr->row_buf != NULL) + { +#ifdef PNG_WRITE_FILTER_SUPPORTED + if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Up filter after starting"); + png_ptr->do_filter = (png_byte)(png_ptr->do_filter & + ~PNG_FILTER_UP); + } + + else + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Average filter after starting"); + png_ptr->do_filter = (png_byte)(png_ptr->do_filter & + ~PNG_FILTER_AVG); + } + + else + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + } + + if ((png_ptr->do_filter & PNG_FILTER_PAETH) && + png_ptr->paeth_row == NULL) + { + if (png_ptr->prev_row == NULL) + { + png_warning(png_ptr, "Can't add Paeth filter after starting"); + png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); + } + + else + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + (png_ptr->rowbytes + 1)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } + + if (png_ptr->do_filter == PNG_NO_FILTERS) +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + png_ptr->do_filter = PNG_FILTER_NONE; + } + } + else + png_error(png_ptr, "Unknown custom filter method"); +} + +/* This allows us to influence the way in which libpng chooses the "best" + * filter for the current scanline. While the "minimum-sum-of-absolute- + * differences metric is relatively fast and effective, there is some + * question as to whether it can be improved upon by trying to keep the + * filtered data going to zlib more consistent, hopefully resulting in + * better compression. + */ +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ +/* Conveneince reset API. */ +static void +png_reset_filter_heuristics(png_structp png_ptr) +{ + /* Clear out any old values in the 'weights' - this must be done because if + * the app calls set_filter_heuristics multiple times with different + * 'num_weights' values we would otherwise potentially have wrong sized + * arrays. + */ + png_ptr->num_prev_filters = 0; + png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; + if (png_ptr->prev_filters != NULL) + { + png_bytep old = png_ptr->prev_filters; + png_ptr->prev_filters = NULL; + png_free(png_ptr, old); + } + if (png_ptr->filter_weights != NULL) + { + png_uint_16p old = png_ptr->filter_weights; + png_ptr->filter_weights = NULL; + png_free(png_ptr, old); + } + + if (png_ptr->inv_filter_weights != NULL) + { + png_uint_16p old = png_ptr->inv_filter_weights; + png_ptr->inv_filter_weights = NULL; + png_free(png_ptr, old); + } + + /* Leave the filter_costs - this array is fixed size. */ +} + +static int +png_init_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights) +{ + if (png_ptr == NULL) + return 0; + + /* Clear out the arrays */ + png_reset_filter_heuristics(png_ptr); + + /* Check arguments; the 'reset' function makes the correct settings for the + * unweighted case, but we must handle the weight case by initializing the + * arrays for the caller. + */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + + if (num_weights > 0) + { + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_byte) * num_weights)); + + /* To make sure that the weighting starts out fairly */ + for (i = 0; i < num_weights; i++) + { + png_ptr->prev_filters[i] = 255; + } + + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); + + for (i = 0; i < num_weights; i++) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + /* Safe to set this now */ + png_ptr->num_prev_filters = (png_byte)num_weights; + } + + /* If, in the future, there are other filter methods, this would + * need to be based on png_ptr->filter. + */ + if (png_ptr->filter_costs == NULL) + { + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); + } + + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + { + png_ptr->inv_filter_costs[i] = + png_ptr->filter_costs[i] = PNG_COST_FACTOR; + } + + /* All the arrays are inited, safe to set this: */ + png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED; + + /* Return the 'ok' code. */ + return 1; + } + else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT || + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) + { + return 1; + } + else + { + png_warning(png_ptr, "Unknown filter heuristic method"); + return 0; + } +} + +/* Provide floating and fixed point APIs */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, + int num_weights, png_const_doublep filter_weights, + png_const_doublep filter_costs) +{ + png_debug(1, "in png_set_filter_heuristics"); + + /* The internal API allocates all the arrays and ensures that the elements of + * those arrays are set to the default value. + */ + if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) + return; + + /* If using the weighted method copy in the weights. */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] <= 0.0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + else + { + png_ptr->inv_filter_weights[i] = + (png_uint_16)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5); + + png_ptr->filter_weights[i] = + (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5); + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) if (filter_costs[i] >= 1.0) + { + png_ptr->inv_filter_costs[i] = + (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5); + + png_ptr->filter_costs[i] = + (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5); + } + } +} +#endif /* FLOATING_POINT */ + +#ifdef PNG_FIXED_POINT_SUPPORTED +void PNGAPI +png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method, + int num_weights, png_const_fixed_point_p filter_weights, + png_const_fixed_point_p filter_costs) +{ + png_debug(1, "in png_set_filter_heuristics_fixed"); + + /* The internal API allocates all the arrays and ensures that the elements of + * those arrays are set to the default value. + */ + if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights)) + return; + + /* If using the weighted method copy in the weights. */ + if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int i; + for (i = 0; i < num_weights; i++) + { + if (filter_weights[i] <= 0) + { + png_ptr->inv_filter_weights[i] = + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + } + + else + { + png_ptr->inv_filter_weights[i] = (png_uint_16) + ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1); + + png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR* + PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]); + } + } + + /* Here is where we set the relative costs of the different filters. We + * should take the desired compression level into account when setting + * the costs, so that Paeth, for instance, has a high relative cost at low + * compression levels, while it has a lower relative cost at higher + * compression settings. The filter types are in order of increasing + * relative cost, so it would be possible to do this with an algorithm. + */ + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) + if (filter_costs[i] >= PNG_FP_1) + { + png_uint_32 tmp; + + /* Use a 32 bit unsigned temporary here because otherwise the + * intermediate value will be a 32 bit *signed* integer (ANSI rules) + * and this will get the wrong answer on division. + */ + tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2); + tmp /= filter_costs[i]; + + png_ptr->inv_filter_costs[i] = (png_uint_16)tmp; + + tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF; + tmp /= PNG_FP_1; + + png_ptr->filter_costs[i] = (png_uint_16)tmp; + } + } +} +#endif /* FIXED_POINT */ +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ + +void PNGAPI +png_set_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_compression_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; + png_ptr->zlib_level = level; +} + +void PNGAPI +png_set_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_compression_mem_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; + png_ptr->zlib_mem_level = mem_level; +} + +void PNGAPI +png_set_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_compression_strategy"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; + png_ptr->zlib_strategy = strategy; +} + +void PNGAPI +png_set_compression_window_bits(png_structp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + + if (window_bits > 15) + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + + else if (window_bits < 8) + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); + +#ifndef WBITS_8_OK + /* Avoid libpng bug with 256-byte windows */ + if (window_bits == 8) + { + png_warning(png_ptr, "Compression window is being reset to 512"); + window_bits = 9; + } + +#endif + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; + png_ptr->zlib_window_bits = window_bits; +} + +void PNGAPI +png_set_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_compression_method"); + + if (png_ptr == NULL) + return; + + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; + png_ptr->zlib_method = method; +} + +void PNGAPI +png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) +{ + if (png_ptr == NULL) + return; + + png_ptr->write_row_fn = write_row_fn; +} + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +void PNGAPI +png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr + write_user_transform_fn) +{ + png_debug(1, "in png_set_write_user_transform_fn"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_USER_TRANSFORM; + png_ptr->write_user_transform_fn = write_user_transform_fn; +} +#endif + + +#ifdef PNG_INFO_IMAGE_SUPPORTED +void PNGAPI +png_write_png(png_structp png_ptr, png_infop info_ptr, + int transforms, voidp params) +{ + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Write the file header information. */ + png_write_info(png_ptr, info_ptr); + + /* ------ these transformations don't touch the info structure ------- */ + +#ifdef PNG_WRITE_INVERT_SUPPORTED + /* Invert monochrome pixels */ + if (transforms & PNG_TRANSFORM_INVERT_MONO) + png_set_invert_mono(png_ptr); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + if ((transforms & PNG_TRANSFORM_SHIFT) + && (info_ptr->valid & PNG_INFO_sBIT)) + png_set_shift(png_ptr, &info_ptr->sig_bit); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED + /* Pack pixels into bytes */ + if (transforms & PNG_TRANSFORM_PACKING) + png_set_packing(png_ptr); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + /* Swap location of alpha bytes from ARGB to RGBA */ + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) + png_set_swap_alpha(png_ptr); +#endif + +#ifdef PNG_WRITE_FILLER_SUPPORTED + /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */ + if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) + png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); + + else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); +#endif + +#ifdef PNG_WRITE_BGR_SUPPORTED + /* Flip BGR pixels to RGB */ + if (transforms & PNG_TRANSFORM_BGR) + png_set_bgr(png_ptr); +#endif + +#ifdef PNG_WRITE_SWAP_SUPPORTED + /* Swap bytes of 16-bit files to most significant byte first */ + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) + png_set_swap(png_ptr); +#endif + +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + /* Swap bits of 1, 2, 4 bit packed pixel formats */ + if (transforms & PNG_TRANSFORM_PACKSWAP) + png_set_packswap(png_ptr); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + /* Invert the alpha channel from opacity to transparency */ + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) + png_set_invert_alpha(png_ptr); +#endif + + /* ----------------------- end of transformations ------------------- */ + + /* Write the bits */ + if (info_ptr->valid & PNG_INFO_IDAT) + png_write_image(png_ptr, info_ptr->row_pointers); + + /* It is REQUIRED to call this to finish writing the rest of the file */ + png_write_end(png_ptr, info_ptr); + + PNG_UNUSED(transforms) /* Quiet compiler warnings */ + PNG_UNUSED(params) +} +#endif +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/contrib/libpng/pngwtran.c b/contrib/libpng/pngwtran.c new file mode 100644 index 0000000..115ca37 --- /dev/null +++ b/contrib/libpng/pngwtran.c @@ -0,0 +1,631 @@ + +/* pngwtran.c - transforms the data in a row for PNG writers + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +/* Transform the data according to the user's wishes. The order of + * transformations is significant. + */ +void /* PRIVATE */ +png_do_write_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_do_write_transformations"); + + if (png_ptr == NULL) + return; + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + if (png_ptr->transformations & PNG_USER_TRANSFORM) + if (png_ptr->write_user_transform_fn != NULL) + (*(png_ptr->write_user_transform_fn)) /* User write transform + function */ + (png_ptr, /* png_ptr */ + &(png_ptr->row_info), /* row_info: */ + /* png_uint_32 width; width of row */ + /* png_size_t rowbytes; number of bytes in row */ + /* png_byte color_type; color type of pixels */ + /* png_byte bit_depth; bit depth of samples */ + /* png_byte channels; number of channels (1-4) */ + /* png_byte pixel_depth; bits per pixel (depth*channels) */ + png_ptr->row_buf + 1); /* start of pixel data for row */ +#endif + +#ifdef PNG_WRITE_FILLER_SUPPORTED + if (png_ptr->transformations & PNG_FILLER) + png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, + png_ptr->flags); +#endif + +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED + if (png_ptr->transformations & PNG_PACKSWAP) + png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_PACK_SUPPORTED + if (png_ptr->transformations & PNG_PACK) + png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, + (png_uint_32)png_ptr->bit_depth); +#endif + +#ifdef PNG_WRITE_SWAP_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_BYTES) + png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED + if (png_ptr->transformations & PNG_SHIFT) + png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1, + &(png_ptr->shift)); +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA) + png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + +#ifdef PNG_WRITE_INVERT_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_MONO) + png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif +} + +#ifdef PNG_WRITE_PACK_SUPPORTED +/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The + * row_info bit depth should be 8 (one pixel per byte). The channels + * should be 1 (this only happens on grayscale and paletted images). + */ +void /* PRIVATE */ +png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) +{ + png_debug(1, "in png_do_pack"); + + if (row_info->bit_depth == 8 && + row_info->channels == 1) + { + switch ((int)bit_depth) + { + case 1: + { + png_bytep sp, dp; + int mask, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + mask = 0x80; + v = 0; + + for (i = 0; i < row_width; i++) + { + if (*sp != 0) + v |= mask; + + sp++; + + if (mask > 1) + mask >>= 1; + + else + { + mask = 0x80; + *dp = (png_byte)v; + dp++; + v = 0; + } + } + + if (mask != 0x80) + *dp = (png_byte)v; + + break; + } + + case 2: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 6; + v = 0; + + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x03); + v |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp = (png_byte)v; + dp++; + v = 0; + } + + else + shift -= 2; + + sp++; + } + + if (shift != 6) + *dp = (png_byte)v; + + break; + } + + case 4: + { + png_bytep sp, dp; + int shift, v; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + sp = row; + dp = row; + shift = 4; + v = 0; + + for (i = 0; i < row_width; i++) + { + png_byte value; + + value = (png_byte)(*sp & 0x0f); + v |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp = (png_byte)v; + dp++; + v = 0; + } + + else + shift -= 4; + + sp++; + } + + if (shift != 4) + *dp = (png_byte)v; + + break; + } + + default: + break; + } + + row_info->bit_depth = (png_byte)bit_depth; + row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +#ifdef PNG_WRITE_SHIFT_SUPPORTED +/* Shift pixel values to take advantage of whole range. Pass the + * true number of bits in bit_depth. The row should be packed + * according to row_info->bit_depth. Thus, if you had a row of + * bit depth 4, but the pixels only had values from 0 to 7, you + * would pass 3 as bit_depth, and this routine would translate the + * data to 0 to 15. + */ +void /* PRIVATE */ +png_do_shift(png_row_infop row_info, png_bytep row, + png_const_color_8p bit_depth) +{ + png_debug(1, "in png_do_shift"); + + if (row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + int shift_start[4], shift_dec[4]; + int channels = 0; + + if (row_info->color_type & PNG_COLOR_MASK_COLOR) + { + shift_start[channels] = row_info->bit_depth - bit_depth->red; + shift_dec[channels] = bit_depth->red; + channels++; + + shift_start[channels] = row_info->bit_depth - bit_depth->green; + shift_dec[channels] = bit_depth->green; + channels++; + + shift_start[channels] = row_info->bit_depth - bit_depth->blue; + shift_dec[channels] = bit_depth->blue; + channels++; + } + + else + { + shift_start[channels] = row_info->bit_depth - bit_depth->gray; + shift_dec[channels] = bit_depth->gray; + channels++; + } + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + shift_start[channels] = row_info->bit_depth - bit_depth->alpha; + shift_dec[channels] = bit_depth->alpha; + channels++; + } + + /* With low row depths, could only be grayscale, so one channel */ + if (row_info->bit_depth < 8) + { + png_bytep bp = row; + png_size_t i; + png_byte mask; + png_size_t row_bytes = row_info->rowbytes; + + if (bit_depth->gray == 1 && row_info->bit_depth == 2) + mask = 0x55; + + else if (row_info->bit_depth == 4 && bit_depth->gray == 3) + mask = 0x11; + + else + mask = 0xff; + + for (i = 0; i < row_bytes; i++, bp++) + { + png_uint_16 v; + int j; + + v = *bp; + *bp = 0; + + for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + + else + *bp |= (png_byte)((v >> (-j)) & mask); + } + } + } + + else if (row_info->bit_depth == 8) + { + png_bytep bp = row; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (i = 0; i < istop; i++, bp++) + { + + png_uint_16 v; + int j; + int c = (int)(i%channels); + + v = *bp; + *bp = 0; + + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + *bp |= (png_byte)((v << j) & 0xff); + + else + *bp |= (png_byte)((v >> (-j)) & 0xff); + } + } + } + + else + { + png_bytep bp; + png_uint_32 i; + png_uint_32 istop = channels * row_info->width; + + for (bp = row, i = 0; i < istop; i++) + { + int c = (int)(i%channels); + png_uint_16 value, v; + int j; + + v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1)); + value = 0; + + for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) + { + if (j > 0) + value |= (png_uint_16)((v << j) & (png_uint_16)0xffff); + + else + value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff); + } + *bp++ = (png_byte)(value >> 8); + *bp++ = (png_byte)(value & 0xff); + } + } + } +} +#endif + +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_swap_alpha"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This converts from ARGB to RGBA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This converts from AARRGGBB to RRGGBBAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This converts from AG to GA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save; + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This converts from AAGG to GGAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + png_byte save[2]; + save[0] = *(sp++); + save[1] = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = save[0]; + *(dp++) = save[1]; + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + } +} +#endif + +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +void /* PRIVATE */ +png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_invert_alpha"); + + { + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in RGBA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=3; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in RRGGBBAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=6; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + if (row_info->bit_depth == 8) + { + /* This inverts the alpha channel in GA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + *(dp++) = *(sp++); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else + { + /* This inverts the alpha channel in GGAA */ + png_bytep sp, dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + for (i = 0, sp = dp = row; i < row_width; i++) + { + /* Does nothing + *(dp++) = *(sp++); + *(dp++) = *(sp++); + */ + sp+=2; dp = sp; + *(dp++) = (png_byte)(255 - *(sp++)); + *(dp++) = (png_byte)(255 - *(sp++)); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } + } +} +#endif + +#ifdef PNG_MNG_FEATURES_SUPPORTED +/* Undoes intrapixel differencing */ +void /* PRIVATE */ +png_do_write_intrapixel(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_write_intrapixel"); + + if ((row_info->color_type & PNG_COLOR_MASK_COLOR)) + { + int bytes_per_pixel; + png_uint_32 row_width = row_info->width; + if (row_info->bit_depth == 8) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 3; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 4; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + *(rp) = (png_byte)((*rp - *(rp + 1)) & 0xff); + *(rp + 2) = (png_byte)((*(rp + 2) - *(rp + 1)) & 0xff); + } + } + +#ifdef PNG_WRITE_16BIT_SUPPORTED + else if (row_info->bit_depth == 16) + { + png_bytep rp; + png_uint_32 i; + + if (row_info->color_type == PNG_COLOR_TYPE_RGB) + bytes_per_pixel = 6; + + else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + bytes_per_pixel = 8; + + else + return; + + for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) + { + png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); + png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); + png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); + png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); + png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); + *(rp ) = (png_byte)((red >> 8) & 0xff); + *(rp + 1) = (png_byte)(red & 0xff); + *(rp + 4) = (png_byte)((blue >> 8) & 0xff); + *(rp + 5) = (png_byte)(blue & 0xff); + } + } +#endif /* PNG_WRITE_16BIT_SUPPORTED */ + } +} +#endif /* PNG_MNG_FEATURES_SUPPORTED */ +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/contrib/libpng/pngwutil.c b/contrib/libpng/pngwutil.c new file mode 100644 index 0000000..2c35785 --- /dev/null +++ b/contrib/libpng/pngwutil.c @@ -0,0 +1,2948 @@ + +/* pngwutil.c - utilities to write a PNG file + * + * Last changed in libpng 1.5.0 [January 6, 2011] + * Copyright (c) 1998-2011 Glenn Randers-Pehrson + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "pngpriv.h" + +#ifdef PNG_WRITE_SUPPORTED + +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED +/* Place a 32-bit number into a buffer in PNG byte order. We work + * with unsigned numbers for convenience, although one supported + * ancillary chunk uses signed (two's complement) numbers. + */ +void PNGAPI +png_save_uint_32(png_bytep buf, png_uint_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} + +#ifdef PNG_SAVE_INT_32_SUPPORTED +/* The png_save_int_32 function assumes integers are stored in two's + * complement format. If this isn't the case, then this routine needs to + * be modified to write data in two's complement format. Note that, + * the following works correctly even if png_int_32 has more than 32 bits + * (compare the more complex code required on read for sign extention.) + */ +void PNGAPI +png_save_int_32(png_bytep buf, png_int_32 i) +{ + buf[0] = (png_byte)((i >> 24) & 0xff); + buf[1] = (png_byte)((i >> 16) & 0xff); + buf[2] = (png_byte)((i >> 8) & 0xff); + buf[3] = (png_byte)(i & 0xff); +} +#endif + +/* Place a 16-bit number into a buffer in PNG byte order. + * The parameter is declared unsigned int, not png_uint_16, + * just to avoid potential problems on pre-ANSI C compilers. + */ +void PNGAPI +png_save_uint_16(png_bytep buf, unsigned int i) +{ + buf[0] = (png_byte)((i >> 8) & 0xff); + buf[1] = (png_byte)(i & 0xff); +} +#endif + +/* Simple function to write the signature. If we have already written + * the magic bytes of the signature, or more likely, the PNG stream is + * being embedded into another stream and doesn't need its own signature, + * we should call png_set_sig_bytes() to tell libpng how many of the + * bytes have already been written. + */ +void PNGAPI +png_write_sig(png_structp png_ptr) +{ + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the signature is being written */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; +#endif + + /* Write the rest of the 8 byte signature */ + png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], + (png_size_t)(8 - png_ptr->sig_bytes)); + + if (png_ptr->sig_bytes < 3) + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; +} + +/* Write a PNG chunk all at once. The type is an array of ASCII characters + * representing the chunk name. The array must be at least 4 bytes in + * length, and does not need to be null terminated. To be safe, pass the + * pre-defined chunk names here, and if you need a new one, define it + * where the others are defined. The length is the length of the data. + * All the data must be present. If that is not possible, use the + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() + * functions instead. + */ +void PNGAPI +png_write_chunk(png_structp png_ptr, png_const_bytep chunk_name, + png_const_bytep data, png_size_t length) +{ + if (png_ptr == NULL) + return; + + png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); + png_write_chunk_data(png_ptr, data, (png_size_t)length); + png_write_chunk_end(png_ptr); +} + +/* Write the start of a PNG chunk. The type is the chunk type. + * The total_length is the sum of the lengths of all the data you will be + * passing in png_write_chunk_data(). + */ +void PNGAPI +png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_name, + png_uint_32 length) +{ + png_byte buf[8]; + + png_debug2(0, "Writing %s chunk, length = %lu", chunk_name, + (unsigned long)length); + + if (png_ptr == NULL) + return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk header is being written. + * PNG_IO_CHUNK_HDR requires a single I/O call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; +#endif + + /* Write the length and the chunk name */ + png_save_uint_32(buf, length); + png_memcpy(buf + 4, chunk_name, 4); + png_write_data(png_ptr, buf, (png_size_t)8); + + /* Put the chunk name into png_ptr->chunk_name */ + png_memcpy(png_ptr->chunk_name, chunk_name, 4); + + /* Reset the crc and run it over the chunk name */ + png_reset_crc(png_ptr); + + png_calculate_crc(png_ptr, chunk_name, 4); + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that chunk data will (possibly) be written. + * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; +#endif +} + +/* Write the data of a PNG chunk started with png_write_chunk_start(). + * Note that multiple calls to this function are allowed, and that the + * sum of the lengths from these calls *must* add up to the total_length + * given to png_write_chunk_start(). + */ +void PNGAPI +png_write_chunk_data(png_structp png_ptr, png_const_bytep data, + png_size_t length) +{ + /* Write the data, and run the CRC over it */ + if (png_ptr == NULL) + return; + + if (data != NULL && length > 0) + { + png_write_data(png_ptr, data, length); + + /* Update the CRC after writing the data, + * in case that the user I/O routine alters it. + */ + png_calculate_crc(png_ptr, data, length); + } +} + +/* Finish a chunk started with png_write_chunk_start(). */ +void PNGAPI +png_write_chunk_end(png_structp png_ptr) +{ + png_byte buf[4]; + + if (png_ptr == NULL) return; + +#ifdef PNG_IO_STATE_SUPPORTED + /* Inform the I/O callback that the chunk CRC is being written. + * PNG_IO_CHUNK_CRC requires a single I/O function call. + */ + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; +#endif + + /* Write the crc in a single operation */ + png_save_uint_32(buf, png_ptr->crc); + + png_write_data(png_ptr, buf, (png_size_t)4); +} + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) +/* This pair of functions encapsulates the operation of (a) compressing a + * text string, and (b) issuing it later as a series of chunk data writes. + * The compression_state structure is shared context for these functions + * set up by the caller in order to make the whole mess thread-safe. + */ + +typedef struct +{ + png_const_bytep input; /* The uncompressed input data */ + png_size_t input_len; /* Its length */ + int num_output_ptr; /* Number of output pointers used */ + int max_output_ptr; /* Size of output_ptr */ + png_bytep *output_ptr; /* Array of pointers to output */ +} compression_state; + +/* Compress given text into storage in the png_ptr structure */ +static int /* PRIVATE */ +png_text_compress(png_structp png_ptr, + png_const_charp text, png_size_t text_len, int compression, + compression_state *comp) +{ + int ret; + + comp->num_output_ptr = 0; + comp->max_output_ptr = 0; + comp->output_ptr = NULL; + comp->input = NULL; + comp->input_len = 0; + + /* We may just want to pass the text right through */ + if (compression == PNG_TEXT_COMPRESSION_NONE) + { + comp->input = (png_const_bytep)text; + comp->input_len = text_len; + return((int)text_len); + } + + if (compression >= PNG_TEXT_COMPRESSION_LAST) + { +#ifdef PNG_CONSOLE_IO_SUPPORTED + char msg[50]; + png_snprintf(msg, 50, "Unknown compression type %d", compression); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "Unknown compression type"); +#endif + } + + /* We can't write the chunk until we find out how much data we have, + * which means we need to run the compressor first and save the + * output. This shouldn't be a problem, as the vast majority of + * comments should be reasonable, but we will set up an array of + * malloc'd pointers to be sure. + * + * If we knew the application was well behaved, we could simplify this + * greatly by assuming we can always malloc an output buffer large + * enough to hold the compressed text ((1001 * text_len / 1000) + 12) + * and malloc this directly. The only time this would be a bad idea is + * if we can't malloc more than 64K and we have 64K of random input + * data, or if the input string is incredibly large (although this + * wouldn't cause a failure, just a slowdown due to swapping). + */ + + /* Set up the compression buffers */ + /* TODO: the following cast hides a potential overflow problem. */ + png_ptr->zstream.avail_in = (uInt)text_len; + /* NOTE: assume zlib doesn't overwrite the input */ + png_ptr->zstream.next_in = (Bytef *)text; + png_ptr->zstream.avail_out = png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + + /* This is the same compression loop as in png_write_row() */ + do + { + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + + if (ret != Z_OK) + { + /* Error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* Make sure the output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_bytepp old_ptr; + + old_ptr = comp->output_ptr; + + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t) + (comp->max_output_ptr * png_sizeof(png_charpp))); + + png_memcpy(comp->output_ptr, old_ptr, old_max + * png_sizeof(png_charp)); + + png_free(png_ptr, old_ptr); + } + else + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t) + (comp->max_output_ptr * png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)png_ptr->zbuf_size); + + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + + comp->num_output_ptr++; + + /* and reset the buffer */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + /* Continue until we don't have any more to compress */ + } while (png_ptr->zstream.avail_in); + + /* Finish the compression */ + do + { + /* Tell zlib we are finished */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + + if (ret == Z_OK) + { + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + /* Check to make sure our output array has room */ + if (comp->num_output_ptr >= comp->max_output_ptr) + { + int old_max; + + old_max = comp->max_output_ptr; + comp->max_output_ptr = comp->num_output_ptr + 4; + if (comp->output_ptr != NULL) + { + png_bytepp old_ptr; + + old_ptr = comp->output_ptr; + + /* This could be optimized to realloc() */ + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t)(comp->max_output_ptr * + png_sizeof(png_charp))); + + png_memcpy(comp->output_ptr, old_ptr, + old_max * png_sizeof(png_charp)); + + png_free(png_ptr, old_ptr); + } + + else + comp->output_ptr = (png_bytepp)png_malloc(png_ptr, + (png_alloc_size_t)(comp->max_output_ptr * + png_sizeof(png_charp))); + } + + /* Save the data */ + comp->output_ptr[comp->num_output_ptr] = + (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)png_ptr->zbuf_size); + + png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, + png_ptr->zbuf_size); + + comp->num_output_ptr++; + + /* and reset the buffer pointers */ + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; + } + } + else if (ret != Z_STREAM_END) + { + /* We got an error */ + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* Text length is number of buffers plus last buffer */ + text_len = png_ptr->zbuf_size * comp->num_output_ptr; + + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; + + return((int)text_len); +} + +/* Ship the compressed text out via chunk writes */ +static void /* PRIVATE */ +png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) +{ + int i; + + /* Handle the no-compression case */ + if (comp->input) + { + png_write_chunk_data(png_ptr, comp->input, comp->input_len); + + return; + } + + /* Write saved output buffers, if any */ + for (i = 0; i < comp->num_output_ptr; i++) + { + png_write_chunk_data(png_ptr, comp->output_ptr[i], + (png_size_t)png_ptr->zbuf_size); + + png_free(png_ptr, comp->output_ptr[i]); + } + + if (comp->max_output_ptr != 0) + png_free(png_ptr, comp->output_ptr); + + /* Write anything left in zbuf */ + if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) + png_write_chunk_data(png_ptr, png_ptr->zbuf, + (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out)); + + /* Reset zlib for another zTXt/iTXt or image data */ + deflateReset(&png_ptr->zstream); + png_ptr->zstream.data_type = Z_BINARY; +} +#endif + +/* Write the IHDR chunk, and update the png_struct with the necessary + * information. Note that the rest of this code depends upon this + * information being correct. + */ +void /* PRIVATE */ +png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, + int bit_depth, int color_type, int compression_type, int filter_type, + int interlace_type) +{ + PNG_IHDR; + int ret; + + png_byte buf[13]; /* Buffer to store the IHDR info */ + + png_debug(1, "in png_write_IHDR"); + + /* Check that we have valid input data from the application info */ + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: +#ifdef PNG_WRITE_16BIT_SUPPORTED + case 16: +#endif + png_ptr->channels = 1; break; + + default: + png_error(png_ptr, + "Invalid bit depth for grayscale image"); + } + break; + + case PNG_COLOR_TYPE_RGB: +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (bit_depth != 8 && bit_depth != 16) +#else + if (bit_depth != 8) +#endif + png_error(png_ptr, "Invalid bit depth for RGB image"); + + png_ptr->channels = 3; + break; + + case PNG_COLOR_TYPE_PALETTE: + switch (bit_depth) + { + case 1: + case 2: + case 4: + case 8: + png_ptr->channels = 1; + break; + + default: + png_error(png_ptr, "Invalid bit depth for paletted image"); + } + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + if (bit_depth != 8 && bit_depth != 16) + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); + + png_ptr->channels = 2; + break; + + case PNG_COLOR_TYPE_RGB_ALPHA: +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (bit_depth != 8 && bit_depth != 16) +#else + if (bit_depth != 8) +#endif + png_error(png_ptr, "Invalid bit depth for RGBA image"); + + png_ptr->channels = 4; + break; + + default: + png_error(png_ptr, "Invalid image color type specified"); + } + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + { + png_warning(png_ptr, "Invalid compression type specified"); + compression_type = PNG_COMPRESSION_TYPE_BASE; + } + + /* Write filter_method 64 (intrapixel differencing) only if + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and + * 2. Libpng did not write a PNG signature (this filter_method is only + * used in PNG datastreams that are embedded in MNG datastreams) and + * 3. The application called png_permit_mng_features with a mask that + * included PNG_FLAG_MNG_FILTER_64 and + * 4. The filter_method is 64 and + * 5. The color_type is RGB or RGBA + */ + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && + (color_type == PNG_COLOR_TYPE_RGB || + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && +#endif + filter_type != PNG_FILTER_TYPE_BASE) + { + png_warning(png_ptr, "Invalid filter type specified"); + filter_type = PNG_FILTER_TYPE_BASE; + } + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + if (interlace_type != PNG_INTERLACE_NONE && + interlace_type != PNG_INTERLACE_ADAM7) + { + png_warning(png_ptr, "Invalid interlace type specified"); + interlace_type = PNG_INTERLACE_ADAM7; + } +#else + interlace_type=PNG_INTERLACE_NONE; +#endif + + /* Save the relevent information */ + png_ptr->bit_depth = (png_byte)bit_depth; + png_ptr->color_type = (png_byte)color_type; + png_ptr->interlaced = (png_byte)interlace_type; +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_ptr->filter_type = (png_byte)filter_type; +#endif + png_ptr->compression_type = (png_byte)compression_type; + png_ptr->width = width; + png_ptr->height = height; + + png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); + /* Set the usr info, so any transformations can modify it */ + png_ptr->usr_width = png_ptr->width; + png_ptr->usr_bit_depth = png_ptr->bit_depth; + png_ptr->usr_channels = png_ptr->channels; + + /* Pack the header information into the buffer */ + png_save_uint_32(buf, width); + png_save_uint_32(buf + 4, height); + buf[8] = (png_byte)bit_depth; + buf[9] = (png_byte)color_type; + buf[10] = (png_byte)compression_type; + buf[11] = (png_byte)filter_type; + buf[12] = (png_byte)interlace_type; + + /* Write the chunk */ + png_write_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); + + /* Initialize zlib with PNG info */ + png_ptr->zstream.zalloc = png_zalloc; + png_ptr->zstream.zfree = png_zfree; + png_ptr->zstream.opaque = (voidpf)png_ptr; + + if (!(png_ptr->do_filter)) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || + png_ptr->bit_depth < 8) + png_ptr->do_filter = PNG_FILTER_NONE; + + else + png_ptr->do_filter = PNG_ALL_FILTERS; + } + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) + { + if (png_ptr->do_filter != PNG_FILTER_NONE) + png_ptr->zlib_strategy = Z_FILTERED; + + else + png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; + } + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) + png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_mem_level = 8; + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_window_bits = 15; + + if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) + png_ptr->zlib_method = 8; + + ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, + png_ptr->zlib_method, png_ptr->zlib_window_bits, + png_ptr->zlib_mem_level, png_ptr->zlib_strategy); + + if (ret != Z_OK) + { + if (ret == Z_VERSION_ERROR) + png_error(png_ptr, + "zlib failed to initialize compressor -- version error"); + + if (ret == Z_STREAM_ERROR) + png_error(png_ptr, + "zlib failed to initialize compressor -- stream error"); + + if (ret == Z_MEM_ERROR) + png_error(png_ptr, + "zlib failed to initialize compressor -- mem error"); + + png_error(png_ptr, "zlib failed to initialize compressor"); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + /* libpng is not interested in zstream.data_type, so set it + * to a predefined value, to avoid its evaluation inside zlib + */ + png_ptr->zstream.data_type = Z_BINARY; + + png_ptr->mode = PNG_HAVE_IHDR; +} + +/* Write the palette. We are careful not to trust png_color to be in the + * correct order for PNG, so people can redefine it to any convenient + * structure. + */ +void /* PRIVATE */ +png_write_PLTE(png_structp png_ptr, png_const_colorp palette, + png_uint_32 num_pal) +{ + PNG_PLTE; + png_uint_32 i; + png_const_colorp pal_ptr; + png_byte buf[3]; + + png_debug(1, "in png_write_PLTE"); + + if (( +#ifdef PNG_MNG_FEATURES_SUPPORTED + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && +#endif + num_pal == 0) || num_pal > 256) + { + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + { + png_error(png_ptr, "Invalid number of colors in palette"); + } + + else + { + png_warning(png_ptr, "Invalid number of colors in palette"); + return; + } + } + + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) + { + png_warning(png_ptr, + "Ignoring request to write a PLTE chunk in grayscale PNG"); + + return; + } + + png_ptr->num_palette = (png_uint_16)num_pal; + png_debug1(3, "num_palette = %d", png_ptr->num_palette); + + png_write_chunk_start(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3)); +#ifdef PNG_POINTER_INDEXING_SUPPORTED + + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) + { + buf[0] = pal_ptr->red; + buf[1] = pal_ptr->green; + buf[2] = pal_ptr->blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } + +#else + /* This is a little slower but some buggy compilers need to do this + * instead + */ + pal_ptr=palette; + + for (i = 0; i < num_pal; i++) + { + buf[0] = pal_ptr[i].red; + buf[1] = pal_ptr[i].green; + buf[2] = pal_ptr[i].blue; + png_write_chunk_data(png_ptr, buf, (png_size_t)3); + } + +#endif + png_write_chunk_end(png_ptr); + png_ptr->mode |= PNG_HAVE_PLTE; +} + +/* Write an IDAT chunk */ +void /* PRIVATE */ +png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) +{ + PNG_IDAT; + + png_debug(1, "in png_write_IDAT"); + + /* Optimize the CMF field in the zlib stream. */ + /* This hack of the zlib stream is compliant to the stream specification. */ + if (!(png_ptr->mode & PNG_HAVE_IDAT) && + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) + { + unsigned int z_cmf = data[0]; /* zlib compression method and flags */ + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + /* Avoid memory underflows and multiplication overflows. + * + * The conditions below are practically always satisfied; + * however, they still must be checked. + */ + if (length >= 2 && + png_ptr->height < 16384 && png_ptr->width < 16384) + { + png_uint_32 uncompressed_idat_size = png_ptr->height * + ((png_ptr->width * + png_ptr->channels * png_ptr->bit_depth + 15) >> 3); + unsigned int z_cinfo = z_cmf >> 4; + unsigned int half_z_window_size = 1 << (z_cinfo + 7); + while (uncompressed_idat_size <= half_z_window_size && + half_z_window_size >= 256) + { + z_cinfo--; + half_z_window_size >>= 1; + } + + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + + if (data[0] != z_cmf) + { + int tmp; + data[0] = (png_byte)z_cmf; + tmp = data[1] & 0xe0; + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; + data[1] = (png_byte)tmp; + } + } + } + + else + png_error(png_ptr, + "Invalid zlib compression method or flags in IDAT"); + } + + png_write_chunk(png_ptr, png_IDAT, data, length); + png_ptr->mode |= PNG_HAVE_IDAT; +} + +/* Write an IEND chunk */ +void /* PRIVATE */ +png_write_IEND(png_structp png_ptr) +{ + PNG_IEND; + + png_debug(1, "in png_write_IEND"); + + png_write_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); + png_ptr->mode |= PNG_HAVE_IEND; +} + +#ifdef PNG_WRITE_gAMA_SUPPORTED +/* Write a gAMA chunk */ +void /* PRIVATE */ +png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) +{ + PNG_gAMA; + png_byte buf[4]; + + png_debug(1, "in png_write_gAMA"); + + /* file_gamma is saved in 1/100,000ths */ + png_save_uint_32(buf, (png_uint_32)file_gamma); + png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); +} +#endif + +#ifdef PNG_WRITE_sRGB_SUPPORTED +/* Write a sRGB chunk */ +void /* PRIVATE */ +png_write_sRGB(png_structp png_ptr, int srgb_intent) +{ + PNG_sRGB; + png_byte buf[1]; + + png_debug(1, "in png_write_sRGB"); + + if (srgb_intent >= PNG_sRGB_INTENT_LAST) + png_warning(png_ptr, + "Invalid sRGB rendering intent specified"); + + buf[0]=(png_byte)srgb_intent; + png_write_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); +} +#endif + +#ifdef PNG_WRITE_iCCP_SUPPORTED +/* Write an iCCP chunk */ +void /* PRIVATE */ +png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type, + png_const_charp profile, int profile_len) +{ + PNG_iCCP; + png_size_t name_len; + png_charp new_name; + compression_state comp; + int embedded_profile_len = 0; + + png_debug(1, "in png_write_iCCP"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if ((name_len = png_check_keyword(png_ptr, name, &new_name)) == 0) + return; + + if (compression_type != PNG_COMPRESSION_TYPE_BASE) + png_warning(png_ptr, "Unknown compression type in iCCP chunk"); + + if (profile == NULL) + profile_len = 0; + + if (profile_len > 3) + embedded_profile_len = + ((*( (png_const_bytep)profile ))<<24) | + ((*( (png_const_bytep)profile + 1))<<16) | + ((*( (png_const_bytep)profile + 2))<< 8) | + ((*( (png_const_bytep)profile + 3)) ); + + if (embedded_profile_len < 0) + { + png_warning(png_ptr, + "Embedded profile length in iCCP chunk is negative"); + + png_free(png_ptr, new_name); + return; + } + + if (profile_len < embedded_profile_len) + { + png_warning(png_ptr, + "Embedded profile length too large in iCCP chunk"); + + png_free(png_ptr, new_name); + return; + } + + if (profile_len > embedded_profile_len) + { + png_warning(png_ptr, + "Truncating profile to actual length in iCCP chunk"); + + profile_len = embedded_profile_len; + } + + if (profile_len) + profile_len = png_text_compress(png_ptr, profile, + (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp); + + /* Make sure we include the NULL after the name and the compression type */ + png_write_chunk_start(png_ptr, png_iCCP, + (png_uint_32)(name_len + profile_len + 2)); + + new_name[name_len + 1] = 0x00; + + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 2)); + + if (profile_len) + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#ifdef PNG_WRITE_sPLT_SUPPORTED +/* Write a sPLT chunk */ +void /* PRIVATE */ +png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette) +{ + PNG_sPLT; + png_size_t name_len; + png_charp new_name; + png_byte entrybuf[10]; + png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); + png_size_t palette_size = entry_size * spalette->nentries; + png_sPLT_entryp ep; +#ifndef PNG_POINTER_INDEXING_SUPPORTED + int i; +#endif + + png_debug(1, "in png_write_sPLT"); + + if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0) + return; + + /* Make sure we include the NULL after the name */ + png_write_chunk_start(png_ptr, png_sPLT, + (png_uint_32)(name_len + 2 + palette_size)); + + png_write_chunk_data(png_ptr, (png_bytep)new_name, + (png_size_t)(name_len + 1)); + + png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); + + /* Loop through each palette entry, writing appropriately */ +#ifdef PNG_POINTER_INDEXING_SUPPORTED + for (ep = spalette->entries; epentries + spalette->nentries; ep++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep->red; + entrybuf[1] = (png_byte)ep->green; + entrybuf[2] = (png_byte)ep->blue; + entrybuf[3] = (png_byte)ep->alpha; + png_save_uint_16(entrybuf + 4, ep->frequency); + } + + else + { + png_save_uint_16(entrybuf + 0, ep->red); + png_save_uint_16(entrybuf + 2, ep->green); + png_save_uint_16(entrybuf + 4, ep->blue); + png_save_uint_16(entrybuf + 6, ep->alpha); + png_save_uint_16(entrybuf + 8, ep->frequency); + } + + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#else + ep=spalette->entries; + for (i = 0; i>spalette->nentries; i++) + { + if (spalette->depth == 8) + { + entrybuf[0] = (png_byte)ep[i].red; + entrybuf[1] = (png_byte)ep[i].green; + entrybuf[2] = (png_byte)ep[i].blue; + entrybuf[3] = (png_byte)ep[i].alpha; + png_save_uint_16(entrybuf + 4, ep[i].frequency); + } + + else + { + png_save_uint_16(entrybuf + 0, ep[i].red); + png_save_uint_16(entrybuf + 2, ep[i].green); + png_save_uint_16(entrybuf + 4, ep[i].blue); + png_save_uint_16(entrybuf + 6, ep[i].alpha); + png_save_uint_16(entrybuf + 8, ep[i].frequency); + } + + png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); + } +#endif + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_name); +} +#endif + +#ifdef PNG_WRITE_sBIT_SUPPORTED +/* Write the sBIT chunk */ +void /* PRIVATE */ +png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type) +{ + PNG_sBIT; + png_byte buf[4]; + png_size_t size; + + png_debug(1, "in png_write_sBIT"); + + /* Make sure we don't depend upon the order of PNG_COLOR_8 */ + if (color_type & PNG_COLOR_MASK_COLOR) + { + png_byte maxbits; + + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : + png_ptr->usr_bit_depth); + + if (sbit->red == 0 || sbit->red > maxbits || + sbit->green == 0 || sbit->green > maxbits || + sbit->blue == 0 || sbit->blue > maxbits) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[0] = sbit->red; + buf[1] = sbit->green; + buf[2] = sbit->blue; + size = 3; + } + + else + { + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[0] = sbit->gray; + size = 1; + } + + if (color_type & PNG_COLOR_MASK_ALPHA) + { + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) + { + png_warning(png_ptr, "Invalid sBIT depth specified"); + return; + } + + buf[size++] = sbit->alpha; + } + + png_write_chunk(png_ptr, png_sBIT, buf, size); +} +#endif + +#ifdef PNG_WRITE_cHRM_SUPPORTED +/* Write the cHRM chunk */ +void /* PRIVATE */ +png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, + png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, + png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, + png_fixed_point blue_y) +{ + PNG_cHRM; + png_byte buf[32]; + + png_debug(1, "in png_write_cHRM"); + + /* Each value is saved in 1/100,000ths */ +#ifdef PNG_CHECK_cHRM_SUPPORTED + if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y, + green_x, green_y, blue_x, blue_y)) +#endif + { + png_save_uint_32(buf, (png_uint_32)white_x); + png_save_uint_32(buf + 4, (png_uint_32)white_y); + + png_save_uint_32(buf + 8, (png_uint_32)red_x); + png_save_uint_32(buf + 12, (png_uint_32)red_y); + + png_save_uint_32(buf + 16, (png_uint_32)green_x); + png_save_uint_32(buf + 20, (png_uint_32)green_y); + + png_save_uint_32(buf + 24, (png_uint_32)blue_x); + png_save_uint_32(buf + 28, (png_uint_32)blue_y); + + png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32); + } +} +#endif + +#ifdef PNG_WRITE_tRNS_SUPPORTED +/* Write the tRNS chunk */ +void /* PRIVATE */ +png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha, + png_const_color_16p tran, int num_trans, int color_type) +{ + PNG_tRNS; + png_byte buf[6]; + + png_debug(1, "in png_write_tRNS"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid number of transparent colors specified"); + return; + } + + /* Write the chunk out as it is */ + png_write_chunk(png_ptr, png_tRNS, trans_alpha, (png_size_t)num_trans); + } + + else if (color_type == PNG_COLOR_TYPE_GRAY) + { + /* One 16 bit value */ + if (tran->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); + + return; + } + + png_save_uint_16(buf, tran->gray); + png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); + } + + else if (color_type == PNG_COLOR_TYPE_RGB) + { + /* Three 16 bit values */ + png_save_uint_16(buf, tran->red); + png_save_uint_16(buf + 2, tran->green); + png_save_uint_16(buf + 4, tran->blue); +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) +#else + if (buf[0] | buf[2] | buf[4]) +#endif + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); + return; + } + + png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); + } + + else + { + png_warning(png_ptr, "Can't write tRNS with an alpha channel"); + } +} +#endif + +#ifdef PNG_WRITE_bKGD_SUPPORTED +/* Write the background chunk */ +void /* PRIVATE */ +png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type) +{ + PNG_bKGD; + png_byte buf[6]; + + png_debug(1, "in png_write_bKGD"); + + if (color_type == PNG_COLOR_TYPE_PALETTE) + { + if ( +#ifdef PNG_MNG_FEATURES_SUPPORTED + (png_ptr->num_palette || + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && +#endif + back->index >= png_ptr->num_palette) + { + png_warning(png_ptr, "Invalid background palette index"); + return; + } + + buf[0] = back->index; + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); + } + + else if (color_type & PNG_COLOR_MASK_COLOR) + { + png_save_uint_16(buf, back->red); + png_save_uint_16(buf + 2, back->green); + png_save_uint_16(buf + 4, back->blue); +#ifdef PNG_WRITE_16BIT_SUPPORTED + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) +#else + if (buf[0] | buf[2] | buf[4]) +#endif + { + png_warning(png_ptr, + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); + + return; + } + + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); + } + + else + { + if (back->gray >= (1 << png_ptr->bit_depth)) + { + png_warning(png_ptr, + "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); + + return; + } + + png_save_uint_16(buf, back->gray); + png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); + } +} +#endif + +#ifdef PNG_WRITE_hIST_SUPPORTED +/* Write the histogram */ +void /* PRIVATE */ +png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist) +{ + PNG_hIST; + int i; + png_byte buf[3]; + + png_debug(1, "in png_write_hIST"); + + if (num_hist > (int)png_ptr->num_palette) + { + png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, + png_ptr->num_palette); + + png_warning(png_ptr, "Invalid number of histogram entries specified"); + return; + } + + png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); + + for (i = 0; i < num_hist; i++) + { + png_save_uint_16(buf, hist[i]); + png_write_chunk_data(png_ptr, buf, (png_size_t)2); + } + + png_write_chunk_end(png_ptr); +} +#endif + +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, + * and if invalid, correct the keyword rather than discarding the entire + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in + * length, forbids leading or trailing whitespace, multiple internal spaces, + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. + * + * The new_key is allocated to hold the corrected keyword and must be freed + * by the calling routine. This avoids problems with trying to write to + * static keywords without having to have duplicate copies of the strings. + */ +png_size_t /* PRIVATE */ +png_check_keyword(png_structp png_ptr, png_const_charp key, png_charpp new_key) +{ + png_size_t key_len; + png_const_charp ikp; + png_charp kp, dp; + int kflag; + int kwarn=0; + + png_debug(1, "in png_check_keyword"); + + *new_key = NULL; + + if (key == NULL || (key_len = png_strlen(key)) == 0) + { + png_warning(png_ptr, "zero length keyword"); + return ((png_size_t)0); + } + + png_debug1(2, "Keyword to be checked is '%s'", key); + + *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); + + if (*new_key == NULL) + { + png_warning(png_ptr, "Out of memory while procesing keyword"); + return ((png_size_t)0); + } + + /* Replace non-printing characters with a blank and print a warning */ + for (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++) + { + if ((png_byte)*ikp < 0x20 || + ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1)) + { +#ifdef PNG_CONSOLE_IO_SUPPORTED + char msg[40]; + + png_snprintf(msg, 40, + "invalid keyword character 0x%02X", (png_byte)*ikp); + png_warning(png_ptr, msg); +#else + png_warning(png_ptr, "invalid character in keyword"); +#endif + *dp = ' '; + } + + else + { + *dp = *ikp; + } + } + *dp = '\0'; + + /* Remove any trailing white space. */ + kp = *new_key + key_len - 1; + if (*kp == ' ') + { + png_warning(png_ptr, "trailing spaces removed from keyword"); + + while (*kp == ' ') + { + *(kp--) = '\0'; + key_len--; + } + } + + /* Remove any leading white space. */ + kp = *new_key; + if (*kp == ' ') + { + png_warning(png_ptr, "leading spaces removed from keyword"); + + while (*kp == ' ') + { + kp++; + key_len--; + } + } + + png_debug1(2, "Checking for multiple internal spaces in '%s'", kp); + + /* Remove multiple internal spaces. */ + for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) + { + if (*kp == ' ' && kflag == 0) + { + *(dp++) = *kp; + kflag = 1; + } + + else if (*kp == ' ') + { + key_len--; + kwarn = 1; + } + + else + { + *(dp++) = *kp; + kflag = 0; + } + } + *dp = '\0'; + if (kwarn) + png_warning(png_ptr, "extra interior spaces removed from keyword"); + + if (key_len == 0) + { + png_free(png_ptr, *new_key); + png_warning(png_ptr, "Zero length keyword"); + } + + if (key_len > 79) + { + png_warning(png_ptr, "keyword length must be 1 - 79 characters"); + (*new_key)[79] = '\0'; + key_len = 79; + } + + return (key_len); +} +#endif + +#ifdef PNG_WRITE_tEXt_SUPPORTED +/* Write a tEXt chunk */ +void /* PRIVATE */ +png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text, + png_size_t text_len) +{ + PNG_tEXt; + png_size_t key_len; + png_charp new_key; + + png_debug(1, "in png_write_tEXt"); + + if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) + return; + + if (text == NULL || *text == '\0') + text_len = 0; + + else + text_len = png_strlen(text); + + /* Make sure we include the 0 after the key */ + png_write_chunk_start(png_ptr, png_tEXt, + (png_uint_32)(key_len + text_len + 1)); + /* + * We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + + if (text_len) + png_write_chunk_data(png_ptr, (png_const_bytep)text, + (png_size_t)text_len); + + png_write_chunk_end(png_ptr); + png_free(png_ptr, new_key); +} +#endif + +#ifdef PNG_WRITE_zTXt_SUPPORTED +/* Write a compressed text chunk */ +void /* PRIVATE */ +png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text, + png_size_t text_len, int compression) +{ + PNG_zTXt; + png_size_t key_len; + png_byte buf; + png_charp new_key; + compression_state comp; + + png_debug(1, "in png_write_zTXt"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + comp.input_len = 0; + + if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0) + { + png_free(png_ptr, new_key); + return; + } + + if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) + { + png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); + png_free(png_ptr, new_key); + return; + } + + text_len = png_strlen(text); + + /* Compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression, + &comp); + + /* Write start of chunk */ + png_write_chunk_start(png_ptr, png_zTXt, + (png_uint_32)(key_len+text_len + 2)); + + /* Write key */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, + (png_size_t)(key_len + 1)); + + png_free(png_ptr, new_key); + + buf = (png_byte)compression; + + /* Write compression */ + png_write_chunk_data(png_ptr, &buf, (png_size_t)1); + + /* Write the compressed data */ + png_write_compressed_data_out(png_ptr, &comp); + + /* Close the chunk */ + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_iTXt_SUPPORTED +/* Write an iTXt chunk */ +void /* PRIVATE */ +png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key, + png_const_charp lang, png_const_charp lang_key, png_const_charp text) +{ + PNG_iTXt; + png_size_t lang_len, key_len, lang_key_len, text_len; + png_charp new_lang; + png_charp new_key = NULL; + png_byte cbuf[2]; + compression_state comp; + + png_debug(1, "in png_write_iTXt"); + + comp.num_output_ptr = 0; + comp.max_output_ptr = 0; + comp.output_ptr = NULL; + comp.input = NULL; + + if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0) + return; + + if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang)) == 0) + { + png_warning(png_ptr, "Empty language field in iTXt chunk"); + new_lang = NULL; + lang_len = 0; + } + + if (lang_key == NULL) + lang_key_len = 0; + + else + lang_key_len = png_strlen(lang_key); + + if (text == NULL) + text_len = 0; + + else + text_len = png_strlen(text); + + /* Compute the compressed data; do it now for the length */ + text_len = png_text_compress(png_ptr, text, text_len, compression - 2, + &comp); + + + /* Make sure we include the compression flag, the compression byte, + * and the NULs after the key, lang, and lang_key parts + */ + + png_write_chunk_start(png_ptr, png_iTXt, (png_uint_32)( + 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ + + key_len + + lang_len + + lang_key_len + + text_len)); + + /* We leave it to the application to meet PNG-1.0 requirements on the + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. + */ + png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1)); + + /* Set the compression flag */ + if (compression == PNG_ITXT_COMPRESSION_NONE || + compression == PNG_TEXT_COMPRESSION_NONE) + cbuf[0] = 0; + + else /* compression == PNG_ITXT_COMPRESSION_zTXt */ + cbuf[0] = 1; + + /* Set the compression method */ + cbuf[1] = 0; + + png_write_chunk_data(png_ptr, cbuf, (png_size_t)2); + + cbuf[0] = 0; + png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf), + (png_size_t)(lang_len + 1)); + + png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf), + (png_size_t)(lang_key_len + 1)); + + png_write_compressed_data_out(png_ptr, &comp); + + png_write_chunk_end(png_ptr); + + png_free(png_ptr, new_key); + png_free(png_ptr, new_lang); +} +#endif + +#ifdef PNG_WRITE_oFFs_SUPPORTED +/* Write the oFFs chunk */ +void /* PRIVATE */ +png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, + int unit_type) +{ + PNG_oFFs; + png_byte buf[9]; + + png_debug(1, "in png_write_oFFs"); + + if (unit_type >= PNG_OFFSET_LAST) + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); + + png_save_int_32(buf, x_offset); + png_save_int_32(buf + 4, y_offset); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); +} +#endif +#ifdef PNG_WRITE_pCAL_SUPPORTED +/* Write the pCAL chunk (described in the PNG extensions document) */ +void /* PRIVATE */ +png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, + png_int_32 X1, int type, int nparams, png_const_charp units, + png_charpp params) +{ + PNG_pCAL; + png_size_t purpose_len, units_len, total_len; + png_uint_32p params_len; + png_byte buf[10]; + png_charp new_purpose; + int i; + + png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); + + if (type >= PNG_EQUATION_LAST) + png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); + + purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; + png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); + units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); + png_debug1(3, "pCAL units length = %d", (int)units_len); + total_len = purpose_len + units_len + 10; + + params_len = (png_uint_32p)png_malloc(png_ptr, + (png_alloc_size_t)(nparams * png_sizeof(png_uint_32))); + + /* Find the length of each parameter, making sure we don't count the + * null terminator for the last parameter. + */ + for (i = 0; i < nparams; i++) + { + params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); + png_debug2(3, "pCAL parameter %d length = %lu", i, + (unsigned long)params_len[i]); + total_len += (png_size_t)params_len[i]; + } + + png_debug1(3, "pCAL total length = %d", (int)total_len); + png_write_chunk_start(png_ptr, png_pCAL, (png_uint_32)total_len); + png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, + (png_size_t)purpose_len); + png_save_int_32(buf, X0); + png_save_int_32(buf + 4, X1); + buf[8] = (png_byte)type; + buf[9] = (png_byte)nparams; + png_write_chunk_data(png_ptr, buf, (png_size_t)10); + png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); + + png_free(png_ptr, new_purpose); + + for (i = 0; i < nparams; i++) + { + png_write_chunk_data(png_ptr, (png_const_bytep)params[i], + (png_size_t)params_len[i]); + } + + png_free(png_ptr, params_len); + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_sCAL_SUPPORTED +/* Write the sCAL chunk */ +void /* PRIVATE */ +png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width, + png_const_charp height) +{ + PNG_sCAL; + png_byte buf[64]; + png_size_t wlen, hlen, total_len; + + png_debug(1, "in png_write_sCAL_s"); + + wlen = png_strlen(width); + hlen = png_strlen(height); + total_len = wlen + hlen + 2; + + if (total_len > 64) + { + png_warning(png_ptr, "Can't write sCAL (buffer too small)"); + return; + } + + buf[0] = (png_byte)unit; + png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ + png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ + + png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); + png_write_chunk(png_ptr, png_sCAL, buf, total_len); +} +#endif + +#ifdef PNG_WRITE_pHYs_SUPPORTED +/* Write the pHYs chunk */ +void /* PRIVATE */ +png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, + png_uint_32 y_pixels_per_unit, + int unit_type) +{ + PNG_pHYs; + png_byte buf[9]; + + png_debug(1, "in png_write_pHYs"); + + if (unit_type >= PNG_RESOLUTION_LAST) + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); + + png_save_uint_32(buf, x_pixels_per_unit); + png_save_uint_32(buf + 4, y_pixels_per_unit); + buf[8] = (png_byte)unit_type; + + png_write_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); +} +#endif + +#ifdef PNG_WRITE_tIME_SUPPORTED +/* Write the tIME chunk. Use either png_convert_from_struct_tm() + * or png_convert_from_time_t(), or fill in the structure yourself. + */ +void /* PRIVATE */ +png_write_tIME(png_structp png_ptr, png_const_timep mod_time) +{ + PNG_tIME; + png_byte buf[7]; + + png_debug(1, "in png_write_tIME"); + + if (mod_time->month > 12 || mod_time->month < 1 || + mod_time->day > 31 || mod_time->day < 1 || + mod_time->hour > 23 || mod_time->second > 60) + { + png_warning(png_ptr, "Invalid time specified for tIME chunk"); + return; + } + + png_save_uint_16(buf, mod_time->year); + buf[2] = mod_time->month; + buf[3] = mod_time->day; + buf[4] = mod_time->hour; + buf[5] = mod_time->minute; + buf[6] = mod_time->second; + + png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7); +} +#endif + +/* Initializes the row writing capability of libpng */ +void /* PRIVATE */ +png_write_start_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + png_size_t buf_size; + + png_debug(1, "in png_write_start_row"); + + buf_size = (png_size_t)(PNG_ROWBYTES( + png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1); + + /* Set up row buffer */ + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, + (png_alloc_size_t)buf_size); + + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; + +#ifdef PNG_WRITE_FILTER_SUPPORTED + /* Set up filtering buffer, if using this filter */ + if (png_ptr->do_filter & PNG_FILTER_SUB) + { + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1); + + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + /* We only need to keep the previous row if we are using one of these. */ + if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) + { + /* Set up previous row buffer */ + png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, + (png_alloc_size_t)buf_size); + + if (png_ptr->do_filter & PNG_FILTER_UP) + { + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, + png_ptr->rowbytes + 1); + + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + + if (png_ptr->do_filter & PNG_FILTER_AVG) + { + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, + png_ptr->rowbytes + 1); + + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + + if (png_ptr->do_filter & PNG_FILTER_PAETH) + { + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, + png_ptr->rowbytes + 1); + + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, we need to set up width and height of pass */ + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + { + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / png_pass_yinc[0]; + + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - + png_pass_start[0]) / png_pass_inc[0]; + } + + else + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + } + + else +#endif + { + png_ptr->num_rows = png_ptr->height; + png_ptr->usr_width = png_ptr->width; + } + + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + png_ptr->zstream.next_out = png_ptr->zbuf; +} + +/* Internal use only. Called when finished processing a row of data. */ +void /* PRIVATE */ +png_write_finish_row(png_structp png_ptr) +{ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + /* Start of interlace block in the y direction */ + int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; + + /* Offset to next interlace block in the y direction */ + int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; +#endif + + int ret; + + png_debug(1, "in png_write_finish_row"); + + /* Next row */ + png_ptr->row_number++; + + /* See if we are done */ + if (png_ptr->row_number < png_ptr->num_rows) + return; + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* If interlaced, go to next pass */ + if (png_ptr->interlaced) + { + png_ptr->row_number = 0; + if (png_ptr->transformations & PNG_INTERLACE) + { + png_ptr->pass++; + } + + else + { + /* Loop until we find a non-zero width or height pass */ + do + { + png_ptr->pass++; + + if (png_ptr->pass >= 7) + break; + + png_ptr->usr_width = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + + png_ptr->num_rows = (png_ptr->height + + png_pass_yinc[png_ptr->pass] - 1 - + png_pass_ystart[png_ptr->pass]) / + png_pass_yinc[png_ptr->pass]; + + if (png_ptr->transformations & PNG_INTERLACE) + break; + + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); + + } + + /* Reset the row above the image for the next pass */ + if (png_ptr->pass < 7) + { + if (png_ptr->prev_row != NULL) + png_memset(png_ptr->prev_row, 0, + (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* + png_ptr->usr_bit_depth, png_ptr->width)) + 1); + + return; + } + } +#endif + + /* If we get here, we've just written the last row, so we need + to flush the compressor */ + do + { + /* Tell the compressor we are done */ + ret = deflate(&png_ptr->zstream, Z_FINISH); + + /* Check for an error */ + if (ret == Z_OK) + { + /* Check to see if we need more room */ + if (!(png_ptr->zstream.avail_out)) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + } + + else if (ret != Z_STREAM_END) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + } while (ret != Z_STREAM_END); + + /* Write any extra space */ + if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) + { + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - + png_ptr->zstream.avail_out); + } + + deflateReset(&png_ptr->zstream); + png_ptr->zstream.data_type = Z_BINARY; +} + +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Pick out the correct pixels for the interlace pass. + * The basic idea here is to go through the row with a source + * pointer and a destination pointer (sp and dp), and copy the + * correct pixels for the pass. As the row gets compacted, + * sp will always be >= dp, so we should never overwrite anything. + * See the default: case for the easiest code to understand. + */ +void /* PRIVATE */ +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) +{ + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + /* Start of interlace block */ + int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; + + /* Offset to next interlace block */ + int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; + + png_debug(1, "in png_do_write_interlace"); + + /* We don't have to do anything on the last pass (6) */ + if (pass < 6) + { + /* Each pixel depth is handled separately */ + switch (row_info->pixel_depth) + { + case 1: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + d = 0; + shift = 7; + + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 3); + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; + d |= (value << shift); + + if (shift == 0) + { + shift = 7; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift--; + + } + if (shift != 7) + *dp = (png_byte)d; + + break; + } + + case 2: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 6; + d = 0; + + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 2); + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; + d |= (value << shift); + + if (shift == 0) + { + shift = 6; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift -= 2; + } + if (shift != 6) + *dp = (png_byte)d; + + break; + } + + case 4: + { + png_bytep sp; + png_bytep dp; + int shift; + int d; + int value; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + + dp = row; + shift = 4; + d = 0; + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + sp = row + (png_size_t)(i >> 1); + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; + d |= (value << shift); + + if (shift == 0) + { + shift = 4; + *dp++ = (png_byte)d; + d = 0; + } + + else + shift -= 4; + } + if (shift != 4) + *dp = (png_byte)d; + + break; + } + + default: + { + png_bytep sp; + png_bytep dp; + png_uint_32 i; + png_uint_32 row_width = row_info->width; + png_size_t pixel_bytes; + + /* Start at the beginning */ + dp = row; + + /* Find out how many bytes each pixel takes up */ + pixel_bytes = (row_info->pixel_depth >> 3); + + /* Loop through the row, only looking at the pixels that matter */ + for (i = png_pass_start[pass]; i < row_width; + i += png_pass_inc[pass]) + { + /* Find out where the original pixel is */ + sp = row + (png_size_t)i * pixel_bytes; + + /* Move the pixel */ + if (dp != sp) + png_memcpy(dp, sp, pixel_bytes); + + /* Next pixel */ + dp += pixel_bytes; + } + break; + } + } + /* Set new row width */ + row_info->width = (row_info->width + + png_pass_inc[pass] - 1 - + png_pass_start[pass]) / + png_pass_inc[pass]; + + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_info->width); + } +} +#endif + +/* This filters the row, chooses which filter to use, if it has not already + * been specified by the application, and then writes the row out with the + * chosen filter. + */ +#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) +#define PNG_HISHIFT 10 +#define PNG_LOMASK ((png_uint_32)0xffffL) +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) +void /* PRIVATE */ +png_write_find_filter(png_structp png_ptr, png_row_infop row_info) +{ + png_bytep best_row; +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_bytep prev_row, row_buf; + png_uint_32 mins, bpp; + png_byte filter_to_do = png_ptr->do_filter; + png_size_t row_bytes = row_info->rowbytes; +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + int num_p_filters = (int)png_ptr->num_prev_filters; +#endif + + png_debug(1, "in png_write_find_filter"); + +#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) + { + /* These will never be selected so we need not test them. */ + filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); + } +#endif + + /* Find out how many bytes offset each pixel is */ + bpp = (row_info->pixel_depth + 7) >> 3; + + prev_row = png_ptr->prev_row; +#endif + best_row = png_ptr->row_buf; +#ifdef PNG_WRITE_FILTER_SUPPORTED + row_buf = best_row; + mins = PNG_MAXSUM; + + /* The prediction method we use is to find which method provides the + * smallest value when summing the absolute values of the distances + * from zero, using anything >= 128 as negative numbers. This is known + * as the "minimum sum of absolute differences" heuristic. Other + * heuristics are the "weighted minimum sum of absolute differences" + * (experimental and can in theory improve compression), and the "zlib + * predictive" method (not implemented yet), which does test compressions + * of lines using different filter methods, and then chooses the + * (series of) filter(s) that give minimum compressed data size (VERY + * computationally expensive). + * + * GRR 980525: consider also + * + * (1) minimum sum of absolute differences from running average (i.e., + * keep running sum of non-absolute differences & count of bytes) + * [track dispersion, too? restart average if dispersion too large?] + * + * (1b) minimum sum of absolute differences from sliding average, probably + * with window size <= deflate window (usually 32K) + * + * (2) minimum sum of squared differences from zero or running average + * (i.e., ~ root-mean-square approach) + */ + + + /* We don't need to test the 'no filter' case if this is the only filter + * that has been chosen, as it doesn't actually do anything to the data. + */ + if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE) + { + png_bytep rp; + png_uint_32 sum = 0; + png_size_t i; + int v; + + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + v = *rp; + sum += (v < 128) ? v : 256 - v; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + png_uint_32 sumhi, sumlo; + int j; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ + + /* Reduce the sum if we match any of the previous rows */ + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + /* Factor in the cost of this filter (this is here for completeness, + * but it makes no sense to have a "cost" for the NONE filter, as + * it has the minimum possible computational cost - none). + */ + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + mins = sum; + } + + /* Sub filter */ + if (filter_to_do == PNG_FILTER_SUB) + /* It's the only filter so no testing is needed */ + { + png_bytep rp, lp, dp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + *dp = *rp; + } + + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + } + + best_row = png_ptr->sub_row; + } + + else if (filter_to_do & PNG_FILTER_SUB) + { + png_bytep rp, dp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* We temporarily increase the "minimum sum" by the factor we + * would reduce the sum of this filter, so that we can do the + * early exit comparison without scaling the sum each time. + */ + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) + { + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->sub_row; + } + } + + /* Up filter */ + if (filter_to_do == PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + } + + best_row = png_ptr->up_row; + } + + else if (filter_to_do & PNG_FILTER_UP) + { + png_bytep rp, dp, pp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, + pp = prev_row + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->up_row; + } + } + + /* Avg filter */ + if (filter_to_do == PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + } + + for (lp = row_buf + 1; i < row_bytes; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + } + best_row = png_ptr->avg_row; + } + + else if (filter_to_do & PNG_FILTER_AVG) + { + png_bytep rp, dp, pp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + mins = sum; + best_row = png_ptr->avg_row; + } + } + + /* Paeth filter */ + if (filter_to_do == PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_size_t i; + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + } + best_row = png_ptr->paeth_row; + } + + else if (filter_to_do & PNG_FILTER_PAETH) + { + png_bytep rp, dp, pp, cp, lp; + png_uint_32 sum = 0, lmins = mins; + png_size_t i; + int v; + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 lmhi, lmlo; + lmlo = lmins & PNG_LOMASK; + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (lmhi > PNG_HIMASK) + lmins = PNG_MAXSUM; + + else + lmins = (lmhi << PNG_HISHIFT) + lmlo; + } +#endif + + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, + pp = prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + +#ifndef PNG_SLOW_PAETH + p = b - c; + pc = a - c; +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; +#else /* PNG_SLOW_PAETH */ + p = a + b - c; + pa = abs(p - a); + pb = abs(p - b); + pc = abs(p - c); + + if (pa <= pb && pa <= pc) + p = a; + + else if (pb <= pc) + p = b; + + else + p = c; +#endif /* PNG_SLOW_PAETH */ + + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + { + int j; + png_uint_32 sumhi, sumlo; + sumlo = sum & PNG_LOMASK; + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; + + for (j = 0; j < num_p_filters; j++) + { + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) + { + sumlo = (sumlo * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + + sumhi = (sumhi * png_ptr->filter_weights[j]) >> + PNG_WEIGHT_SHIFT; + } + } + + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> + PNG_COST_SHIFT; + + if (sumhi > PNG_HIMASK) + sum = PNG_MAXSUM; + + else + sum = (sumhi << PNG_HISHIFT) + sumlo; + } +#endif + + if (sum < mins) + { + best_row = png_ptr->paeth_row; + } + } +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + /* Do the actual writing of the filtered row data from the chosen filter. */ + + png_write_filtered_row(png_ptr, best_row); + +#ifdef PNG_WRITE_FILTER_SUPPORTED +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED + /* Save the type of filter we picked this time for future calculations */ + if (png_ptr->num_prev_filters > 0) + { + int j; + + for (j = 1; j < num_p_filters; j++) + { + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; + } + + png_ptr->prev_filters[j] = best_row[0]; + } +#endif +#endif /* PNG_WRITE_FILTER_SUPPORTED */ +} + + +/* Do the actual writing of a previously filtered row. */ +void /* PRIVATE */ +png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) +{ + png_size_t avail; + + png_debug(1, "in png_write_filtered_row"); + + png_debug1(2, "filter = %d", filtered_row[0]); + /* Set up the zlib input buffer */ + + png_ptr->zstream.next_in = filtered_row; + png_ptr->zstream.avail_in = 0; + avail = png_ptr->row_info.rowbytes + 1; + /* Repeat until we have compressed all the data */ + do + { + int ret; /* Return of zlib */ + + /* Record the number of bytes available - zlib supports at least 65535 + * bytes at one step, depending on the size of the zlib type 'uInt', the + * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h). + * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e. + * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a + * uInt. ZLIB_IO_MAX can be safely reduced to cause zlib to be called + * with smaller chunks of data. + */ + if (png_ptr->zstream.avail_in == 0) + { + if (avail > ZLIB_IO_MAX) + { + png_ptr->zstream.avail_in = ZLIB_IO_MAX; + avail -= ZLIB_IO_MAX; + } + + else + { + /* So this will fit in the available uInt space: */ + png_ptr->zstream.avail_in = (uInt)avail; + avail = 0; + } + } + + /* Compress the data */ + ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); + + /* Check for compression errors */ + if (ret != Z_OK) + { + if (png_ptr->zstream.msg != NULL) + png_error(png_ptr, png_ptr->zstream.msg); + + else + png_error(png_ptr, "zlib error"); + } + + /* See if it is time to write another IDAT */ + if (!(png_ptr->zstream.avail_out)) + { + /* Write the IDAT and reset the zlib output buffer */ + png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + } + /* Repeat until all data has been compressed */ + } while (avail > 0 || png_ptr->zstream.avail_in > 0); + + /* Swap the current and previous rows */ + if (png_ptr->prev_row != NULL) + { + png_bytep tptr; + + tptr = png_ptr->prev_row; + png_ptr->prev_row = png_ptr->row_buf; + png_ptr->row_buf = tptr; + } + + /* Finish row - updates counters and flushes zlib if last row */ + png_write_finish_row(png_ptr); + +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_ptr->flush_rows++; + + if (png_ptr->flush_dist > 0 && + png_ptr->flush_rows >= png_ptr->flush_dist) + { + png_write_flush(png_ptr); + } +#endif +} +#endif /* PNG_WRITE_SUPPORTED */ diff --git a/contrib/libpng/projects/visualc71/PRJ0041.mak b/contrib/libpng/projects/visualc71/PRJ0041.mak new file mode 100644 index 0000000..e15e12b --- /dev/null +++ b/contrib/libpng/projects/visualc71/PRJ0041.mak @@ -0,0 +1,21 @@ +# Prevent "Cannot find missing dependency..." warnings while compiling +# pngwin.rc (PRJ0041). + +all: $(IntDir)\alloc.h \ + $(IntDir)\fp.h \ + $(IntDir)\m68881.h \ + $(IntDir)\mem.h \ + $(IntDir)\pngusr.h \ + $(IntDir)\strings.h \ + $(IntDir)\unistd.h \ + $(IntDir)\unixio.h + +$(IntDir)\alloc.h \ +$(IntDir)\fp.h \ +$(IntDir)\m68881.h \ +$(IntDir)\mem.h \ +$(IntDir)\pngusr.h \ +$(IntDir)\strings.h \ +$(IntDir)\unistd.h \ +$(IntDir)\unixio.h: + @!echo.>$@ diff --git a/contrib/libpng/projects/visualc71/README.txt b/contrib/libpng/projects/visualc71/README.txt new file mode 100644 index 0000000..625eefc --- /dev/null +++ b/contrib/libpng/projects/visualc71/README.txt @@ -0,0 +1,58 @@ +Microsoft Developer Studio Project File, Format Version 7.10 for libpng. + +Copyright (C) 2004 Simon-Pierre Cadieux. + +This code is released under the libpng license. +For conditions of distribution and use, see copyright notice in png.h + +NOTE: This project will be removed from libpng-1.5.0. It has +been replaced with the "vstudio" project. + +Assumptions: +* The libpng source files are in ..\.. +* The zlib source files are in ..\..\..\zlib +* The zlib project file is in . /* Warning: This is until the zlib project + files get intergrated into the next zlib release. The final zlib project + directory will then be ..\..\..\zlib\projects\visualc71. */ + +To use: + +1) On the main menu, select "File | Open Solution". + Open "libpng.sln". + +2) Display the Solution Explorer view (Ctrl+Alt+L) + +3) Set one of the project as the StartUp project. If you just want to build the + binaries set "libpng" as the startup project (Select "libpng" tree view + item + Project | Set as StartUp project). If you want to build and test the + binaries set it to "pngtest" (Select "pngtest" tree view item + + Project | Set as StartUp project) + +4) Select "Build | Configuration Manager...". + Choose the configuration you wish to build. + +5) Select "Build | Clean Solution". + +6) Select "Build | Build Solution (Ctrl-Shift-B)" + +This project builds the libpng binaries as follows: + +* Win32_DLL_Release\libpng15.dll DLL build +* Win32_DLL_Debug\libpng15d.dll DLL build (debug version) +* Win32_DLL_VB\libpng15vb.dll DLL build for Visual Basic, using stdcall +* Win32_LIB_Release\libpng.lib static build +* Win32_LIB_Debug\libpngd.lib static build (debug version) + +Notes: + +If you change anything in the source files, or select different compiler +settings, please change the DLL name to something different than any of +the above names. Also, make sure that in your "pngusr.h" you define +PNG_USER_PRIVATEBUILD and PNG_USER_DLLFNAME_POSTFIX according to the +instructions provided in "pngconf.h". + +All DLLs built by this project use the Microsoft dynamic C runtime library +MSVCR71.DLL (MSVCR71D.DLL for debug versions). If you distribute any of the +above mentioned libraries you may have to include this DLL in your package. +For a list of files that are redistributable in Visual Studio see +$(VCINSTALLDIR)\redist.txt. diff --git a/contrib/libpng/projects/visualc71/README_zlib.txt b/contrib/libpng/projects/visualc71/README_zlib.txt new file mode 100644 index 0000000..81d11cb --- /dev/null +++ b/contrib/libpng/projects/visualc71/README_zlib.txt @@ -0,0 +1,44 @@ +/* WARNING: This file was put in the LibPNG distribution for convenience only. + It is expected to be part of the next zlib release under + "projects\visualc71\README.txt." */ + +Microsoft Developer Studio Project File, Format Version 7.10 for zlib. + +Copyright (C) 2004 Simon-Pierre Cadieux. +Copyright (C) 2004 Cosmin Truta. + +This code is released under the libpng license. +For conditions of distribution and use, see copyright notice in zlib.h. + +NOTE: This project will be removed from libpng-1.5.0. It has +been replaced with the "vstudio" project. + +To use: + +1) On the main menu, select "File | Open Solution". + Open "zlib.sln". + +2) Display the Solution Explorer view (Ctrl+Alt+L) + +3) Set one of the project as the StartUp project. If you just want to build the + binaries set "zlib" as the startup project (Select "zlib" tree view item + + Project | Set as StartUp project). If you want to build and test the + binaries set it to "example" (Select "example" tree view item + Project | + Set as StartUp project), If you want to build the minigzip utility set it to + "minigzip" (Select "minigzip" tree view item + Project | Set as StartUp + project + +4) Select "Build | Configuration Manager...". + Choose the configuration you wish to build. + +5) Select "Build | Clean Solution". + +6) Select "Build | Build Solution (Ctrl-Shift-B)" + +This project builds the zlib binaries as follows: + +* Win32_DLL_Release\zlib1.dll DLL build +* Win32_DLL_Debug\zlib1d.dll DLL build (debug version) +* Win32_LIB_Release\zlib.lib static build +* Win32_LIB_Debug\zlibd.lib static build (debug version) + diff --git a/contrib/libpng/projects/visualc71/libpng.sln b/contrib/libpng/projects/visualc71/libpng.sln new file mode 100644 index 0000000..eeb101f --- /dev/null +++ b/contrib/libpng/projects/visualc71/libpng.sln @@ -0,0 +1,60 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng", "libpng.vcproj", "{0008960E-E0DD-41A6-8265-00B31DDB4C21}" + ProjectSection(ProjectDependencies) = postProject + {2D4F8105-7D21-454C-9932-B47CAB71A5C0} = {2D4F8105-7D21-454C-9932-B47CAB71A5C0} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pngtest", "pngtest.vcproj", "{FD1C2F86-9EEF-47BD-95A4-530917E17FDA}" + ProjectSection(ProjectDependencies) = postProject + {0008960E-E0DD-41A6-8265-00B31DDB4C21} = {0008960E-E0DD-41A6-8265-00B31DDB4C21} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib.vcproj", "{2D4F8105-7D21-454C-9932-B47CAB71A5C0}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + DLL Debug = DLL Debug + DLL Release = DLL Release + DLL VB = DLL VB + LIB Debug = LIB Debug + LIB Release = LIB Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.DLL Debug.ActiveCfg = DLL Debug|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.DLL Debug.Build.0 = DLL Debug|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.DLL Release.ActiveCfg = DLL Release|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.DLL Release.Build.0 = DLL Release|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.DLL VB.ActiveCfg = DLL VB|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.DLL VB.Build.0 = DLL VB|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.LIB Debug.ActiveCfg = LIB Debug|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.LIB Debug.Build.0 = LIB Debug|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.LIB Release.ActiveCfg = LIB Release|Win32 + {0008960E-E0DD-41A6-8265-00B31DDB4C21}.LIB Release.Build.0 = LIB Release|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.DLL Debug.ActiveCfg = DLL Debug|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.DLL Debug.Build.0 = DLL Debug|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.DLL Release.ActiveCfg = DLL Release|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.DLL Release.Build.0 = DLL Release|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.DLL VB.ActiveCfg = DLL VB|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.DLL VB.Build.0 = DLL VB|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.LIB Debug.ActiveCfg = LIB Debug|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.LIB Debug.Build.0 = LIB Debug|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.LIB Release.ActiveCfg = LIB Release|Win32 + {FD1C2F86-9EEF-47BD-95A4-530917E17FDA}.LIB Release.Build.0 = LIB Release|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.DLL Debug.ActiveCfg = DLL Debug|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.DLL Debug.Build.0 = DLL Debug|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.DLL Release.ActiveCfg = DLL Release|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.DLL Release.Build.0 = DLL Release|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.DLL VB.ActiveCfg = DLL Release|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.DLL VB.Build.0 = DLL Release|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.LIB Debug.ActiveCfg = LIB Debug|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.LIB Debug.Build.0 = LIB Debug|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.LIB Release.ActiveCfg = LIB Release|Win32 + {2D4F8105-7D21-454C-9932-B47CAB71A5C0}.LIB Release.Build.0 = LIB Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/contrib/libpng/projects/visualc71/libpng.vcproj b/contrib/libpng/projects/visualc71/libpng.vcproj new file mode 100644 index 0000000..4c5acf9 --- /dev/null +++ b/contrib/libpng/projects/visualc71/libpng.vcproj @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/libpng/projects/visualc71/pngtest.vcproj b/contrib/libpng/projects/visualc71/pngtest.vcproj new file mode 100644 index 0000000..ff330ae --- /dev/null +++ b/contrib/libpng/projects/visualc71/pngtest.vcproj @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/libpng/projects/visualc71/zlib.vcproj b/contrib/libpng/projects/visualc71/zlib.vcproj new file mode 100644 index 0000000..eb21848 --- /dev/null +++ b/contrib/libpng/projects/visualc71/zlib.vcproj @@ -0,0 +1,391 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/libpng/projects/vstudio/libpng/libpng.vcxproj b/contrib/libpng/projects/vstudio/libpng/libpng.vcxproj new file mode 100644 index 0000000..6977900 --- /dev/null +++ b/contrib/libpng/projects/vstudio/libpng/libpng.vcxproj @@ -0,0 +1,233 @@ + + + + + Debug Library + Win32 + + + Debug + Win32 + + + Release Library + Win32 + + + Release + Win32 + + + + {D6973076-9317-4EF2-A0B8-B7A18AC0713E} + Win32Proj + libpng + + + + + DynamicLibrary + MultiByte + true + + + StaticLibrary + MultiByte + + + DynamicLibrary + true + MultiByte + + + StaticLibrary + MultiByte + + + + + + + + + + + + + + + + + + + false + + + $(ProjectName)15 + + + false + + $(ProjectName)15 + + + false + + + $(ProjectName)15 + + + false + + $(ProjectName)15 + + + + Use + Level4 + false + ProgramDatabase + EnableFastChecks + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + true + false + false + pngpriv.h + true + CompileAsC + true + 4996;4127 + $(ZLibSrcDir);%(AdditionalIncludeDirectories) + true + Disabled + + + Windows + true + zlib.lib + 15 + $(OutDir) + + + + + Use + Level4 + false + ProgramDatabase + Disabled + EnableFastChecks + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + true + false + false + pngpriv.h + true + CompileAsC + true + 4996;4127 + $(ZLibSrcDir);%(AdditionalIncludeDirectories) + true + MultiThreadedDebug + + + Windows + true + + + + + Level4 + Use + ProgramDatabase + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + false + false + pngpriv.h + true + CompileAsC + true + false + 4996;4127 + $(ZLibSrcDir);%(AdditionalIncludeDirectories) + true + Full + + + Windows + true + true + true + zlib.lib + 15 + $(OutDir) + + + + + Level4 + Use + ProgramDatabase + MultiThreaded + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + false + false + pngpriv.h + true + CompileAsC + true + false + 4996;4127 + $(ZLibSrcDir);%(AdditionalIncludeDirectories) + true + Full + true + + + Windows + true + true + true + + + true + + + + + Create + Create + Create + Create + + + + + + + + + + + + + + + + + + + true + true + + + + + + diff --git a/contrib/libpng/projects/vstudio/pnglibconf/pnglibconf.vcxproj b/contrib/libpng/projects/vstudio/pnglibconf/pnglibconf.vcxproj new file mode 100644 index 0000000..7c691c3 --- /dev/null +++ b/contrib/libpng/projects/vstudio/pnglibconf/pnglibconf.vcxproj @@ -0,0 +1,60 @@ + + + + + Release + Win32 + + + + {EB33566E-DA7F-4D28-9077-88C0B7C77E35} + pnglibconf + + + + Application + false + true + MultiByte + + + + + + + + + + Build + + + + Level3 + MaxSpeed + true + true + + + true + true + true + + + copy ..\..\..\scripts\pnglibconf.h.prebuilt ..\..\..\pnglibconf.h + + + Generating pnglibconf.h + + + ..\..\..\pnglibconf.h + + + ..\..\..\scripts\pnglibconf.h.prebuilt + + + + + + + + diff --git a/contrib/libpng/projects/vstudio/pngtest/pngtest.vcxproj b/contrib/libpng/projects/vstudio/pngtest/pngtest.vcxproj new file mode 100644 index 0000000..a03dca5 --- /dev/null +++ b/contrib/libpng/projects/vstudio/pngtest/pngtest.vcxproj @@ -0,0 +1,219 @@ + + + + + Debug Library + Win32 + + + Debug + Win32 + + + Release Library + Win32 + + + Release + Win32 + + + + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D} + Win32Proj + pngtest + + + + + Application + Unicode + + + Application + Unicode + + + Application + Unicode + + + Application + Unicode + + + + + + + + + + + + + + + + + + + false + + + + false + + + + false + + + + false + + + + + NotUsing + Level4 + false + ProgramDatabase + Disabled + EnableFastChecks + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996 + false + true + true + true + false + true + false + + + Console + true + libpng15.lib + $(OutDir) + + + Executing PNG test program + "$(OutDir)pngtest.exe" ..\..\..\pngtest.png "$(IntDir)pngout.png" + $(IntDir)pngout.png + ..\..\..\pngtest.png;$(OutDir)pngtest.exe + + + + + NotUsing + Level4 + false + ProgramDatabase + Disabled + EnableFastChecks + MultiThreadedDebug + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996 + false + true + true + true + false + true + false + + + Console + true + libpng15.lib;zlib.lib + $(OutDir) + + + Executing PNG test program + "$(OutDir)pngtest.exe" ..\..\..\pngtest.png "$(IntDir)pngout.png" + $(IntDir)pngout.png + ..\..\..\pngtest.png;$(OutDir)pngtest.exe + + + + + Level4 + NotUsing + ProgramDatabase + Full + false + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996 + false + true + true + false + true + true + false + + + Console + true + true + true + UseLinkTimeCodeGeneration + libpng15.lib + $(OutDir) + + + Executing PNG test program + "$(OutDir)pngtest.exe" ..\..\..\pngtest.png "$(IntDir)pngout.png" + $(IntDir)pngout.png + ..\..\..\pngtest.png;$(OutDir)pngtest.exe + + + + + Level4 + NotUsing + ProgramDatabase + Full + MultiThreaded + false + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996 + false + true + true + false + true + true + false + + + Console + true + true + true + libpng15.lib;zlib.lib + UseLinkTimeCodeGeneration + $(OutDir) + + + Executing PNG test program + $(OutDir)pngtest.exe ..\..\..\pngtest.png $(IntDir)pngout.png + "$(OutDir)pngtest.exe" ..\..\..\pngtest.png "$(IntDir)pngout.png" + $(IntDir)pngout.png + ..\..\..\pngtest.png;$(OutDir)pngtest.exe + + + + + + + + + diff --git a/contrib/libpng/projects/vstudio/pngvalid/pngvalid.vcxproj b/contrib/libpng/projects/vstudio/pngvalid/pngvalid.vcxproj new file mode 100644 index 0000000..79fd1bd --- /dev/null +++ b/contrib/libpng/projects/vstudio/pngvalid/pngvalid.vcxproj @@ -0,0 +1,219 @@ + + + + + Debug Library + Win32 + + + Debug + Win32 + + + Release Library + Win32 + + + Release + Win32 + + + + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8} + Win32Proj + pngvalid + + + + + Application + Unicode + + + Application + Unicode + + + Application + Unicode + + + Application + Unicode + + + + + + + + + + + + + + + + + + + false + + + + false + + + + false + + + + false + + + + + NotUsing + Level4 + false + ProgramDatabase + Disabled + EnableFastChecks + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996;4127 + false + true + true + true + false + true + false + + + Console + true + libpng15.lib;zlib.lib + $(OutDir) + + + Executing PNG validation program + "$(OutDir)pngvalid.exe" --touch "$(IntDir)pngvalid.out" + $(IntDir)pngvalid.out + $(OutDir)pngvalid.exe + + + + + NotUsing + Level4 + false + ProgramDatabase + Disabled + EnableFastChecks + MultiThreadedDebug + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996;4127 + false + true + true + true + false + true + false + + + Console + true + libpng15.lib;zlib.lib + $(OutDir) + + + Executing PNG validation program + "$(OutDir)pngvalid.exe" --touch "$(IntDir)pngvalid.out" + $(IntDir)pngvalid.out + $(OutDir)pngvalid.exe + + + + + Level4 + NotUsing + ProgramDatabase + Full + false + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996;4127 + false + true + true + false + true + true + false + + + Console + true + true + true + libpng15.lib;zlib.lib + $(OutDir) + UseLinkTimeCodeGeneration + + + Executing PNG validation program + "$(OutDir)pngvalid.exe" --touch "$(IntDir)pngvalid.out" + $(IntDir)pngvalid.out + $(OutDir)pngvalid.exe + + + + + Level4 + NotUsing + ProgramDatabase + Full + MultiThreaded + false + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996;4127 + false + true + true + false + true + true + false + + + Console + true + true + true + libpng15.lib;zlib.lib + $(OutDir) + UseLinkTimeCodeGeneration + + + Executing PNG validation program + $(OutDir)pngvalid.exe ..\..\..\pngvalid.png $(IntDir)pngout.png + "$(OutDir)pngvalid.exe" --touch "$(IntDir)pngvalid.out" + $(IntDir)pngvalid.out + $(OutDir)pngvalid.exe + + + + + + + + + diff --git a/contrib/libpng/projects/vstudio/readme.txt b/contrib/libpng/projects/vstudio/readme.txt new file mode 100644 index 0000000..8f3daef --- /dev/null +++ b/contrib/libpng/projects/vstudio/readme.txt @@ -0,0 +1,64 @@ + +VisualStudio instructions + +libpng version 1.5.1 - February 3, 2011 + +Copyright (c) 1998-2010 Glenn Randers-Pehrson + +This code is released under the libpng license. +For conditions of distribution and use, see the disclaimer +and license in png.h + +This directory contains support for building libpng under MicroSoft +VisualStudio 2010. It may also work under later versions of VisualStudio. +You should be familiar with VisualStudio before using this directory. + +Initial preparations +==================== +You must enter some information in zlib.props before attempting to build +with this 'solution'. Please read and edit zlib.props first. You will +probably not be familiar with the contents of zlib.props - do not worry, +it is mostly harmless. + +This is all you need to do to build the 'release' and 'release library' +configurations. + +Debugging +========= +The release configurations default to /Ox optimization. Full debugging +information is produced (in the .pdb), but if you encounter a problem the +optimization may make it difficult to debug. Simply rebuild with a lower +optimization level (e.g. /Od.) + +Linking your application +======================== +Normally you should link against the 'release' configuration. This builds a +DLL for libpng 1.5 with the default runtime options used by Visual Studio +2010. In particular the runtime library is the "MultiThreaded DLL" version. +If you use Visual Studio defaults to build your application you will have no +problems. + +If you don't use the Visual Studio defaults your application must still be built +with the default runtime option (/MD). If, for some reason, it is not then your +application will crash inside libpng15.dll as soon as libpng tries to read +from a file handle you pass in. + +If you do not want to use the DLL, for example for a very small application, +the 'release library' configuration may be more appropriate. This is built +with a non-standard runtime library - the "MultiThreaded" version. When you +build your application it must be compiled with this option (/MT), otherwise +it will not build (if you are lucky) or crash (if you are not.) + +Stop reading here +================= +You have enough information to build a working application. + +Debug versions have limited support +=================================== +This solution includes limited support for debug versions of libpng. You +do not need these unless your own solution itself uses debug builds (it is +far more effective to debug on the release builds, there is no point building +a special debug build.) + +The debug build of libpng is minimally supported. Support for debug builds of +zlib is also minimal. You really don't want to do this. diff --git a/contrib/libpng/projects/vstudio/vstudio.sln b/contrib/libpng/projects/vstudio/vstudio.sln new file mode 100644 index 0000000..fad771b --- /dev/null +++ b/contrib/libpng/projects/vstudio/vstudio.sln @@ -0,0 +1,79 @@ +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng", "libpng\libpng.vcxproj", "{D6973076-9317-4EF2-A0B8-B7A18AC0713E}" + ProjectSection(ProjectDependencies) = postProject + {64CE4900-97EA-2DD5-4226-F2E36FFF2867} = {64CE4900-97EA-2DD5-4226-F2E36FFF2867} + {EB33566E-DA7F-4D28-9077-88C0B7C77E35} = {EB33566E-DA7F-4D28-9077-88C0B7C77E35} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pngtest", "pngtest\pngtest.vcxproj", "{228BA965-50D5-42B2-8BCF-AFCC227E3C1D}" + ProjectSection(ProjectDependencies) = postProject + {64CE4900-97EA-2DD5-4226-F2E36FFF2867} = {64CE4900-97EA-2DD5-4226-F2E36FFF2867} + {EB33566E-DA7F-4D28-9077-88C0B7C77E35} = {EB33566E-DA7F-4D28-9077-88C0B7C77E35} + {D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {D6973076-9317-4EF2-A0B8-B7A18AC0713E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib\zlib.vcxproj", "{64CE4900-97EA-2DD5-4226-F2E36FFF2867}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pngvalid", "pngvalid\pngvalid.vcxproj", "{9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}" + ProjectSection(ProjectDependencies) = postProject + {64CE4900-97EA-2DD5-4226-F2E36FFF2867} = {64CE4900-97EA-2DD5-4226-F2E36FFF2867} + {EB33566E-DA7F-4D28-9077-88C0B7C77E35} = {EB33566E-DA7F-4D28-9077-88C0B7C77E35} + {D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {D6973076-9317-4EF2-A0B8-B7A18AC0713E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pnglibconf", "pnglibconf\pnglibconf.vcxproj", "{EB33566E-DA7F-4D28-9077-88C0B7C77E35}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug Library|Win32 = Debug Library|Win32 + Debug|Win32 = Debug|Win32 + Release Library|Win32 = Release Library|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug Library|Win32.ActiveCfg = Debug Library|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug Library|Win32.Build.0 = Debug Library|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug|Win32.ActiveCfg = Debug|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug|Win32.Build.0 = Debug|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release Library|Win32.ActiveCfg = Release Library|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release Library|Win32.Build.0 = Release Library|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release|Win32.ActiveCfg = Release|Win32 + {D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release|Win32.Build.0 = Release|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Debug Library|Win32.ActiveCfg = Debug Library|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Debug Library|Win32.Build.0 = Debug Library|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Debug|Win32.ActiveCfg = Debug|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Debug|Win32.Build.0 = Debug|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Release Library|Win32.ActiveCfg = Release Library|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Release Library|Win32.Build.0 = Release Library|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Release|Win32.ActiveCfg = Release|Win32 + {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Release|Win32.Build.0 = Release|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Debug Library|Win32.ActiveCfg = Debug Library|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Debug Library|Win32.Build.0 = Debug Library|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Debug|Win32.ActiveCfg = Debug|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Debug|Win32.Build.0 = Debug|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Release Library|Win32.ActiveCfg = Release Library|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Release Library|Win32.Build.0 = Release Library|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Release|Win32.ActiveCfg = Release|Win32 + {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Release|Win32.Build.0 = Release|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Debug Library|Win32.ActiveCfg = Debug Library|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Debug Library|Win32.Build.0 = Debug Library|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Debug|Win32.ActiveCfg = Debug|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Debug|Win32.Build.0 = Debug|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Release Library|Win32.ActiveCfg = Release Library|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Release Library|Win32.Build.0 = Release Library|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Release|Win32.ActiveCfg = Release|Win32 + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Release|Win32.Build.0 = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Debug Library|Win32.ActiveCfg = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Debug Library|Win32.Build.0 = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Debug|Win32.ActiveCfg = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Debug|Win32.Build.0 = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release Library|Win32.ActiveCfg = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release Library|Win32.Build.0 = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release|Win32.ActiveCfg = Release|Win32 + {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/contrib/libpng/projects/vstudio/zlib.props b/contrib/libpng/projects/vstudio/zlib.props new file mode 100644 index 0000000..44cf64e --- /dev/null +++ b/contrib/libpng/projects/vstudio/zlib.props @@ -0,0 +1,30 @@ + + + + + + + ..\..\..\..\zlib-1.2.4 + + diff --git a/contrib/libpng/projects/vstudio/zlib/zlib.vcxproj b/contrib/libpng/projects/vstudio/zlib/zlib.vcxproj new file mode 100644 index 0000000..aa125de --- /dev/null +++ b/contrib/libpng/projects/vstudio/zlib/zlib.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug Library + Win32 + + + Debug + Win32 + + + Release Library + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + Win32Proj + + + + + StaticLibrary + + + StaticLibrary + + + StaticLibrary + + + StaticLibrary + + + StaticLibrary + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + true + + + true + + + + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + MultiThreadedDebug + TurnOffAllWarnings + ProgramDatabase + Disabled + true + + + MachineX86 + true + Windows + + + + + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + TurnOffAllWarnings + ProgramDatabase + Disabled + true + + + MachineX86 + true + Windows + + + + + Level3 + ProgramDatabase + Full + true + true + false + true + true + true + MultiThreaded + + + MachineX86 + true + Windows + + + true + + + + + Level3 + ProgramDatabase + Full + true + true + false + true + true + true + + + MachineX86 + true + Windows + + + true + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;DEBUGZLIB_EXPORTS;%(PreprocessorDefinitions) + Level3 + ProgramDatabase + + + MachineX86 + true + Windows + true + true + + + + + + diff --git a/contrib/libpng/scripts/README.txt b/contrib/libpng/scripts/README.txt new file mode 100644 index 0000000..a427f8e --- /dev/null +++ b/contrib/libpng/scripts/README.txt @@ -0,0 +1,77 @@ + +Makefiles for libpng version 1.5.1 - February 3, 2011 + +pnglibconf.h.prebuilt => Stores configuration settings + makefile.linux => Linux/ELF makefile + (gcc, creates libpng15.so.15.1.5.1) + makefile.gcc => Generic makefile (gcc, creates static libpng.a) + makefile.knr => Archaic UNIX Makefile that converts files with + ansi2knr (Requires ansi2knr.c from + ftp://ftp.cs.wisc.edu/ghost) + makefile.acorn => Acorn makefile + makefile.aix => AIX/gcc makefile + makefile.amiga => Amiga makefile + makefile.atari => Atari makefile + makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode) + makefile.beos => beos makefile + makefile.bor => Borland makefile (uses bcc) + makefile.cegcc => minge32ce for Windows CE makefile + makefile.darwin => Darwin makefile, can use on MacosX + makefile.dec => DEC Alpha UNIX makefile + makefile.dj2 => DJGPP 2 makefile + makefile.elf => Linux/ELF makefile symbol versioning, + (gcc, creates libpng15.so.15.1.5.1) + makefile.freebsd => FreeBSD makefile + makefile.gcc => Generic gcc makefile + makefile.hpgcc => HPUX makefile using gcc + makefile.hpux => HPUX (10.20 and 11.00) makefile + makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64-bit + makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2 (static) + makefile.intel => Intel C/C++ version 4.0 and later + makefile.mips => MIPS makefile + makefile.msc => Microsoft C makefile + makefile.netbsd => NetBSD/cc makefile, makes libpng.so. + makefile.openbsd => OpenBSD makefile + makefile.os2 => OS/2 Makefile (gcc and emx, requires libpng.def) + makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc + makefile.sggcc => Silicon Graphics (gcc, + creates libpng15.so.15.1.5.1) + makefile.sgi => Silicon Graphics IRIX makefile (cc, creates static lib) + makefile.solaris => Solaris 2.X makefile (gcc, + creates libpng15.so.15.1.5.1) + makefile.so9 => Solaris 9 makefile (gcc, + creates libpng15.so.15.1.5.1) + makefile.std => Generic UNIX makefile (cc, creates static libpng.a) + makefile.sunos => Sun makefile + makefile.32sunu => Sun Ultra 32-bit makefile + makefile.64sunu => Sun Ultra 64-bit makefile + makefile.tc3 => Turbo C 3.0 makefile + makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and later + makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model + makevms.com => VMS build script + smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC compiler + (Requires SCOPTIONS, copied from scripts/SCOPTIONS.ppc) + +Other supporting scripts: + README.txt => This file + descrip.mms => VMS makefile for MMS or MMK + libpng-config-body.in => used by several makefiles to create libpng-config + libpng-config-head.in => used by several makefiles to create libpng-config + libpng.pc.in => Used by several makefiles to create libpng.pc + pngwin.rc => Used by the visualc6 and visualc71 projects. + pngwin.def => Used by makefile.os2 + pngwin.dfn => Used to maintain pngwin.def + SCOPTIONS.ppc => Used with smakefile.ppc + +checksym.awk => Used for maintaining pnglibconf.h +def.dfn => Used for maintaining pnglibconf.h +options.awk => Used for maintaining pnglibconf.h +pnglibconf.dfa => Used for maintaining pnglibconf.h +pnglibconf.mak => Used for maintaining pnglibconf.h +sym.dfn => Used for symbol versioning +symbols.def => Used for symbol versioning +symbols.dfn => Used for symbol versioning +vers.dfn => Used for symbol versioning + + +Further information can be found in comments in the individual makefiles. diff --git a/contrib/libpng/scripts/SCOPTIONS.ppc b/contrib/libpng/scripts/SCOPTIONS.ppc new file mode 100644 index 0000000..2c3503e --- /dev/null +++ b/contrib/libpng/scripts/SCOPTIONS.ppc @@ -0,0 +1,7 @@ +OPTIMIZE +OPTPEEP +OPTTIME +OPTSCHED +AUTOREGISTER +PARMS=REGISTERS +INCLUDEDIR=hlp:ppc/include diff --git a/contrib/libpng/scripts/checksym.awk b/contrib/libpng/scripts/checksym.awk new file mode 100755 index 0000000..ba4c99b --- /dev/null +++ b/contrib/libpng/scripts/checksym.awk @@ -0,0 +1,161 @@ +#!/bin/awk -f +# Check a list of symbols against the master definition +# (official) list. Arguments: +# +# awk -f checksym.awk official-def list-to-check +# +# Output is a file in the current directory called 'symbols.new', +# stdout holds error messages. Error code indicates success or +# failure. +# +# NOTE: this is a pure, old fashioned, awk script. It will +# work with any awk + +BEGIN{ + err=0 + master="" # master file + official[1] = "" # defined symbols from master file + symbol[1] = "" # defined symbols from png.h + removed[1] = "" # removed symbols from png.h + lasto = 0 # last ordinal value from png.h + mastero = 0 # highest ordinal in master file + symbolo = 0 # highest ordinal in png.h + missing = "error"# log an error on missing symbols +} + +# Read existing definitions from the master file (the first +# file on the command line.) This must be a def file and it +# has definition lines (others are ignored) of the form: +# +# symbol @ordinal +# +master == "" { + master = FILENAME +} +FILENAME==master && NF==2 && $2~/^@/ && $1!~/^;/ { + o=0+substr($2,2) + if (o > 0) { + if (official[o] == "") { + official[o] = $1 + if (o > mastero) mastero = o + next + } else + print master ": duplicated symbol:", official[o] ":", $0 + } else + print master ": bad export line format:", $0 + err = 1 +} +FILENAME==master && $1==";missing" && NF==2{ + # This allows the master file to control how missing symbols + # are handled; symbols that aren't in either the master or + # the new file. Valid values are 'ignore', 'warning' and + # 'error' + missing = $2 +} +FILENAME==master { + next +} + +# Read new definitions, these are free form but the lines must +# just be symbol definitions. Lines will be commented out for +# 'removed' symbols, introduced in png.h using PNG_REMOVED rather +# than PNG_EXPORT. Use symbols.dfn or pngwin.dfn to generate the +# input file. +# +# symbol @ordinal # two fields, exported symbol +# ; symbol @ordinal # three fields, removed symbol +# ; @ordinal # two fields, the last ordinal +NF==2 && $1 == ";" && $2 ~ /^@[1-9][0-9]*$/ { # last ordinal + o=0+substr($2,2) + if (lasto == 0 || lasto == o) + lasto=o + else { + print "png.h: duplicated last ordinal:", lasto, o + err = 1 + } + next +} +NF==3 && $1 == ";" && $3 ~ /^@[1-9][0-9]*$/ { # removed symbol + o=0+substr($3,2) + if (removed[o] == "" || removed[o] == $2) { + removed[o] = $2 + if (o > symbolo) symbolo = o + } else { + print "png.h: duplicated removed symbol", o ": '" removed[o] "' != '" $2 "'" + err = 1 + } + next +} +NF==2 && $2 ~ /^@[1-9][0-9]*$/ { # exported symbol + o=0+substr($2,2) + if (symbol[o] == "" || symbol[o] == $1) { + symbol[o] = $1 + if (o > symbolo) symbolo = o + } else { + print "png.h: duplicated symbol", o ": '" symbol[o] "' != '" $1 "'" + err = 1 + } +} +{ + next # skip all other lines +} + +# At the end check for symbols marked as both duplicated and removed +END{ + if (symbolo > lasto) { + print "highest symbol ordinal in png.h,", symbolo ", exceeds last ordinal from png.h", lasto + err = 1 + } + if (mastero > lasto) { + print "highest symbol ordinal in", master ",", mastero ", exceeds last ordinal from png.h", lasto + err = 1 + } + unexported=0 + for (o=1; o<=lasto; ++o) { + if (symbol[o] == "" && removed[o] == "") { + if (unexported == 0) unexported = o + if (official[o] == "") { + # missing in export list too, so ok + if (o < lasto) continue + } + } + if (unexported != 0) { + # Symbols in the .def but not in the new file are errors, but + # the 'unexported' symbols aren't in either. By default this + # is an error too (see the setting of 'missing' at the start), + # but this can be reset on the command line or by stuff in the + # file - see the comments above. + if (missing != "ignore") { + if (o-1 > unexported) + print "png.h:", missing ": missing symbols:", unexported "-" o-1 + else + print "png.h:", missing ": missing symbol:", unexported + if (missing != "warning") + err = 1 + } + unexported = 0 + } + if (symbol[o] != "" && removed[o] != "") { + print "png.h: symbol", o, "both exported as '" symbol[o] "' and removed as '" removed[o] "'" + err = 1 + } else if (symbol[o] != official[o]) { + # either the symbol is missing somewhere or it changed + err = 1 + if (symbol[o] == "") + print "png.h: symbol", o, "is exported as '" official[o] "' in", master + else if (official[o] == "") + print "png.h: exported symbol", o, "'" symbol[o] "' not present in", master + else + print "png.h: exported symbol", o, "'" symbol[o] "' exists as '" official[o] "' in", master + } + + # Finally generate symbols.new + if (symbol[o] != "") + print " " symbol[o], "@" o > "symbols.new" + } + + if (err != 0) { + print "*** A new list is in symbols.new ***" + exit 1 + } +} diff --git a/contrib/libpng/scripts/chkfmt b/contrib/libpng/scripts/chkfmt new file mode 100755 index 0000000..9da6475 --- /dev/null +++ b/contrib/libpng/scripts/chkfmt @@ -0,0 +1,137 @@ +#!/bin/sh +# +# Check the format of the source files in the current directory - checks for a +# line length of 80 characters max and no tab characters. +# +# Optionally arguments are files or directories to check. +# +# -v: output the long lines (makes fixing them easier) +# -e: spawn an editor for each file that needs a change ($EDITOR must be +# defined). When using -e the script MUST be run from an interactive +# command line. +verbose= +edit= +vers= +test "$1" = "-v" && { + shift + verbose=yes +} +test "$1" = "-e" && { + shift + if test -n "$EDITOR" + then + edit=yes + + # Copy the standard streams for the editor + exec 3>&0 4>&1 5>&2 + else + echo "chkfmt -e: EDITOR must be defined" >&2 + exit 1 + fi +} + +# Function to edit a single file - if the file isn't changed ask the user +# whether or not to continue. This stuff only works if the script is run from +# the command line (otherwise, don't specify -e or you will be sorry). +doed(){ + cp "$file" "$file".orig + "$EDITOR" "$file" 0>&3 1>&4 2>&5 3>&- 4>&- 5>&- || exit 1 + if cmp -s "$file".orig "$file" + then + rm "$file".orig + echo -n "$file: file not changed, type anything to continue: " >&5 + read ans 0>&3 + test -n "$ans" || return 1 + fi + return 0 +} + +# In beta versions the version string which appears in files can be a little +# long and cause spuriously overlong lines. To avoid this subtitute the version +# string with a 'standard' version a.b.cc before checking for long lines. +if test -r png.h +then + vers="`sed -n -e \ + 's/^#define PNG_LIBPNG_VER_STRING .\([0-9]\.[0-9]\.[0-9][0-9a-z]*\).$/\1/p' \ + png.h`" + echo "chkfmt: checking version $vers" +fi +if test -z "$vers" +then + echo "chkfmt: png.h not found, ignoring version number" >&2 +fi + +test -n "$1" || set -- . +find "$@" \( -type d \( -name '.git' -o -name '.libs' -o -name 'projects' \) \ + -prune \) -o \( -type f \ + ! -name '*.[oa]' ! -name '*.l[oa]' ! -name '*.png' ! -name '*.out' \ + ! -name '*.jpg' ! -name '*.patch' ! -name '*.obj' ! -name '*.exe' \ + ! -name '*.com' ! -name '*.tar.*' ! -name '*.zip' ! -name '*.ico' \ + ! -name '*.res' ! -name '*.rc' ! -name '*.mms' ! -name '*.rej' \ + ! -name '*.dsp' ! -name '*.orig' ! -name '*.dfn' ! -name '*.swp' \ + ! -name '~*' ! -name '*.3' \ + ! -name 'missing' ! -name 'mkinstalldirs' ! -name 'depcomp' \ + ! -name 'aclocal.m4' ! -name 'install-sh' ! -name 'Makefile.in' \ + ! -name 'ltmain.sh' ! -name 'config*' -print \) | { + st=0 + while read file + do + case "$file" in + *.mak|*[Mm]akefile.*|*[Mm]akefile) + # Makefiles require tabs, dependency lines can be this long. + check_tabs= + line_length=100;; + *.awk) + # Includes literal tabs + check_tabs= + # The following is arbitrary + line_length=132;; + *contrib/*/*.[ch]) + check_tabs=yes + line_length=96;; + *) + check_tabs=yes + line_length=80;; + esac + + # Note that vers can only contain 0-9, . and a-z + if test -n "$vers" + then + sed -e "s/$vers/a.b.cc/g" "$file" >"$file".$$ + else + cp "$file" "$file".$$ + fi + splt="`fold -$line_length "$file".$$ | diff -c "$file".$$ -`" + rm "$file".$$ + + if test -n "$splt" + then + echo "$file: lines too long" + st=1 + if test -n "$EDITOR" -a -n "$edit" + then + doed "$file" || exit 1 + elif test -n "$verbose" + then + echo "$splt" + fi + fi + if test -n "$check_tabs" + then + tab="`tr -c -d '\t' <"$file"`" + if test -n "$tab" + then + echo "$file: file contains tab characters" + st=1 + if test -n "$EDITOR" -a -n "$edit" + then + doed "$file" || exit 1 + elif test -n "$verbose" + then + echo "$splt" + fi + fi + fi + done + exit $st +} diff --git a/contrib/libpng/scripts/def.dfn b/contrib/libpng/scripts/def.dfn new file mode 100644 index 0000000..d918d4c --- /dev/null +++ b/contrib/libpng/scripts/def.dfn @@ -0,0 +1,38 @@ +/* def.dfn - define format of libpng.def + * + * Last changed in libpng version 1.5.0 [(PENDING RELEASE)] + * Copyright (c) 2010-2011 Glenn Randers-Pehrson + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* These macros exist to make the header and trailer shorter below: */ +#define S PNG_DEFN_MAGIC +#define E PNG_DEFN_END + +/* Write the export file header: */ +S-;---------------------------------------------------------------E +S-; LIBPNG module definition file for OS/2-E +S-;---------------------------------------------------------------E +S--E +S-; If you give the library an explicit name one or other files-E +S-; may need modifying to support the new name on one or more-E +S-; systems.-E +S-LIBRARY-E +S-OS2 DESCRIPTION "PNG image compression library"-E +S-OS2 CODE PRELOAD MOVEABLE DISCARDABLE-E +S--E +S-EXPORTS-E +S-;Version 1.5.0beta58-E + +/* NOTE: @@@ is interpreted by the calling script as a signal to + * join the two things on either side, so we can do symbol + * substitution within the name, regular C ## joins the pp-tokens, + * not their final values. + */ +#define PNG_EXPORTA(ordinal, type, name, args, attributes)\ + PNG_DEFN_MAGIC- SYMBOL_PREFIX @@@ name-PNG_DEFN_END + +#include "../png.h" diff --git a/contrib/libpng/scripts/descrip.mms b/contrib/libpng/scripts/descrip.mms new file mode 100644 index 0000000..99ea1ab --- /dev/null +++ b/contrib/libpng/scripts/descrip.mms @@ -0,0 +1,52 @@ + +cc_defs = /inc=$(ZLIBSRC) +c_deb = + +.ifdef __DECC__ +pref = /prefix=all +.endif + + + +OBJS = png.obj, pngset.obj, pngget.obj, pngrutil.obj, pngtrans.obj,\ + pngwutil.obj, pngread.obj, pngmem.obj, pngwrite.obj, pngrtran.obj,\ + pngwtran.obj, pngrio.obj, pngwio.obj, pngerror.obj, pngpread.obj + + +CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF) + +all : pngtest.exe libpng.olb + @ write sys$output " pngtest available" + +libpng.olb : libpng.olb($(OBJS)) + @ write sys$output " Libpng available" + + +pngtest.exe : pngtest.obj libpng.olb + link pngtest,libpng.olb/lib,$(ZLIBSRC)libz.olb/lib + +test : pngtest.exe + run pngtest + +clean : + delete *.obj;*,*.exe; + + +# Other dependencies. +png.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngpread.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngset.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngget.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngread.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngrtran.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngrutil.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngerror.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngmem.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngrio.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngwio.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngtrans.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngwrite.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngwtran.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h +pngwutil.obj : png.h, pngconf.h, pnglibconf.h, pngpriv.h, pngstruct.h, pnginfo.h, pngdebug.h + +pngtest.obj : png.h, pngconf.h diff --git a/contrib/libpng/scripts/libpng-config-body.in b/contrib/libpng/scripts/libpng-config-body.in new file mode 100755 index 0000000..b466432 --- /dev/null +++ b/contrib/libpng/scripts/libpng-config-body.in @@ -0,0 +1,96 @@ + +usage() +{ + cat < libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo libdir=\"$(LIBPATH)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo R_opts=\"-R$(LIBPATH)\"; \ + echo ccopts=\"-xtarget=ultra\"; \ + echo ldopts=\"-xtarget=ultra\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + @case "`type ld`" in *ucb*) \ + echo; \ + echo '## WARNING:'; \ + echo '## The commands "CC" and "LD" must NOT refer to /usr/ucb/cc'; \ + echo '## and /usr/ucb/ld. If they do, you need to adjust your PATH'; \ + echo '## environment variable to put /usr/ccs/bin ahead of /usr/ucb.'; \ + echo '## The environment variable LD_LIBRARY_PATH should not be set'; \ + echo '## at all. If it is, things are likely to break because of'; \ + echo '## the libucb dependency that is created.'; \ + echo; \ + ;; \ + esac + $(LD) -G -L$(ZLIBLIB) -R$(ZLIBLIB) -h $(LIBSOMAJ) \ + -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) $(SUN_CC_FLAGS) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtestd -L$(DL) -R$(DL) `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + $(SUN_LD_FLAGS) -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) $(SUN_CC_FLAGS) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + $(SUN_LD_FLAGS) -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.64sunu b/contrib/libpng/scripts/makefile.64sunu new file mode 100644 index 0000000..a0331d6 --- /dev/null +++ b/contrib/libpng/scripts/makefile.64sunu @@ -0,0 +1,241 @@ +# makefile for libpng on Solaris 2.x with cc +# Contributed by William L. Sebok, based on makefile.linux +# Copyright (C) 2002, 2006, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1998 Greg Roelofs +# Copyright (C) 1996, 1997 Andreas Dilger + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME=libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +CC=cc +AR_RC=ar rc +MKDIR_P=mkdir -p +LN_SF=ln -f -s +RANLIB=echo +RM_F=/bin/rm -f + +SUN_CC_FLAGS=-fast -xtarget=ultra -xarch=v9 +SUN_LD_FLAGS=-fast -xtarget=ultra -xarch=v9 + +# where make install puts libpng.a, libpng15.so and libpng15/png.h +prefix=/a +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +# Changing these to ../zlib poses a security risk. If you want +# to have zlib in an adjacent directory, specify the full path instead of "..". +#ZLIBLIB=../zlib +#ZLIBINC=../zlib + +ZLIBLIB=/usr/lib +ZLIBINC=/usr/include + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion +CFLAGS=-I$(ZLIBINC) $(SUN_CC_FLAGS) \ + # $(WARNMORE) -g -DPNG_DEBUG=5 +LDFLAGS=-L. -R. $(SUN_LD_FLAGS) -L$(ZLIBLIB) -R$(ZLIBLIB) -lpng15 -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -KPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +include scripts/pnglibconf.mak +DELETE = $(RM_F) +DFNFLAGS = $(DEFS) $(CPPFLAGS) + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo libdir=\"$(LIBPATH)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo R_opts=\"-R$(LIBPATH)\"; \ + echo ccopts=\"-xtarget=ultra -xarch=v9\"; \ + echo ldopts=\"-xtarget=ultra -xarch=v9\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + @case "`type ld`" in *ucb*) \ + echo; \ + echo '## WARNING:'; \ + echo '## The commands "CC" and "LD" must NOT refer to /usr/ucb/cc'; \ + echo '## and /usr/ucb/ld. If they do, you need to adjust your PATH'; \ + echo '## environment variable to put /usr/ccs/bin ahead of /usr/ucb.'; \ + echo '## The environment variable LD_LIBRARY_PATH should not be set'; \ + echo '## at all. If it is, things are likely to break because of'; \ + echo '## the libucb dependency that is created.'; \ + echo; \ + ;; \ + esac + $(LD) -G -L$(ZLIBLIB) -R$(ZLIBLIB) -h $(LIBSOMAJ) \ + -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) $(SUN_CC_FLAGS) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtestd -L$(DL) -R$(DL) `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + $(SUN_LD_FLAGS) -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) $(SUN_CC_FLAGS) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + $(SUN_LD_FLAGS) -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.acorn b/contrib/libpng/scripts/makefile.acorn new file mode 100644 index 0000000..00b8fb5 --- /dev/null +++ b/contrib/libpng/scripts/makefile.acorn @@ -0,0 +1,57 @@ +# Project: libpng + + +# Toolflags: +CCflags = -c -depend !Depend -IC:,Zlib: -g -throwback -DRISCOS -fnah +C++flags = -c -depend !Depend -IC: -throwback +Linkflags = -aif -c++ -o $@ +ObjAsmflags = -throwback -NoCache -depend !Depend +CMHGflags = +LibFileflags = -c -l -o $@ +Squeezeflags = -o $@ + +# Final targets: +@.libpng-lib: @.o.png @.o.pngerror @.o.pngrio @.o.pngwio @.o.pngmem \ + @.o.pngpread @.o.pngset @.o.pngget @.o.pngread @.o.pngrtran \ + @.o.pngrutil @.o.pngtrans @.o.pngwrite @.o.pngwtran @.o.pngwutil + LibFile $(LibFileflags) @.o.png @.o.pngerror @.o.pngrio @.o.pngrtran \ + @.o.pngmem @.o.pngpread @.o.pngset @.o.pngget @.o.pngread @.o.pngwio \ + @.o.pngrutil @.o.pngtrans @.o.pngwrite @.o.pngwtran @.o.pngwutil +@.mm-libpng-lib: @.mm.png @.mm.pngerror @.mm.pngrio @.mm.pngwio @.mm.pngmem \ + @.mm.pngpread @.mm.pngset @.mm.pngget @.mm.pngread @.mm.pngrtran \ + @.mm.pngrutil @.mm.pngtrans @.mm.pngwrite @.mm.pngwtran @.mm.pngwutil + LibFile $(LibFileflags) @.mm.png @.mm.pngerror @.mm.pngrio \ + @.mm.pngwio @.mm.pngmem @.mm.pngpread @.mm.pngset @.mm.pngget \ + @.mm.pngread @.mm.pngrtran @.mm.pngrutil @.mm.pngtrans @.mm.pngwrite \ + @.mm.pngwtran @.mm.pngwutil + + +# User-editable dependencies: +# (C) Copyright 1997 Tom Tanner +Test: @.pngtest + .pngtest + @remove .pngtest + +#It would be nice if you could stop "make" listing from here on! +@.pngtest: @.o.pngtest @.libpng-lib C:o.Stubs Zlib:zlib_lib + Link $(Linkflags) @.o.pngtest @.libpng-lib C:o.Stubs Zlib:zlib_lib + +.SUFFIXES: .o .mm .c + +.c.mm: + MemCheck.CC cc $(ccflags) -o $@ LibPng:$< +.c.o: + cc $(ccflags) -o $@ $< + +# See scripts.mak.libpngconf for how to generate this: +@.h.libpngconf: @.scripts.h.libpngconf + copy @.scripts.h.libpngconf $@ + +# Static dependencies: +@.o.png @.o.pngerror @.o.pngrio @.o.pngwio @.o.pngmem \ +@.o.pngpread @.o.pngset @.o.pngget @.o.pngread @.o.pngrtran \ +@.o.pngrutil @.o.pngtrans @.o.pngwrite @.o.pngwtran @.o.pngwutil \ +@.o.pngtest: @.h.libpngconf + + +# Dynamic dependencies: diff --git a/contrib/libpng/scripts/makefile.aix b/contrib/libpng/scripts/makefile.aix new file mode 100644 index 0000000..bb4c40d --- /dev/null +++ b/contrib/libpng/scripts/makefile.aix @@ -0,0 +1,121 @@ +# makefile for libpng using gcc (generic, static library) +# Copyright (C) 2002, 2006-2009 Glenn Randers-Pehrson +# Copyright (C) 2000 Cosmin Truta +# Copyright (C) 2000 Marc O. Gloor (AIX support added, from makefile.gcc) +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Location of the zlib library and include files +ZLIBINC = ../zlib +ZLIBLIB = ../zlib + +# Compiler, linker, lib and other tools +CC = gcc +LD = $(CC) +AR_RC = ar rcs +MKDIR_P = mkdir -p +RANLIB = ranlib +RM_F = rm -f +LN_SF = ln -f -s + +LIBNAME=libpng15 +PNGMAJ = 15 + +prefix=/usr/local +INCPATH=$(prefix)/include +LIBPATH=$(prefix)/lib + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) + +CDEBUG = -g -DPNG_DEBUG=5 +LDDEBUG = +CRELEASE = -O2 +LDRELEASE = -s +WARNMORE=-W -Wall +CFLAGS = -I$(ZLIBINC) $(WARNMORE) $(CRELEASE) +LDFLAGS = -L. -L$(ZLIBLIB) -lpng15 -lz -lm $(LDRELEASE) + +# File extensions +O=.o +A=.a +E= + +# Variables +OBJS = png$(O) pngerror$(O) pngget$(O) pngmem$(O) pngpread$(O) \ + pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) pngset$(O) \ + pngtrans$(O) pngwio$(O) pngwrite$(O) pngwtran$(O) pngwutil$(O) + +# Targets +all: $(LIBNAME)$(A) pngtest$(E) + +include scripts/pnglibconf.mak +REMOVE = $(RM_F) +DFNFLAGS = $(DEFS) $(CPPFLAGS) + +$(LIBNAME)$(A): $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +test: pngtest$(E) + ./pngtest$(E) + +pngtest$(E): pngtest$(O) $(LIBNAME)$(A) + $(LD) -o $@ pngtest$(O) $(LDFLAGS) + +install: $(LIBNAME)$(A) + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DI)/$(LIBNAME)/png.h + -@$(RM_F) $(DI)/$(LIBNAME)/pngconf.h + -@$(RM_F) $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h + -@$(RM_F) $(DI)/pngconf.h + -@$(RM_F) $(DI)/pnglibconf.h + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h \ + $(DI)/$(LIBNAME)/pngconf.h \ + $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) -r $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + -@$(RM_F) $(DL)/$(LIBNAME)$(A) + -@$(RM_F) $(DL)/libpng$(A) + cp $(LIBNAME)$(A) $(DL)/$(LIBNAME)$(A) + chmod 644 $(DL)/$(LIBNAME)$(A) + (cd $(DL); $(LN_SF) $(LIBNAME)$(A) libpng$(A)) + (cd $(DI); $(LN_SF) libpng/* .;) + +clean: + $(RM_F) *.o $(LIBNAME)$(A) pngtest pngout.png pnglibconf.h + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest$(O): png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.amiga b/contrib/libpng/scripts/makefile.amiga new file mode 100644 index 0000000..228b5c2 --- /dev/null +++ b/contrib/libpng/scripts/makefile.amiga @@ -0,0 +1,56 @@ +# Commodore Amiga Makefile +# makefile for libpng and SAS C V6.5x compiler +# Copyright (C) 1995-2000 Wolf Faust +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# Location/path of zlib include files +ZLIB=/zlib +#compiler +CC=sc +#compiler flags +# WARNING: a bug in V6.51 causes bad code with OPTGO +# So use V6.55 or set NOOPTGO!!!!!!!!! +CFLAGS= NOSTKCHK PARMS=REG OPTIMIZE OPTGO OPTPEEP OPTINLOCAL OPTINL\ + OPTLOOP OPTRDEP=4 OPTDEP=4 OPTCOMP=4 INCLUDEDIR=$(ZLIB) \ + DEFINE=PNG_INTERNAL +#linker flags +LDFLAGS= SD ND BATCH +#link libs +LDLIBS= libpng.lib libgz.lib LIB:scm.lib LIB:sc.lib Lib:amiga.lib +# linker +LN= slink +# file deletion command +RM= delete quiet +# file copy command? +CP= copy +# library (.lib) file creation command +AR= oml +# make directory command +MKDIR= makedir + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: libpng.lib pngtest + +libpng.lib: $(OBJS) +-$(RM) libpng.lib +$(AR) libpng.lib r $(OBJS) + +$(OBJS): pngpriv.h png.h pngconf.h pnglibconf.h pnginfo.h pngstruct.h pngdebug.h + +pnglibconf.h: scripts/pnglibconf.h.prebuilt +$(CP) scripts/pnglibconf.h.prebuilt pnglibconf.h + +pngtest: pngtest.o libpng.lib +$(LN) libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo libs=\"-lpng15 -lz \"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + cp $(LIBSO)* /boot/home/config/lib + +$(LIBSOMAJ): $(OBJSDLL) + $(CC) -nostart -Wl,-soname,$(LIBSOMAJ) -o \ + $(LIBSOMAJ) $(OBJSDLL) $(LDFLAGS) + +pngtest: pngtest.o $(LIBSO) + $(CC) -L$(ZLIBLIB) -L. -lz -lpng15 -o pngtest pngtest.o + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) $(CFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) -Wl,-rpath $(ZLIBLIB):$(DL) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + $(CC) $(CFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngout.png libpng-config \ + $(LIBSO) $(LIBSOMAJ)* pngtesti \ + pnglibconf.h libpng.pc + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.bor b/contrib/libpng/scripts/makefile.bor new file mode 100644 index 0000000..96d5e86 --- /dev/null +++ b/contrib/libpng/scripts/makefile.bor @@ -0,0 +1,161 @@ +# Makefile for libpng +# 16-bit Borland C++ (Note: All modules are compiled in C mode) +# To build the library, do: +# "make -fmakefile.bor -DMODEL=c" +# or: "make -fmakefile.bor -DMODEL=l" +# +# ------------ Borland C++ ------------ + +### Absolutely necessary for this makefile to work +.AUTODEPEND + +## Where zlib.h, zconf.h and zlib_MODEL.lib are +ZLIB_DIR=..\zlib + +## Compiler, linker and lib stuff +CC=bcc +LD=bcc +LIB=tlib + +!ifndef MODEL +MODEL=l +!endif + +MODEL_ARG=-m$(MODEL) + +#TARGET_CPU=3 +# 2 = 286, 3 = 386, etc. +!ifndef TARGET_CPU +TARGET_CPU=2 +!endif + +# Use this if you don't want Borland's fancy exception handling +# (for Borland C++ 4.0 or later) +#NOEHLIB=noeh$(MODEL).lib + +!ifdef DEBUG +CDEBUG=-v +LDEBUG=-v +!else +CDEBUG= +LDEBUG= +!endif + +# STACKOFLOW=1 +!ifdef STACKOFLOW +CDEBUG=$(CDEBUG) -N +LDEBUG=$(LDEBUG) -N +!endif + +# -X- turn on dependency generation in the object file +# -w set all warnings on +# -O2 optimize for speed +# -Z global optimization +CFLAGS=-O2 -Z -X- -w -I$(ZLIB_DIR) -$(TARGET_CPU) $(MODEL_ARG) $(CDEBUG) + +# -M generate map file +LDFLAGS=-M -L$(ZLIB_DIR) $(MODEL_ARG) $(LDEBUG) + +## Variables + +OBJS = \ + png.obj \ + pngerror.obj \ + pngget.obj \ + pngmem.obj \ + pngpread.obj \ + pngread.obj \ + pngrio.obj \ + pngrtran.obj \ + pngrutil.obj \ + pngset.obj \ + pngtrans.obj \ + pngwio.obj \ + pngwrite.obj \ + pngwtran.obj \ + pngwutil.obj + +LIBOBJS = \ + +png.obj \ + +pngerror.obj \ + +pngget.obj \ + +pngmem.obj \ + +pngpread.obj \ + +pngread.obj \ + +pngrio.obj \ + +pngrtran.obj \ + +pngrutil.obj \ + +pngset.obj \ + +pngtrans.obj \ + +pngwio.obj \ + +pngwrite.obj \ + +pngwtran.obj \ + +pngwutil.obj + +LIBNAME=libpng$(MODEL).lib + +## Implicit rules + +# Braces let make "batch" calls to the compiler, +# 2 calls instead of 12; space is important. +.c.obj: + $(CC) $(CFLAGS) -c {$*.c } + +.c.exe: + $(CC) $(CFLAGS) $(LDFLAGS) $*.c $(LIBNAME) zlib_$(MODEL).lib $(NOEHLIB) + +## Major targets + +all: libpng pngtest + +# try !inlude scripts\pnglibconf.mak for more options +pnglibconf.h: scripts\pnglibconf.h.prebuilt + copy scripts\pnglibconf.h.prebuilt $@ + +libpng: $(LIBNAME) + +pngtest: pngtest$(MODEL).exe + +test: pngtest$(MODEL).exe + pngtest$(MODEL) + +## Minor Targets + +png.obj: png.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.obj: pngerror.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.obj: pngget.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.obj: pngmem.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.obj: pngpread.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.obj: pngread.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.obj: pngrio.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.obj: pngrtran.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.obj: pngrutil.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.obj: pngset.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.obj: pngtrans.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.obj: pngwio.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.obj: pngwrite.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.obj: pngwtran.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.obj: pngwutil.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +$(LIBNAME): $(OBJS) + -del $(LIBNAME) + $(LIB) $(LIBNAME) @&&| +$(LIBOBJS), libpng$(MODEL) +| + +pngtest$(MODEL).obj: pngtest.c png.h pngconf.h pnglibconf.h + $(CC) $(CFLAGS) -opngtest$(MODEL) -c pngtest.c + +pngtest$(MODEL).exe: pngtest$(MODEL).obj + $(LD) $(LDFLAGS) pngtest$(MODEL).obj $(LIBNAME) zlib_$(MODEL).lib $(NOEHLIB) + +# Clean up anything else you want +clean: + -del pnglibconf.h + -del *.obj + -del *.exe + -del *.lib + -del *.lst + -del *.map + +# End of makefile for libpng diff --git a/contrib/libpng/scripts/makefile.cegcc b/contrib/libpng/scripts/makefile.cegcc new file mode 100644 index 0000000..f44c881 --- /dev/null +++ b/contrib/libpng/scripts/makefile.cegcc @@ -0,0 +1,116 @@ +# Makefile for creating Windows CE release archives, with the +# mingw32ce compiler. + +# Last updated: 22-Jul-2008 + +# Copyright (C) 2008 Vincent Torri + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# To get some help, type +# +# make help +# +# To create the archives +# +# make +# +# To remove everything, type: +# +# make clean + +VERMAJ = 1 +VERMIN = 5 +VERMIC = 1 +VER = $(VERMAJ).$(VERMIN).$(VERMIC) +NAME = libpng +PACKAGE = $(NAME)-$(VER) + +BIN = libpng15-0.dll +LIB = libpng15.a libpng15.dll.a libpng.a libpng.dll.a +INCLUDE = png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +PC = libpng15.pc libpng.pc + +MANIFESTVERBIN = "Libpng-$(VER): Binary files" +MANIFESTVERDEV = "Libpng-$(VER): Developer files" +MANIFESTVERDESC = "Libpng: the official PNG reference library" + +all: $(NAME) + +$(NAME): remove-old copy-src compilation copy manifest archive + @echo " * Removal of the directories" + @rm -rf $(PACKAGE)/ $(PACKAGE)-bin/ $(PACKAGE)-dev/ + +remove-old: + @echo " * Removal of the old files" + @rm -rf $(PACKAGE)-bin* + @rm -rf $(PACKAGE)-dev* + +copy-src: + @echo " * Copy of source files" + @cp -R ../src/$(PACKAGE) . + @echo " * Creation of directories and files" + @mkdir -p $(PACKAGE)-bin/bin + @mkdir -p $(PACKAGE)-bin/manifest + @mkdir -p $(PACKAGE)-dev/lib/pkgconfig + @mkdir -p $(PACKAGE)-dev/include/$(NAME)$(VERMAJ)$(VERMIN) + @mkdir -p $(PACKAGE)-dev/manifest + @touch $(PACKAGE)-bin/manifest/$(PACKAGE)-bin.mft + @touch $(PACKAGE)-bin/manifest/$(PACKAGE)-bin.ver + @touch $(PACKAGE)-dev/manifest/$(PACKAGE)-dev.mft + @touch $(PACKAGE)-dev/manifest/$(PACKAGE)-dev.ver + +compilation: + @echo " * Compilation of $(PACKAGE)" + cd $(PACKAGE) && CPPFLAGS="$(CPPFLAGS) -DPNG_CONSOLE_IO_SUPPORTED -D_WIN32_WCE=0x0420" \ + CFLAGS="$(CFLAGS) -mms-bitfields -O3 -pipe -fomit-frame-pointer" \ + LDFLAGS="$(LDFLAGS) -Wl,--enable-auto-import -Wl,-s" \ + ./configure --prefix=/opt/wince --host=arm-mingw32ce && make + +copy: + @echo " * Copy of binary and development files" + @for i in $(BIN); do \ + cp $(PACKAGE)/.libs/$$i $(PACKAGE)-bin/bin; \ + done + @for i in $(LIB); do \ + cp $(PACKAGE)/.libs/$$i $(PACKAGE)-dev/lib; \ + done + @for i in $(INCLUDE); do \ + cp $(PACKAGE)/$$i $(PACKAGE)-dev/include/$(NAME)$(VERMAJ)$(VERMIN); \ + done + @for i in $(PC); do \ + cp $(PACKAGE)/$$i $(PACKAGE)-dev/lib/pkgconfig; \ + done + +manifest: + @echo " * Creation of the manifest" + @cd $(PACKAGE)-bin && find * >> manifest/$(PACKAGE)-bin.mft + @cd $(PACKAGE)-bin && \ + echo $(MANIFESTVERBIN) >> manifest/$(PACKAGE)-bin.ver && \ + echo $(MANIFESTVERDESC) >> manifest/$(PACKAGE)-bin.ver + @cd $(PACKAGE)-dev && find * >> manifest/$(PACKAGE)-dev.mft + @cd $(PACKAGE)-dev && \ + echo $(MANIFESTVERDEV) >> manifest/$(PACKAGE)-dev.ver && \ + echo $(MANIFESTVERDESC) >> manifest/$(PACKAGE)-dev.ver + +archive: + @echo " * Creation of the archives" + @tar cf $(PACKAGE)-bin.tar $(PACKAGE)-bin + @bzip2 -9 $(PACKAGE)-bin.tar + @tar cf $(PACKAGE)-dev.tar $(PACKAGE)-dev + @bzip2 -9 $(PACKAGE)-dev.tar + +clean: + @echo " * Cleaning" + @rm -rf $(PACKAGE)* + +help: + @echo + @echo "To create the archives, type:" + @echo " make" + @echo + @echo "To remove everything, type:" + @echo " make clean" + @echo diff --git a/contrib/libpng/scripts/makefile.darwin b/contrib/libpng/scripts/makefile.darwin new file mode 100644 index 0000000..aaec54d --- /dev/null +++ b/contrib/libpng/scripts/makefile.darwin @@ -0,0 +1,219 @@ +# makefile for libpng on Darwin / Mac OS X +# Copyright (C) 2002, 2004, 2006, 2008, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 2001 Christoph Pfisterer +# derived from makefile.linux: +# Copyright (C) 1998, 1999 Greg Roelofs +# Copyright (C) 1996, 1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# where "make install" puts libpng.a, libpng15.dylib, png.h, pngconf.h, +# and pnglibconf.h +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).dylib +LIBSOMAJ=$(LIBNAME).$(PNGMAJ).dylib +LIBSOREL=$(LIBNAME).$(PNGMAJ).$(RELEASE).dylib +OLDSO=libpng.dylib + +# Utilities: +CC=cc +AR_RC=ar rc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=ranlib +RM_F=/bin/rm -f + +# CFLAGS=-I$(ZLIBINC) -W -Wall -O3 -funroll-loops +CFLAGS=-I$(ZLIBINC) -W -Wall -O -funroll-loops +LDFLAGS=-L. -L$(ZLIBLIB) -lpng15 -lz + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -fno-common -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + $(CC) -dynamiclib \ + -install_name $(LIBPATH)/$(LIBSOMAJ) \ + -current_version 15 -compatibility_version 15 \ + -o $(LIBSOMAJ) \ + $(OBJSDLL) -L$(ZLIBLIB) -lz + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + $(RANLIB) $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + $(CC) $(CFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngout.png libpng-config \ + libpng.pc $(LIBNAME).*dylib pngtesti pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.dec b/contrib/libpng/scripts/makefile.dec new file mode 100644 index 0000000..5301d87 --- /dev/null +++ b/contrib/libpng/scripts/makefile.dec @@ -0,0 +1,202 @@ +# makefile for libpng on DEC Alpha Unix +# Copyright (C) 2000-2002, 2006, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +PNGMAJ = 15 +LIBNAME = libpng15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +AR_RC=ar rc +CC=cc +MKDIR_P=mkdir +LN_SF=ln -f -s +RANLIB=ranlib +RM_F=/bin/rm -f + +# where make install puts libpng.a and png.h +prefix=/usr/local +exec_prefix=$(prefix) +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +CFLAGS=-std -w1 -I$(ZLIBINC) -O # -g -DPNG_DEBUG=1 +LDFLAGS=-L$(ZLIBLIB) -rpath $(ZLIBLIB) libpng.a -lz -lm + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: $(LIBSO) libpng.a pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo ccopts=\"-std\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJS) + $(CC) -shared -o $@ $(OBJS) -L$(ZLIBLIB) \ + -soname $(LIBSOMAJ) + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@/bin/rm -f $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@/bin/rm -f $(DI)/libpng + (cd $(DI); $(LN_SF)(LIBNAME) libpng; $(LN_SF)(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@/bin/rm -f $(DL)/libpng.a + (cd $(DL); $(LN_SF)(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@/bin/rm -f $(DM)/man3/libpng.3 + -@/bin/rm -f $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@/bin/rm -f $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@/bin/rm -f $(DB)/libpng-config + -@/bin/rm -f $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF)(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -w1 -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) -R$(ZLIBLIB) -R$(DL) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -w1 -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) -R$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + /bin/rm -f *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.dj2 b/contrib/libpng/scripts/makefile.dj2 new file mode 100644 index 0000000..87a05a3 --- /dev/null +++ b/contrib/libpng/scripts/makefile.dj2 @@ -0,0 +1,62 @@ +# DJGPP (DOS gcc) makefile for libpng +# Copyright (C) 2002, 2006, 2009-2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# where make install will put libpng.a and png.h +#prefix=/usr/local +prefix=. +INCPATH=$(prefix)/include +LIBPATH=$(prefix)/lib + +CC=gcc +CFLAGS=-I../zlib -O -DPNG_NO_SNPRINTF +LDFLAGS=-L. -L../zlib/ -lpng -lz -lm + +RANLIB=ranlib + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o pngwtran.o \ + pngmem.o pngerror.o pngpread.o + +all: libpng.a pngtest + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + ar rc $@ $(OBJS) + $(RANLIB) $@ + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + coff2exe pngtest + +test: pngtest + ./pngtest +clean: + rm -f *.o libpng.a pngtest pngout.png pnglibconf.h + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.elf b/contrib/libpng/scripts/makefile.elf new file mode 100644 index 0000000..5af43b1 --- /dev/null +++ b/contrib/libpng/scripts/makefile.elf @@ -0,0 +1,263 @@ +# makefile for libpng.a and libpng15.so on Linux ELF with gcc +# Copyright (C) 1998, 1999, 2002, 2006, 2008, 2010-2011 Greg Roelofs +# and Glenn Randers-Pehrson +# Copyright (C) 1996, 1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Modified for Debian by Junichi Uekawa and Josselin Mouette +# Major modifications are: +# * link libpng explicitly with libz and libm +# * $(OLDSO).15 is a symlink rather than a different library +# * versioned symbols + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so +OLDSOMAJ=libpng.so.15 + +# Utilities: +AR_RC=ar rc +CC=gcc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=ranlib +RM_F=/bin/rm -f + +# where "make install" puts libpng15.a, libpng15.so*, +# libpng15/png.h, libpng15/pngconf.h, and libpng15/pnglibconf.h +# Prefix must be a full pathname. +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located. +ZLIBLIB=/usr/local/lib +ZLIBINC=/usr/local/include +# ZLIBLIB=../zlib +# ZLIBINC=../zlib + +ALIGN= +# for i386: +#ALIGN=-malign-loops=2 -malign-functions=2 + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion + +# for pgcc version 2.95.1, -O3 is buggy; don't use it. + +CFLAGS=-W -Wall -D_REENTRANT -O2 \ + $(ALIGN) # $(WARNMORE) -g -DPNG_DEBUG=5 + +LDFLAGS=-L. -lpng15 +LDFLAGS_A=libpng.a -lz -lm +LIBADDFLAGS=-lz -lm + + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -fPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest pngtest-static libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng.syms: png.h pngconf.h pnglibconf.h + $(CC) $(CFLAGS) -E -DPNG_BUILDSYMS -DPNG_INTERNAL png.h |\ + awk -F '[\t [\\]();]' -v PNGMAJ=$(PNGMAJ) 'BEGIN{printf("PNG15_%s {global:\n",PNGMAJ)}\ + { for (i=1;i+2<=NF;++i)\ + if ($$(i)=="PNG_FUNCTION_EXPORT" && $$(i+2)=="END")\ + print $$(i+1) ";";\ + for (i=1;i+1<=NF;++i)\ + if ($$(i)=="PNG_DATA_EXPORT")\ + print $$(i+1) ";";}\ + END{print "local: *; };"}' >$@.new + $(RM_F) $@ + mv $@.new $@ + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo L_opts=\"\"; \ + echo R_opts=\"\"; \ + echo libs=\"-lpng15\"; \ + echo all_libs=\"-lpng15 $(LIBADDFLAGS)\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) libpng.syms + $(CC) -shared -Wl,-soname,$(LIBSOMAJ) \ + -Wl,-version-script,libpng.syms \ + -o $(LIBSOMAJ) \ + $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +pngtest-static: pngtest.o libpng.a + $(CC) -o pngtest-static $(CFLAGS) pngtest.o $(LDFLAGS_A) + +test: pngtest pngtest-static + @echo "" + @echo " Running pngtest dynamically linked with $(LIBSO):" + @echo "" + LD_LIBRARY_PATH=".:${LD_LIBRARY_PATH}" ./pngtest + @echo "" + @echo " Running pngtest statically linked with libpng.a:" + @echo "" + ./pngtest-static + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) -Wl, -rpath,$(DL) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a libpng.syms pngtest pngout.png libpng-config \ + $(LIBSO) $(LIBSOMAJ)* pngtest-static pngtesti \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.freebsd b/contrib/libpng/scripts/makefile.freebsd new file mode 100644 index 0000000..994608c --- /dev/null +++ b/contrib/libpng/scripts/makefile.freebsd @@ -0,0 +1,53 @@ +# makefile for libpng under FreeBSD +# Copyright (C) 2002, 2007, 2009 Glenn Randers-Pehrson and Andrey A. Chernov +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +PREFIX?= /usr/local +SHLIB_VER?= 15 + +LIB= png +SHLIB_MAJOR= ${SHLIB_VER} +SHLIB_MINOR= 0 +NOPROFILE= YES +NOOBJ= YES + +# where make install puts libpng.a and png.h +DESTDIR= ${PREFIX} +LIBDIR= /lib +INCS= png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +INCSDIR= /include/libpng +INCDIR= ${INCSDIR} # for 4.x bsd.lib.mk +MAN= libpng.3 libpngpf.3 png.5 +MANDIR= /man/man +SYMLINKS= libpng/png.h ${INCSDIR}/../png.h \ + libpng/pngconf.h ${INCSDIR}/../pngconf.h \ + libpng/pnglibconf.h ${INCSDIR}/../pnglibconf.h +LDADD+= -lm -lz +DPADD+= ${LIBM} ${LIBZ} + +CFLAGS+= -I. + +SRCS= png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \ + pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \ + pngwtran.c pngmem.c pngerror.c pngpread.c + +pngtest: pngtest.o libpng.a + ${CC} ${CFLAGS} -L. -static -o pngtest pngtest.o -lpng -lz -lm + +CLEANFILES= pngtest pngtest.o pngout.png + +test: pngtest + ./pngtest + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +.include diff --git a/contrib/libpng/scripts/makefile.gcc b/contrib/libpng/scripts/makefile.gcc new file mode 100644 index 0000000..2e5b611 --- /dev/null +++ b/contrib/libpng/scripts/makefile.gcc @@ -0,0 +1,87 @@ +# makefile for libpng using gcc (generic, static library) +# Copyright (C) 2008 Glenn Randers-Pehrson +# Copyright (C) 2000 Cosmin Truta +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Location of the zlib library and include files +ZLIBINC = ../zlib +ZLIBLIB = ../zlib + +# Compiler, linker, lib and other tools +CC = gcc +LD = $(CC) +AR_RC = ar rcs +RANLIB = ranlib +RM_F = rm -f + +CDEBUG = -g -DPNG_DEBUG=5 +LDDEBUG = +CRELEASE = -O2 +LDRELEASE = -s +#CFLAGS = -W -Wall $(CDEBUG) +CFLAGS = -W -Wall $(CRELEASE) +#LDFLAGS = $(LDDEBUG) +LDFLAGS = $(LDRELEASE) +LIBS = -lz -lm + +# File extensions +O=.o +A=.a +EXE= + +# Variables +OBJS = png$(O) pngerror$(O) pngget$(O) pngmem$(O) pngpread$(O) \ + pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) pngset$(O) \ + pngtrans$(O) pngwio$(O) pngwrite$(O) pngwtran$(O) pngwutil$(O) + +# Targets +all: static + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +.c$(O): + $(CC) -c $(CFLAGS) -I$(ZLIBINC) $< + +static: libpng$(A) pngtest$(EXE) + +shared: + @echo This is a generic makefile that cannot create shared libraries. + @echo Please use a configuration that is specific to your platform. + @false + +libpng$(A): $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +test: pngtest$(EXE) + ./pngtest$(EXE) + +pngtest$(EXE): pngtest$(O) libpng$(A) + $(LD) $(LDFLAGS) -L$(ZLIBLIB) -o $@ pngtest$(O) libpng$(A) $(LIBS) + +clean: + $(RM_F) *$(O) libpng$(A) pngtest$(EXE) pngout.png pnglibconf.h + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest$(O): png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.hp64 b/contrib/libpng/scripts/makefile.hp64 new file mode 100644 index 0000000..b5b631d --- /dev/null +++ b/contrib/libpng/scripts/makefile.hp64 @@ -0,0 +1,224 @@ +# makefile for libpng, HPUX (10.20 and 11.00) using the ANSI/C product. +# Copyright (C) 1999-2002, 2006, 2009, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42 +# contributed by Jim Rice and updated by Chris Schleicher, Hewlett Packard +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Where the zlib library and include files are located +ZLIBLIB=/opt/zlib/lib +ZLIBINC=/opt/zlib/include + +# Note that if you plan to build a libpng shared library, zlib must also +# be a shared library, which zlib's configure does not do. After running +# zlib's configure, edit the appropriate lines of makefile to read: +# CFLAGS=-O1 -DHAVE_UNISTD -DUSE_MAP -fPIC \ +# LDSHARED=ld -b +# SHAREDLIB=libz.sl + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).sl +LIBSOMAJ=$(LIBNAME).sl.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.sl + +# Utilities: +AR_RC=ar rc +CC=cc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=ranlib +RM_F=/bin/rm -f + +CFLAGS=-I$(ZLIBINC) -O -Ae -Wl,+vnocompatwarnings +DD64 \ +-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 +Z -DHAVE_UNISTD_H -DUSE_MMAP +# Caution: be sure you have built zlib with the same CFLAGS. +CCFLAGS=-I$(ZLIBINC) -O -Ae -Wl,+vnocompatwarnings +DD64 \ +-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 +Z -DHAVE_UNISTD_H -DUSE_MMAP + +LDFLAGS=-L. -L$(ZLIBLIB) -lpng -lz -lm + +# where make install puts libpng.a, libpng15.sl, and png.h +prefix=/opt/libpng +exec_prefix=$(prefix) +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) +z -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo ccopts=\"-Ae +DA1.1 +DS2.0\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + $(LD) -b +s \ + +h $(LIBSOMAJ) -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) $(CCFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) $(CCFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.hpgcc b/contrib/libpng/scripts/makefile.hpgcc new file mode 100644 index 0000000..3fe2117 --- /dev/null +++ b/contrib/libpng/scripts/makefile.hpgcc @@ -0,0 +1,230 @@ +# makefile for libpng on HP-UX using GCC with the HP ANSI/C linker. +# Copyright (C) 2002, 2006-2008, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 2001, Laurent faillie +# Copyright (C) 1998, 1999 Greg Roelofs +# Copyright (C) 1996, 1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).sl +LIBSOMAJ=$(LIBNAME).sl.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.sl + +# Utilities: +CC=gcc +LD=ld +AR_RC=ar rc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=ranlib +RM_F=/bin/rm -f + +# where "make install" puts libpng.a, $(OLDSO)*, png.h, pngconf.h +# and pnglibconf.h +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +ZLIBLIB=/opt/zlib/lib +ZLIBINC=/opt/zlib/include + +# Note that if you plan to build a libpng shared library, zlib must also +# be a shared library, which zlib's configure does not do. After running +# zlib's configure, edit the appropriate lines of makefile to read: +# CFLAGS=-O1 -DHAVE_UNISTD -DUSE_MAP -fPIC \ +# LDSHARED=ld -b +# SHAREDLIB=libz.sl + +ALIGN= +# for i386: +#ALIGN=-malign-loops=2 -malign-functions=2 + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion + +# for pgcc version 2.95.1, -O3 is buggy; don't use it. + +CFLAGS=-I$(ZLIBINC) -W -Wall -O3 -funroll-loops -DPNG_NO_MMX_CODE \ + $(ALIGN) # $(WARNMORE) -g -DPNG_DEBUG=5 +#LDFLAGS=-L. -Wl,-rpath,. -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) -lpng15 -lz -lm +LDFLAGS=-L. -L$(ZLIBLIB) -lpng15 -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -fPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + $(LD) -b +s \ + +h $(LIBSOMAJ) -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) -Wl,-rpath,$(DL) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.hpux b/contrib/libpng/scripts/makefile.hpux new file mode 100644 index 0000000..650ab4f --- /dev/null +++ b/contrib/libpng/scripts/makefile.hpux @@ -0,0 +1,221 @@ +# makefile for libpng, HPUX (10.20 and 11.00) using the ANSI/C product. +# Copyright (C) 1999-2002, 2006, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42 +# contributed by Jim Rice and updated by Chris Schleicher, Hewlett Packard +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Where the zlib library and include files are located +ZLIBLIB=/opt/zlib/lib +ZLIBINC=/opt/zlib/include + +# Note that if you plan to build a libpng shared library, zlib must also +# be a shared library, which zlib's configure does not do. After running +# zlib's configure, edit the appropriate lines of makefile to read: +# CFLAGS=-O1 -DHAVE_UNISTD -DUSE_MAP -fPIC \ +# LDSHARED=ld -b +# SHAREDLIB=libz.sl + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).sl +LIBSOMAJ=$(LIBNAME).sl.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.sl + +# Utilities: +AR_RC=ar rc +CC=cc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=ranlib +RM_F=/bin/rm -f + +# where make install puts libpng.a, libpng15.sl, and png.h +prefix=/opt/libpng +exec_prefix=$(prefix) +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +CFLAGS=-I$(ZLIBINC) -O -Ae +DA1.1 +DS2.0 +# Caution: be sure you have built zlib with the same CFLAGS. +CCFLAGS=-I$(ZLIBINC) -O -Ae +DA1.1 +DS2.0 +LDFLAGS=-L. -L$(ZLIBLIB) -lpng -lz -lm + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) +z -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo ccopts=\"-Ae +DA1.1 +DS2.0\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + $(LD) -b +s \ + +h $(LIBSOMAJ) -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) $(CCFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) $(CCFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.ibmc b/contrib/libpng/scripts/makefile.ibmc new file mode 100644 index 0000000..209d513 --- /dev/null +++ b/contrib/libpng/scripts/makefile.ibmc @@ -0,0 +1,82 @@ +# Makefile for libpng (static) +# IBM C version 3.x for Win32 and OS/2 +# Copyright (C) 2006 Glenn Randers-Pehrson +# Copyright (C) 2000 Cosmin Truta +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# Notes: +# Derived from makefile.std +# All modules are compiled in C mode +# Tested under Win32, expected to work under OS/2 +# Can be easily adapted for IBM VisualAge/C++ for AIX + +# Location of the zlib library and include files +ZLIBINC = ../zlib +ZLIBLIB = ../zlib + +# Compiler, linker, lib and other tools +CC = icc +LD = ilink +AR = ilib +RM = del + +CFLAGS = -I$(ZLIBINC) -Mc -O2 -W3 +LDFLAGS = + +# File extensions +O=.obj +A=.lib +E=.exe + +# Variables +OBJS = png$(O) pngerror$(O) pngget$(O) pngmem$(O) pngpread$(O) \ + pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) pngset$(O) \ + pngtrans$(O) pngwio$(O) pngwrite$(O) pngwtran$(O) pngwutil$(O) + +LIBS = libpng$(A) $(ZLIBLIB)/zlib$(A) + +# Targets +all: libpng$(A) pngtest$(E) + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng$(A): $(OBJS) + $(AR) -out:$@ $(OBJS) + +test: pngtest$(E) + pngtest$(E) + +pngtest: pngtest$(E) + +pngtest$(E): pngtest$(O) libpng$(A) + $(LD) $(LDFLAGS) pngtest$(O) $(LIBS) + +clean: + $(RM) *$(O) + $(RM) libpng$(A) + $(RM) pnglibconf.h + $(RM) pngtest$(E) + $(RM) pngout.png + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest$(O): png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.intel b/contrib/libpng/scripts/makefile.intel new file mode 100644 index 0000000..1cb9ef3 --- /dev/null +++ b/contrib/libpng/scripts/makefile.intel @@ -0,0 +1,110 @@ +# Makefile for libpng +# Microsoft Visual C++ with Intel C/C++ Compiler 4.0 and later + +# Copyright (C) 2006 Glenn Randers-Pehrson +# Copyright (C) 2000, Pawel Mrochen, based on makefile.msc which is +# copyright 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# To use, do "nmake /f scripts\makefile.intel" +# +# ------------------- Intel C/C++ Compiler 4.0 and later ------------------- + +# Where the zlib library and include files are located +ZLIBLIB=..\zlib +ZLIBINC=..\zlib + +# Target CPU +CPU=6 # Pentium II +#CPU=5 # Pentium + +# Calling convention +CALLING=r # __fastcall +#CALLING=z # __stdcall +#CALLING=d # __cdecl + +# Uncomment next to put error messages in a file +#ERRFILE=>>pngerrs + +# -------------------------------------------------------------------------- + +CC=icl -c +CFLAGS=-O2 -G$(CPU)$(CALLING) -Qip -Qunroll4 -I$(ZLIBINC) -nologo +LD=link +LDFLAGS=/SUBSYSTEM:CONSOLE /NOLOGO + +O=.obj + +OBJS=png$(O) pngset$(O) pngget$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O) \ +pngmem$(O) pngpread$(O) pngread$(O) pngerror$(O) pngwrite$(O) \ +pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O) + +all: test + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +libpng.lib: $(OBJS) + if exist libpng.lib del libpng.lib + lib /NOLOGO /OUT:libpng.lib $(OBJS) + +pngtest.exe: pngtest.obj libpng.lib + $(LD) $(LDFLAGS) /OUT:pngtest.exe pngtest.obj libpng.lib $(ZLIBLIB)\zlib.lib + +pngtest$(O): png.h pngconf.h pnglibconf.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +test: pngtest.exe + pngtest.exe + + +# End of makefile for libpng diff --git a/contrib/libpng/scripts/makefile.knr b/contrib/libpng/scripts/makefile.knr new file mode 100644 index 0000000..18a39f5 --- /dev/null +++ b/contrib/libpng/scripts/makefile.knr @@ -0,0 +1,109 @@ +# makefile for libpng +# Copyright (C) 2002, 2006, 2009 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# This makefile requires the file ansi2knr.c, which you can get +# from the Ghostscript ftp site at ftp://ftp.cs.wisc.edu/ghost/ +# If you have libjpeg, you probably already have ansi2knr.c in the jpeg +# source distribution. + +# where make install puts libpng.a and png.h +prefix=/usr/local +INCPATH=$(prefix)/include +LIBPATH=$(prefix)/lib + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +CC=cc +CFLAGS=-I../zlib -O +LDFLAGS=-L. -L../zlib/ -lpng -lz -lm +# flags for ansi2knr +ANSI2KNRFLAGS= + +RANLIB=ranlib +#RANLIB=echo + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: ansi2knr libpng.a pngtest + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +# general rule to allow ansi2knr to work +.c.o: + ./ansi2knr $*.c T$*.c + $(CC) $(CFLAGS) -c T$*.c + rm -f T$*.c $*.o + mv T$*.o $*.o + +ansi2knr: ansi2knr.c + $(CC) $(CFLAGS) $(ANSI2KNRFLAGS) -o ansi2knr ansi2knr.c + +libpng.a: ansi2knr $(OBJS) + ar rc $@ $(OBJS) + $(RANLIB) $@ + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install: libpng.a png.h pngconf.h pnglibconf.h + -@mkdir $(DESTDIR)$(INCPATH) + -@mkdir $(DESTDIR)$(INCPATH)/libpng + -@mkdir $(DESTDIR)$(LIBPATH) + -@rm -f $(DESTDIR)$(INCPATH)/png.h + -@rm -f $(DESTDIR)$(INCPATH)/pngconf.h + cp png.h $(DESTDIR)$(INCPATH)/libpng + cp pngconf.h $(DESTDIR)$(INCPATH)/libpng + cp pnglibconf.h $(DESTDIR)$(INCPATH)/libpng + chmod 644 $(DESTDIR)$(INCPATH)/libpng/png.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pngconf.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pnglibconf.h + (cd $(DESTDIR)$(INCPATH); ln -f -s libpng/* .) + cp libpng.a $(DESTDIR)$(LIBPATH) + chmod 644 $(DESTDIR)$(LIBPATH)/libpng.a + +clean: + rm -f *.o libpng.a pngtest pngout.png ansi2knr pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.linux b/contrib/libpng/scripts/makefile.linux new file mode 100644 index 0000000..d1dc970 --- /dev/null +++ b/contrib/libpng/scripts/makefile.linux @@ -0,0 +1,239 @@ +# makefile for libpng.a and libpng15.so on Linux ELF with gcc +# Copyright (C) 1998, 1999, 2002, 2006, 2008, 2010-2011 Greg Roelofs and +# Glenn Randers-Pehrson +# Copyright (C) 1996, 1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 +RELEASE = 1 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +AR_RC=ar rc +CC=gcc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=ranlib +RM_F=/bin/rm -f + +# where "make install" puts libpng15.a, libpng15.so*, +# libpng15/png.h, libpng15/pngconf.h, and libpng15/pnglibconf.h +# Prefix must be a full pathname. +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located. +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +ALIGN= +# for i386: +#ALIGN=-malign-loops=2 -malign-functions=2 + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion + +# for pgcc version 2.95.1, -O3 is buggy; don't use it. + +CFLAGS=-I$(ZLIBINC) -W -Wall -O3 -funroll-loops \ + $(ALIGN) # $(WARNMORE) -g -DPNG_DEBUG=5 + +LDFLAGS=-L. -Wl,-rpath,. -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) -lpng15 -lz -lm +LDFLAGS_A=-L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) libpng.a -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -fPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest pngtest-static libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo R_opts=\"-Wl,-rpath,$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + $(CC) -shared -Wl,-soname,$(LIBSOMAJ) -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +pngtest-static: pngtest.o libpng.a + $(CC) -o pngtest-static $(CFLAGS) pngtest.o $(LDFLAGS_A) + +test: pngtest pngtest-static + @echo "" + @echo " Running pngtest dynamically linked with $(LIBSO):" + @echo "" + ./pngtest + @echo "" + @echo " Running pngtest statically linked with libpng.a:" + @echo "" + ./pngtest-static + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) -Wl, -rpath,$(DL) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngout.png libpng-config \ + $(LIBSO) $(LIBSOMAJ)* pngtest-static pngtesti \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h diff --git a/contrib/libpng/scripts/makefile.mips b/contrib/libpng/scripts/makefile.mips new file mode 100644 index 0000000..179d385 --- /dev/null +++ b/contrib/libpng/scripts/makefile.mips @@ -0,0 +1,94 @@ +# makefile for libpng +# Copyright (C) Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# where make install puts libpng.a and png.h +prefix=/usr/local +INCPATH=$(prefix)/include +LIBPATH=$(prefix)/lib + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +CC=cc +CFLAGS=-I../zlib -O -systype sysv -DSYSV -w -Dmips +#CFLAGS=-O +LDFLAGS=-L. -L../zlib/ -lpng -lz -lm + +#RANLIB=ranlib +RANLIB=echo + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: libpng.a pngtest + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + ar rc $@ $(OBJS) + $(RANLIB) $@ + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install: libpng.a + -@mkdir $(DESTDIR)$(INCPATH) + -@mkdir $(DESTDIR)$(INCPATH)/libpng + -@mkdir $(DESTDIR)$(LIBPATH) + -@rm -f $(DESTDIR)$(INCPATH)/png.h + -@rm -f $(DESTDIR)$(INCPATH)/pngconf.h + -@rm -f $(DESTDIR)$(INCPATH)/pnglibconf.h + cp png.h $(DESTDIR)$(INCPATH)/libpng + cp pngconf.h $(DESTDIR)$(INCPATH)/libpng + cp pnglibconf.h $(DESTDIR)$(INCPATH)/libpng + chmod 644 $(DESTDIR)$(INCPATH)/libpng/png.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pngconf.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pnglibconf.h + (cd $(DESTDIR)$(INCPATH); ln -f -s libpng/* .) + cp libpng.a $(DESTDIR)$(LIBPATH) + chmod 644 $(DESTDIR)$(LIBPATH)/libpng.a + +clean: + rm -f *.o libpng.a pngtest pngout.png pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.msc b/contrib/libpng/scripts/makefile.msc new file mode 100644 index 0000000..baa863d --- /dev/null +++ b/contrib/libpng/scripts/makefile.msc @@ -0,0 +1,95 @@ +# makefile for libpng +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# Copyright (C) 2006, 2009 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# Assumes that zlib.lib, zconf.h, and zlib.h have been copied to ..\zlib + +# -------- Microsoft C 5.1 and later, does not use assembler code -------- +MODEL=L +CFLAGS=-Oait -Gs -nologo -W3 -A$(MODEL) -I..\zlib +#-Ox generates bad code with MSC 5.1 +CC=cl +LD=link +LDFLAGS=/e/st:0x1500/noe +O=.obj + +#uncomment next to put error messages in a file +ERRFILE= >> pngerrs + +# variables +OBJS1 = png$(O) pngset$(O) pngget$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O) +OBJS2 = pngmem$(O) pngpread$(O) pngread$(O) pngerror$(O) pngwrite$(O) +OBJS3 = pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O) + +all: libpng.lib + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +libpng.lib: $(OBJS1) $(OBJS2) $(OBJS3) + del libpng.lib + lib libpng $(OBJS1); + lib libpng $(OBJS2); + lib libpng $(OBJS3); + +pngtest$(O): png.h pngconf.h pnglibconf.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngtest.exe: pngtest.obj libpng.lib + $(LD) $(LDFLAGS) pngtest.obj,,,libpng.lib ..\zlib\zlib.lib ; + +test: pngtest.exe + pngtest + +# End of makefile for libpng + diff --git a/contrib/libpng/scripts/makefile.ne12bsd b/contrib/libpng/scripts/makefile.ne12bsd new file mode 100644 index 0000000..7988915 --- /dev/null +++ b/contrib/libpng/scripts/makefile.ne12bsd @@ -0,0 +1,50 @@ +# makefile for libpng for NetBSD for the standard +# make obj && make depend && make && make test +# make includes && make install +# Copyright (C) 2002 Patrick R.L. Welche +# Copyright (C) 2007, 2009 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# You should also run makefile.netbsd + +LOCALBASE?=/usr/local +LIBDIR= ${LOCALBASE}/lib +MANDIR= ${LOCALBASE}/man +INCSDIR=${LOCALBASE}/include/libpng15 + +LIB= png15 +SHLIB_MAJOR= 0 +SHLIB_MINOR= 1.5.1 +SRCS= png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \ + pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \ + pngwtran.c pngmem.c pngerror.c pngpread.c +INCS= png.h pngconf.h pnglibconf.h +MAN= libpng.3 libpngpf.3 png.5 + +CPPFLAGS+=-I${.CURDIR} + +# We should be able to do something like this instead of the manual +# uncommenting, but it core dumps for me at the moment: +# .if ${MACHINE_ARCH} == "i386" +# MKLINT= no +# .endif + +CLEANFILES+=pngtest.o pngtest pnglibconf.h + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +pngtest.o: pngtest.c + ${CC} -c ${CPPFLAGS} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} + +pngtest: pngtest.o libpng.a + ${CC} ${LDFLAGS} ${.ALLSRC} -o${.TARGET} -lz -lm + +test: pngtest + cd ${.CURDIR} && ${.OBJDIR}/pngtest + +.include diff --git a/contrib/libpng/scripts/makefile.netbsd b/contrib/libpng/scripts/makefile.netbsd new file mode 100644 index 0000000..fc98579 --- /dev/null +++ b/contrib/libpng/scripts/makefile.netbsd @@ -0,0 +1,50 @@ +# makefile for libpng for NetBSD for the standard +# make obj && make depend && make && make test +# make includes && make install +# Copyright (C) 2002 Patrick R.L. Welche +# Copyright (C) 2007-2009 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# You should also run makefile.ne15bsd + +LOCALBASE?=/usr/local +LIBDIR= ${LOCALBASE}/lib +MANDIR= ${LOCALBASE}/man +INCSDIR=${LOCALBASE}/include + +LIB= png +SHLIB_MAJOR= 15 +SHLIB_MINOR= 1.5.1 +SRCS= png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \ + pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \ + pngwtran.c pngmem.c pngerror.c pngpread.c +INCS= png.h pngconf.h pnglibconf.h +MAN= libpng.3 libpngpf.3 png.5 + +CPPFLAGS+=-I${.CURDIR} + +# We should be able to do something like this instead of the manual +# uncommenting, but it core dumps for me at the moment: +# .if ${MACHINE_ARCH} == "i386" +# MKLINT= no +# .endif + +CLEANFILES+=pngtest.o pngtest pnglibconf.h + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +pngtest.o: pngtest.c + ${CC} -c ${CPPFLAGS} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} + +pngtest: pngtest.o libpng.a + ${CC} ${LDFLAGS} ${.ALLSRC} -o${.TARGET} -lz -lm + +test: pngtest + cd ${.CURDIR} && ${.OBJDIR}/pngtest + +.include diff --git a/contrib/libpng/scripts/makefile.openbsd b/contrib/libpng/scripts/makefile.openbsd new file mode 100644 index 0000000..196cd0f --- /dev/null +++ b/contrib/libpng/scripts/makefile.openbsd @@ -0,0 +1,82 @@ +# makefile for libpng +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# Copyright (C) 2007-2009 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +PREFIX?= /usr/local +LIBDIR= ${PREFIX}/lib +MANDIR= ${PREFIX}/man/cat + +SHLIB_MAJOR= 15 +SHLIB_MINOR= 1.5.1 + +LIB= png +SRCS= png.c pngerror.c pngget.c pngmem.c pngpread.c \ + pngread.c pngrio.c pngrtran.c pngrutil.c pngset.c pngtrans.c \ + pngwio.c pngwrite.c pngwtran.c pngwutil.c + +HDRS= png.h pngconf.h pnglibconf.h + +CFLAGS+= -W -Wall +CPPFLAGS+= -I${.CURDIR} + +NOPROFILE= Yes + +CLEANFILES+= pngtest.o pngtest pnglibconf.h + +MAN= libpng.3 libpngpf.3 png.5 +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO \ + libpng-manual.txt + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +pngtest.o: pngtest.c + ${CC} ${CPPFLAGS} ${CFLAGS} -c ${.ALLSRC} -o ${.TARGET} + +pngtest: pngtest.o + ${CC} ${LDFLAGS} ${.ALLSRC} -o ${.TARGET} -L${.OBJDIR} -lpng -lz -lm + +test: pngtest + cd ${.OBJDIR} && env \ + LD_LIBRARY_PATH="${.OBJDIR}" ${.OBJDIR}/pngtest + +beforeinstall: + if [ ! -d ${DESTDIR}${PREFIX}/include/libpng ]; then \ + ${INSTALL} -d -o root -g wheel ${DESTDIR}${PREFIX}/include; \ + fi + if [ ! -d ${DESTDIR}${LIBDIR} ]; then \ + ${INSTALL} -d -o root -g wheel ${DESTDIR}${LIBDIR}; \ + fi + if [ ! -d ${DESTDIR}${LIBDIR}/debug ]; then \ + ${INSTALL} -d -o root -g wheel ${DESTDIR}${LIBDIR}/debug; \ + fi + if [ ! -d ${DESTDIR}${MANDIR}3 ]; then \ + ${INSTALL} -d -o root -g wheel ${DESTDIR}${MANDIR}3; \ + fi + if [ ! -d ${DESTDIR}${MANDIR}5 ]; then \ + ${INSTALL} -d -o root -g wheel ${DESTDIR}${MANDIR}5; \ + fi + if [ ! -d ${DESTDIR}${PREFIX}/share/doc/png ]; then \ + ${INSTALL} -d -o root -g wheel ${DESTDIR}${PREFIX}/share/doc/png; \ + fi + +afterinstall: + @rm -f ${DESTDIR}${LIBDIR}/libpng_pic.a + @rm -f ${DESTDIR}${LIBDIR}/debug/libpng.a + @rm -f ${DESTDIR}${PREFIX}/include/png.h + @rm -f ${DESTDIR}${PREFIX}/include/pngconf.h + @rm -f ${DESTDIR}${PREFIX}/include/pnglibconf.h + @rmdir ${DESTDIR}${LIBDIR}/debug 2>/dev/null || true + ${INSTALL} ${INSTALL_COPY} -o ${SHAREOWN} -g ${SHAREGRP} \ + -m ${NONBINMODE} ${HDRS} ${DESTDIR}${PREFIX}/include + ${INSTALL} ${INSTALL_COPY} -o ${SHAREOWN} -g ${SHAREGRP} \ + -m ${NONBINMODE} ${HDRS} ${DESTDIR}${PREFIX}/include + ${INSTALL} ${INSTALL_COPY} -o ${SHAREOWN} -g ${SHAREGRP} \ + -m ${NONBINMODE} ${DOCS} ${DESTDIR}${PREFIX}/share/doc/png + +.include diff --git a/contrib/libpng/scripts/makefile.sco b/contrib/libpng/scripts/makefile.sco new file mode 100644 index 0000000..0aad789 --- /dev/null +++ b/contrib/libpng/scripts/makefile.sco @@ -0,0 +1,218 @@ +# makefile for SCO OSr5 ELF and Unixware 7 with Native cc +# Contributed by Mike Hopkirk (hops@sco.com) modified from Makefile.lnx +# force ELF build dynamic linking, SONAME setting in lib and RPATH in app +# Copyright (C) 2002, 2006, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1998 Greg Roelofs +# Copyright (C) 1996, 1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +CC=cc +AR_RC=ar rc +MKDIR_P=mkdir +LN_SF=ln -f -s +RANLIB=echo +RM_F=/bin/rm -f + +# where make install puts libpng.a, $(OLDSO)*, and png.h +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +CFLAGS= -dy -belf -I$(ZLIBINC) -O3 +LDFLAGS=-L. -L$(ZLIBLIB) -lpng15 -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -KPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo ccopts=\"-belf\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + $(CC) -G -Wl,-h,$(LIBSOMAJ) -o $(LIBSOMAJ) \ + $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + LD_RUN_PATH=.:$(ZLIBLIB) $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + -@$(RM_F) $(DI)/png.h + -@$(RM_F) $(DI)/pngconf.h + -@$(RM_F) $(DI)/pnglibconf.h + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) $(CFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + $(CC) $(CFLAGS) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngout.png libpng-config \ + $(LIBSO) $(LIBSOMAJ)* pngtest-static pngtesti \ + pnglibconf.h libpng.pc + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.sggcc b/contrib/libpng/scripts/makefile.sggcc new file mode 100644 index 0000000..1611638 --- /dev/null +++ b/contrib/libpng/scripts/makefile.sggcc @@ -0,0 +1,228 @@ +# makefile for libpng.a and libpng15.so, SGI IRIX with 'cc' +# Copyright (C) 2001-2002, 2006, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME=libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +AR_RC=ar rc +CC=gcc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=echo +RM_F=/bin/rm -f + +# Where make install puts libpng.a, libpng15.so, and libpng15/png.h +# Prefix must be a full pathname. + +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib32 +#ZLIBINC=/usr/local/include +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +# ABI can be blank to use default for your system, -32, -o32, -n32, or -64 +# See "man abi". zlib must be built with the same ABI. +ABI= + +WARNMORE= # -g -DPNG_DEBUG=5 +CFLAGS=$(ABI) -I$(ZLIBINC) -O $(WARNMORE) -fPIC -mabi=n32 +LDFLAGS=$(ABI) -L. -L$(ZLIBLIB) -lpng -lz -lm +LDSHARED=cc $(ABI) -shared -soname $(LIBSOMAJ) \ + -set_version sgi$(PNGMAJ).0 +# See "man dso" for info about shared objects + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +#LIBPATH=$(exec_prefix)/lib32 +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: libpng.a pngtest shared libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +shared: $(LIBSOMAJ) + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo ccopts=\"$(ABI)\"; \ + echo cppflags=\"\"; \ + echo ldopts=\"$(ABI)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libdir=\"$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJS) + $(LDSHARED) -o $@ $(OBJS) + $(RM_F) $(LIBSO) $(LIBSOMAJ) + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + echo + echo Testing local static library. + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) \ + -rpath $(ZLIBLIB):$(DL) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) \ + -rpath $(ZLIBLIB):`$(BINPATH)/$(LIBNAME)-config --libdir` \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) libpng.a pngtest pngtesti pngout.png libpng.pc \ + so_locations libpng-config $(LIBSO) $(LIBSOMAJ)* pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.sgi b/contrib/libpng/scripts/makefile.sgi new file mode 100644 index 0000000..83db59f --- /dev/null +++ b/contrib/libpng/scripts/makefile.sgi @@ -0,0 +1,229 @@ +# makefile for libpng.a and libpng15.so, SGI IRIX with 'cc' +# Copyright (C) 2001-2002, 2006, 2007, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME=libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +AR_RC=ar rc +CC=cc +MKDIR_P=mkdir -p +LN_SF=ln -sf +RANLIB=echo +RM_F=/bin/rm -f + +# Where make install puts libpng.a, libpng15.so, and libpng15/png.h +# Prefix must be a full pathname. + +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib32 +#ZLIBINC=/usr/local/include +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +# ABI can be blank to use default for your system, -32, -o32, -n32, or -64 +# See "man abi". zlib must be built with the same ABI. +ABI= + +WARNMORE=-fullwarn +# Note: -KPIC is the default anyhow +#CFLAGS= $(ABI) -I$(ZLIBINC) -O $(WARNMORE) -KPIC # -g -DPNG_DEBUG=5 +CFLAGS=$(ABI) -I$(ZLIBINC) -O $(WARNMORE) +LDFLAGS_A=$(ABI) -L. -L$(ZLIBLIB) -lpng15 -lz -lm +LDFLAGS=$(ABI) -L. -L$(ZLIBLIB) -lpng -lz -lm +LDSHARED=cc $(ABI) -shared -soname $(LIBSOMAJ) \ + -set_version sgi$(PNGMAJ).0 +# See "man dso" for info about shared objects + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +#LIBPATH=$(exec_prefix)/lib32 +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: libpng.a pngtest shared libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo ccopts=\"$(ABI)\"; \ + echo ldopts=\"$(ABI)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo libdir=\"$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJS) + $(LDSHARED) -o $@ $(OBJS) + $(RM_F) $(LIBSO) $(LIBSOMAJ) + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + echo + echo Testing local static library. + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(DL) -L$(ZLIBLIB) \ + -rpath $(ZLIBLIB):$(DL) \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -L$(ZLIBLIB) \ + -rpath $(ZLIBLIB):`$(BINPATH)/$(LIBNAME)-config --libdir` \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png libpng.pc libpng-config \ + $(LIBSO) $(LIBSOMAJ)* \ + so_locations pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.so9 b/contrib/libpng/scripts/makefile.so9 new file mode 100644 index 0000000..615c2e3 --- /dev/null +++ b/contrib/libpng/scripts/makefile.so9 @@ -0,0 +1,239 @@ +# makefile for libpng on Solaris 9 (beta) with Forte cc +# Updated by Chad Schrock for Solaris 9 +# Contributed by William L. Sebok, based on makefile.linux +# Copyright (C) 2002, 2006, 2008, 2010-2011 Glenn Randers-Pehrson +# Copyright (C) 1998-2001 Greg Roelofs +# Copyright (C) 1996-1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +PNGMAJ = 15 +LIBNAME = libpng15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +# gcc 2.95 doesn't work. +CC=cc +AR_RC=ar rc +MKDIR_P=mkdir -p +LN_SF=ln -f -s +RANLIB=echo +RM_F=/bin/rm -f + +# Where make install puts libpng.a, $(OLDSO)*, and png.h +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +# Changing these to ../zlib poses a security risk. If you want +# to have zlib in an adjacent directory, specify the full path instead of "..". +#ZLIBLIB=../zlib +#ZLIBINC=../zlib +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +#Use the preinstalled zlib that comes with Solaris 9: +ZLIBLIB=/usr/lib +ZLIBINC=/usr/include + +#WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion +#CFLAGS=-I$(ZLIBINC) -W -Wall -O3 $(WARNMORE) -g -DPNG_DEBUG=5 -DPNG_NO_MMX_CODE +CFLAGS=-I$(ZLIBINC) -O3 -DPNG_NO_MMX_CODE +LDFLAGS=-L. -R. -L$(ZLIBLIB) -R$(ZLIBLIB) -lpng15 -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -KPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo R_opts=\"-R$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + @case "`type ld`" in *ucb*) \ + echo; \ + echo '## WARNING:'; \ + echo '## The commands "CC" and "LD" must NOT refer to /usr/ucb/cc'; \ + echo '## and /usr/ucb/ld. If they do, you need to adjust your PATH'; \ + echo '## environment variable to put /usr/ccs/bin ahead of /usr/ucb.'; \ + echo '## The environment variable LD_LIBRARY_PATH should not be set'; \ + echo '## at all. If it is, things are likely to break because of'; \ + echo '## the libucb dependency that is created.'; \ + echo; \ + ;; \ + esac + $(LD) -G -h $(LIBSOMAJ) \ + -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + -L$(DL) -L$(ZLIBLIB) -R$(ZLIBLIB) -R$(DL) + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.solaris b/contrib/libpng/scripts/makefile.solaris new file mode 100644 index 0000000..24bd610 --- /dev/null +++ b/contrib/libpng/scripts/makefile.solaris @@ -0,0 +1,236 @@ +# makefile for libpng on Solaris 2.x with gcc +# Copyright (C) 2004, 2006-2008, 2010-2011 Glenn Randers-Pehrson +# Contributed by William L. Sebok, based on makefile.linux +# Copyright (C) 1998 Greg Roelofs +# Copyright (C) 1996, 1997 Andreas Dilger +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +AR_RC=ar rc +CC=gcc +MKDIR_P=mkdir -p +LN_SF=ln -f -s +RANLIB=echo +RM_F=/bin/rm -f + +# Where make install puts libpng.a, libpng15.so*, and png.h +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +# Changing these to ../zlib poses a security risk. If you want +# to have zlib in an adjacent directory, specify the full path instead of "..". +#ZLIBLIB=../zlib +#ZLIBINC=../zlib + +ZLIBLIB=/usr/local/lib +ZLIBINC=/usr/local/include + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion +CFLAGS=-I$(ZLIBINC) -W -Wall -O \ + # $(WARNMORE) -g -DPNG_DEBUG=5 +LDFLAGS=-L. -R. -L$(ZLIBLIB) -R$(ZLIBLIB) -lpng15 -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -fPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo cppflags=\"\"; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo R_opts=\"-R$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + @case "`type ld`" in *ucb*) \ + echo; \ + echo '## WARNING:'; \ + echo '## The commands "CC" and "LD" must NOT refer to /usr/ucb/cc'; \ + echo '## and /usr/ucb/ld. If they do, you need to adjust your PATH'; \ + echo '## environment variable to put /usr/ccs/bin ahead of /usr/ucb.'; \ + echo '## The environment variable LD_LIBRARY_PATH should not be set'; \ + echo '## at all. If it is, things are likely to break because of'; \ + echo '## the libucb dependency that is created.'; \ + echo; \ + ;; \ + esac + $(LD) -G -h $(LIBSOMAJ) \ + -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + -L$(DL) -L$(ZLIBLIB) -R$(ZLIBLIB) -R$(DL) + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.solaris-x86 b/contrib/libpng/scripts/makefile.solaris-x86 new file mode 100644 index 0000000..7646762 --- /dev/null +++ b/contrib/libpng/scripts/makefile.solaris-x86 @@ -0,0 +1,236 @@ +# makefile for libpng on Solaris 2.x with gcc +# Copyright (C) 2004, 2006-2008, 2010-2011 Glenn Randers-Pehrson +# Contributed by William L. Sebok, based on makefile.linux +# Copyright (C) 1998 Greg Roelofs +# Copyright (C) 1996, 1997 Andreas Dilger + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Library name: +LIBNAME = libpng15 +PNGMAJ = 15 + +# Shared library names: +LIBSO=$(LIBNAME).so +LIBSOMAJ=$(LIBNAME).so.$(PNGMAJ) +LIBSOREL=$(LIBSOMAJ).$(RELEASE) +OLDSO=libpng.so + +# Utilities: +AR_RC=ar rc +CC=gcc +MKDIR_P=mkdir -p +LN_SF=ln -f -s +RANLIB=echo +RM_F=/bin/rm -f + +# Where make install puts libpng.a, libpng15.so*, and png.h +prefix=/usr/local +exec_prefix=$(prefix) + +# Where the zlib library and include files are located +# Changing these to ../zlib poses a security risk. If you want +# to have zlib in an adjacent directory, specify the full path instead of "..". +#ZLIBLIB=../zlib +#ZLIBINC=../zlib + +ZLIBLIB=/usr/local/lib +ZLIBINC=/usr/local/include + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes #-Wconversion +CFLAGS=-I$(ZLIBINC) -W -Wall -O \ + # $(WARNMORE) -g -DPNG_DEBUG=5 +LDFLAGS=-L. -R. -L$(ZLIBLIB) -R$(ZLIBLIB) -lpng15 -lz -lm + +INCPATH=$(prefix)/include +LIBPATH=$(exec_prefix)/lib +MANPATH=$(prefix)/man +BINPATH=$(exec_prefix)/bin + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +DB=$(DESTDIR)$(BINPATH) +DI=$(DESTDIR)$(INCPATH) +DL=$(DESTDIR)$(LIBPATH) +DM=$(DESTDIR)$(MANPATH) + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +OBJSDLL = $(OBJS:.o=.pic.o) + +.SUFFIXES: .c .o .pic.o + +.c.pic.o: + $(CC) -c $(CFLAGS) -fPIC -o $@ $*.c + +all: libpng.a $(LIBSO) pngtest libpng.pc libpng-config + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +libpng.pc: + cat scripts/libpng.pc.in | sed -e s!@prefix@!$(prefix)! \ + -e s!@exec_prefix@!$(exec_prefix)! \ + -e s!@libdir@!$(LIBPATH)! \ + -e s!@includedir@!$(INCPATH)! \ + -e s!-lpng15!-lpng15\ -lz\ -lm! > libpng.pc + +libpng-config: + ( cat scripts/libpng-config-head.in; \ + echo prefix=\"$(prefix)\"; \ + echo I_opts=\"-I$(INCPATH)/$(LIBNAME)\"; \ + echo cppflags=\""; \ + echo L_opts=\"-L$(LIBPATH)\"; \ + echo R_opts=\"-R$(LIBPATH)\"; \ + echo libs=\"-lpng15 -lz -lm\"; \ + cat scripts/libpng-config-body.in ) > libpng-config + chmod +x libpng-config + +$(LIBSO): $(LIBSOMAJ) + $(LN_SF) $(LIBSOMAJ) $(LIBSO) + +$(LIBSOMAJ): $(OBJSDLL) + @case "`type ld`" in *ucb*) \ + echo; \ + echo '## WARNING:'; \ + echo '## The commands "CC" and "LD" must NOT refer to /usr/ucb/cc'; \ + echo '## and /usr/ucb/ld. If they do, you need to adjust your PATH'; \ + echo '## environment variable to put /usr/ccs/bin ahead of /usr/ucb.'; \ + echo '## The environment variable LD_LIBRARY_PATH should not be set'; \ + echo '## at all. If it is, things are likely to break because of'; \ + echo '## the libucb dependency that is created.'; \ + echo; \ + ;; \ + esac + $(LD) -G -h $(LIBSOMAJ) \ + -o $(LIBSOMAJ) $(OBJSDLL) + +pngtest: pngtest.o $(LIBSO) + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install-headers: png.h pngconf.h pnglibconf.h + -@if [ ! -d $(DI) ]; then $(MKDIR_P) $(DI); fi + -@if [ ! -d $(DI)/$(LIBNAME) ]; then $(MKDIR_P) $(DI)/$(LIBNAME); fi + cp png.h pngconf.h pnglibconf.h $(DI)/$(LIBNAME) + chmod 644 $(DI)/$(LIBNAME)/png.h $(DI)/$(LIBNAME)/pngconf.h $(DI)/$(LIBNAME)/pnglibconf.h + -@$(RM_F) $(DI)/png.h $(DI)/pngconf.h $(DI)/pnglibconf.h + -@$(RM_F) $(DI)/libpng + (cd $(DI); $(LN_SF) $(LIBNAME) libpng; $(LN_SF) $(LIBNAME)/* .) + +install-static: install-headers libpng.a + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + cp libpng.a $(DL)/$(LIBNAME).a + chmod 644 $(DL)/$(LIBNAME).a + -@$(RM_F) $(DL)/libpng.a + (cd $(DL); $(LN_SF) $(LIBNAME).a libpng.a) + +install-shared: install-headers $(LIBSOMAJ) libpng.pc + -@if [ ! -d $(DL) ]; then $(MKDIR_P) $(DL); fi + -@$(RM_F) $(DL)/$(LIBSO) + -@$(RM_F) $(DL)/$(LIBSOREL) + -@$(RM_F) $(DL)/$(OLDSO) + cp $(LIBSOMAJ) $(DL)/$(LIBSOREL) + chmod 755 $(DL)/$(LIBSOREL) + (cd $(DL); \ + $(LN_SF) $(LIBSOREL) $(LIBSO); \ + $(LN_SF) $(LIBSO) $(OLDSO)) + -@if [ ! -d $(DL)/pkgconfig ]; then $(MKDIR_P) $(DL)/pkgconfig; fi + -@$(RM_F) $(DL)/pkgconfig/$(LIBNAME).pc + -@$(RM_F) $(DL)/pkgconfig/libpng.pc + cp libpng.pc $(DL)/pkgconfig/$(LIBNAME).pc + chmod 644 $(DL)/pkgconfig/$(LIBNAME).pc + (cd $(DL)/pkgconfig; $(LN_SF) $(LIBNAME).pc libpng.pc) + +install-man: libpng.3 libpngpf.3 png.5 + -@if [ ! -d $(DM) ]; then $(MKDIR_P) $(DM); fi + -@if [ ! -d $(DM)/man3 ]; then $(MKDIR_P) $(DM)/man3; fi + -@$(RM_F) $(DM)/man3/libpng.3 + -@$(RM_F) $(DM)/man3/libpngpf.3 + cp libpng.3 $(DM)/man3 + cp libpngpf.3 $(DM)/man3 + -@if [ ! -d $(DM)/man5 ]; then $(MKDIR_P) $(DM)/man5; fi + -@$(RM_F) $(DM)/man5/png.5 + cp png.5 $(DM)/man5 + +install-config: libpng-config + -@if [ ! -d $(DB) ]; then $(MKDIR_P) $(DB); fi + -@$(RM_F) $(DB)/libpng-config + -@$(RM_F) $(DB)/$(LIBNAME)-config + cp libpng-config $(DB)/$(LIBNAME)-config + chmod 755 $(DB)/$(LIBNAME)-config + (cd $(DB); $(LN_SF) $(LIBNAME)-config libpng-config) + +install: install-static install-shared install-man install-config + +# If you installed in $(DESTDIR), test-installed won't work until you +# move the library to its final location. Use test-dd to test it +# before then. + +test-dd: + echo + echo Testing installed dynamic shared library in $(DL). + $(CC) -I$(DI) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtestd `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + -L$(DL) -L$(ZLIBLIB) -R$(ZLIBLIB) -R$(DL) + ./pngtestd pngtest.png + +test-installed: + echo + echo Testing installed dynamic shared library. + $(CC) -I$(ZLIBINC) \ + `$(BINPATH)/$(LIBNAME)-config --cflags` pngtest.c \ + -o pngtesti `$(BINPATH)/$(LIBNAME)-config --ldflags` \ + -L$(ZLIBLIB) -R$(ZLIBLIB) + ./pngtesti pngtest.png + +clean: + $(RM_F) *.o libpng.a pngtest pngtesti pngout.png \ + libpng-config $(LIBSO) $(LIBSOMAJ)* \ + libpng.pc pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o png.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o pngerror.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o pngrio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o pngwio.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o pngmem.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o pngset.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o pngget.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o pngread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o pngrtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o pngrutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o pngtrans.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o pngwrite.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o pngwtran.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o pngwutil.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o pngpread.pic.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.std b/contrib/libpng/scripts/makefile.std new file mode 100644 index 0000000..30e1646 --- /dev/null +++ b/contrib/libpng/scripts/makefile.std @@ -0,0 +1,123 @@ +# makefile for libpng +# Copyright (C) 2002, 2006 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# where make install puts libpng.a and png.h +prefix=/usr/local +INCPATH=$(prefix)/include +LIBPATH=$(prefix)/lib + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + +CC=cc +AR_RC=ar rc +MKDIR_P=mkdir +LN_SF=ln -sf +RANLIB=ranlib +RM_F=rm -f +AWK = awk +SED = sed +CPP = $(CC) -E +ECHO = echo + +DFNFLAGS = # DFNFLAGS contains -D options to use in the libpng build +CFLAGS=-I$(ZLIBINC) -O # -g -DPNG_DEBUG=5 +LDFLAGS=-L. -L$(ZLIBLIB) -lpng -lz -lm + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: libpng.a pngtest + +# The standard pnglibconf.h exists as scripts/pnglibconf.h.prebuilt, +# copy this if the following doesn't work. +pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk + $(RM_F) $@ dfn?.out + $(AWK) -f scripts/options.awk out=dfn1.out\ + scripts/pnglibconf.dfa $(DFA_XTRA) 1>&2 + $(AWK) -f scripts/options.awk out=dfn2.out dfn1.out 1>&2 + cp dfn2.out $@ + $(RM_F) dfn?.out + +pnglibconf.h: pnglibconf.dfn + $(RM_F) $@ dfn.c dfn?.out + $(ECHO) '#include "pnglibconf.dfn"' >dfn.c + $(CPP) $(DFNFLAGS) dfn.c >dfn1.out + $(SED) -n -e 's|^.*PNG_DEFN_MAGIC-\(.*\)-PNG_DEFN_END.*$$|\1|p'\ + dfn1.out >dfn2.out + $(SED) -e 's| *@@@ *||g' -e 's| *$$||' dfn2.out >dfn3.out + cp dfn3.out $@ + $(RM_F) dfn.c dfn?.out + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install: libpng.a pnglibconf.h + -@$(MKDIR_P) $(DESTDIR)$(INCPATH) + -@$(MKDIR_P) $(DESTDIR)$(INCPATH)/libpng + -@$(MKDIR_P) $(DESTDIR)$(LIBPATH) + -@$(RM_F) $(DESTDIR)$(INCPATH)/png.h + -@$(RM_F) $(DESTDIR)$(INCPATH)/pngconf.h + -@$(RM_F) $(DESTDIR)$(INCPATH)/pnglibconf.h + cp png.h $(DESTDIR)$(INCPATH)/libpng + cp pngconf.h $(DESTDIR)$(INCPATH)/libpng + cp pnglibconf.h $(DESTDIR)$(INCPATH)/libpng + chmod 644 $(DESTDIR)$(INCPATH)/libpng/png.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pngconf.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pnglibconf.h + (cd $(DESTDIR)$(INCPATH); ln -f -s libpng/* .) + cp libpng.a $(DESTDIR)$(LIBPATH) + chmod 644 $(DESTDIR)$(LIBPATH)/libpng.a + +clean: + $(RM_F) *.o libpng.a pngtest pngout.png pnglibconf.* dfn.c dfn?.out + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.sunos b/contrib/libpng/scripts/makefile.sunos new file mode 100644 index 0000000..3839549 --- /dev/null +++ b/contrib/libpng/scripts/makefile.sunos @@ -0,0 +1,107 @@ +# makefile for libpng +# Copyright (C) 2002, 2006 Glenn Randers-Pehrson +# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# where make install puts libpng.a and png.h +prefix=/usr/local +INCPATH=$(prefix)/include +LIBPATH=$(prefix)/lib + +# override DESTDIR= on the make install command line to easily support +# installing into a temporary location. Example: +# +# make install DESTDIR=/tmp/build/libpng +# +# If you're going to install into a temporary location +# via DESTDIR, $(DESTDIR)$(prefix) must already exist before +# you execute make install. +DESTDIR= + +# Where the zlib library and include files are located +#ZLIBLIB=/usr/local/lib +#ZLIBINC=/usr/local/include +ZLIBLIB=../zlib +ZLIBINC=../zlib + + +WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow -Wconversion \ + -Wmissing-declarations -Wtraditional -Wcast-align \ + -Wstrict-prototypes -Wmissing-prototypes + +CC=gcc +AR_RC=ar rc +MKDIR_P=mkdir -p +LN_SF=ln -f -s +RANLIB=ranlib +RM_F=/bin/rm -f + +CFLAGS=-I$(ZLIBINC) -O # $(WARNMORE) -DPNG_DEBUG=5 +LDFLAGS=-L. -L$(ZLIBLIB) -lpng -lz -lm + +OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \ + pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ + pngwtran.o pngmem.o pngerror.o pngpread.o + +all: libpng.a pngtest + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +libpng.a: $(OBJS) + $(AR_RC) $@ $(OBJS) + $(RANLIB) $@ + +pngtest: pngtest.o libpng.a + $(CC) -o pngtest $(CFLAGS) pngtest.o $(LDFLAGS) + +test: pngtest + ./pngtest + +install: libpng.a + -@$(MKDIR_P) $(DESTDIR)$(INCPATH) + -@$(MKDIR_P) $(DESTDIR)$(INCPATH)/libpng + -@$(MKDIR_P) $(DESTDIR)$(LIBPATH) + -@$(RM_F) $(DESTDIR)$(INCPATH)/png.h + -@$(RM_F) $(DESTDIR)$(INCPATH)/pngconf.h + -@$(RM_F) $(DESTDIR)$(INCPATH)/pnglibconf.h + cp png.h $(DESTDIR)$(INCPATH)/libpng + cp pngconf.h $(DESTDIR)$(INCPATH)/libpng + cp pnglibconf.h $(DESTDIR)$(INCPATH)/libpng + chmod 644 $(DESTDIR)$(INCPATH)/libpng/png.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pngconf.h + chmod 644 $(DESTDIR)$(INCPATH)/libpng/pnglibconf.h + (cd $(DESTDIR)$(INCPATH); $(LN_SF) libpng/* .) + cp libpng.a $(DESTDIR)$(LIBPATH) + chmod 644 $(DESTDIR)$(LIBPATH)/libpng.a + +clean: + $(RM_F) *.o libpng.a pngtest pngout.png pnglibconf.h + +DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO +writelock: + chmod a-w *.[ch35] $(DOCS) scripts/* + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +png.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngerror.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwio.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngmem.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngset.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngget.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngrutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngtrans.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwrite.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwtran.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngwutil.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +pngpread.o: png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + +pngtest.o: png.h pngconf.h pnglibconf.h diff --git a/contrib/libpng/scripts/makefile.tc3 b/contrib/libpng/scripts/makefile.tc3 new file mode 100644 index 0000000..462c47f --- /dev/null +++ b/contrib/libpng/scripts/makefile.tc3 @@ -0,0 +1,93 @@ +# Makefile for libpng +# TurboC/C++ (Note: All modules are compiled in C mode) + +# To use, do "make -fmakefile.tc3" + +# ----- Turbo C 3.00 (can be modified to work with earlier versions) ----- + +MODEL=l +CFLAGS=-O2 -Z -m$(MODEL) -I..\zlib +#CFLAGS=-D_NO_PROTO -O2 -Z -m$(MODEL) -I..\zlib # Turbo C older than 3.00 +CC=tcc +LD=tcc +LIB=tlib +LDFLAGS=-m$(MODEL) -L..\zlib +O=.obj +E=.exe + +# variables +OBJS1 = png$(O) pngset$(O) pngget$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O) +OBJS2 = pngmem$(O) pngpread$(O) pngread$(O) pngerror$(O) pngwrite$(O) +OBJS3 = pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O) +OBJSL1 = +png$(O) +pngset$(O) +pngget$(O) +pngrutil$(O) +pngtrans$(O) +OBJSL2 = +pngwutil$(O) +pngmem$(O) +pngpread$(O) +pngread$(O) +pngerror$(O) +OBJSL3 = +pngwrite$(O) +pngrtran$(O) +pngwtran$(O) +pngrio$(O) +pngwio$(O) + +all: libpng$(MODEL).lib pngtest$(E) + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +pngtest: pngtest$(E) + +test: pngtest$(E) + pngtest$(E) + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngtest$(O): png.h pngconf.h pnglibconf.h + $(CC) -c $(CFLAGS) $*.c + +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c + +libpng$(MODEL).lib: $(OBJS1) $(OBJS2) $(OBJS3) + $(LIB) libpng$(MODEL) +$(OBJSL1) + $(LIB) libpng$(MODEL) +$(OBJSL2) + $(LIB) libpng$(MODEL) +$(OBJSL3) + +pngtest$(E): pngtest$(O) libpng$(MODEL).lib + $(LD) $(LDFLAGS) pngtest.obj libpng$(MODEL).lib zlib_$(MODEL).lib + +# End of makefile for libpng diff --git a/contrib/libpng/scripts/makefile.vcwin32 b/contrib/libpng/scripts/makefile.vcwin32 new file mode 100644 index 0000000..e3b2b82 --- /dev/null +++ b/contrib/libpng/scripts/makefile.vcwin32 @@ -0,0 +1,108 @@ +# makefile for libpng +# Copyright (C) 1998 Tim Wegner +# Copyright (C) 2006,2009 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# Assumes that zlib.lib, zconf.h, and zlib.h have been copied to ..\zlib +# To use, do "nmake /f scripts\makefile.vcwin32" + +# -------- Microsoft Visual C++ 2.0 and later, no assembler code -------- + +# Compiler, linker, librarian, and other tools +CC = cl +LD = link +AR = lib +CFLAGS = -nologo -MD -O2 -W3 -I..\zlib +LDFLAGS = -nologo +ARFLAGS = -nologo +RM = del + +# File extensions +O=.obj + +#uncomment next to put error messages in a file +#ERRFILE= >> pngerrs.log + +# Variables +OBJS1 = png$(O) pngerror$(O) pngget$(O) pngmem$(O) pngpread$(O) +OBJS2 = pngread$(O) pngrio$(O) pngrtran$(O) pngrutil$(O) pngset$(O) +OBJS3 = pngtrans$(O) pngwio$(O) pngwrite$(O) pngwtran$(O) pngwutil$(O) +OBJS = $(OBJS1) $(OBJS2) $(OBJS3) + +# Targets +all: libpng.lib + +# see scripts/pnglibconf.mak for more options +pnglibconf.h: scripts/pnglibconf.h.prebuilt + cp scripts/pnglibconf.h.prebuilt $@ + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +libpng.lib: $(OBJS) + -$(RM) $@ + $(AR) $(ARFLAGS) -out:$@ $(OBJS) $(ERRFILE) + +pngtest$(O): png.h pngconf.h pnglibconf.h + $(CC) -c $(CFLAGS) $*.c $(ERRFILE) + +pngtest.exe: pngtest$(O) libpng.lib + $(LD) $(LDFLAGS) -out:$@ pngtest$(O) libpng.lib ..\zlib\zlib.lib $(ERRFILE) + +test: pngtest.exe + pngtest + +clean: + -$(RM) *$(O) + -$(RM) libpng.lib + -$(RM) pnglibconf.h + -$(RM) pngtest.exe + -$(RM) pngout.png + +# End of makefile for libpng + diff --git a/contrib/libpng/scripts/makefile.watcom b/contrib/libpng/scripts/makefile.watcom new file mode 100644 index 0000000..983b4e3 --- /dev/null +++ b/contrib/libpng/scripts/makefile.watcom @@ -0,0 +1,122 @@ +# Makefile for libpng +# Watcom C/C++ 10.0 and later, 32-bit protected mode, flat memory model + +# Copyright (C) 2000, Pawel Mrochen, based on makefile.msc which is +# copyright 1995 Guy Eric Schalnat, Group 42, Inc. +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# To use, do "wmake /f scripts\makefile.watcom" + + +# ---------------------- Watcom C/C++ 10.0 and later ----------------------- + +# Where the zlib library and include files are located +ZLIBLIB=..\zlib +ZLIBINC=..\zlib + +# Target OS +OS=DOS +#OS=NT + +# Target CPU +CPU=6 # Pentium Pro +#CPU=5 # Pentium + +# Calling convention +CALLING=r # registers +#CALLING=s # stack + +# Uncomment next to put error messages in a file +#ERRFILE=>>pngerrs + +# -------------------------------------------------------------------------- + + +CC=wcc386 +CFLAGS=-$(CPU)$(CALLING) -fp$(CPU) -fpi87 -oneatx -mf -bt=$(OS) -i=$(ZLIBINC) -zq +LD=wcl386 +LDFLAGS=-zq + +O=.obj + +OBJS1=png$(O) pngset$(O) pngget$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O) +OBJS2=pngmem$(O) pngpread$(O) pngread$(O) pngerror$(O) pngwrite$(O) +OBJS3=pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O) + + +all: test + +# see scripts/pnglibconf.mak for more options +# to support watcom calling conventions it is necessary to set PNG_API_RULE to 2 +# in pnglibconf.h - copy scripts/pnglibconf.h.prebuilt, delete the first line and change +# the definition of PNG_API_RULE from 0 to 2. +# +# If you know how to do this with the Watcom build system please supply a patch +# for this makefile to the PNG implementation list. +pnglibconf.h: scripts/pnglibconf.h.prebuilt + @echo please copy scripts/pnglibconf.h.prebuilt and change PNG_API_RULE to 2 + +png$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngset$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngget$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngpread$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngrtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngrutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngerror$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngmem$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngrio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwio$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngtest$(O): png.h pngconf.h pnglibconf.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngtrans$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwrite$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwtran$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +pngwutil$(O): png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h + $(CC) $(CFLAGS) $*.c $(ERRFILE) + +libpng.lib: $(OBJS1) $(OBJS2) $(OBJS3) + wlib -b -c -n -q libpng.lib $(OBJS1) + wlib -b -c -q libpng.lib $(OBJS2) + wlib -b -c -q libpng.lib $(OBJS3) + +pngtest.exe: pngtest.obj libpng.lib + $(LD) $(LDFLAGS) pngtest.obj libpng.lib $(ZLIBLIB)\zlib.lib + +test: pngtest.exe .symbolic + pngtest.exe + + +# End of makefile for libpng diff --git a/contrib/libpng/scripts/makevms.com b/contrib/libpng/scripts/makevms.com new file mode 100644 index 0000000..f6c3261 --- /dev/null +++ b/contrib/libpng/scripts/makevms.com @@ -0,0 +1,142 @@ +$! make libpng under VMS +$! +$! +$! Check for MMK/MMS +$! +$! This procedure accepts one parameter (contrib), which causes it to build +$! the programs from the contrib directory instead of libpng. +$! +$ p1 = f$edit(p1,"UPCASE") +$ if p1 .eqs. "CONTRIB" +$ then +$ set def [.contrib.gregbook] +$ @makevms +$ set def [-.pngminus] +$ @makevms +$ set def [--] +$ exit +$ endif +$ Make = "" +$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS" +$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK" +$! +$! Look for the compiler used +$! +$ zlibsrc = "[-.zlib]" +$ ccopt="/include=''zlibsrc'" +$ 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 +$! +$! Build the thing plain or with mms/mmk +$! +$ write sys$output "Compiling Libpng sources ..." +$ if make.eqs."" +$ then +$ dele pngtest.obj;* +$ CALL MAKE png.OBJ "cc ''CCOPT' png" - + png.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngset.OBJ "cc ''CCOPT' pngset" - + pngset.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngget.OBJ "cc ''CCOPT' pngget" - + pngget.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngread.OBJ "cc ''CCOPT' pngread" - + pngread.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngpread.OBJ "cc ''CCOPT' pngpread" - + pngpread.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngrtran.OBJ "cc ''CCOPT' pngrtran" - + pngrtran.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngrutil.OBJ "cc ''CCOPT' pngrutil" - + pngrutil.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngerror.OBJ "cc ''CCOPT' pngerror" - + pngerror.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngmem.OBJ "cc ''CCOPT' pngmem" - + pngmem.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngrio.OBJ "cc ''CCOPT' pngrio" - + pngrio.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngwio.OBJ "cc ''CCOPT' pngwio" - + pngwio.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngtrans.OBJ "cc ''CCOPT' pngtrans" - + pngtrans.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngwrite.OBJ "cc ''CCOPT' pngwrite" - + pngwrite.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngwtran.OBJ "cc ''CCOPT' pngwtran" - + pngwtran.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ CALL MAKE pngwutil.OBJ "cc ''CCOPT' pngwutil" - + pngwutil.c png.h pngconf.h pnglibconf.h pngpriv.h pngstruct.h pnginfo.h pngdebug.h +$ write sys$output "Building Libpng ..." +$ CALL MAKE libpng.OLB "lib/crea libpng.olb *.obj" *.OBJ +$ write sys$output "Building pngtest..." +$ CALL MAKE pngtest.OBJ "cc ''CCOPT' pngtest" - + pngtest.c png.h pngconf.h pnglibconf.h +$ call make pngtest.exe - + "LINK pngtest,libpng.olb/lib,''zlibsrc'libz.olb/lib" - + pngtest.obj libpng.olb +$ write sys$output "Testing Libpng..." +$ run pngtest +$ else +$ if f$search("DESCRIP.MMS") .eqs. "" then copy/nolog [.SCRIPTS]DESCRIP.MMS [] +$ 'make'/macro=('comp',zlibsrc='zlibsrc') +$ endif +$ write sys$output "Libpng build completed" +$ 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 diff --git a/contrib/libpng/scripts/options.awk b/contrib/libpng/scripts/options.awk new file mode 100755 index 0000000..96c600e --- /dev/null +++ b/contrib/libpng/scripts/options.awk @@ -0,0 +1,734 @@ +#!/bin/awk -f +# scripts/options.awk - library build configuration control +# +# last changed in libpng version 1.5.0 - January 6, 2011 +# +# Copyright (c) 1998-2011 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# The output of this script is written to the file given by +# the variable 'out'. The script is run twice, once with +# an intermediate output file, 'options.tmp' then again on +# that file to produce the final output: +# +# awk -f scripts/options.awk out=options.tmp scripts/options.dfa 1>&2 +# awk -f scripts/options.awk out=options.dfn options.tmp 1>&2 +# +# Some options may be specified on the command line: +# +# deb=1 Causes debugging to be output +# logunsupported=1 Causes all options to be recorded in the output +# everything=off Causes all options to be disabled by default +# everything=on Causes all options to be enabled by default +# +# If awk fails on your platform, try nawk instead. +# +# These options may also be specified in the original input file (and +# are copied to the preprocessed file). + +BEGIN{ + out="/dev/null" # intermediate, preprocessed, file + pre=-1 # preprocess (first line) + err=0 # in-line exit sets this + start="PNG_DEFN_MAGIC-" # Arbitrary start + end="-PNG_DEFN_END" # Arbitrary end + cx= "/@@@*" # Open C comment for output file + comment=start cx # Comment start + cend="*/" end # Comment end + def=start "#define PNG_@@@" # Arbitrary define + sup="@@@_SUPPORTED" end # end supported option + und=comment "#undef PNG_@@@" # Unsupported option + une="@@@_SUPPORTED" cend # end unsupported option + error=start "ERROR:" # error message + + # Variables + deb=0 # debug - set on command line + everything="" # do not override defaults + logunsupported=0 # write unsupported options too + + # Precreate arrays + option[""] = "" # list of all options: default enabled/disabled + done[""] = 1 # marks option as having been output + requires[""] = "" # requires by option + iffs[""] = "" # if by option + enabledby[""] = "" # options that enable it by option + setting[""] = "" # requires by setting + defaults[""] = "" # used for a defaulted value + doneset[""] = 1 # marks setting as having been output + r[""] = "" # Temporary array + + # For decorating the output file + protect = "" +} + +# The output file must be specified before any input: +out == "/dev/null" { + print "out=output.file must be given on the command line" + err = 1 + exit 1 +} + +# The very first line indicates whether we are reading pre-processed +# input or not, this must come *first* because 'PREPROCESSED' needs +# to be the very first line in the temporary file. +pre == -1{ + if ($0 == "PREPROCESSED") { + pre = 0 + next + } else { + pre = 1 + print "PREPROCESSED" >out + # And fall through to continue processing + } +} + +# variable=value +# Sets the given variable to the given value (the syntax is fairly +# free form, except for deb (you are expected to understand how to +# set the debug variable...) +# +# This happens before the check on 'pre' below skips most of the +# rest of the actions, so the variable settings happen during +# preprocessing but are recorded in the END action too. This +# allows them to be set on the command line too. +$0 ~ /^[ ]*everything[ =]*off[ ]*$/{ + everything = "off" + next +} +$0 ~ /^[ ]*everything[ =]*on[ ]*$/{ + everything = "on" + next +} +$0 ~ /^[ ]*logunsupported[ =]*0[ ]*$/{ + logunsupported = 0 + next +} +$0 ~ /^[ ]*logunsupported[ =]*1[ ]*$/{ + logunsupported = 1 + next +} +$1 == "deb" && $2 == "=" && NF == 3{ + deb = $3 + next +} + +# Preprocessing - this just copies the input file with lines +# that need preprocessing (just chunk at present) expanded +# The bare "pre" instead of "pre != 0" crashes under Sunos awk +pre && $1 != "chunk"{ + print >out + next +} + +# The first characters of the line determine how it is processed, +# leading spaces are ignored. In general tokens that are not +# keywords are the names of options. An option 'name' is +# controlled by the definition of the corresponding macros: +# +# PNG_name_SUPPORTED The option is turned on +# PNG_NO_name +# PNG_NO_name_SUPPORTED If the first macro is not defined +# either of these will turn the option off +# +# If none of these macros are defined the option is turned on, unless +# the keyword 'off' is given in a line relating to the option. The +# keyword 'on' can also be given, but it will be ignored (since it is +# the default.) +# +# In the syntax below a 'name' is indicated by "NAME", other macro +# values are indicated by "MACRO", as with "NAME" the leading "PNG_" +# is omitted, but in this case the "NO_" prefix and the "_SUPPORTED" +# suffix are never used. +# +# Each line is introduced by a keyword - the first non-space characters +# on the line. A line starting with a '#' is a comment - it is totally +# ignored. Keywords are as follows, a NAME, is simply a macro name +# without the leading PNG_, PNG_NO_ or the trailing _SUPPORTED. + +$1 ~ /^#/ || $0 ~ /^[ ]*$/{ + next +} + +# com +# The whole line is placed in the output file as a comment with +# the preceding 'com' removed +$1 == "com"{ + if (NF > 1) { + # sub(/^[ ]*com[ ]*/, "") + $1 = "" + print comment, $0, cend >out + } else + print start end >out + next +} + +# file output input protect +# Informational: the official name of the input file (without +# make generated local directories), the official name of the +# output file and, if required, a name to use in a protection +# macro for the contents. +$1 == "file" && NF >= 2{ + print comment, $2, cend >out + print comment, "Machine generated file: DO NOT EDIT", cend >out + if (NF >= 3) + print comment, "Derived from:", $3, cend >out + protect = $4 + if (protect != "") { + print start "#ifndef", protect end >out + print start "#define", protect end >out + } + next +} + +# option NAME ( (requires|enables|if) NAME* | on | off | disabled )* +# Declares an option 'NAME' and describes its default setting (disabled) +# and its relationship to other options. The option is disabled +# unless *all* the options listed after 'requires' are set and at +# least one of the options listed after 'if' is set. If the +# option is set then it turns on all the options listed after 'enables'. +# +# Note that "enables" takes priority over the required/if/disabled/off +# setting of the target option. +# +# The definition file may list an option as 'disabled': off by default, +# otherwise the option is enabled: on by default. A later (and it must +# be later) entry may turn an option on or off explicitly. + +$1 == "option" && NF >= 2{ + onoff = option[$2] # records current (and the default is "", enabled) + key = "" + for (i=3; i<=NF; ++i) { + if ($(i) == "on" || $(i) == "off" || $(i) == "disabled") { + key = "" + if (onoff != $(i)) { + # on or off can zap disabled or enabled: + if (onoff == "" || (onoff == "disabled" || onoff == "enabled") && ($(i) == "on" || $(i) == "off")) { + # It's easy to mis-spell the option when turning it + # on or off, so warn about it here: + if (onoff == "" && ($(i) == "on" || $(i) == "off")) { + print $2 ": ERROR: turning unrecognized option", $(i) + # For the moment error out - it is safer + err = 1 # prevent END{} running + exit 1 + } + onoff = $(i) + } else { + # Print a message, otherwise the error + # below is incomprehensible + print $2 ": currently", onoff ": attempt to turn", $(i) + break + } + } + } else if ($(i) == "requires" || $(i) == "if" || $(i) == "enables") { + key = $(i) + } else if (key == "requires") { + requires[$2] = requires[$2] " " $(i) + } else if (key == "if") { + iffs[$2] = iffs[$2] " " $(i) + } else if (key == "enables") { + enabledby[$(i)] = enabledby[$(i)] " " $2 + } else + break # bad line format + } + + if (i > NF) { + # Set the option, defaulting to 'enabled' + if (onoff == "") onoff = "enabled" + option[$2] = onoff + next + } + # Else fall through to the error handler +} + +# chunk NAME [requires OPT] [on|off|disabled] +# Expands to the 'option' settings appropriate to the reading and +# writing of an ancilliary PNG chunk 'NAME': +# +# option READ_NAME requires READ_ANCILLARY_CHUNKS [READ_OPT] +# option READ_NAME enables NAME +# [option READ_NAME off] +# option WRITE_NAME requires WRITE_ANCILLARY_CHUNKS [WRITE_OPT] +# option WRITE_NAME enables NAME +# [option WRITE_NAME off] + +pre != 0 && $1 == "chunk" && NF >= 2{ + # 'chunk' is handled on the first pass by writing appropriate + # 'option' lines into the intermediate file. + onoff = "" + reqread = "" + reqwrite = "" + i = 3 # indicates format error + if (NF > 2) { + # read the keywords/additional OPTS + req = 0 + for (i=3; i<=NF; ++i) { + if ($(i) == "on" || $(i) == "off" || $(i) == "disabled") { + if (onoff != $(i)) { + if (onoff == "") + onoff = $(i) + else + break # on/off conflict + } + } else if ($(i) == "requires") + req = 1 + else if (req != 1) + break # bad line: handled below + else { + reqread = reqread " READ_" $(i) + reqwrite = reqwrite " WRITE_" $(i) + } + } + } + + if (i > NF) { + # Output new 'option' lines to the intermediate file (out) + print "option READ_" $2, "requires READ_ANCILLARY_CHUNKS" reqread, "enables", $2, onoff >out + print "option WRITE_" $2, "requires WRITE_ANCILLARY_CHUNKS" reqwrite, "enables", $2, onoff >out + next + } + # Else hit the error handler below - bad line format! +} + +# setting MACRO ( requires MACRO* )* [ default VALUE ] +# Behaves in a similar way to 'option' without looking for NO_ or +# _SUPPORTED; the macro is enabled if it is defined so long as all +# the 'requires' macros are also defined. The definitions may be +# empty, an error will be issued if the 'requires' macros are +# *not* defined. If given the 'default' value is used if the +# macro is not defined. The default value will be re-tokenised. +# (BTW: this is somewhat restrictive, it mainly exists for the +# support of non-standard configurations and numeric parameters, +# see the uses in scripts/options.dat + +$1 == "setting" && (NF == 2 || NF >= 3 && ($3 == "requires" || $3 == "default")){ + reqs = "" + deflt = "" + isdef = 0 + key = "" + for (i=3; i<=NF; ++i) + if ($(i) == "requires" || $(i) == "default") { + key = $(i) + if (key == "default") isdef = 1 + } else if (key == "requires") + reqs = reqs " " $(i) + else if (key == "default") + deflt = deflt " " $(i) + else + break # Format error, handled below + + setting[$2] = reqs + # NOTE: this overwrites a previous value silently + if (isdef && deflt == "") + deflt = " " # as a flag to force output + defaults[$2] = deflt + next +} + +# The order of the dependency lines (option, chunk, setting) is irrelevant +# - the 'enables', 'requires' and 'if' settings will be used to determine +# the correct order in the output and the final values in pnglibconf.h are +# not order dependent. 'requires' and 'if' entries take precedence over +# 'enables' from other options; if an option requires another option it +# won't be set regardless of any options that enable it unless the other +# option is also enabled. +# +# Similarly 'enables' trumps a NO_ definition in CFLAGS or pngusr.h +# +# For simplicity cycles in the definitions are regarded as errors, +# even if they are not ambiguous. +# A given NAME can be specified in as many 'option' lines as required, the +# definitions are additive. + +# For backwards compatibility equivalent macros may be listed thus: +# +# = [NO_]NAME MACRO +# Makes -DMACRO equivalent to -DPNG_NO_NAME or -DPNG_NAME_SUPPORTED +# as appropriate. +# +# The definition is injected into the C compiler input when encountered +# in the second pass (so all these definitions appear *after* the @ +# lines!) +# +# 'NAME' is as above, but 'MACRO' is the full text of the equivalent +# old, deprecated, macro. + +$1 == "=" && NF == 3{ + print "#ifdef PNG_" $3 >out + if ($2 ~ /^NO_/) + print "# define PNG_" $2 >out + else + print "# define PNG_" $2 "_SUPPORTED" >out + print "#endif" >out + next +} + +# Lines may be injected into the C compiler input by preceding them +# with an "@" character. The line is copied with just the leading +# @ removed. + +$1 ~ /^@/{ + # sub(/^[ ]*@/, "") + $1 = substr($1, 2) + print >out + next +} + +# Check for unreognized lines, because of the preprocessing chunk +# format errors will be detected on the first pass independent of +# any other format errors. +{ + print "options.awk: bad line (" NR "):", $0 + err = 1 # prevent END{} running + exit 1 +} + +# For checking purposes names that start with "ok_" or "fail_" are +# not output to pnglibconf.h and must be either enabled or disabled +# respectively for the build to succeed. This allows interdependencies +# between options of the form "at least one of" or "at most one of" +# to be checked. For example: +# +# option FLOATING_POINT enables ok_math +# option FIXED_POINT enables ok_math +# This ensures that at least one of FLOATING_POINT and FIXED_POINT +# must be set for the build to succeed. +# +# option fail_math requires FLOATING_POINT FIXED_POINT +# This means the build will fail if *both* FLOATING_POINT and +# FIXED_POINT are set (this is an example; in fact both are allowed.) +# +# If all these options were given the build would require exactly one +# of the names to be enabled. + +END{ + # END{} gets run on an exit (a traditional awk feature) + if (err) exit 1 + + if (pre) { + # Record the final value of the variables + print "deb =", deb >out + if (everything != "") { + print "everything =", everything >out + } + print "logunsupported =", logunsupported >out + exit 0 + } + + # Do the 'setting' values first, the algorithm the standard + # tree walk (O(1)) done in an O(2) while/for loop; interations + # settings x depth, outputing the deepest required macros + # first. + print "" >out + print "/* SETTINGS */" >out + print comment, "settings", cend >out + finished = 0 + while (!finished) { + finished = 1 + movement = 0 # done nothing + for (i in setting) if (!doneset[i]) { + nreqs = split(setting[i], r) + if (nreqs > 0) { + for (j=1; j<=nreqs; ++j) if (!doneset[r[j]]) { + break + } + if (j<=nreqs) { + finished = 0 + continue # try a different setting + } + } + + # All the requirements have been processed, output + # this setting. + if (deb) print "setting", i + print "" >out + print "/* setting: ", i >out + print " * requires:" setting[i] >out + print " * default: ", defaults[i], "*/" >out + if (defaults[i] == "") { # no default, only check if defined + print "#ifdef PNG_" i >out + } + for (j=1; j<=nreqs; ++j) { + print "# ifndef PNG_" r[j] >out + print error, i, "requires", r[j] end >out + print "# endif" >out + } + if (defaults[i] != "") { # default handling + print "#ifdef PNG_" i >out + } + print def i, "PNG_" i end >out + if (defaults[i] != "") { + print "#else /*default*/" >out + # And add the default definition for the benefit + # of later settings an options test: + print "# define PNG_" i defaults[i] >out + print def i defaults[i] end >out + } + print "#endif" >out + + doneset[i] = 1 + ++movement + } + + if (!finished && !movement) { + print "setting: loop or missing setting in 'requires', cannot process:" + for (i in setting) if (!doneset[i]) { + print " setting", i, "requires" setting[i] + } + exit 1 + } + } + print comment, "end of settings", cend >out + + # Now do the options - somewhat more complex. The dependency + # tree is thus: + # + # name > name + # name requires name + # name if name + # name enabledby name + # + # First build a list 'tree' by option of all the things on which + # it depends. + print "" >out + print "/* OPTIONS */" >out + print comment, "options", cend >out + for (opt in enabledby) tree[opt] = 1 # may not be explicit options + for (opt in option) if (opt != "") { + o = option[opt] + # option should always be one of the following values + if (o != "on" && o != "off" && o != "disabled" && o != "enabled") { + print "internal option error (" o ")" + exit 1 + } + tree[opt] = "" # so unlisted options marked + } + for (opt in tree) if (opt != "") { + if (tree[opt] == 1) { + tree[opt] = "" + if (option[opt] != "") { + print "internal error (1)" + exit 1 + } + # Macros only listed in 'enables' remain off unless + # one of the enabling macros is on. + option[opt] = "disabled" + } + + split("", list) # clear 'list' + # Now add every requires, iffs or enabledby entry to 'list' + # so that we can add a unique list of requirements to tree[i] + split(requires[opt] iffs[opt] enabledby[opt], r) + for (i in r) list[r[i]] = 1 + for (i in list) tree[opt] = tree[opt] " " i + } + + # print the tree for extreme debugging + if (deb > 2) for (i in tree) if (i != "") print i, "depends-on" tree[i] + + # Ok, now check all options marked explicitly 'on' or 'off': + # + # If an option[opt] is 'on' then turn on all requires[opt] + # If an option[opt] is 'off' then turn off all enabledby[opt] + # + # Error out if we have to turn 'on' an 'off' option or vice versa. + npending = 0 + for (opt in option) if (opt != "") { + if (option[opt] == "on" || option[opt] == "off") { + pending[++npending] = opt + } + } + + err = 0 # set on error + while (npending > 0) { + opt = pending[npending--] + if (option[opt] == "on") { + nreqs = split(requires[opt], r) + for (j=1; j<=nreqs; ++j) { + if (option[r[j]] == "off") { + print "option", opt, "turned on, but requirement", r[j], "is turned off" + err = 1 + } else if (option[r[j]] != "on") { + option[r[j]] = "on" + pending[++npending] = r[j] + } + } + } else { + if (option[opt] != "off") { + print "internal error (2)" + exit 1 + } + nreqs = split(enabledby[opt], r) + for (j=1; j<=nreqs; ++j) { + if (option[r[j]] == "on") { + print "option", opt, "turned off, but enabled by", r[j], "which is turned on" + err = 1 + } else if (option[r[j]] != "off") { + option[r[j]] = "off" + pending[++npending] = r[j] + } + } + } + } + if (err) exit 1 + + # option[i] is now the complete list of all the tokens we may + # need to output, go through it as above, depth first. + finished = 0 + while (!finished) { + finished = 1 + movement = 0 # done nothing + for (i in option) if (!done[i]) { + nreqs = split(tree[i], r) + if (nreqs > 0) { + for (j=1; j<=nreqs; ++j) if (!done[r[j]]) { + break + } + if (j<=nreqs) { + finished = 0 + continue # next option + } + } + + # All the requirements have been processed, output + # this option. An option is _SUPPORTED if: + # + # all 'requires' are _SUPPORTED AND + # at least one of the 'if' options are _SUPPORTED AND + # EITHER: + # The name is _SUPPORTED (on the command line) + # OR: + # an 'enabledby' is _SUPPORTED + # OR: + # NO_name is not defined AND + # the option is not disabled; an option is disabled if: + # option == off + # option == disabled && everything != on + # option == "" && everything == off + if (deb) print "option", i + print "" >out + print "/* option:", i, option[i] >out + print " * requires: " requires[i] >out + print " * if: " iffs[i] >out + print " * enabled-by:" enabledby[i], "*/" >out + print "#undef PNG_on" >out + print "#define PNG_on 1" >out + + # requires + nreqs = split(requires[i], r) + for (j=1; j<=nreqs; ++j) { + print "#ifndef PNG_" r[j] "_SUPPORTED" >out + print "# undef PNG_on /*!" r[j] "*/" >out + # this error appears in the final output if something + # was switched 'on' but the processing above to force + # the requires did not work + if (option[i] == "on") { + print error, i, "requires", r[j] end >out + } + print "#endif" >out + } + + # if + nreqs = split(iffs[i], r) + print "#undef PNG_no_if" >out + if (nreqs > 0) { + print "/* if" iffs[i], "*/" >out + print "#define PNG_no_if 1" >out + for (j=1; j<=nreqs; ++j) { + print "#ifdef PNG_" r[j] "_SUPPORTED" >out + print "# undef PNG_no_if /*" r[j] "*/" >out + print "#endif" >out + } + print "#ifdef PNG_no_if /*missing if*/" >out + print "# undef PNG_on" >out + # There is no checking above for this, because we + # don't know which 'if' to choose, so whine about + # it here: + if (option[i] == "on") { + print error, i, "needs one of:", iffs[i] end >out + } + print "#endif" >out + } + + print "#ifdef PNG_on /*requires, if*/" >out + # enables + print "# undef PNG_not_enabled" >out + print "# define PNG_not_enabled 1" >out + print " /* enabled by" enabledby[i], "*/" >out + nreqs = split(enabledby[i], r) + for (j=1; j<=nreqs; ++j) { + print "#ifdef PNG_" r[j] "_SUPPORTED" >out + print "# undef PNG_not_enabled /*" r[j] "*/" >out + # Oops, probably not intended (should be factored + # out by the checks above). + if (option[i] == "off") { + print error, i, "enabled by:", r[j] end >out + } + print "#endif" >out + } + + print "# ifndef PNG_" i "_SUPPORTED /*!command line*/" >out + print "# ifdef PNG_not_enabled /*!enabled*/" >out + if (option[i] == "off" || option[i] == "disabled" && everything != "on" || option[i] == "enabled" && everything == "off") { + print "# undef PNG_on /*default off*/" >out + } else { + print "# ifdef PNG_NO_" i >out + print "# undef PNG_on /*turned off*/" >out + print "# endif" >out + print "# ifdef PNG_NO_" i "_SUPPORTED" >out + print "# undef PNG_on /*turned off*/" >out + print "# endif" >out + } + print "# endif /*!enabled*/" >out + print "# ifdef PNG_on" >out + # The _SUPPORTED macro must be defined so that dependent + # options output later work. + print "# define PNG_" i "_SUPPORTED" >out + print "# endif" >out + print "# endif /*!command line*/" >out + # If PNG_on is still set the option should be defined in + # pnglibconf.h + print "# ifdef PNG_on" >out + if (i ~ /^fail_/) { + print error, i, "is on: enabled by:" iffs[i] enabledby[i] ", requires" requires[i] end >out + } else if (i !~ /^ok_/) { + print def i sup >out + } + print "# endif /* definition */" >out + print "#endif /*requires, if*/" >out + if (logunsupported || i ~ /^ok_/) { + print "#ifndef PNG_on" >out + if (logunsupported) { + print und i une >out + } + if (i ~ /^ok_/) { + print error, i, "not enabled: requires:" requires[i] ", enabled by:" iffs[i] enabledby[i] end >out + } + print "#endif" >out + } + + done[i] = 1 + ++movement + } + + if (!finished && !movement) { + print "option: loop or missing option in dependency tree, cannot process:" + for (i in option) if (!done[i]) { + print " option", i, "depends on" tree[i], "needs:" + nreqs = split(tree[i], r) + if (nreqs > 0) for (j=1; j<=nreqs; ++j) if (!done[r[j]]) { + print " " r[j] + } + } + exit 1 + } + } + print comment, "end of options", cend >out + + # Regular end - everything looks ok + if (protect != "") { + print start "#endif", cx, protect, "*/" end >out + } +} diff --git a/contrib/libpng/scripts/pnglibconf.dfa b/contrib/libpng/scripts/pnglibconf.dfa new file mode 100644 index 0000000..9fe0d60 --- /dev/null +++ b/contrib/libpng/scripts/pnglibconf.dfa @@ -0,0 +1,549 @@ +# scripts/pnglibconf.dfa - library build configuration control +# +@/*- pnglibconf.dfn intermediate file +@ * generated from scripts/pnglibconf.dfa +@ */ +# +com pnglibconf.h - library build configuration +com +com libpng version 1.5.0 - January 6, 2011 +com +com Copyright (c) 1998-2011 Glenn Randers-Pehrson +com +com This code is released under the libpng license. +com For conditions of distribution and use, see the disclaimer +com and license in png.h +com + +file pnglibconf.h scripts/pnglibconf.dfa PNGLCONF_H + +# This file is preprocessed by scripts/options.awk and the +# C compiler to generate 'pnglibconf.h' - a list of all the +# configuration options. The file lists the various options +# that can *only* be specified during the libpng build; +# pnglibconf.h freezes the definitons selected for the specific +# build. +# +# The syntax is detailed in scripts/options.awk, this is a summary +# only: +# +# setting [requires ...] [default] +# #define PNG_ /* value comes from current setting */ +# option [requires ...] [if ...] [enables ...] [disabled] +# #define PNG__SUPPORTED if the requirements are met and +# enable the other options listed +# chunk [requires ...] [disabled] +# Enable chunk processing for the given ancillary chunk +# +# Note that the 'on' and 'off' keywords, while valid on both option +# and chunk, should not be used in this file because they force the +# relevant options on or off. + +#---------------------------------------------------------------------- + +# The following setting, option and chunk values can all be changed +# while building libpng: +# +# setting: change 'setting' lines to fine tune library performance, +# changes to the settings don't affect the libpng API functionally +# +# option: change 'option' lines to remove or add capabilities from +# or to the library; options change the library API +# +# chunk: change 'chunk' lines to remove capabilities to process +# optional ('ancillary') chunks. This does not prevent PNG +# decoding but does change the libpng API because some chunks +# will be ignored. +# +# There are three ways of disabling features, in no particular order: +# +# 1) Create 'pngusr.h', enter the required private build information +# detailed below and #define PNG_NO_