API usage: add 'basic' configuration

This adds a new configuration file, 'contrib/conftest/basic.dfa' which
disables unused APIs on a test Linux-based system.  So support the
configuration several fixes were necessary in the test programs so that
the tests are skipped correctly when APIs are not available.

The configuration has been tested on a range of common Linux apps
including web browser code (qtwebengine), image processing code (e.g.
ImageMagick) and general display code (X11, Qt5 and Qt6, KDE).  Overall
this first step reduces libpng linked code and data size to about 2/3 of
the full configuration.

To use the new test simply copy basic.dfa to 'pngusr.dfa' in the root of
the source directory and build.

Signed-off-by: John Bowler <jbowler@acm.org>
diff --git a/contrib/conftest/basic.dfa b/contrib/conftest/basic.dfa
new file mode 100644
index 0000000..f9ae5c3
--- /dev/null
+++ b/contrib/conftest/basic.dfa
@@ -0,0 +1,133 @@
+# basic.dfa
+#  Build time configuration of libpng
+#
+# Author: John Bowler
+# Copyright: (c) John Bowler, 2024
+# Usage rights:
+#  To the extent possible under law, the author has waived all copyright and
+#  related or neighboring rights to this work.  This work is published from:
+#  United States.
+#
+# Build libpng with basic read and write support.  This enables the lowest
+# level libpng read and write APIs - the "row-by-row" ones.
+#
+# Support is enabled only for those transformations that are observed to be
+# required by widely used apps or are in the v3 specification.
+#
+
+everything = off
+
+# The sequential read code is enabled here; the progressive code can be used
+# instead but there is no point enabling both.
+
+option READ on
+option SEQUENTIAL_READ on
+option EASY_ACCESS on
+option SET_USER_LIMITS on
+option INFO_IMAGE on
+option READ_16BIT on
+
+# Errors: these can be disabled but then there won't be any error messages
+# just failures and the error messages are really needed for apps:
+option WARNINGS on
+option ERROR_TEXT on
+option BENIGN_READ_ERRORS on
+
+# Required for many display programs such as web browsers:
+option PROGRESSIVE_READ on
+
+# Switch on the write code - this makes a minimalist encoder but with
+# interlace support turned on; otherwise png_read_png..png_write_png will
+# fail on an interlaced image.
+option WRITE on
+option WRITE_INTERLACING on
+option WRITE_16BIT on
+
+# Usages of the 'fixed' APIs are relatively rare but they do occur
+# one or the other for both the API and the internal math.
+
+#Fixed point:
+option FIXED_POINT on
+
+#Floating point:
+option FLOATING_POINT on
+option FLOATING_ARITHMETIC on
+
+# Basic error handling, IO and user memory support.  The latter allows the
+# application program to provide its own implementations of 'malloc' and 'free'.
+option SETJMP on
+option STDIO on
+option USER_MEM on
+
+# Gamma handling: this needs to be on for the gamma handling
+option READ_GAMMA on
+
+# The supported chunks
+chunk bKGD on
+chunk cHRM on
+chunk eXIf on
+chunk gAMA on
+chunk iCCP on
+chunk iTXt on
+chunk pHYs on
+chunk sBIT on
+chunk sRGB on
+chunk tEXt on
+chunk tIME on
+chunk tRNS on
+chunk zTXt on
+
+# These don't seem to be used anywhere:
+# chunk pCAL
+# chunk sCAL
+# chunk sPLT
+
+# The rest of this is app dependent: none of these options are required for
+# read/write of the full range of PNG files and the normal chunk handling on
+# read.
+option WRITE_CUSTOMIZE_ZTXT_COMPRESSION on
+option WRITE_CUSTOMIZE_COMPRESSION on
+
+option READ_EXPAND on
+option READ_FILLER on
+option READ_GRAY_TO_RGB on
+option READ_INVERT on
+option READ_PACK on
+option READ_RGB_TO_GRAY on
+option READ_SCALE_16_TO_8 on
+option READ_SHIFT on
+option READ_STRIP_16_TO_8 on
+option READ_STRIP_ALPHA on
+option READ_SWAP on
+
+option CONVERT_tIME on
+
+# optipng
+option IO_STATE on
+option STORE_UNKNOWN_CHUNKS on
+option HANDLE_AS_UNKNOWN on
+
+# pngcrush
+option READ_USER_TRANSFORM on
+option WRITE_FLUSH on
+
+# pnmtopng
+chunk hIST on
+
+# cairo
+option WRITE_PACKSWAP on
+option WRITE_USER_TRANSFORM on
+
+# graphicsmagick
+option READ_USER_CHUNKS on
+
+# Qt5.15 qtgui (gentoo package split) Qt6.6 qtbase
+option READ_BGR on
+option WRITE_BGR on
+option READ_SWAP_ALPHA on
+option WRITE_SWAP_ALPHA on
+chunk oFFs on
+
+# ghostscript-gpl
+option WRITE_INVERT_ALPHA on
+option WRITE_INVERT on
diff --git a/contrib/libtests/pngvalid.c b/contrib/libtests/pngvalid.c
index 6a7422e..3d66154 100644
--- a/contrib/libtests/pngvalid.c
+++ b/contrib/libtests/pngvalid.c
@@ -70,9 +70,12 @@
 #endif
 
 /* pngvalid requires write support and one of the fixed or floating point APIs.
+ * progressive read is also required currently as the progressive read pointer
+ * is used to record the 'display' structure.
  */
-#if defined(PNG_WRITE_SUPPORTED) &&\
-   (defined(PNG_FIXED_POINT_SUPPORTED) || defined(PNG_FLOATING_POINT_SUPPORTED))
+#if defined PNG_WRITE_SUPPORTED &&\
+   (defined PNG_PROGRESSIVE_READ_SUPPORTED) &&\
+   (defined PNG_FIXED_POINT_SUPPORTED || defined PNG_FLOATING_POINT_SUPPORTED)
 
 #if PNG_LIBPNG_VER < 10500
 /* This deliberately lacks the const. */
@@ -10009,9 +10012,12 @@
                case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN:
                case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED:
 #           endif /* ALPHA_MODE_SUPPORTED */
+#           if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
+               (defined PNG_READ_ALPHA_MODE_SUPPORTED)
                do_compose = (alpha > 0 && alpha < 1);
                use_input = (alpha != 0);
                break;
+#           endif
 
             default:
                break;
@@ -11924,7 +11930,14 @@
          pm.test_gamma_alpha_mode = 0;
 
       else if (strcmp(*argv, "--expand16") == 0)
-         pm.test_gamma_expand16 = 1;
+      {
+#        ifdef PNG_READ_EXPAND_16_SUPPORTED
+            pm.test_gamma_expand16 = 1;
+#        else
+            fprintf(stderr, "pngvalid: --expand16: no read support\n");
+            return SKIP;
+#        endif
+      }
 
       else if (strcmp(*argv, "--noexpand16") == 0)
          pm.test_gamma_expand16 = 0;
@@ -11939,10 +11952,15 @@
             pm.test_lbg_gamma_transform = pm.test_lbg_gamma_sbit =
             pm.test_lbg_gamma_composition = 0;
 
-#     ifdef PNG_WRITE_tRNS_SUPPORTED
-         else if (strcmp(*argv, "--tRNS") == 0)
+      else if (strcmp(*argv, "--tRNS") == 0)
+      {
+#        ifdef PNG_WRITE_tRNS_SUPPORTED
             pm.test_tRNS = 1;
-#     endif
+#        else
+            fprintf(stderr, "pngvalid: --tRNS: no write support\n");
+            return SKIP;
+#        endif
+      }
 
       else if (strcmp(*argv, "--notRNS") == 0)
          pm.test_tRNS = 0;
diff --git a/contrib/tools/pngfix.c b/contrib/tools/pngfix.c
index 025e687..8d5dc46 100644
--- a/contrib/tools/pngfix.c
+++ b/contrib/tools/pngfix.c
@@ -133,11 +133,6 @@
 /* Is it safe to copy? */
 #define SAFE_TO_COPY(chunk) (((chunk) & PNG_U32(0,0,0,32)) != 0)
 
-/* Fix ups for builds with limited read support */
-#ifndef PNG_ERROR_TEXT_SUPPORTED
-#  define png_error(a,b) png_err(a)
-#endif
-
 /********************************* UTILITIES **********************************/
 /* UNREACHED is a value to cause an assert to fail. Because of the way the
  * assert macro is written the string "UNREACHED" is produced in the error
diff --git a/pngtest.c b/pngtest.c
index 3d42679..49cc2dd 100644
--- a/pngtest.c
+++ b/pngtest.c
@@ -43,6 +43,17 @@
 
 #include "png.h"
 
+/* 1.6.1 added support for the configure test harness, which uses 77 to indicate
+ * a skipped test, in earlier versions  and cmake builds we need to succeed on
+ * a skipped test, so:
+ */
+#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H)
+#  define SKIP 77
+#else
+#  define SKIP 0
+#endif
+
+
 /* Known chunks that exist in pngtest.png must be supported or pngtest will fail
  * simply as a result of re-ordering them.  This may be fixed in 1.7
  *
@@ -2150,7 +2161,7 @@
    fprintf(STDERR,
        " test ignored because libpng was not built with read support\n");
    /* And skip this test */
-   return PNG_LIBPNG_VER < 10600 ? 0 : 77;
+   return SKIP;
 }
 #endif
 
diff --git a/tests/pngtest-all b/tests/pngtest-all
index 7a9b64a..b4280f5 100755
--- a/tests/pngtest-all
+++ b/tests/pngtest-all
@@ -1,17 +1,24 @@
 #!/bin/sh
 
-st=0    # exit status (set to 1 if a test fails)
+st=0        # exit status (set to 1 if a test fails)
+skipped=
 fail="**FAIL**"
+skip="**SKIP**"
 success=" SUCCESS"
 TEST(){
    # Try to make the log file easier to read:
-   test_status="$success"
-   echo "=============== PNGTEST $* ===================="
-   ./pngtest "$@" || {
-      st=$?
-      test_status="$fail"
-   }
+   echo "=============== pngtest $* ===================="
+   ./pngtest "$@"
+   status=$?
+   case "$status" in
+       0)  test_status="$success";;
+       77) test_status="$skip"
+           skipped=1;;
+       *)  test_status="$fail"
+           st="$status";; 
+   esac
    echo "===============$test_status $* ===================="
+   return "$status"
 }
 
 # The "standard" test
@@ -48,15 +55,17 @@
    # variable 'line' below.  The pattern matching ignores this because of the
    # '*' at the end of the pattern match.
    found=
+   skipped=
    while read line
    do
       case "$line" in
          *"$2"*) found=1;;
+         *"TEST SKIPPED"*) skipped=1;;
       esac
       echo "$line" # preserve the original output verbatim
    done
    # output the missing warning on descriptor 3:
-   test -z "$found" && echo "$1: $2" >&3
+   test -z "$found" -a -z "$skipped" && echo "$1: $2" >&3
 }
 # NOTE: traditionally the Bourne shell executed the last element in a pipe
 # sequence in the original shell so it could set variables in the original
@@ -74,7 +83,10 @@
      # The exit code is ignored here, the test is that the particular errors
      # (warnings) are produced.  The original output still ends up in the log
      # file.
-     TEST "$file" |
+     {
+        TEST "$file"
+        test "$?" -eq 77 && echo "TEST SKIPPED"
+     } |
         check_stdout "$file" 'IDAT: Read palette index exceeding num_palette' |
         check_stdout "$file" 'Wrote palette index exceeding num_palette' >&4
    done
@@ -90,4 +102,6 @@
    exit $st
 } || st=$?
 
-exit $st
+test "$st" -gt 0 && exit "$st"
+test -n "$skipped" && exit 77
+exit 0